1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_errors.h"
48 #include "bgpd/bgp_aspath.h"
49 #include "bgpd/bgp_regex.h"
50 #include "bgpd/bgp_community.h"
51 #include "bgpd/bgp_ecommunity.h"
52 #include "bgpd/bgp_lcommunity.h"
53 #include "bgpd/bgp_clist.h"
54 #include "bgpd/bgp_packet.h"
55 #include "bgpd/bgp_filter.h"
56 #include "bgpd/bgp_fsm.h"
57 #include "bgpd/bgp_mplsvpn.h"
58 #include "bgpd/bgp_nexthop.h"
59 #include "bgpd/bgp_damp.h"
60 #include "bgpd/bgp_advertise.h"
61 #include "bgpd/bgp_zebra.h"
62 #include "bgpd/bgp_vty.h"
63 #include "bgpd/bgp_mpath.h"
64 #include "bgpd/bgp_nht.h"
65 #include "bgpd/bgp_updgrp.h"
66 #include "bgpd/bgp_label.h"
69 #include "bgpd/rfapi/rfapi_backend.h"
70 #include "bgpd/rfapi/vnc_import_bgp.h"
71 #include "bgpd/rfapi/vnc_export_bgp.h"
73 #include "bgpd/bgp_encap_types.h"
74 #include "bgpd/bgp_encap_tlv.h"
75 #include "bgpd/bgp_evpn.h"
76 #include "bgpd/bgp_evpn_vty.h"
77 #include "bgpd/bgp_flowspec.h"
78 #include "bgpd/bgp_flowspec_util.h"
79 #include "bgpd/bgp_pbr.h"
81 #ifndef VTYSH_EXTRACT_PL
82 #include "bgpd/bgp_route_clippy.c"
85 /* Extern from bgp_dump.c */
86 extern const char *bgp_origin_str
[];
87 extern const char *bgp_origin_long_str
[];
90 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
91 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
92 static const struct message bgp_pmsi_tnltype_str
[] = {
93 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
94 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
95 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
96 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
97 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
98 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
99 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
100 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
104 #define VRFID_NONE_STR "-"
106 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
107 safi_t safi
, struct prefix
*p
,
108 struct prefix_rd
*prd
)
111 struct bgp_node
*prn
= NULL
;
117 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
118 || (safi
== SAFI_EVPN
)) {
119 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
121 if (prn
->info
== NULL
)
122 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
124 bgp_unlock_node(prn
);
128 rn
= bgp_node_get(table
, p
);
130 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
131 || (safi
== SAFI_EVPN
))
137 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
138 safi_t safi
, struct prefix
*p
,
139 struct prefix_rd
*prd
)
142 struct bgp_node
*prn
= NULL
;
147 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
148 || (safi
== SAFI_EVPN
)) {
149 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
153 if (prn
->info
== NULL
) {
154 bgp_unlock_node(prn
);
161 rn
= bgp_node_lookup(table
, p
);
166 /* Allocate bgp_info_extra */
167 static struct bgp_info_extra
*bgp_info_extra_new(void)
169 struct bgp_info_extra
*new;
170 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
171 new->label
[0] = MPLS_INVALID_LABEL
;
176 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
178 struct bgp_info_extra
*e
;
180 if (!extra
|| !*extra
)
185 bgp_damp_info_free(e
->damp_info
, 0);
189 struct bgp_info
*bi
= (struct bgp_info
*)e
->parent
;
192 /* FIXME: since multiple e may have the same e->parent
193 * and e->parent->net is holding a refcount for each
194 * of them, we need to do some fudging here.
196 * WARNING: if bi->net->lock drops to 0, bi may be
197 * freed as well (because bi->net was holding the
198 * last reference to bi) => write after free!
202 bi
= bgp_info_lock(bi
);
203 refcount
= bi
->net
->lock
- 1;
204 bgp_unlock_node((struct bgp_node
*)bi
->net
);
209 bgp_info_unlock(e
->parent
);
214 bgp_unlock(e
->bgp_orig
);
216 if ((*extra
)->bgp_fs_pbr
)
217 list_delete_and_null(&((*extra
)->bgp_fs_pbr
));
218 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
223 /* Get bgp_info extra information for the given bgp_info, lazy allocated
226 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
229 ri
->extra
= bgp_info_extra_new();
233 /* Allocate new bgp info structure. */
234 struct bgp_info
*bgp_info_new(void)
236 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
239 /* Free bgp route information. */
240 static void bgp_info_free(struct bgp_info
*binfo
)
243 bgp_attr_unintern(&binfo
->attr
);
245 bgp_unlink_nexthop(binfo
);
246 bgp_info_extra_free(&binfo
->extra
);
247 bgp_info_mpath_free(&binfo
->mpath
);
249 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
251 XFREE(MTYPE_BGP_ROUTE
, binfo
);
254 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
260 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
262 assert(binfo
&& binfo
->lock
> 0);
265 if (binfo
->lock
== 0) {
267 zlog_debug ("%s: unlocked and freeing", __func__
);
268 zlog_backtrace (LOG_DEBUG
);
270 bgp_info_free(binfo
);
275 if (binfo
->lock
== 1)
277 zlog_debug ("%s: unlocked to 1", __func__
);
278 zlog_backtrace (LOG_DEBUG
);
285 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
287 struct bgp_info
*top
;
299 peer_lock(ri
->peer
); /* bgp_info peer reference */
302 /* Do the actual removal of info from RIB, for use by bgp_process
303 completion callback *only* */
304 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
307 ri
->next
->prev
= ri
->prev
;
309 ri
->prev
->next
= ri
->next
;
313 bgp_info_mpath_dequeue(ri
);
318 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
320 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
321 /* set of previous already took care of pcount */
322 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
325 /* undo the effects of a previous call to bgp_info_delete; typically
326 called when a route is deleted and then quickly re-added before the
327 deletion has been processed */
328 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
330 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
331 /* unset of previous already took care of pcount */
332 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
335 /* Adjust pcount as required */
336 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
338 struct bgp_table
*table
;
340 assert(rn
&& bgp_node_table(rn
));
341 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
343 table
= bgp_node_table(rn
);
345 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
348 if (!BGP_INFO_COUNTABLE(ri
)
349 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
351 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
353 /* slight hack, but more robust against errors. */
354 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
355 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
358 "%s: Asked to decrement 0 prefix count for peer %s",
359 __func__
, ri
->peer
->host
);
360 zlog_backtrace(LOG_WARNING
);
362 } else if (BGP_INFO_COUNTABLE(ri
)
363 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
364 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
365 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
369 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
371 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
374 /* Set/unset bgp_info flags, adjusting any other state as needed.
375 * This is here primarily to keep prefix-count in check.
377 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
379 SET_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 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
393 UNSET_FLAG(ri
->flags
, flag
);
395 /* early bath if we know it's not a flag that changes countability state
397 if (!CHECK_FLAG(flag
,
398 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
401 bgp_pcount_adjust(rn
, ri
);
404 /* Get MED value. If MED value is missing and "bgp bestpath
405 missing-as-worst" is specified, treat it as the worst value. */
406 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
408 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
411 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
418 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
420 if (ri
->addpath_rx_id
)
421 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
424 sprintf(buf
, "path %s", ri
->peer
->host
);
427 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
429 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
430 struct bgp_info
*exist
, int *paths_eq
,
431 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
432 char *pfx_buf
, afi_t afi
, safi_t safi
)
434 struct attr
*newattr
, *existattr
;
435 bgp_peer_sort_t new_sort
;
436 bgp_peer_sort_t exist_sort
;
442 uint32_t exist_weight
;
443 uint32_t newm
, existm
;
444 struct in_addr new_id
;
445 struct in_addr exist_id
;
448 int internal_as_route
;
451 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
452 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
454 uint32_t exist_mm_seq
;
461 zlog_debug("%s: new is NULL", pfx_buf
);
466 bgp_info_path_with_addpath_rx_str(new, new_buf
);
470 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
476 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
477 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
478 pfx_buf
, new_buf
, new->flags
, exist_buf
,
483 existattr
= exist
->attr
;
485 /* For EVPN routes, we cannot just go by local vs remote, we have to
486 * look at the MAC mobility sequence number, if present.
488 if (safi
== SAFI_EVPN
) {
489 /* This is an error condition described in RFC 7432 Section
491 * states that in this scenario "the PE MUST alert the operator"
493 * does not state what other action to take. In order to provide
495 * consistency in this scenario we are going to prefer the path
499 if (newattr
->sticky
!= existattr
->sticky
) {
501 prefix2str(&new->net
->p
, pfx_buf
,
503 * PREFIX2STR_BUFFER
);
504 bgp_info_path_with_addpath_rx_str(new, new_buf
);
505 bgp_info_path_with_addpath_rx_str(exist
,
509 if (newattr
->sticky
&& !existattr
->sticky
) {
512 "%s: %s wins over %s due to sticky MAC flag",
513 pfx_buf
, new_buf
, exist_buf
);
517 if (!newattr
->sticky
&& existattr
->sticky
) {
520 "%s: %s loses to %s due to sticky MAC flag",
521 pfx_buf
, new_buf
, exist_buf
);
526 new_mm_seq
= mac_mobility_seqnum(newattr
);
527 exist_mm_seq
= mac_mobility_seqnum(existattr
);
529 if (new_mm_seq
> exist_mm_seq
) {
532 "%s: %s wins over %s due to MM seq %u > %u",
533 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
538 if (new_mm_seq
< exist_mm_seq
) {
541 "%s: %s loses to %s due to MM seq %u < %u",
542 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
548 /* 1. Weight check. */
549 new_weight
= newattr
->weight
;
550 exist_weight
= existattr
->weight
;
552 if (new_weight
> exist_weight
) {
554 zlog_debug("%s: %s wins over %s due to weight %d > %d",
555 pfx_buf
, new_buf
, exist_buf
, new_weight
,
560 if (new_weight
< exist_weight
) {
562 zlog_debug("%s: %s loses to %s due to weight %d < %d",
563 pfx_buf
, new_buf
, exist_buf
, new_weight
,
568 /* 2. Local preference check. */
569 new_pref
= exist_pref
= bgp
->default_local_pref
;
571 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
572 new_pref
= newattr
->local_pref
;
573 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
574 exist_pref
= existattr
->local_pref
;
576 if (new_pref
> exist_pref
) {
579 "%s: %s wins over %s due to localpref %d > %d",
580 pfx_buf
, new_buf
, exist_buf
, new_pref
,
585 if (new_pref
< exist_pref
) {
588 "%s: %s loses to %s due to localpref %d < %d",
589 pfx_buf
, new_buf
, exist_buf
, new_pref
,
594 /* 3. Local route check. We prefer:
596 * - BGP_ROUTE_AGGREGATE
597 * - BGP_ROUTE_REDISTRIBUTE
599 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
600 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
603 "%s: %s wins over %s due to preferred BGP_ROUTE type",
604 pfx_buf
, new_buf
, exist_buf
);
608 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
609 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
612 "%s: %s loses to %s due to preferred BGP_ROUTE type",
613 pfx_buf
, new_buf
, exist_buf
);
617 /* 4. AS path length check. */
618 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
619 int exist_hops
= aspath_count_hops(existattr
->aspath
);
620 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
622 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
625 aspath_hops
= aspath_count_hops(newattr
->aspath
);
626 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
628 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
631 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
632 pfx_buf
, new_buf
, exist_buf
,
634 (exist_hops
+ exist_confeds
));
638 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
641 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
642 pfx_buf
, new_buf
, exist_buf
,
644 (exist_hops
+ exist_confeds
));
648 int newhops
= aspath_count_hops(newattr
->aspath
);
650 if (newhops
< exist_hops
) {
653 "%s: %s wins over %s due to aspath hopcount %d < %d",
654 pfx_buf
, new_buf
, exist_buf
,
655 newhops
, exist_hops
);
659 if (newhops
> exist_hops
) {
662 "%s: %s loses to %s due to aspath hopcount %d > %d",
663 pfx_buf
, new_buf
, exist_buf
,
664 newhops
, exist_hops
);
670 /* 5. Origin check. */
671 if (newattr
->origin
< existattr
->origin
) {
673 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
674 pfx_buf
, new_buf
, exist_buf
,
675 bgp_origin_long_str
[newattr
->origin
],
676 bgp_origin_long_str
[existattr
->origin
]);
680 if (newattr
->origin
> existattr
->origin
) {
682 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
683 pfx_buf
, new_buf
, exist_buf
,
684 bgp_origin_long_str
[newattr
->origin
],
685 bgp_origin_long_str
[existattr
->origin
]);
690 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
691 && aspath_count_hops(existattr
->aspath
) == 0);
692 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
693 && aspath_count_confeds(existattr
->aspath
) > 0
694 && aspath_count_hops(newattr
->aspath
) == 0
695 && aspath_count_hops(existattr
->aspath
) == 0);
697 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
698 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
699 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
700 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
701 || internal_as_route
) {
702 new_med
= bgp_med_value(new->attr
, bgp
);
703 exist_med
= bgp_med_value(exist
->attr
, bgp
);
705 if (new_med
< exist_med
) {
708 "%s: %s wins over %s due to MED %d < %d",
709 pfx_buf
, new_buf
, exist_buf
, new_med
,
714 if (new_med
> exist_med
) {
717 "%s: %s loses to %s due to MED %d > %d",
718 pfx_buf
, new_buf
, exist_buf
, new_med
,
724 /* 7. Peer type check. */
725 new_sort
= new->peer
->sort
;
726 exist_sort
= exist
->peer
->sort
;
728 if (new_sort
== BGP_PEER_EBGP
729 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
732 "%s: %s wins over %s due to eBGP peer > iBGP peer",
733 pfx_buf
, new_buf
, exist_buf
);
737 if (exist_sort
== BGP_PEER_EBGP
738 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
741 "%s: %s loses to %s due to iBGP peer < eBGP peer",
742 pfx_buf
, new_buf
, exist_buf
);
746 /* 8. IGP metric check. */
750 newm
= new->extra
->igpmetric
;
752 existm
= exist
->extra
->igpmetric
;
757 "%s: %s wins over %s due to IGP metric %d < %d",
758 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
765 "%s: %s loses to %s due to IGP metric %d > %d",
766 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
770 /* 9. Same IGP metric. Compare the cluster list length as
771 representative of IGP hops metric. Rewrite the metric value
772 pair (newm, existm) with the cluster list length. Prefer the
773 path with smaller cluster list length. */
774 if (newm
== existm
) {
775 if (peer_sort(new->peer
) == BGP_PEER_IBGP
776 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
777 && (mpath_cfg
== NULL
779 mpath_cfg
->ibgp_flags
,
780 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
781 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
782 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
787 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
788 pfx_buf
, new_buf
, exist_buf
,
796 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
797 pfx_buf
, new_buf
, exist_buf
,
804 /* 10. confed-external vs. confed-internal */
805 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
806 if (new_sort
== BGP_PEER_CONFED
807 && exist_sort
== BGP_PEER_IBGP
) {
810 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
811 pfx_buf
, new_buf
, exist_buf
);
815 if (exist_sort
== BGP_PEER_CONFED
816 && new_sort
== BGP_PEER_IBGP
) {
819 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
820 pfx_buf
, new_buf
, exist_buf
);
825 /* 11. Maximum path check. */
826 if (newm
== existm
) {
827 /* If one path has a label but the other does not, do not treat
828 * them as equals for multipath
830 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
832 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
835 "%s: %s and %s cannot be multipath, one has a label while the other does not",
836 pfx_buf
, new_buf
, exist_buf
);
837 } else if (bgp_flag_check(bgp
,
838 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
841 * For the two paths, all comparison steps till IGP
843 * have succeeded - including AS_PATH hop count. Since
845 * bestpath as-path multipath-relax' knob is on, we
847 * an exact match of AS_PATH. Thus, mark the paths are
849 * That will trigger both these paths to get into the
857 "%s: %s and %s are equal via multipath-relax",
858 pfx_buf
, new_buf
, exist_buf
);
859 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
860 if (aspath_cmp(new->attr
->aspath
,
861 exist
->attr
->aspath
)) {
866 "%s: %s and %s are equal via matching aspaths",
867 pfx_buf
, new_buf
, exist_buf
);
869 } else if (new->peer
->as
== exist
->peer
->as
) {
874 "%s: %s and %s are equal via same remote-as",
875 pfx_buf
, new_buf
, exist_buf
);
879 * TODO: If unequal cost ibgp multipath is enabled we can
880 * mark the paths as equal here instead of returning
885 "%s: %s wins over %s after IGP metric comparison",
886 pfx_buf
, new_buf
, exist_buf
);
889 "%s: %s loses to %s after IGP metric comparison",
890 pfx_buf
, new_buf
, exist_buf
);
895 /* 12. If both paths are external, prefer the path that was received
896 first (the oldest one). This step minimizes route-flap, since a
897 newer path won't displace an older one, even if it was the
898 preferred route based on the additional decision criteria below. */
899 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
900 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
901 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
904 "%s: %s wins over %s due to oldest external",
905 pfx_buf
, new_buf
, exist_buf
);
909 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
912 "%s: %s loses to %s due to oldest external",
913 pfx_buf
, new_buf
, exist_buf
);
918 /* 13. Router-ID comparision. */
919 /* If one of the paths is "stale", the corresponding peer router-id will
920 * be 0 and would always win over the other path. If originator id is
921 * used for the comparision, it will decide which path is better.
923 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
924 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
926 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
927 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
928 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
930 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
932 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
935 "%s: %s wins over %s due to Router-ID comparison",
936 pfx_buf
, new_buf
, exist_buf
);
940 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
943 "%s: %s loses to %s due to Router-ID comparison",
944 pfx_buf
, new_buf
, exist_buf
);
948 /* 14. Cluster length comparision. */
949 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
950 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
952 if (new_cluster
< exist_cluster
) {
955 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
956 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
961 if (new_cluster
> exist_cluster
) {
964 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
965 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
970 /* 15. Neighbor address comparision. */
971 /* Do this only if neither path is "stale" as stale paths do not have
972 * valid peer information (as the connection may or may not be up).
974 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
977 "%s: %s wins over %s due to latter path being STALE",
978 pfx_buf
, new_buf
, exist_buf
);
982 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
985 "%s: %s loses to %s due to former path being STALE",
986 pfx_buf
, new_buf
, exist_buf
);
990 /* locally configured routes to advertise do not have su_remote */
991 if (new->peer
->su_remote
== NULL
)
993 if (exist
->peer
->su_remote
== NULL
)
996 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1001 "%s: %s loses to %s due to Neighor IP comparison",
1002 pfx_buf
, new_buf
, exist_buf
);
1009 "%s: %s wins over %s due to Neighor IP comparison",
1010 pfx_buf
, new_buf
, exist_buf
);
1015 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1016 pfx_buf
, new_buf
, exist_buf
);
1021 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1022 * is preferred, or 0 if they are the same (usually will only occur if
1023 * multipath is enabled
1024 * This version is compatible with */
1025 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
1026 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
1031 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1045 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1046 struct attr
*attr
, afi_t afi
,
1049 struct bgp_filter
*filter
;
1051 filter
= &peer
->filter
[afi
][safi
];
1053 #define FILTER_EXIST_WARN(F, f, filter) \
1054 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1055 zlog_warn("%s: Could not find configured input %s-list %s!", \
1056 peer->host, #f, F##_IN_NAME(filter));
1058 if (DISTRIBUTE_IN_NAME(filter
)) {
1059 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1061 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1065 if (PREFIX_LIST_IN_NAME(filter
)) {
1066 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1068 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1072 if (FILTER_LIST_IN_NAME(filter
)) {
1073 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1075 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1080 return FILTER_PERMIT
;
1081 #undef FILTER_EXIST_WARN
1084 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1085 struct attr
*attr
, afi_t afi
,
1088 struct bgp_filter
*filter
;
1090 filter
= &peer
->filter
[afi
][safi
];
1092 #define FILTER_EXIST_WARN(F, f, filter) \
1093 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1094 zlog_warn("%s: Could not find configured output %s-list %s!", \
1095 peer->host, #f, F##_OUT_NAME(filter));
1097 if (DISTRIBUTE_OUT_NAME(filter
)) {
1098 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1100 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1104 if (PREFIX_LIST_OUT_NAME(filter
)) {
1105 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1107 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1112 if (FILTER_LIST_OUT_NAME(filter
)) {
1113 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1115 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1120 return FILTER_PERMIT
;
1121 #undef FILTER_EXIST_WARN
1124 /* If community attribute includes no_export then return 1. */
1125 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1127 if (attr
->community
) {
1128 /* NO_ADVERTISE check. */
1129 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1132 /* NO_EXPORT check. */
1133 if (peer
->sort
== BGP_PEER_EBGP
1134 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1137 /* NO_EXPORT_SUBCONFED check. */
1138 if (peer
->sort
== BGP_PEER_EBGP
1139 || peer
->sort
== BGP_PEER_CONFED
)
1140 if (community_include(attr
->community
,
1141 COMMUNITY_NO_EXPORT_SUBCONFED
))
1147 /* Route reflection loop check. */
1148 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1150 struct in_addr cluster_id
;
1152 if (attr
->cluster
) {
1153 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1154 cluster_id
= peer
->bgp
->cluster_id
;
1156 cluster_id
= peer
->bgp
->router_id
;
1158 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1164 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1165 struct attr
*attr
, afi_t afi
, safi_t safi
,
1166 const char *rmap_name
)
1168 struct bgp_filter
*filter
;
1169 struct bgp_info info
;
1170 route_map_result_t ret
;
1171 struct route_map
*rmap
= NULL
;
1173 filter
= &peer
->filter
[afi
][safi
];
1175 /* Apply default weight value. */
1176 if (peer
->weight
[afi
][safi
])
1177 attr
->weight
= peer
->weight
[afi
][safi
];
1180 rmap
= route_map_lookup_by_name(rmap_name
);
1185 if (ROUTE_MAP_IN_NAME(filter
)) {
1186 rmap
= ROUTE_MAP_IN(filter
);
1193 /* Route map apply. */
1195 memset(&info
, 0, sizeof(struct bgp_info
));
1196 /* Duplicate current value to new strucutre for modification. */
1200 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1202 /* Apply BGP route map to the attribute. */
1203 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1205 peer
->rmap_type
= 0;
1207 if (ret
== RMAP_DENYMATCH
)
1213 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1214 struct attr
*attr
, afi_t afi
, safi_t safi
,
1215 const char *rmap_name
)
1217 struct bgp_info info
;
1218 route_map_result_t ret
;
1219 struct route_map
*rmap
= NULL
;
1223 * So if we get to this point and have no rmap_name
1224 * we want to just show the output as it currently
1230 /* Apply default weight value. */
1231 if (peer
->weight
[afi
][safi
])
1232 attr
->weight
= peer
->weight
[afi
][safi
];
1234 rmap
= route_map_lookup_by_name(rmap_name
);
1237 * If we have a route map name and we do not find
1238 * the routemap that means we have an implicit
1244 memset(&info
, 0, sizeof(struct bgp_info
));
1245 /* Route map apply. */
1246 /* Duplicate current value to new strucutre for modification. */
1250 rmap_type
= peer
->rmap_type
;
1251 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1253 /* Apply BGP route map to the attribute. */
1254 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1256 peer
->rmap_type
= rmap_type
;
1258 if (ret
== RMAP_DENYMATCH
)
1260 * caller has multiple error paths with bgp_attr_flush()
1267 /* If this is an EBGP peer with remove-private-AS */
1268 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1269 struct peer
*peer
, struct attr
*attr
)
1271 if (peer
->sort
== BGP_PEER_EBGP
1272 && (peer_af_flag_check(peer
, afi
, safi
,
1273 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1274 || peer_af_flag_check(peer
, afi
, safi
,
1275 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1276 || peer_af_flag_check(peer
, afi
, safi
,
1277 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1278 || peer_af_flag_check(peer
, afi
, safi
,
1279 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1280 // Take action on the entire aspath
1281 if (peer_af_flag_check(peer
, afi
, safi
,
1282 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1283 || peer_af_flag_check(peer
, afi
, safi
,
1284 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1285 if (peer_af_flag_check(
1287 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1288 attr
->aspath
= aspath_replace_private_asns(
1289 attr
->aspath
, bgp
->as
);
1291 // The entire aspath consists of private ASNs so create
1293 else if (aspath_private_as_check(attr
->aspath
))
1294 attr
->aspath
= aspath_empty_get();
1296 // There are some public and some private ASNs, remove
1299 attr
->aspath
= aspath_remove_private_asns(
1303 // 'all' was not specified so the entire aspath must be private
1305 // for us to do anything
1306 else if (aspath_private_as_check(attr
->aspath
)) {
1307 if (peer_af_flag_check(
1309 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1310 attr
->aspath
= aspath_replace_private_asns(
1311 attr
->aspath
, bgp
->as
);
1313 attr
->aspath
= aspath_empty_get();
1318 /* If this is an EBGP peer with as-override */
1319 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1320 struct peer
*peer
, struct attr
*attr
)
1322 if (peer
->sort
== BGP_PEER_EBGP
1323 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1324 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1325 attr
->aspath
= aspath_replace_specific_asn(
1326 attr
->aspath
, peer
->as
, bgp
->as
);
1330 void bgp_attr_add_gshut_community(struct attr
*attr
)
1332 struct community
*old
;
1333 struct community
*new;
1334 struct community
*merge
;
1335 struct community
*gshut
;
1337 old
= attr
->community
;
1338 gshut
= community_str2com("graceful-shutdown");
1343 merge
= community_merge(community_dup(old
), gshut
);
1345 if (old
->refcnt
== 0)
1346 community_free(old
);
1348 new = community_uniq_sort(merge
);
1349 community_free(merge
);
1351 new = community_dup(gshut
);
1354 community_free(gshut
);
1355 attr
->community
= new;
1356 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1358 /* When we add the graceful-shutdown community we must also
1359 * lower the local-preference */
1360 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1361 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1365 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1367 if (family
== AF_INET
) {
1368 attr
->nexthop
.s_addr
= 0;
1369 attr
->mp_nexthop_global_in
.s_addr
= 0;
1371 if (family
== AF_INET6
)
1372 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1373 if (family
== AF_EVPN
)
1374 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1377 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1378 struct update_subgroup
*subgrp
, struct prefix
*p
,
1381 struct bgp_filter
*filter
;
1384 struct peer
*onlypeer
;
1386 struct attr
*riattr
;
1387 char buf
[PREFIX_STRLEN
];
1393 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1395 if (DISABLE_BGP_ANNOUNCE
)
1398 afi
= SUBGRP_AFI(subgrp
);
1399 safi
= SUBGRP_SAFI(subgrp
);
1400 peer
= SUBGRP_PEER(subgrp
);
1402 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1403 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1406 filter
= &peer
->filter
[afi
][safi
];
1407 bgp
= SUBGRP_INST(subgrp
);
1408 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1411 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1412 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1413 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1416 * direct and direct_ext type routes originate internally even
1417 * though they can have peer pointers that reference other
1420 prefix2str(p
, buf
, PREFIX_STRLEN
);
1421 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1427 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1428 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1429 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1430 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1432 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1437 /* With addpath we may be asked to TX all kinds of paths so make sure
1439 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1440 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1441 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1445 /* If this is not the bestpath then check to see if there is an enabled
1447 * feature that requires us to advertise it */
1448 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1449 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1454 /* Aggregate-address suppress check. */
1455 if (ri
->extra
&& ri
->extra
->suppress
)
1456 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1461 * If we are doing VRF 2 VRF leaking via the import
1462 * statement, we want to prevent the route going
1463 * off box as that the RT and RD created are localy
1464 * significant and globaly useless.
1466 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1467 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1470 /* If it's labeled safi, make sure the route has a valid label. */
1471 if (safi
== SAFI_LABELED_UNICAST
) {
1472 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1473 if (!bgp_is_valid_label(&label
)) {
1474 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1475 zlog_debug("u%" PRIu64
":s%" PRIu64
1476 " %s/%d is filtered - no label (%p)",
1477 subgrp
->update_group
->id
, subgrp
->id
,
1478 inet_ntop(p
->family
, &p
->u
.prefix
,
1479 buf
, SU_ADDRSTRLEN
),
1480 p
->prefixlen
, &label
);
1485 /* Do not send back route to sender. */
1486 if (onlypeer
&& from
== onlypeer
) {
1490 /* Do not send the default route in the BGP table if the neighbor is
1491 * configured for default-originate */
1492 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1493 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1494 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1496 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1500 /* Transparency check. */
1501 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1502 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1507 /* If community is not disabled check the no-export and local. */
1508 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1509 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1511 "subgrpannouncecheck: community filter check fail");
1515 /* If the attribute has originator-id and it is same as remote
1517 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1518 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1519 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1521 "%s [Update:SEND] %s originator-id is same as "
1524 prefix2str(p
, buf
, sizeof(buf
)));
1528 /* ORF prefix-list filter check */
1529 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1530 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1531 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1532 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1533 if (peer
->orf_plist
[afi
][safi
]) {
1534 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1536 if (bgp_debug_update(NULL
, p
,
1537 subgrp
->update_group
, 0))
1539 "%s [Update:SEND] %s is filtered via ORF",
1547 /* Output filter check. */
1548 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1549 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1550 zlog_debug("%s [Update:SEND] %s is filtered",
1551 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1555 #ifdef BGP_SEND_ASPATH_CHECK
1556 /* AS path loop check. */
1557 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1558 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1560 "%s [Update:SEND] suppress announcement to peer AS %u "
1561 "that is part of AS path.",
1562 onlypeer
->host
, onlypeer
->as
);
1565 #endif /* BGP_SEND_ASPATH_CHECK */
1567 /* If we're a CONFED we need to loop check the CONFED ID too */
1568 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1569 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1570 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1572 "%s [Update:SEND] suppress announcement to peer AS %u"
1574 peer
->host
, bgp
->confed_id
);
1579 /* Route-Reflect check. */
1580 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1585 /* IBGP reflection check. */
1586 if (reflect
&& !samepeer_safe
) {
1587 /* A route from a Client peer. */
1588 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1589 PEER_FLAG_REFLECTOR_CLIENT
)) {
1590 /* Reflect to all the Non-Client peers and also to the
1591 Client peers other than the originator. Originator
1593 is already done. So there is noting to do. */
1594 /* no bgp client-to-client reflection check. */
1595 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1596 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1597 PEER_FLAG_REFLECTOR_CLIENT
))
1600 /* A route from a Non-client peer. Reflect to all other
1602 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1603 PEER_FLAG_REFLECTOR_CLIENT
))
1608 /* For modify attribute, copy it to temporary structure. */
1609 bgp_attr_dup(attr
, riattr
);
1611 /* If local-preference is not set. */
1612 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1613 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1614 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1615 attr
->local_pref
= bgp
->default_local_pref
;
1618 /* If originator-id is not set and the route is to be reflected,
1619 set the originator id */
1621 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1622 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1623 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1626 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1628 if (peer
->sort
== BGP_PEER_EBGP
1629 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1630 if (from
!= bgp
->peer_self
&& !transparent
1631 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1632 PEER_FLAG_MED_UNCHANGED
))
1634 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1637 /* Since the nexthop attribute can vary per peer, it is not explicitly
1639 * in announce check, only certain flags and length (or number of
1641 * -- for IPv6/MP_REACH) are set here in order to guide the update
1643 * code in setting the nexthop(s) on a per peer basis in
1645 * Typically, the source nexthop in the attribute is preserved but in
1647 * scenarios where we know it will always be overwritten, we reset the
1648 * nexthop to "0" in an attempt to achieve better Update packing. An
1649 * example of this is when a prefix from each of 2 IBGP peers needs to
1651 * announced to an EBGP peer (and they have the same attributes barring
1655 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1657 #define NEXTHOP_IS_V6 \
1658 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1659 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1660 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1661 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1663 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1665 * the peer (group) is configured to receive link-local nexthop
1667 * and it is available in the prefix OR we're not reflecting the route
1669 * the peer (group) to whom we're going to announce is on a shared
1671 * and this is either a self-originated route or the peer is EBGP.
1673 if (NEXTHOP_IS_V6
) {
1674 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1675 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1676 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1677 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1678 || (!reflect
&& peer
->shared_network
1679 && (from
== bgp
->peer_self
1680 || peer
->sort
== BGP_PEER_EBGP
))) {
1681 attr
->mp_nexthop_len
=
1682 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1685 /* Clear off link-local nexthop in source, whenever it is not
1687 * ensure more prefixes share the same attribute for
1690 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1691 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1692 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1695 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1696 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1698 /* Route map & unsuppress-map apply. */
1699 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1700 struct bgp_info info
;
1701 struct bgp_info_extra dummy_info_extra
;
1702 struct attr dummy_attr
;
1704 memset(&info
, 0, sizeof(struct bgp_info
));
1709 memcpy(&dummy_info_extra
, ri
->extra
,
1710 sizeof(struct bgp_info_extra
));
1711 info
.extra
= &dummy_info_extra
;
1714 /* don't confuse inbound and outbound setting */
1715 RESET_FLAG(attr
->rmap_change_flags
);
1718 * The route reflector is not allowed to modify the attributes
1719 * of the reflected IBGP routes unless explicitly allowed.
1721 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1722 && !bgp_flag_check(bgp
,
1723 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1724 bgp_attr_dup(&dummy_attr
, attr
);
1725 info
.attr
= &dummy_attr
;
1728 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1730 if (ri
->extra
&& ri
->extra
->suppress
)
1731 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1734 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1737 peer
->rmap_type
= 0;
1739 if (ret
== RMAP_DENYMATCH
) {
1740 bgp_attr_flush(attr
);
1745 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1746 if (peer
->sort
== BGP_PEER_IBGP
1747 || peer
->sort
== BGP_PEER_CONFED
) {
1748 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1749 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1751 bgp_attr_add_gshut_community(attr
);
1755 /* After route-map has been applied, we check to see if the nexthop to
1756 * be carried in the attribute (that is used for the announcement) can
1757 * be cleared off or not. We do this in all cases where we would be
1758 * setting the nexthop to "ourselves". For IPv6, we only need to
1760 * the global nexthop here; the link-local nexthop would have been
1762 * already, and if not, it is required by the update formation code.
1763 * Also see earlier comments in this function.
1766 * If route-map has performed some operation on the nexthop or the peer
1767 * configuration says to pass it unchanged, we cannot reset the nexthop
1768 * here, so only attempt to do it if these aren't true. Note that the
1769 * route-map handler itself might have cleared the nexthop, if for
1771 * it is configured as 'peer-address'.
1773 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1774 riattr
->rmap_change_flags
)
1776 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1777 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1778 /* We can reset the nexthop, if setting (or forcing) it to
1780 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1781 PEER_FLAG_NEXTHOP_SELF
)
1782 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1783 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1785 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1786 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1787 subgroup_announce_reset_nhop(
1788 (peer_cap_enhe(peer
, afi
, safi
)
1792 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1793 /* Can also reset the nexthop if announcing to EBGP, but
1795 * no peer in the subgroup is on a shared subnet.
1796 * Note: 3rd party nexthop currently implemented for
1799 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1801 subgroup_announce_reset_nhop(
1802 (peer_cap_enhe(peer
, afi
, safi
)
1806 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1808 * This flag is used for leaked vpn-vrf routes
1810 int family
= p
->family
;
1812 if (peer_cap_enhe(peer
, afi
, safi
))
1815 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1817 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1818 __func__
, family2str(family
));
1819 subgroup_announce_reset_nhop(family
, attr
);
1822 /* If IPv6/MP and nexthop does not have any override and happens
1824 * be a link-local address, reset it so that we don't pass along
1826 * source's link-local IPv6 address to recipients who may not be
1828 * the same interface.
1830 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1831 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1832 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1839 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1840 struct bgp_maxpaths_cfg
*mpath_cfg
,
1841 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1843 struct bgp_info
*new_select
;
1844 struct bgp_info
*old_select
;
1845 struct bgp_info
*ri
;
1846 struct bgp_info
*ri1
;
1847 struct bgp_info
*ri2
;
1848 struct bgp_info
*nextri
= NULL
;
1849 int paths_eq
, do_mpath
, debug
;
1850 struct list mp_list
;
1851 char pfx_buf
[PREFIX2STR_BUFFER
];
1852 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1854 bgp_mp_list_init(&mp_list
);
1856 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1858 debug
= bgp_debug_bestpath(&rn
->p
);
1861 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1863 /* bgp deterministic-med */
1865 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1867 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1868 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1869 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1871 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1872 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1874 if (BGP_INFO_HOLDDOWN(ri1
))
1876 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1877 if (ri1
->peer
->status
!= Established
)
1882 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1883 if (CHECK_FLAG(ri2
->flags
,
1884 BGP_INFO_DMED_CHECK
))
1886 if (BGP_INFO_HOLDDOWN(ri2
))
1889 && ri2
->peer
!= bgp
->peer_self
1892 PEER_STATUS_NSF_WAIT
))
1893 if (ri2
->peer
->status
1897 if (aspath_cmp_left(ri1
->attr
->aspath
,
1899 || aspath_cmp_left_confed(
1901 ri2
->attr
->aspath
)) {
1902 if (bgp_info_cmp(bgp
, ri2
,
1908 bgp_info_unset_flag(
1910 BGP_INFO_DMED_SELECTED
);
1916 BGP_INFO_DMED_CHECK
);
1920 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1921 bgp_info_set_flag(rn
, new_select
,
1922 BGP_INFO_DMED_SELECTED
);
1925 bgp_info_path_with_addpath_rx_str(new_select
,
1927 zlog_debug("%s: %s is the bestpath from AS %u",
1929 aspath_get_first_as(
1930 new_select
->attr
->aspath
));
1935 /* Check old selected route and new selected route. */
1938 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1940 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1943 if (BGP_INFO_HOLDDOWN(ri
)) {
1944 /* reap REMOVED routes, if needs be
1945 * selected route must stay for a while longer though
1947 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1948 && (ri
!= old_select
))
1949 bgp_info_reap(rn
, ri
);
1952 zlog_debug("%s: ri %p in holddown", __func__
,
1958 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1959 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1960 if (ri
->peer
->status
!= Established
) {
1964 "%s: ri %p non self peer %s not estab state",
1965 __func__
, ri
, ri
->peer
->host
);
1970 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1971 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1972 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1974 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1978 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1980 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1981 debug
, pfx_buf
, afi
, safi
)) {
1986 /* Now that we know which path is the bestpath see if any of the other
1988 * qualify as multipaths
1992 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1994 sprintf(path_buf
, "NONE");
1996 "%s: After path selection, newbest is %s oldbest was %s",
1998 old_select
? old_select
->peer
->host
: "NONE");
2001 if (do_mpath
&& new_select
) {
2002 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
2006 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
2008 if (ri
== new_select
) {
2011 "%s: %s is the bestpath, add to the multipath list",
2013 bgp_mp_list_add(&mp_list
, ri
);
2017 if (BGP_INFO_HOLDDOWN(ri
))
2020 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
2021 && !CHECK_FLAG(ri
->peer
->sflags
,
2022 PEER_STATUS_NSF_WAIT
))
2023 if (ri
->peer
->status
!= Established
)
2026 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
2029 "%s: %s has the same nexthop as the bestpath, skip it",
2034 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
2035 debug
, pfx_buf
, afi
, safi
);
2040 "%s: %s is equivalent to the bestpath, add to the multipath list",
2042 bgp_mp_list_add(&mp_list
, ri
);
2047 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2048 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2049 bgp_mp_list_clear(&mp_list
);
2051 result
->old
= old_select
;
2052 result
->new = new_select
;
2058 * A new route/change in bestpath of an existing route. Evaluate the path
2059 * for advertisement to the subgroup.
2061 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2062 struct bgp_info
*selected
,
2063 struct bgp_node
*rn
,
2064 uint32_t addpath_tx_id
)
2067 struct peer
*onlypeer
;
2073 afi
= SUBGRP_AFI(subgrp
);
2074 safi
= SUBGRP_SAFI(subgrp
);
2075 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2078 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2079 char buf_prefix
[PREFIX_STRLEN
];
2080 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2081 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2085 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2086 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2087 PEER_STATUS_ORF_WAIT_REFRESH
))
2090 memset(&attr
, 0, sizeof(struct attr
));
2091 /* It's initialized in bgp_announce_check() */
2093 /* Announcement to the subgroup. If the route is filtered withdraw it.
2096 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2097 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2099 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2100 selected
->addpath_tx_id
);
2103 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2105 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2112 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2113 * This is called at the end of route processing.
2115 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2117 struct bgp_info
*ri
;
2119 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2120 if (BGP_INFO_HOLDDOWN(ri
))
2122 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2123 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2128 * Has the route changed from the RIB's perspective? This is invoked only
2129 * if the route selection returns the same best route as earlier - to
2130 * determine if we need to update zebra or not.
2132 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2134 struct bgp_info
*mpinfo
;
2136 /* If this is multipath, check all selected paths for any nexthop
2137 * change or attribute change. Some attribute changes (e.g., community)
2138 * aren't of relevance to the RIB, but we'll update zebra to ensure
2139 * we handle the case of BGP nexthop change. This is the behavior
2140 * when the best path has an attribute change anyway.
2142 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2143 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2147 * If this is multipath, check all selected paths for any nexthop change
2149 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2150 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2151 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2152 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2156 /* Nothing has changed from the RIB's perspective. */
2160 struct bgp_process_queue
{
2162 STAILQ_HEAD(, bgp_node
) pqueue
;
2163 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2165 unsigned int queued
;
2169 * old_select = The old best path
2170 * new_select = the new best path
2172 * if (!old_select && new_select)
2173 * We are sending new information on.
2175 * if (old_select && new_select) {
2176 * if (new_select != old_select)
2177 * We have a new best path send a change
2179 * We've received a update with new attributes that needs
2183 * if (old_select && !new_select)
2184 * We have no eligible route that we can announce or the rn
2187 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2188 afi_t afi
, safi_t safi
)
2190 struct bgp_info
*new_select
;
2191 struct bgp_info
*old_select
;
2192 struct bgp_info_pair old_and_new
;
2193 char pfx_buf
[PREFIX2STR_BUFFER
];
2196 /* Is it end of initial update? (after startup) */
2198 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2199 sizeof(bgp
->update_delay_zebra_resume_time
));
2201 bgp
->main_zebra_update_hold
= 0;
2202 FOREACH_AFI_SAFI (afi
, safi
) {
2203 if (bgp_fibupd_safi(safi
))
2204 bgp_zebra_announce_table(bgp
, afi
, safi
);
2206 bgp
->main_peers_update_hold
= 0;
2208 bgp_start_routeadv(bgp
);
2212 struct prefix
*p
= &rn
->p
;
2214 debug
= bgp_debug_bestpath(&rn
->p
);
2216 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2217 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2218 afi2str(afi
), safi2str(safi
));
2221 /* Best path selection. */
2222 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2224 old_select
= old_and_new
.old
;
2225 new_select
= old_and_new
.new;
2227 /* Do we need to allocate or free labels?
2228 * Right now, since we only deal with per-prefix labels, it is not
2229 * necessary to do this upon changes to best path except if the label
2232 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2235 || bgp_label_index_differs(new_select
, old_select
)
2236 || new_select
->sub_type
!= old_select
->sub_type
) {
2237 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2238 && new_select
->attr
->flag
2240 BGP_ATTR_PREFIX_SID
)
2241 && new_select
->attr
->label_index
2242 != BGP_INVALID_LABEL_INDEX
) {
2245 BGP_NODE_REGISTERED_FOR_LABEL
))
2246 bgp_unregister_for_label(rn
);
2247 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2249 bgp_set_valid_label(&rn
->local_label
);
2251 bgp_register_for_label(rn
, new_select
);
2253 } else if (CHECK_FLAG(rn
->flags
,
2254 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2255 bgp_unregister_for_label(rn
);
2257 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2258 bgp_unregister_for_label(rn
);
2262 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2264 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2265 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2266 old_select
, new_select
);
2269 /* If best route remains the same and this is not due to user-initiated
2270 * clear, see exactly what needs to be done.
2272 if (old_select
&& old_select
== new_select
2273 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2274 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2275 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2276 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2278 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2279 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2281 if (bgp_fibupd_safi(safi
)
2282 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2284 if (new_select
->type
== ZEBRA_ROUTE_BGP
2285 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2286 || new_select
->sub_type
2287 == BGP_ROUTE_IMPORTED
))
2289 bgp_zebra_announce(rn
, p
, old_select
,
2293 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2294 bgp_zebra_clear_route_change_flags(rn
);
2296 /* If there is a change of interest to peers, reannounce the
2298 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2299 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2300 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2302 /* unicast routes must also be annouced to
2303 * labeled-unicast update-groups */
2304 if (safi
== SAFI_UNICAST
)
2305 group_announce_route(bgp
, afi
,
2306 SAFI_LABELED_UNICAST
, rn
,
2309 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2310 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2313 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2317 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2319 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2321 /* bestpath has changed; bump version */
2322 if (old_select
|| new_select
) {
2323 bgp_bump_version(rn
);
2325 if (!bgp
->t_rmap_def_originate_eval
) {
2329 update_group_refresh_default_originate_route_map
,
2330 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2331 &bgp
->t_rmap_def_originate_eval
);
2336 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2339 zlog_debug("%s: setting SELECTED flag", __func__
);
2340 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2341 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2342 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2346 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2347 if (old_select
!= new_select
) {
2349 vnc_import_bgp_exterior_del_route(bgp
, p
,
2351 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2354 vnc_import_bgp_exterior_add_route(bgp
, p
,
2356 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2362 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2364 /* unicast routes must also be annouced to labeled-unicast update-groups
2366 if (safi
== SAFI_UNICAST
)
2367 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2371 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2372 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2373 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2374 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2375 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2376 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2378 /* if this is an evpn imported type-5 prefix,
2379 * we need to withdraw the route first to clear
2380 * the nh neigh and the RMAC entry.
2383 is_route_parent_evpn(old_select
))
2384 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2386 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2388 /* Withdraw the route from the kernel. */
2389 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2390 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2391 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2392 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2394 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2398 /* advertise/withdraw type-5 routes */
2399 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2400 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2401 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2403 /* apply the route-map */
2404 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2407 ret
= route_map_apply(
2408 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2409 &rn
->p
, RMAP_BGP
, new_select
);
2410 if (ret
== RMAP_MATCH
)
2411 bgp_evpn_advertise_type5_route(
2412 bgp
, &rn
->p
, new_select
->attr
,
2415 bgp_evpn_advertise_type5_route(bgp
,
2421 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2422 (!old_select
->extra
|| !old_select
->extra
->parent
))
2423 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2426 /* Clear any route change flags. */
2427 bgp_zebra_clear_route_change_flags(rn
);
2429 /* Reap old select bgp_info, if it has been removed */
2430 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2431 bgp_info_reap(rn
, old_select
);
2433 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2437 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2439 struct bgp_process_queue
*pqnode
= data
;
2440 struct bgp
*bgp
= pqnode
->bgp
;
2441 struct bgp_table
*table
;
2442 struct bgp_node
*rn
;
2445 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2446 bgp_process_main_one(bgp
, NULL
, 0, 0);
2447 /* should always have dedicated wq call */
2448 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2452 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2453 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2454 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2455 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2456 table
= bgp_node_table(rn
);
2457 /* note, new RNs may be added as part of processing */
2458 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2460 bgp_unlock_node(rn
);
2461 bgp_table_unlock(table
);
2467 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2469 struct bgp_process_queue
*pqnode
= data
;
2471 bgp_unlock(pqnode
->bgp
);
2473 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2476 void bgp_process_queue_init(void)
2478 if (!bm
->process_main_queue
)
2479 bm
->process_main_queue
=
2480 work_queue_new(bm
->master
, "process_main_queue");
2482 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2483 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2484 bm
->process_main_queue
->spec
.max_retries
= 0;
2485 bm
->process_main_queue
->spec
.hold
= 50;
2486 /* Use a higher yield value of 50ms for main queue processing */
2487 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2490 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2492 struct bgp_process_queue
*pqnode
;
2494 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2495 sizeof(struct bgp_process_queue
));
2497 /* unlocked in bgp_processq_del */
2498 pqnode
->bgp
= bgp_lock(bgp
);
2499 STAILQ_INIT(&pqnode
->pqueue
);
2504 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2506 #define ARBITRARY_PROCESS_QLEN 10000
2507 struct work_queue
*wq
= bm
->process_main_queue
;
2508 struct bgp_process_queue
*pqnode
;
2509 int pqnode_reuse
= 0;
2511 /* already scheduled for processing? */
2512 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2518 /* Add route nodes to an existing work queue item until reaching the
2519 limit only if is from the same BGP view and it's not an EOIU marker
2521 if (work_queue_item_count(wq
)) {
2522 struct work_queue_item
*item
= work_queue_last_item(wq
);
2523 pqnode
= item
->data
;
2525 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2526 || pqnode
->bgp
!= bgp
2527 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2528 pqnode
= bgp_processq_alloc(bgp
);
2532 pqnode
= bgp_processq_alloc(bgp
);
2533 /* all unlocked in bgp_process_wq */
2534 bgp_table_lock(bgp_node_table(rn
));
2536 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2539 /* can't be enqueued twice */
2540 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2541 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2545 work_queue_add(wq
, pqnode
);
2550 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2552 struct bgp_process_queue
*pqnode
;
2554 if (bm
->process_main_queue
== NULL
)
2557 pqnode
= bgp_processq_alloc(bgp
);
2559 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2560 work_queue_add(bm
->process_main_queue
, pqnode
);
2563 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2567 peer
= THREAD_ARG(thread
);
2568 peer
->t_pmax_restart
= NULL
;
2570 if (bgp_debug_neighbor_events(peer
))
2572 "%s Maximum-prefix restart timer expired, restore peering",
2575 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2576 zlog_debug("%s: %s peer_clear failed",
2577 __PRETTY_FUNCTION__
, peer
->host
);
2582 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2586 iana_safi_t pkt_safi
;
2588 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2591 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2592 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2593 PEER_STATUS_PREFIX_LIMIT
)
2598 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2600 afi_safi_print(afi
, safi
), peer
->host
,
2601 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2602 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2604 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2605 PEER_FLAG_MAX_PREFIX_WARNING
))
2608 /* Convert AFI, SAFI to values for packet. */
2609 pkt_afi
= afi_int2iana(afi
);
2610 pkt_safi
= safi_int2iana(safi
);
2614 ndata
[0] = (pkt_afi
>> 8);
2616 ndata
[2] = pkt_safi
;
2617 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2618 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2619 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2620 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2622 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2623 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2624 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2628 /* Dynamic peers will just close their connection. */
2629 if (peer_dynamic_neighbor(peer
))
2632 /* restart timer start */
2633 if (peer
->pmax_restart
[afi
][safi
]) {
2634 peer
->v_pmax_restart
=
2635 peer
->pmax_restart
[afi
][safi
] * 60;
2637 if (bgp_debug_neighbor_events(peer
))
2639 "%s Maximum-prefix restart timer started for %d secs",
2640 peer
->host
, peer
->v_pmax_restart
);
2642 BGP_TIMER_ON(peer
->t_pmax_restart
,
2643 bgp_maximum_prefix_restart_timer
,
2644 peer
->v_pmax_restart
);
2649 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2650 PEER_STATUS_PREFIX_LIMIT
);
2652 if (peer
->pcount
[afi
][safi
]
2653 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2654 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2655 PEER_STATUS_PREFIX_THRESHOLD
)
2660 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2661 afi_safi_print(afi
, safi
), peer
->host
,
2662 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2663 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2664 PEER_STATUS_PREFIX_THRESHOLD
);
2666 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2667 PEER_STATUS_PREFIX_THRESHOLD
);
2671 /* Unconditionally remove the route from the RIB, without taking
2672 * damping into consideration (eg, because the session went down)
2674 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2675 afi_t afi
, safi_t safi
)
2677 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2679 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2680 bgp_info_delete(rn
, ri
); /* keep historical info */
2682 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2685 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2686 struct peer
*peer
, afi_t afi
, safi_t safi
,
2687 struct prefix_rd
*prd
)
2689 /* apply dampening, if result is suppressed, we'll be retaining
2690 * the bgp_info in the RIB for historical reference.
2692 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2693 && peer
->sort
== BGP_PEER_EBGP
)
2694 if ((bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2695 == BGP_DAMP_SUPPRESSED
) {
2696 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2702 if (safi
== SAFI_MPLS_VPN
) {
2703 struct bgp_node
*prn
= NULL
;
2704 struct bgp_table
*table
= NULL
;
2706 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2707 (struct prefix
*)prd
);
2709 table
= (struct bgp_table
*)(prn
->info
);
2711 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2712 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2714 bgp_unlock_node(prn
);
2716 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2717 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2719 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2720 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2726 /* If this is an EVPN route, process for un-import. */
2727 if (safi
== SAFI_EVPN
)
2728 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2730 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2733 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2734 struct peer
*peer
, struct attr
*attr
,
2735 struct bgp_node
*rn
)
2737 struct bgp_info
*new;
2739 /* Make new BGP info. */
2740 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2742 new->instance
= instance
;
2743 new->sub_type
= sub_type
;
2746 new->uptime
= bgp_clock();
2748 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2752 static void overlay_index_update(struct attr
*attr
,
2753 struct eth_segment_id
*eth_s_id
,
2754 union gw_addr
*gw_ip
)
2759 if (eth_s_id
== NULL
) {
2760 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2761 sizeof(struct eth_segment_id
));
2763 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2764 sizeof(struct eth_segment_id
));
2766 if (gw_ip
== NULL
) {
2767 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2769 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2770 sizeof(union gw_addr
));
2774 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2775 struct eth_segment_id
*eth_s_id
,
2776 union gw_addr
*gw_ip
)
2778 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2779 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2782 if (afi
!= AFI_L2VPN
)
2785 memset(&temp
, 0, 16);
2786 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2787 info_gw_ip
= (union gw_addr
*)&temp
;
2788 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2791 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2792 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2795 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2797 info_gw_ip_remote
= gw_ip
;
2798 if (eth_s_id
== NULL
)
2799 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2801 info_eth_s_id_remote
= eth_s_id
;
2802 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2804 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2805 sizeof(struct eth_segment_id
));
2808 /* Check if received nexthop is valid or not. */
2809 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2814 /* Only validated for unicast and multicast currently. */
2815 /* Also valid for EVPN where the nexthop is an IP address. */
2816 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2819 /* If NEXT_HOP is present, validate it. */
2820 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2821 if (attr
->nexthop
.s_addr
== 0
2822 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2823 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2827 /* If MP_NEXTHOP is present, validate it. */
2828 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2829 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2830 * it is not an IPv6 link-local address.
2832 if (attr
->mp_nexthop_len
) {
2833 switch (attr
->mp_nexthop_len
) {
2834 case BGP_ATTR_NHLEN_IPV4
:
2835 case BGP_ATTR_NHLEN_VPNV4
:
2836 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2837 || IPV4_CLASS_DE(ntohl(
2838 attr
->mp_nexthop_global_in
.s_addr
))
2839 || bgp_nexthop_self(bgp
,
2840 attr
->mp_nexthop_global_in
));
2843 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2844 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2845 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2846 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2847 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2848 || IN6_IS_ADDR_MULTICAST(
2849 &attr
->mp_nexthop_global
));
2861 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2862 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2863 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2864 uint32_t num_labels
, int soft_reconfig
,
2865 struct bgp_route_evpn
*evpn
)
2868 int aspath_loop_count
= 0;
2869 struct bgp_node
*rn
;
2871 struct attr new_attr
;
2872 struct attr
*attr_new
;
2873 struct bgp_info
*ri
;
2874 struct bgp_info
*new;
2875 struct bgp_info_extra
*extra
;
2877 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2879 int do_loop_check
= 1;
2880 int has_valid_label
= 0;
2882 int vnc_implicit_withdraw
= 0;
2886 memset(&new_attr
, 0, sizeof(struct attr
));
2887 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2888 new_attr
.label
= MPLS_INVALID_LABEL
;
2891 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2892 /* TODO: Check to see if we can get rid of "is_valid_label" */
2893 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2894 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2896 has_valid_label
= bgp_is_valid_label(label
);
2898 /* When peer's soft reconfiguration enabled. Record input packet in
2901 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2902 && peer
!= bgp
->peer_self
)
2903 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2905 /* Check previously received route. */
2906 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2907 if (ri
->peer
== peer
&& ri
->type
== type
2908 && ri
->sub_type
== sub_type
2909 && ri
->addpath_rx_id
== addpath_id
)
2912 /* AS path local-as loop check. */
2913 if (peer
->change_local_as
) {
2914 if (peer
->allowas_in
[afi
][safi
])
2915 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2916 else if (!CHECK_FLAG(peer
->flags
,
2917 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2918 aspath_loop_count
= 1;
2920 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2921 > aspath_loop_count
) {
2922 reason
= "as-path contains our own AS;";
2927 /* If the peer is configured for "allowas-in origin" and the last ASN in
2929 * as-path is our ASN then we do not need to call aspath_loop_check
2931 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2932 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2935 /* AS path loop check. */
2936 if (do_loop_check
) {
2937 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2938 > peer
->allowas_in
[afi
][safi
]
2939 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2940 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2941 > peer
->allowas_in
[afi
][safi
])) {
2942 reason
= "as-path contains our own AS;";
2947 /* Route reflector originator ID check. */
2948 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2949 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2950 reason
= "originator is us;";
2954 /* Route reflector cluster ID check. */
2955 if (bgp_cluster_filter(peer
, attr
)) {
2956 reason
= "reflected from the same cluster;";
2960 /* Apply incoming filter. */
2961 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2966 bgp_attr_dup(&new_attr
, attr
);
2968 /* Apply incoming route-map.
2969 * NB: new_attr may now contain newly allocated values from route-map
2971 * commands, so we need bgp_attr_flush in the error paths, until we
2973 * the attr (which takes over the memory references) */
2974 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2976 reason
= "route-map;";
2977 bgp_attr_flush(&new_attr
);
2981 if (peer
->sort
== BGP_PEER_EBGP
) {
2983 /* If we receive the graceful-shutdown community from an eBGP
2984 * peer we must lower local-preference */
2985 if (new_attr
.community
2986 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2987 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2988 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2990 /* If graceful-shutdown is configured then add the GSHUT
2991 * community to all paths received from eBGP peers */
2992 } else if (bgp_flag_check(peer
->bgp
,
2993 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2994 bgp_attr_add_gshut_community(&new_attr
);
2998 /* next hop check. */
2999 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3000 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3001 reason
= "martian or self next-hop;";
3002 bgp_attr_flush(&new_attr
);
3006 attr_new
= bgp_attr_intern(&new_attr
);
3008 /* If the update is implicit withdraw. */
3010 ri
->uptime
= bgp_clock();
3011 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
3013 /* Same attribute comes in. */
3014 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
3015 && attrhash_cmp(ri
->attr
, attr_new
)
3016 && (!has_valid_label
3017 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
3018 num_labels
* sizeof(mpls_label_t
))
3020 && (overlay_index_equal(
3021 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3022 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3023 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3024 BGP_CONFIG_DAMPENING
)
3025 && peer
->sort
== BGP_PEER_EBGP
3026 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3027 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3028 bgp_debug_rdpfxpath2str(
3029 afi
, safi
, prd
, p
, label
,
3030 num_labels
, addpath_id
? 1 : 0,
3031 addpath_id
, pfx_buf
,
3033 zlog_debug("%s rcvd %s", peer
->host
,
3037 if (bgp_damp_update(ri
, rn
, afi
, safi
)
3038 != BGP_DAMP_SUPPRESSED
) {
3039 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
3041 bgp_process(bgp
, rn
, afi
, safi
);
3043 } else /* Duplicate - odd */
3045 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3046 if (!peer
->rcvd_attr_printed
) {
3048 "%s rcvd UPDATE w/ attr: %s",
3050 peer
->rcvd_attr_str
);
3051 peer
->rcvd_attr_printed
= 1;
3054 bgp_debug_rdpfxpath2str(
3055 afi
, safi
, prd
, p
, label
,
3056 num_labels
, addpath_id
? 1 : 0,
3057 addpath_id
, pfx_buf
,
3060 "%s rcvd %s...duplicate ignored",
3061 peer
->host
, pfx_buf
);
3064 /* graceful restart STALE flag unset. */
3065 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3066 bgp_info_unset_flag(rn
, ri
,
3068 bgp_process(bgp
, rn
, afi
, safi
);
3072 bgp_unlock_node(rn
);
3073 bgp_attr_unintern(&attr_new
);
3078 /* Withdraw/Announce before we fully processed the withdraw */
3079 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3080 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3081 bgp_debug_rdpfxpath2str(
3082 afi
, safi
, prd
, p
, label
, num_labels
,
3083 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3086 "%s rcvd %s, flapped quicker than processing",
3087 peer
->host
, pfx_buf
);
3090 bgp_info_restore(rn
, ri
);
3093 /* Received Logging. */
3094 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3095 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3096 num_labels
, addpath_id
? 1 : 0,
3097 addpath_id
, pfx_buf
,
3099 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3102 /* graceful restart STALE flag unset. */
3103 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3104 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3106 /* The attribute is changed. */
3107 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3109 /* implicit withdraw, decrement aggregate and pcount here.
3110 * only if update is accepted, they'll increment below.
3112 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3114 /* Update bgp route dampening information. */
3115 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3116 && peer
->sort
== BGP_PEER_EBGP
) {
3117 /* This is implicit withdraw so we should update
3120 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3121 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3124 if (safi
== SAFI_MPLS_VPN
) {
3125 struct bgp_node
*prn
= NULL
;
3126 struct bgp_table
*table
= NULL
;
3128 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3129 (struct prefix
*)prd
);
3131 table
= (struct bgp_table
*)(prn
->info
);
3133 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3134 bgp
, prd
, table
, p
, ri
);
3136 bgp_unlock_node(prn
);
3138 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3139 && (safi
== SAFI_UNICAST
)) {
3140 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3142 * Implicit withdraw case.
3144 ++vnc_implicit_withdraw
;
3145 vnc_import_bgp_del_route(bgp
, p
, ri
);
3146 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3151 /* Special handling for EVPN update of an existing route. If the
3152 * extended community attribute has changed, we need to
3154 * the route using its existing extended community. It will be
3155 * subsequently processed for import with the new extended
3158 if (safi
== SAFI_EVPN
&& !same_attr
) {
3160 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3162 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3165 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3166 attr_new
->ecommunity
);
3168 if (bgp_debug_update(peer
, p
, NULL
, 1))
3170 "Change in EXT-COMM, existing %s new %s",
3172 ri
->attr
->ecommunity
),
3174 attr_new
->ecommunity
));
3175 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3181 /* Update to new attribute. */
3182 bgp_attr_unintern(&ri
->attr
);
3183 ri
->attr
= attr_new
;
3185 /* Update MPLS label */
3186 if (has_valid_label
) {
3187 extra
= bgp_info_extra_get(ri
);
3188 memcpy(&extra
->label
, label
,
3189 num_labels
* sizeof(mpls_label_t
));
3190 extra
->num_labels
= num_labels
;
3191 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3192 bgp_set_valid_label(&extra
->label
[0]);
3196 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3197 && (safi
== SAFI_UNICAST
)) {
3198 if (vnc_implicit_withdraw
) {
3200 * Add back the route with its new attributes
3202 * The route is still selected, until the route
3204 * queued by bgp_process actually runs. We have
3206 * update to the VNC side immediately to avoid
3208 * configuration changes (e.g., route-map
3210 * trigger re-importation of the entire RIB.
3212 vnc_import_bgp_add_route(bgp
, p
, ri
);
3213 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3217 /* Update Overlay Index */
3218 if (afi
== AFI_L2VPN
) {
3219 overlay_index_update(
3220 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3221 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3224 /* Update bgp route dampening information. */
3225 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3226 && peer
->sort
== BGP_PEER_EBGP
) {
3227 /* Now we do normal update dampening. */
3228 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3229 if (ret
== BGP_DAMP_SUPPRESSED
) {
3230 bgp_unlock_node(rn
);
3235 /* Nexthop reachability check - for unicast and
3236 * labeled-unicast.. */
3237 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3238 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3239 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3240 && !CHECK_FLAG(peer
->flags
,
3241 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3243 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3248 struct bgp
*bgp_nexthop
= bgp
;
3250 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3251 bgp_nexthop
= ri
->extra
->bgp_orig
;
3253 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3254 ri
, NULL
, connected
)
3255 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3256 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3258 if (BGP_DEBUG(nht
, NHT
)) {
3259 char buf1
[INET6_ADDRSTRLEN
];
3261 (const void *)&attr_new
3263 buf1
, INET6_ADDRSTRLEN
);
3264 zlog_debug("%s(%s): NH unresolved",
3265 __FUNCTION__
, buf1
);
3267 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3270 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3273 if (safi
== SAFI_MPLS_VPN
) {
3274 struct bgp_node
*prn
= NULL
;
3275 struct bgp_table
*table
= NULL
;
3277 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3278 (struct prefix
*)prd
);
3280 table
= (struct bgp_table
*)(prn
->info
);
3282 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3283 bgp
, prd
, table
, p
, ri
);
3285 bgp_unlock_node(prn
);
3289 /* If this is an EVPN route and some attribute has changed,
3291 * route for import. If the extended community has changed, we
3293 * have done the un-import earlier and the import would result
3295 * route getting injected into appropriate L2 VNIs. If it is
3297 * some other attribute change, the import will result in
3299 * the attributes for the route in the VNI(s).
3301 if (safi
== SAFI_EVPN
&& !same_attr
)
3302 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3304 /* Process change. */
3305 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3307 bgp_process(bgp
, rn
, afi
, safi
);
3308 bgp_unlock_node(rn
);
3310 if (SAFI_UNICAST
== safi
3311 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3312 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3314 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3316 if ((SAFI_MPLS_VPN
== safi
)
3317 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3319 vpn_leak_to_vrf_update(bgp
, ri
);
3323 if (SAFI_MPLS_VPN
== safi
) {
3324 mpls_label_t label_decoded
= decode_label(label
);
3326 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3327 type
, sub_type
, &label_decoded
);
3329 if (SAFI_ENCAP
== safi
) {
3330 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3331 type
, sub_type
, NULL
);
3336 } // End of implicit withdraw
3338 /* Received Logging. */
3339 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3340 if (!peer
->rcvd_attr_printed
) {
3341 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3342 peer
->rcvd_attr_str
);
3343 peer
->rcvd_attr_printed
= 1;
3346 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3347 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3349 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3352 /* Make new BGP info. */
3353 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3355 /* Update MPLS label */
3356 if (has_valid_label
) {
3357 extra
= bgp_info_extra_get(new);
3358 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3359 extra
->num_labels
= num_labels
;
3360 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3361 bgp_set_valid_label(&extra
->label
[0]);
3364 /* Update Overlay Index */
3365 if (afi
== AFI_L2VPN
) {
3366 overlay_index_update(new->attr
,
3367 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3368 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3370 /* Nexthop reachability check. */
3371 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3372 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3373 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3374 && !CHECK_FLAG(peer
->flags
,
3375 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3376 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3381 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3382 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3383 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3385 if (BGP_DEBUG(nht
, NHT
)) {
3386 char buf1
[INET6_ADDRSTRLEN
];
3388 (const void *)&attr_new
->nexthop
,
3389 buf1
, INET6_ADDRSTRLEN
);
3390 zlog_debug("%s(%s): NH unresolved",
3391 __FUNCTION__
, buf1
);
3393 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3396 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3399 new->addpath_rx_id
= addpath_id
;
3401 /* Increment prefix */
3402 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3404 /* Register new BGP information. */
3405 bgp_info_add(rn
, new);
3407 /* route_node_get lock */
3408 bgp_unlock_node(rn
);
3411 if (safi
== SAFI_MPLS_VPN
) {
3412 struct bgp_node
*prn
= NULL
;
3413 struct bgp_table
*table
= NULL
;
3415 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3417 table
= (struct bgp_table
*)(prn
->info
);
3419 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3420 bgp
, prd
, table
, p
, new);
3422 bgp_unlock_node(prn
);
3426 /* If maximum prefix count is configured and current prefix
3428 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3431 /* If this is an EVPN route, process for import. */
3432 if (safi
== SAFI_EVPN
)
3433 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3435 /* Process change. */
3436 bgp_process(bgp
, rn
, afi
, safi
);
3438 if (SAFI_UNICAST
== safi
3439 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3440 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3441 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3443 if ((SAFI_MPLS_VPN
== safi
)
3444 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3446 vpn_leak_to_vrf_update(bgp
, new);
3449 if (SAFI_MPLS_VPN
== safi
) {
3450 mpls_label_t label_decoded
= decode_label(label
);
3452 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3453 sub_type
, &label_decoded
);
3455 if (SAFI_ENCAP
== safi
) {
3456 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3463 /* This BGP update is filtered. Log the reason then update BGP
3466 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3467 if (!peer
->rcvd_attr_printed
) {
3468 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3469 peer
->rcvd_attr_str
);
3470 peer
->rcvd_attr_printed
= 1;
3473 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3474 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3476 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3477 peer
->host
, pfx_buf
, reason
);
3481 /* If this is an EVPN route, un-import it as it is now filtered.
3483 if (safi
== SAFI_EVPN
)
3484 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3486 if (SAFI_UNICAST
== safi
3487 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3488 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3490 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3492 if ((SAFI_MPLS_VPN
== safi
)
3493 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3495 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3498 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3501 bgp_unlock_node(rn
);
3505 * Filtered update is treated as an implicit withdrawal (see
3507 * a few lines above)
3509 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3510 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3518 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3519 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3520 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3521 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3524 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3525 struct bgp_node
*rn
;
3526 struct bgp_info
*ri
;
3529 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3530 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3538 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3540 /* If peer is soft reconfiguration enabled. Record input packet for
3541 * further calculation.
3543 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3544 * routes that are filtered. This tanks out Quagga RS pretty badly due
3546 * the iteration over all RS clients.
3547 * Since we need to remove the entry from adj_in anyway, do that first
3549 * if there was no entry, we don't need to do anything more.
3551 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3552 && peer
!= bgp
->peer_self
)
3553 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3554 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3555 bgp_debug_rdpfxpath2str(
3556 afi
, safi
, prd
, p
, label
, num_labels
,
3557 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3560 "%s withdrawing route %s not in adj-in",
3561 peer
->host
, pfx_buf
);
3563 bgp_unlock_node(rn
);
3567 /* Lookup withdrawn route. */
3568 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3569 if (ri
->peer
== peer
&& ri
->type
== type
3570 && ri
->sub_type
== sub_type
3571 && ri
->addpath_rx_id
== addpath_id
)
3575 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3576 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3577 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3579 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3583 /* Withdraw specified route from routing table. */
3584 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3585 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3586 if (SAFI_UNICAST
== safi
3587 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3588 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3589 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3591 if ((SAFI_MPLS_VPN
== safi
)
3592 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3594 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3596 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3597 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3598 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3600 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3603 /* Unlock bgp_node_get() lock. */
3604 bgp_unlock_node(rn
);
3609 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3612 struct update_subgroup
*subgrp
;
3613 subgrp
= peer_subgroup(peer
, afi
, safi
);
3614 subgroup_default_originate(subgrp
, withdraw
);
3619 * bgp_stop_announce_route_timer
3621 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3623 if (!paf
->t_announce_route
)
3626 THREAD_TIMER_OFF(paf
->t_announce_route
);
3630 * bgp_announce_route_timer_expired
3632 * Callback that is invoked when the route announcement timer for a
3635 static int bgp_announce_route_timer_expired(struct thread
*t
)
3637 struct peer_af
*paf
;
3640 paf
= THREAD_ARG(t
);
3643 if (peer
->status
!= Established
)
3646 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3649 peer_af_announce_route(paf
, 1);
3654 * bgp_announce_route
3656 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3658 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3660 struct peer_af
*paf
;
3661 struct update_subgroup
*subgrp
;
3663 paf
= peer_af_find(peer
, afi
, safi
);
3666 subgrp
= PAF_SUBGRP(paf
);
3669 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3670 * or a refresh has already been triggered.
3672 if (!subgrp
|| paf
->t_announce_route
)
3676 * Start a timer to stagger/delay the announce. This serves
3677 * two purposes - announcement can potentially be combined for
3678 * multiple peers and the announcement doesn't happen in the
3681 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3682 (subgrp
->peer_count
== 1)
3683 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3684 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3685 &paf
->t_announce_route
);
3689 * Announce routes from all AF tables to a peer.
3691 * This should ONLY be called when there is a need to refresh the
3692 * routes to the peer based on a policy change for this peer alone
3693 * or a route refresh request received from the peer.
3694 * The operation will result in splitting the peer from its existing
3695 * subgroups and putting it in new subgroups.
3697 void bgp_announce_route_all(struct peer
*peer
)
3702 FOREACH_AFI_SAFI (afi
, safi
)
3703 bgp_announce_route(peer
, afi
, safi
);
3706 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3707 struct bgp_table
*table
,
3708 struct prefix_rd
*prd
)
3711 struct bgp_node
*rn
;
3712 struct bgp_adj_in
*ain
;
3715 table
= peer
->bgp
->rib
[afi
][safi
];
3717 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3718 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3719 if (ain
->peer
!= peer
)
3722 struct bgp_info
*ri
= rn
->info
;
3723 uint32_t num_labels
= 0;
3724 mpls_label_t
*label_pnt
= NULL
;
3726 if (ri
&& ri
->extra
)
3727 num_labels
= ri
->extra
->num_labels
;
3729 label_pnt
= &ri
->extra
->label
[0];
3731 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3732 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3733 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3734 num_labels
, 1, NULL
);
3737 bgp_unlock_node(rn
);
3743 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3745 struct bgp_node
*rn
;
3746 struct bgp_table
*table
;
3748 if (peer
->status
!= Established
)
3751 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3752 && (safi
!= SAFI_EVPN
))
3753 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3755 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3756 rn
= bgp_route_next(rn
))
3757 if ((table
= rn
->info
) != NULL
) {
3758 struct prefix_rd prd
;
3759 prd
.family
= AF_UNSPEC
;
3761 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3763 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3769 struct bgp_clear_node_queue
{
3770 struct bgp_node
*rn
;
3773 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3775 struct bgp_clear_node_queue
*cnq
= data
;
3776 struct bgp_node
*rn
= cnq
->rn
;
3777 struct peer
*peer
= wq
->spec
.data
;
3778 struct bgp_info
*ri
;
3780 afi_t afi
= bgp_node_table(rn
)->afi
;
3781 safi_t safi
= bgp_node_table(rn
)->safi
;
3786 /* It is possible that we have multiple paths for a prefix from a peer
3787 * if that peer is using AddPath.
3789 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3790 if (ri
->peer
!= peer
)
3793 /* graceful restart STALE flag set. */
3794 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3795 && peer
->nsf
[afi
][safi
]
3796 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3797 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3798 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3800 /* If this is an EVPN route, process for
3802 if (safi
== SAFI_EVPN
)
3803 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3805 /* Handle withdraw for VRF route-leaking and L3VPN */
3806 if (SAFI_UNICAST
== safi
3807 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3808 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3809 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3812 if (SAFI_MPLS_VPN
== safi
&&
3813 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3814 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3817 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3823 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3825 struct bgp_clear_node_queue
*cnq
= data
;
3826 struct bgp_node
*rn
= cnq
->rn
;
3827 struct bgp_table
*table
= bgp_node_table(rn
);
3829 bgp_unlock_node(rn
);
3830 bgp_table_unlock(table
);
3831 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3834 static void bgp_clear_node_complete(struct work_queue
*wq
)
3836 struct peer
*peer
= wq
->spec
.data
;
3838 /* Tickle FSM to start moving again */
3839 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3841 peer_unlock(peer
); /* bgp_clear_route */
3844 static void bgp_clear_node_queue_init(struct peer
*peer
)
3846 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3848 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3849 #undef CLEAR_QUEUE_NAME_LEN
3851 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3852 peer
->clear_node_queue
->spec
.hold
= 10;
3853 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3854 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3855 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3856 peer
->clear_node_queue
->spec
.max_retries
= 0;
3858 /* we only 'lock' this peer reference when the queue is actually active
3860 peer
->clear_node_queue
->spec
.data
= peer
;
3863 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3864 struct bgp_table
*table
)
3866 struct bgp_node
*rn
;
3867 int force
= bm
->process_main_queue
? 0 : 1;
3870 table
= peer
->bgp
->rib
[afi
][safi
];
3872 /* If still no table => afi/safi isn't configured at all or smth. */
3876 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3877 struct bgp_info
*ri
, *next
;
3878 struct bgp_adj_in
*ain
;
3879 struct bgp_adj_in
*ain_next
;
3881 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3882 * queued for every clearing peer, regardless of whether it is
3883 * relevant to the peer at hand.
3885 * Overview: There are 3 different indices which need to be
3886 * scrubbed, potentially, when a peer is removed:
3888 * 1 peer's routes visible via the RIB (ie accepted routes)
3889 * 2 peer's routes visible by the (optional) peer's adj-in index
3890 * 3 other routes visible by the peer's adj-out index
3892 * 3 there is no hurry in scrubbing, once the struct peer is
3893 * removed from bgp->peer, we could just GC such deleted peer's
3894 * adj-outs at our leisure.
3896 * 1 and 2 must be 'scrubbed' in some way, at least made
3897 * invisible via RIB index before peer session is allowed to be
3898 * brought back up. So one needs to know when such a 'search' is
3903 * - there'd be a single global queue or a single RIB walker
3904 * - rather than tracking which route_nodes still need to be
3905 * examined on a peer basis, we'd track which peers still
3908 * Given that our per-peer prefix-counts now should be reliable,
3909 * this may actually be achievable. It doesn't seem to be a huge
3910 * problem at this time,
3912 * It is possible that we have multiple paths for a prefix from
3914 * if that peer is using AddPath.
3918 ain_next
= ain
->next
;
3920 if (ain
->peer
== peer
) {
3921 bgp_adj_in_remove(rn
, ain
);
3922 bgp_unlock_node(rn
);
3928 for (ri
= rn
->info
; ri
; ri
= next
) {
3930 if (ri
->peer
!= peer
)
3934 bgp_info_reap(rn
, ri
);
3936 struct bgp_clear_node_queue
*cnq
;
3938 /* both unlocked in bgp_clear_node_queue_del */
3939 bgp_table_lock(bgp_node_table(rn
));
3942 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3943 sizeof(struct bgp_clear_node_queue
));
3945 work_queue_add(peer
->clear_node_queue
, cnq
);
3953 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3955 struct bgp_node
*rn
;
3956 struct bgp_table
*table
;
3958 if (peer
->clear_node_queue
== NULL
)
3959 bgp_clear_node_queue_init(peer
);
3961 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3962 * Idle until it receives a Clearing_Completed event. This protects
3963 * against peers which flap faster than we can we clear, which could
3966 * a) race with routes from the new session being installed before
3967 * clear_route_node visits the node (to delete the route of that
3969 * b) resource exhaustion, clear_route_node likely leads to an entry
3970 * on the process_main queue. Fast-flapping could cause that queue
3974 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3975 * the unlock will happen upon work-queue completion; other wise, the
3976 * unlock happens at the end of this function.
3978 if (!peer
->clear_node_queue
->thread
)
3981 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3982 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3984 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3985 rn
= bgp_route_next(rn
))
3986 if ((table
= rn
->info
) != NULL
)
3987 bgp_clear_route_table(peer
, afi
, safi
, table
);
3989 /* unlock if no nodes got added to the clear-node-queue. */
3990 if (!peer
->clear_node_queue
->thread
)
3994 void bgp_clear_route_all(struct peer
*peer
)
3999 FOREACH_AFI_SAFI (afi
, safi
)
4000 bgp_clear_route(peer
, afi
, safi
);
4003 rfapiProcessPeerDown(peer
);
4007 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4009 struct bgp_table
*table
;
4010 struct bgp_node
*rn
;
4011 struct bgp_adj_in
*ain
;
4012 struct bgp_adj_in
*ain_next
;
4014 table
= peer
->bgp
->rib
[afi
][safi
];
4016 /* It is possible that we have multiple paths for a prefix from a peer
4017 * if that peer is using AddPath.
4019 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4023 ain_next
= ain
->next
;
4025 if (ain
->peer
== peer
) {
4026 bgp_adj_in_remove(rn
, ain
);
4027 bgp_unlock_node(rn
);
4035 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4037 struct bgp_node
*rn
;
4038 struct bgp_info
*ri
;
4039 struct bgp_table
*table
;
4041 if (safi
== SAFI_MPLS_VPN
) {
4042 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4043 rn
= bgp_route_next(rn
)) {
4044 struct bgp_node
*rm
;
4045 struct bgp_info
*ri
;
4047 /* look for neighbor in tables */
4048 if ((table
= rn
->info
) == NULL
)
4051 for (rm
= bgp_table_top(table
); rm
;
4052 rm
= bgp_route_next(rm
))
4053 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4054 if (ri
->peer
!= peer
)
4056 if (!CHECK_FLAG(ri
->flags
,
4060 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4065 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4066 rn
= bgp_route_next(rn
))
4067 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4068 if (ri
->peer
!= peer
)
4070 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4072 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4078 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4081 struct bgp_node
*rn
;
4082 struct bgp_info
*ri
;
4083 struct bgp_info
*next
;
4085 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4086 for (ri
= rn
->info
; ri
; ri
= next
) {
4088 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4089 && ri
->type
== ZEBRA_ROUTE_BGP
4090 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4091 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4092 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4094 if (bgp_fibupd_safi(safi
))
4095 bgp_zebra_withdraw(&rn
->p
, ri
,
4097 bgp_info_reap(rn
, ri
);
4102 /* Delete all kernel routes. */
4103 void bgp_cleanup_routes(struct bgp
*bgp
)
4106 struct bgp_node
*rn
;
4108 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4109 if (afi
== AFI_L2VPN
)
4111 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4114 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4116 if (afi
!= AFI_L2VPN
) {
4118 safi
= SAFI_MPLS_VPN
;
4119 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4120 rn
= bgp_route_next(rn
)) {
4122 bgp_cleanup_table(bgp
,
4123 (struct bgp_table
*)(rn
->info
),
4125 bgp_table_finish((struct bgp_table
**)&(
4128 bgp_unlock_node(rn
);
4132 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4133 rn
= bgp_route_next(rn
)) {
4135 bgp_cleanup_table(bgp
,
4136 (struct bgp_table
*)(rn
->info
),
4138 bgp_table_finish((struct bgp_table
**)&(
4141 bgp_unlock_node(rn
);
4146 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4147 rn
= bgp_route_next(rn
)) {
4149 bgp_cleanup_table(bgp
,
4150 (struct bgp_table
*)(rn
->info
),
4152 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4154 bgp_unlock_node(rn
);
4159 void bgp_reset(void)
4162 bgp_zclient_reset();
4163 access_list_reset();
4164 prefix_list_reset();
4167 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4169 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4170 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4171 PEER_CAP_ADDPATH_AF_TX_RCV
));
4174 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4176 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4177 struct bgp_nlri
*packet
)
4186 int addpath_encoded
;
4187 uint32_t addpath_id
;
4190 lim
= pnt
+ packet
->length
;
4192 safi
= packet
->safi
;
4194 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4196 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4197 syntactic validity. If the field is syntactically incorrect,
4198 then the Error Subcode is set to Invalid Network Field. */
4199 for (; pnt
< lim
; pnt
+= psize
) {
4200 /* Clear prefix structure. */
4201 memset(&p
, 0, sizeof(struct prefix
));
4203 if (addpath_encoded
) {
4205 /* When packet overflow occurs return immediately. */
4206 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4209 addpath_id
= ntohl(*((uint32_t *)pnt
));
4210 pnt
+= BGP_ADDPATH_ID_LEN
;
4213 /* Fetch prefix length. */
4214 p
.prefixlen
= *pnt
++;
4215 /* afi/safi validity already verified by caller,
4216 * bgp_update_receive */
4217 p
.family
= afi2family(afi
);
4219 /* Prefix length check. */
4220 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4223 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4224 peer
->host
, p
.prefixlen
, packet
->afi
);
4228 /* Packet size overflow check. */
4229 psize
= PSIZE(p
.prefixlen
);
4231 /* When packet overflow occur return immediately. */
4232 if (pnt
+ psize
> lim
) {
4235 "%s [Error] Update packet error (prefix length %d overflows packet)",
4236 peer
->host
, p
.prefixlen
);
4240 /* Defensive coding, double-check the psize fits in a struct
4242 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4245 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4246 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4250 /* Fetch prefix from NLRI packet. */
4251 memcpy(p
.u
.val
, pnt
, psize
);
4253 /* Check address. */
4254 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4255 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4256 /* From RFC4271 Section 6.3:
4258 * If a prefix in the NLRI field is semantically
4260 * (e.g., an unexpected multicast IP address),
4262 * be logged locally, and the prefix SHOULD be
4267 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4268 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4273 /* Check address. */
4274 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4275 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4280 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4282 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4287 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4292 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4294 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4301 /* Normal process. */
4303 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4304 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4305 NULL
, NULL
, 0, 0, NULL
);
4307 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4308 safi
, ZEBRA_ROUTE_BGP
,
4309 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4312 /* Address family configuration mismatch or maximum-prefix count
4318 /* Packet length consistency check. */
4322 "%s [Error] Update packet error (prefix length mismatch with total length)",
4330 static struct bgp_static
*bgp_static_new(void)
4332 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4335 static void bgp_static_free(struct bgp_static
*bgp_static
)
4337 if (bgp_static
->rmap
.name
)
4338 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4339 if (bgp_static
->eth_s_id
)
4340 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4341 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4344 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4345 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4347 struct bgp_node
*rn
;
4348 struct bgp_info
*ri
;
4349 struct bgp_info
*new;
4350 struct bgp_info info
;
4352 struct attr
*attr_new
;
4355 int vnc_implicit_withdraw
= 0;
4362 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4364 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4366 attr
.nexthop
= bgp_static
->igpnexthop
;
4367 attr
.med
= bgp_static
->igpmetric
;
4368 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4370 if (bgp_static
->atomic
)
4371 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4373 /* Store label index, if required. */
4374 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4375 attr
.label_index
= bgp_static
->label_index
;
4376 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4379 /* Apply route-map. */
4380 if (bgp_static
->rmap
.name
) {
4381 struct attr attr_tmp
= attr
;
4383 memset(&info
, 0, sizeof(struct bgp_info
));
4384 info
.peer
= bgp
->peer_self
;
4385 info
.attr
= &attr_tmp
;
4387 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4389 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4391 bgp
->peer_self
->rmap_type
= 0;
4393 if (ret
== RMAP_DENYMATCH
) {
4394 /* Free uninterned attribute. */
4395 bgp_attr_flush(&attr_tmp
);
4397 /* Unintern original. */
4398 aspath_unintern(&attr
.aspath
);
4399 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4403 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4404 bgp_attr_add_gshut_community(&attr_tmp
);
4406 attr_new
= bgp_attr_intern(&attr_tmp
);
4409 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4410 bgp_attr_add_gshut_community(&attr
);
4412 attr_new
= bgp_attr_intern(&attr
);
4415 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4416 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4417 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4421 if (attrhash_cmp(ri
->attr
, attr_new
)
4422 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4423 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4424 bgp_unlock_node(rn
);
4425 bgp_attr_unintern(&attr_new
);
4426 aspath_unintern(&attr
.aspath
);
4429 /* The attribute is changed. */
4430 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4432 /* Rewrite BGP route information. */
4433 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4434 bgp_info_restore(rn
, ri
);
4436 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4438 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4439 && (safi
== SAFI_UNICAST
)) {
4440 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4442 * Implicit withdraw case.
4443 * We have to do this before ri is
4446 ++vnc_implicit_withdraw
;
4447 vnc_import_bgp_del_route(bgp
, p
, ri
);
4448 vnc_import_bgp_exterior_del_route(
4453 bgp_attr_unintern(&ri
->attr
);
4454 ri
->attr
= attr_new
;
4455 ri
->uptime
= bgp_clock();
4457 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4458 && (safi
== SAFI_UNICAST
)) {
4459 if (vnc_implicit_withdraw
) {
4460 vnc_import_bgp_add_route(bgp
, p
, ri
);
4461 vnc_import_bgp_exterior_add_route(
4467 /* Nexthop reachability check. */
4468 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4469 && (safi
== SAFI_UNICAST
4470 || safi
== SAFI_LABELED_UNICAST
)) {
4472 struct bgp
*bgp_nexthop
= bgp
;
4474 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4475 bgp_nexthop
= ri
->extra
->bgp_orig
;
4477 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4479 bgp_info_set_flag(rn
, ri
,
4482 if (BGP_DEBUG(nht
, NHT
)) {
4483 char buf1
[INET6_ADDRSTRLEN
];
4484 inet_ntop(p
->family
,
4488 "%s(%s): Route not in table, not advertising",
4489 __FUNCTION__
, buf1
);
4491 bgp_info_unset_flag(rn
, ri
,
4495 /* Delete the NHT structure if any, if we're
4497 * enabling/disabling import check. We
4498 * deregister the route
4499 * from NHT to avoid overloading NHT and the
4500 * process interaction
4502 bgp_unlink_nexthop(ri
);
4503 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4505 /* Process change. */
4506 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4507 bgp_process(bgp
, rn
, afi
, safi
);
4509 if (SAFI_UNICAST
== safi
4510 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4512 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4513 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4517 bgp_unlock_node(rn
);
4518 aspath_unintern(&attr
.aspath
);
4523 /* Make new BGP info. */
4524 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4526 /* Nexthop reachability check. */
4527 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4528 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4529 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4530 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4532 if (BGP_DEBUG(nht
, NHT
)) {
4533 char buf1
[INET6_ADDRSTRLEN
];
4534 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4537 "%s(%s): Route not in table, not advertising",
4538 __FUNCTION__
, buf1
);
4540 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4543 /* Delete the NHT structure if any, if we're toggling between
4544 * enabling/disabling import check. We deregister the route
4545 * from NHT to avoid overloading NHT and the process interaction
4547 bgp_unlink_nexthop(new);
4549 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4552 /* Aggregate address increment. */
4553 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4555 /* Register new BGP information. */
4556 bgp_info_add(rn
, new);
4558 /* route_node_get lock */
4559 bgp_unlock_node(rn
);
4561 /* Process change. */
4562 bgp_process(bgp
, rn
, afi
, safi
);
4564 if (SAFI_UNICAST
== safi
4565 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4566 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4567 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4570 /* Unintern original. */
4571 aspath_unintern(&attr
.aspath
);
4574 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4577 struct bgp_node
*rn
;
4578 struct bgp_info
*ri
;
4580 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4582 /* Check selected route and self inserted route. */
4583 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4584 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4585 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4588 /* Withdraw static BGP route from routing table. */
4590 if (SAFI_UNICAST
== safi
4591 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4592 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4593 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4595 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4596 bgp_unlink_nexthop(ri
);
4597 bgp_info_delete(rn
, ri
);
4598 bgp_process(bgp
, rn
, afi
, safi
);
4601 /* Unlock bgp_node_lookup. */
4602 bgp_unlock_node(rn
);
4606 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4608 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4609 afi_t afi
, safi_t safi
,
4610 struct prefix_rd
*prd
)
4612 struct bgp_node
*rn
;
4613 struct bgp_info
*ri
;
4615 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4617 /* Check selected route and self inserted route. */
4618 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4619 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4620 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4623 /* Withdraw static BGP route from routing table. */
4626 rfapiProcessWithdraw(
4627 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4628 1); /* Kill, since it is an administrative change */
4630 if (SAFI_MPLS_VPN
== safi
4631 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4632 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4634 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4635 bgp_info_delete(rn
, ri
);
4636 bgp_process(bgp
, rn
, afi
, safi
);
4639 /* Unlock bgp_node_lookup. */
4640 bgp_unlock_node(rn
);
4643 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4644 struct bgp_static
*bgp_static
, afi_t afi
,
4647 struct bgp_node
*rn
;
4648 struct bgp_info
*new;
4649 struct attr
*attr_new
;
4650 struct attr attr
= {0};
4651 struct bgp_info
*ri
;
4653 mpls_label_t label
= 0;
4655 uint32_t num_labels
= 0;
4660 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4662 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4665 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4667 attr
.nexthop
= bgp_static
->igpnexthop
;
4668 attr
.med
= bgp_static
->igpmetric
;
4669 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4671 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4672 || (safi
== SAFI_ENCAP
)) {
4673 if (afi
== AFI_IP
) {
4674 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4675 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4678 if (afi
== AFI_L2VPN
) {
4679 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4681 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4682 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4683 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4684 sizeof(struct in6_addr
));
4685 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4686 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4687 struct bgp_encap_type_vxlan bet
;
4688 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4689 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4690 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4692 if (bgp_static
->router_mac
) {
4693 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4696 /* Apply route-map. */
4697 if (bgp_static
->rmap
.name
) {
4698 struct attr attr_tmp
= attr
;
4699 struct bgp_info info
;
4702 info
.peer
= bgp
->peer_self
;
4703 info
.attr
= &attr_tmp
;
4705 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4707 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4709 bgp
->peer_self
->rmap_type
= 0;
4711 if (ret
== RMAP_DENYMATCH
) {
4712 /* Free uninterned attribute. */
4713 bgp_attr_flush(&attr_tmp
);
4715 /* Unintern original. */
4716 aspath_unintern(&attr
.aspath
);
4717 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4722 attr_new
= bgp_attr_intern(&attr_tmp
);
4724 attr_new
= bgp_attr_intern(&attr
);
4727 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4728 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4729 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4734 memset(&add
, 0, sizeof(union gw_addr
));
4735 if (attrhash_cmp(ri
->attr
, attr_new
)
4736 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4737 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4738 bgp_unlock_node(rn
);
4739 bgp_attr_unintern(&attr_new
);
4740 aspath_unintern(&attr
.aspath
);
4743 /* The attribute is changed. */
4744 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4746 /* Rewrite BGP route information. */
4747 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4748 bgp_info_restore(rn
, ri
);
4750 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4751 bgp_attr_unintern(&ri
->attr
);
4752 ri
->attr
= attr_new
;
4753 ri
->uptime
= bgp_clock();
4756 label
= decode_label(&ri
->extra
->label
[0]);
4759 /* Process change. */
4760 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4761 bgp_process(bgp
, rn
, afi
, safi
);
4763 if (SAFI_MPLS_VPN
== safi
4764 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4765 vpn_leak_to_vrf_update(bgp
, ri
);
4768 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4769 ri
->attr
, afi
, safi
, ri
->type
,
4770 ri
->sub_type
, &label
);
4772 bgp_unlock_node(rn
);
4773 aspath_unintern(&attr
.aspath
);
4779 /* Make new BGP info. */
4780 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4782 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4783 new->extra
= bgp_info_extra_new();
4785 new->extra
->label
[0] = bgp_static
->label
;
4786 new->extra
->num_labels
= num_labels
;
4789 label
= decode_label(&bgp_static
->label
);
4792 /* Aggregate address increment. */
4793 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4795 /* Register new BGP information. */
4796 bgp_info_add(rn
, new);
4797 /* route_node_get lock */
4798 bgp_unlock_node(rn
);
4800 /* Process change. */
4801 bgp_process(bgp
, rn
, afi
, safi
);
4803 if (SAFI_MPLS_VPN
== safi
4804 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4805 vpn_leak_to_vrf_update(bgp
, new);
4808 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4809 safi
, new->type
, new->sub_type
, &label
);
4812 /* Unintern original. */
4813 aspath_unintern(&attr
.aspath
);
4816 /* Configure static BGP network. When user don't run zebra, static
4817 route should be installed as valid. */
4818 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4819 const char *ip_str
, afi_t afi
, safi_t safi
,
4820 const char *rmap
, int backdoor
, uint32_t label_index
)
4822 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4825 struct bgp_static
*bgp_static
;
4826 struct bgp_node
*rn
;
4827 uint8_t need_update
= 0;
4829 /* Convert IP prefix string to struct prefix. */
4830 ret
= str2prefix(ip_str
, &p
);
4832 vty_out(vty
, "%% Malformed prefix\n");
4833 return CMD_WARNING_CONFIG_FAILED
;
4835 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4836 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4837 return CMD_WARNING_CONFIG_FAILED
;
4844 /* Set BGP static route configuration. */
4845 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4848 vty_out(vty
, "%% Can't find static route specified\n");
4849 return CMD_WARNING_CONFIG_FAILED
;
4852 bgp_static
= rn
->info
;
4854 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4855 && (label_index
!= bgp_static
->label_index
)) {
4857 "%% label-index doesn't match static route\n");
4858 return CMD_WARNING_CONFIG_FAILED
;
4861 if ((rmap
&& bgp_static
->rmap
.name
)
4862 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4864 "%% route-map name doesn't match static route\n");
4865 return CMD_WARNING_CONFIG_FAILED
;
4868 /* Update BGP RIB. */
4869 if (!bgp_static
->backdoor
)
4870 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4872 /* Clear configuration. */
4873 bgp_static_free(bgp_static
);
4875 bgp_unlock_node(rn
);
4876 bgp_unlock_node(rn
);
4879 /* Set BGP static route configuration. */
4880 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4883 /* Configuration change. */
4884 bgp_static
= rn
->info
;
4886 /* Label index cannot be changed. */
4887 if (bgp_static
->label_index
!= label_index
) {
4888 vty_out(vty
, "%% cannot change label-index\n");
4889 return CMD_WARNING_CONFIG_FAILED
;
4892 /* Check previous routes are installed into BGP. */
4893 if (bgp_static
->valid
4894 && bgp_static
->backdoor
!= backdoor
)
4897 bgp_static
->backdoor
= backdoor
;
4900 if (bgp_static
->rmap
.name
)
4901 XFREE(MTYPE_ROUTE_MAP_NAME
,
4902 bgp_static
->rmap
.name
);
4903 bgp_static
->rmap
.name
=
4904 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4905 bgp_static
->rmap
.map
=
4906 route_map_lookup_by_name(rmap
);
4908 if (bgp_static
->rmap
.name
)
4909 XFREE(MTYPE_ROUTE_MAP_NAME
,
4910 bgp_static
->rmap
.name
);
4911 bgp_static
->rmap
.name
= NULL
;
4912 bgp_static
->rmap
.map
= NULL
;
4913 bgp_static
->valid
= 0;
4915 bgp_unlock_node(rn
);
4917 /* New configuration. */
4918 bgp_static
= bgp_static_new();
4919 bgp_static
->backdoor
= backdoor
;
4920 bgp_static
->valid
= 0;
4921 bgp_static
->igpmetric
= 0;
4922 bgp_static
->igpnexthop
.s_addr
= 0;
4923 bgp_static
->label_index
= label_index
;
4926 if (bgp_static
->rmap
.name
)
4927 XFREE(MTYPE_ROUTE_MAP_NAME
,
4928 bgp_static
->rmap
.name
);
4929 bgp_static
->rmap
.name
=
4930 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4931 bgp_static
->rmap
.map
=
4932 route_map_lookup_by_name(rmap
);
4934 rn
->info
= bgp_static
;
4937 bgp_static
->valid
= 1;
4939 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4941 if (!bgp_static
->backdoor
)
4942 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4948 void bgp_static_add(struct bgp
*bgp
)
4952 struct bgp_node
*rn
;
4953 struct bgp_node
*rm
;
4954 struct bgp_table
*table
;
4955 struct bgp_static
*bgp_static
;
4957 FOREACH_AFI_SAFI (afi
, safi
)
4958 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4959 rn
= bgp_route_next(rn
)) {
4960 if (rn
->info
== NULL
)
4963 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4964 || (safi
== SAFI_EVPN
)) {
4967 for (rm
= bgp_table_top(table
); rm
;
4968 rm
= bgp_route_next(rm
)) {
4969 bgp_static
= rm
->info
;
4970 bgp_static_update_safi(bgp
, &rm
->p
,
4975 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4981 /* Called from bgp_delete(). Delete all static routes from the BGP
4983 void bgp_static_delete(struct bgp
*bgp
)
4987 struct bgp_node
*rn
;
4988 struct bgp_node
*rm
;
4989 struct bgp_table
*table
;
4990 struct bgp_static
*bgp_static
;
4992 FOREACH_AFI_SAFI (afi
, safi
)
4993 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4994 rn
= bgp_route_next(rn
)) {
4995 if (rn
->info
== NULL
)
4998 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4999 || (safi
== SAFI_EVPN
)) {
5002 for (rm
= bgp_table_top(table
); rm
;
5003 rm
= bgp_route_next(rm
)) {
5004 bgp_static
= rm
->info
;
5005 bgp_static_withdraw_safi(
5006 bgp
, &rm
->p
, AFI_IP
, safi
,
5007 (struct prefix_rd
*)&rn
->p
);
5008 bgp_static_free(bgp_static
);
5010 bgp_unlock_node(rn
);
5013 bgp_static
= rn
->info
;
5014 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5015 bgp_static_free(bgp_static
);
5017 bgp_unlock_node(rn
);
5022 void bgp_static_redo_import_check(struct bgp
*bgp
)
5026 struct bgp_node
*rn
;
5027 struct bgp_node
*rm
;
5028 struct bgp_table
*table
;
5029 struct bgp_static
*bgp_static
;
5031 /* Use this flag to force reprocessing of the route */
5032 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5033 FOREACH_AFI_SAFI (afi
, safi
) {
5034 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5035 rn
= bgp_route_next(rn
)) {
5036 if (rn
->info
== NULL
)
5039 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5040 || (safi
== SAFI_EVPN
)) {
5043 for (rm
= bgp_table_top(table
); rm
;
5044 rm
= bgp_route_next(rm
)) {
5045 bgp_static
= rm
->info
;
5046 bgp_static_update_safi(bgp
, &rm
->p
,
5051 bgp_static
= rn
->info
;
5052 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5057 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5060 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5063 struct bgp_table
*table
;
5064 struct bgp_node
*rn
;
5065 struct bgp_info
*ri
;
5067 table
= bgp
->rib
[afi
][safi
];
5068 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5069 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5070 if (ri
->peer
== bgp
->peer_self
5071 && ((ri
->type
== ZEBRA_ROUTE_BGP
5072 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5073 || (ri
->type
!= ZEBRA_ROUTE_BGP
5075 == BGP_ROUTE_REDISTRIBUTE
))) {
5076 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5078 bgp_unlink_nexthop(ri
);
5079 bgp_info_delete(rn
, ri
);
5080 bgp_process(bgp
, rn
, afi
, safi
);
5087 * Purge all networks and redistributed routes from routing table.
5088 * Invoked upon the instance going down.
5090 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5095 FOREACH_AFI_SAFI (afi
, safi
)
5096 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5101 * Currently this is used to set static routes for VPN and ENCAP.
5102 * I think it can probably be factored with bgp_static_set.
5104 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5105 const char *ip_str
, const char *rd_str
,
5106 const char *label_str
, const char *rmap_str
,
5107 int evpn_type
, const char *esi
, const char *gwip
,
5108 const char *ethtag
, const char *routermac
)
5110 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5113 struct prefix_rd prd
;
5114 struct bgp_node
*prn
;
5115 struct bgp_node
*rn
;
5116 struct bgp_table
*table
;
5117 struct bgp_static
*bgp_static
;
5118 mpls_label_t label
= MPLS_INVALID_LABEL
;
5119 struct prefix gw_ip
;
5121 /* validate ip prefix */
5122 ret
= str2prefix(ip_str
, &p
);
5124 vty_out(vty
, "%% Malformed prefix\n");
5125 return CMD_WARNING_CONFIG_FAILED
;
5128 if ((afi
== AFI_L2VPN
)
5129 && (bgp_build_evpn_prefix(evpn_type
,
5130 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5131 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5132 return CMD_WARNING_CONFIG_FAILED
;
5135 ret
= str2prefix_rd(rd_str
, &prd
);
5137 vty_out(vty
, "%% Malformed rd\n");
5138 return CMD_WARNING_CONFIG_FAILED
;
5142 unsigned long label_val
;
5143 label_val
= strtoul(label_str
, NULL
, 10);
5144 encode_label(label_val
, &label
);
5147 if (safi
== SAFI_EVPN
) {
5148 if (esi
&& str2esi(esi
, NULL
) == 0) {
5149 vty_out(vty
, "%% Malformed ESI\n");
5150 return CMD_WARNING_CONFIG_FAILED
;
5152 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5153 vty_out(vty
, "%% Malformed Router MAC\n");
5154 return CMD_WARNING_CONFIG_FAILED
;
5157 memset(&gw_ip
, 0, sizeof(struct prefix
));
5158 ret
= str2prefix(gwip
, &gw_ip
);
5160 vty_out(vty
, "%% Malformed GatewayIp\n");
5161 return CMD_WARNING_CONFIG_FAILED
;
5163 if ((gw_ip
.family
== AF_INET
5164 && is_evpn_prefix_ipaddr_v6(
5165 (struct prefix_evpn
*)&p
))
5166 || (gw_ip
.family
== AF_INET6
5167 && is_evpn_prefix_ipaddr_v4(
5168 (struct prefix_evpn
*)&p
))) {
5170 "%% GatewayIp family differs with IP prefix\n");
5171 return CMD_WARNING_CONFIG_FAILED
;
5175 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5176 if (prn
->info
== NULL
)
5177 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5179 bgp_unlock_node(prn
);
5182 rn
= bgp_node_get(table
, &p
);
5185 vty_out(vty
, "%% Same network configuration exists\n");
5186 bgp_unlock_node(rn
);
5188 /* New configuration. */
5189 bgp_static
= bgp_static_new();
5190 bgp_static
->backdoor
= 0;
5191 bgp_static
->valid
= 0;
5192 bgp_static
->igpmetric
= 0;
5193 bgp_static
->igpnexthop
.s_addr
= 0;
5194 bgp_static
->label
= label
;
5195 bgp_static
->prd
= prd
;
5198 if (bgp_static
->rmap
.name
)
5199 XFREE(MTYPE_ROUTE_MAP_NAME
,
5200 bgp_static
->rmap
.name
);
5201 bgp_static
->rmap
.name
=
5202 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5203 bgp_static
->rmap
.map
=
5204 route_map_lookup_by_name(rmap_str
);
5207 if (safi
== SAFI_EVPN
) {
5209 bgp_static
->eth_s_id
=
5211 sizeof(struct eth_segment_id
));
5212 str2esi(esi
, bgp_static
->eth_s_id
);
5215 bgp_static
->router_mac
=
5216 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5217 (void)prefix_str2mac(routermac
,
5218 bgp_static
->router_mac
);
5221 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5223 rn
->info
= bgp_static
;
5225 bgp_static
->valid
= 1;
5226 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5232 /* Configure static BGP network. */
5233 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5234 const char *ip_str
, const char *rd_str
,
5235 const char *label_str
, int evpn_type
, const char *esi
,
5236 const char *gwip
, const char *ethtag
)
5238 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5241 struct prefix_rd prd
;
5242 struct bgp_node
*prn
;
5243 struct bgp_node
*rn
;
5244 struct bgp_table
*table
;
5245 struct bgp_static
*bgp_static
;
5246 mpls_label_t label
= MPLS_INVALID_LABEL
;
5248 /* Convert IP prefix string to struct prefix. */
5249 ret
= str2prefix(ip_str
, &p
);
5251 vty_out(vty
, "%% Malformed prefix\n");
5252 return CMD_WARNING_CONFIG_FAILED
;
5255 if ((afi
== AFI_L2VPN
)
5256 && (bgp_build_evpn_prefix(evpn_type
,
5257 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5258 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5259 return CMD_WARNING_CONFIG_FAILED
;
5261 ret
= str2prefix_rd(rd_str
, &prd
);
5263 vty_out(vty
, "%% Malformed rd\n");
5264 return CMD_WARNING_CONFIG_FAILED
;
5268 unsigned long label_val
;
5269 label_val
= strtoul(label_str
, NULL
, 10);
5270 encode_label(label_val
, &label
);
5273 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5274 if (prn
->info
== NULL
)
5275 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5277 bgp_unlock_node(prn
);
5280 rn
= bgp_node_lookup(table
, &p
);
5283 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5285 bgp_static
= rn
->info
;
5286 bgp_static_free(bgp_static
);
5288 bgp_unlock_node(rn
);
5289 bgp_unlock_node(rn
);
5291 vty_out(vty
, "%% Can't find the route\n");
5296 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5297 const char *rmap_name
)
5299 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5300 struct bgp_rmap
*rmap
;
5302 rmap
= &bgp
->table_map
[afi
][safi
];
5305 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5306 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5307 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5310 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5315 if (bgp_fibupd_safi(safi
))
5316 bgp_zebra_announce_table(bgp
, afi
, safi
);
5321 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5322 const char *rmap_name
)
5324 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5325 struct bgp_rmap
*rmap
;
5327 rmap
= &bgp
->table_map
[afi
][safi
];
5329 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5333 if (bgp_fibupd_safi(safi
))
5334 bgp_zebra_announce_table(bgp
, afi
, safi
);
5339 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5342 if (bgp
->table_map
[afi
][safi
].name
) {
5343 vty_out(vty
, " table-map %s\n",
5344 bgp
->table_map
[afi
][safi
].name
);
5348 DEFUN (bgp_table_map
,
5351 "BGP table to RIB route download filter\n"
5352 "Name of the route map\n")
5355 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5356 argv
[idx_word
]->arg
);
5358 DEFUN (no_bgp_table_map
,
5359 no_bgp_table_map_cmd
,
5360 "no table-map WORD",
5362 "BGP table to RIB route download filter\n"
5363 "Name of the route map\n")
5366 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5367 argv
[idx_word
]->arg
);
5373 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5374 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5375 backdoor$backdoor}]",
5377 "Specify a network to announce via BGP\n"
5382 "Route-map to modify the attributes\n"
5383 "Name of the route map\n"
5384 "Label index to associate with the prefix\n"
5385 "Label index value\n"
5386 "Specify a BGP backdoor route\n")
5388 char addr_prefix_str
[BUFSIZ
];
5393 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5396 vty_out(vty
, "%% Inconsistent address and mask\n");
5397 return CMD_WARNING_CONFIG_FAILED
;
5401 return bgp_static_set(
5402 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5403 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5404 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5407 DEFPY(ipv6_bgp_network
,
5408 ipv6_bgp_network_cmd
,
5409 "[no] network X:X::X:X/M$prefix \
5410 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5412 "Specify a network to announce via BGP\n"
5414 "Route-map to modify the attributes\n"
5415 "Name of the route map\n"
5416 "Label index to associate with the prefix\n"
5417 "Label index value\n")
5419 return bgp_static_set(
5420 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5421 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5424 /* Aggreagete address:
5426 advertise-map Set condition to advertise attribute
5427 as-set Generate AS set path information
5428 attribute-map Set attributes of aggregate
5429 route-map Set parameters of aggregate
5430 summary-only Filter more specific routes from updates
5431 suppress-map Conditionally filter more specific routes from updates
5434 struct bgp_aggregate
{
5435 /* Summary-only flag. */
5436 uint8_t summary_only
;
5438 /* AS set generation. */
5441 /* Route-map for aggregated route. */
5442 struct route_map
*map
;
5444 /* Suppress-count. */
5445 unsigned long count
;
5447 /* SAFI configuration. */
5451 static struct bgp_aggregate
*bgp_aggregate_new(void)
5453 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5456 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5458 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5461 static int bgp_aggregate_info_same(struct bgp_info
*ri
, struct aspath
*aspath
,
5462 struct community
*comm
)
5464 static struct aspath
*ae
= NULL
;
5467 ae
= aspath_empty();
5472 if (!aspath_cmp(ri
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5475 if (!community_cmp(ri
->attr
->community
, comm
))
5481 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5482 struct prefix
*p
, uint8_t origin
,
5483 struct aspath
*aspath
,
5484 struct community
*community
,
5485 uint8_t atomic_aggregate
,
5486 struct bgp_aggregate
*aggregate
)
5488 struct bgp_node
*rn
;
5489 struct bgp_table
*table
;
5490 struct bgp_info
*ri
, *new;
5492 table
= bgp
->rib
[afi
][safi
];
5494 rn
= bgp_node_get(table
, p
);
5496 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5497 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5498 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5501 if (aggregate
->count
> 0) {
5503 * If the aggregate information has not changed
5504 * no need to re-install it again.
5506 if (bgp_aggregate_info_same(rn
->info
, aspath
, community
)) {
5507 bgp_unlock_node(rn
);
5510 aspath_free(aspath
);
5512 community_free(community
);
5518 * Mark the old as unusable
5521 bgp_info_delete(rn
, ri
);
5524 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5525 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5526 community
, aggregate
->as_set
,
5529 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5531 bgp_info_add(rn
, new);
5532 bgp_process(bgp
, rn
, afi
, safi
);
5534 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5535 if (ri
->peer
== bgp
->peer_self
5536 && ri
->type
== ZEBRA_ROUTE_BGP
5537 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5540 /* Withdraw static BGP route from routing table. */
5542 bgp_info_delete(rn
, ri
);
5543 bgp_process(bgp
, rn
, afi
, safi
);
5547 bgp_unlock_node(rn
);
5550 /* Update an aggregate as routes are added/removed from the BGP table */
5551 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5552 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5553 struct bgp_info
*del
,
5554 struct bgp_aggregate
*aggregate
)
5556 struct bgp_table
*table
;
5557 struct bgp_node
*top
;
5558 struct bgp_node
*rn
;
5560 struct aspath
*aspath
= NULL
;
5561 struct aspath
*asmerge
= NULL
;
5562 struct community
*community
= NULL
;
5563 struct community
*commerge
= NULL
;
5564 struct bgp_info
*ri
;
5565 unsigned long match
= 0;
5566 uint8_t atomic_aggregate
= 0;
5568 /* ORIGIN attribute: If at least one route among routes that are
5569 aggregated has ORIGIN with the value INCOMPLETE, then the
5570 aggregated route must have the ORIGIN attribute with the value
5571 INCOMPLETE. Otherwise, if at least one route among routes that
5572 are aggregated has ORIGIN with the value EGP, then the aggregated
5573 route must have the origin attribute with the value EGP. In all
5574 other case the value of the ORIGIN attribute of the aggregated
5575 route is INTERNAL. */
5576 origin
= BGP_ORIGIN_IGP
;
5578 table
= bgp
->rib
[afi
][safi
];
5580 top
= bgp_node_get(table
, p
);
5581 for (rn
= bgp_node_get(table
, p
); rn
;
5582 rn
= bgp_route_next_until(rn
, top
)) {
5583 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5588 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5589 if (BGP_INFO_HOLDDOWN(ri
))
5592 if (del
&& ri
== del
)
5596 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5597 atomic_aggregate
= 1;
5599 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5603 * summary-only aggregate route suppress
5604 * aggregated route announcements.
5606 if (aggregate
->summary_only
) {
5607 (bgp_info_extra_get(ri
))->suppress
++;
5608 bgp_info_set_flag(rn
, ri
,
5609 BGP_INFO_ATTR_CHANGED
);
5616 * If at least one route among routes that are
5617 * aggregated has ORIGIN with the value INCOMPLETE,
5618 * then the aggregated route MUST have the ORIGIN
5619 * attribute with the value INCOMPLETE. Otherwise, if
5620 * at least one route among routes that are aggregated
5621 * has ORIGIN with the value EGP, then the aggregated
5622 * route MUST have the ORIGIN attribute with the value
5625 if (origin
< ri
->attr
->origin
)
5626 origin
= ri
->attr
->origin
;
5628 if (!aggregate
->as_set
)
5632 * as-set aggregate route generate origin, as path,
5633 * and community aggregation.
5636 asmerge
= aspath_aggregate(aspath
,
5638 aspath_free(aspath
);
5641 aspath
= aspath_dup(ri
->attr
->aspath
);
5643 if (!ri
->attr
->community
)
5647 commerge
= community_merge(community
,
5648 ri
->attr
->community
);
5649 community
= community_uniq_sort(commerge
);
5650 community_free(commerge
);
5652 community
= community_dup(ri
->attr
->community
);
5655 bgp_process(bgp
, rn
, afi
, safi
);
5657 bgp_unlock_node(top
);
5662 if (aggregate
->summary_only
)
5663 (bgp_info_extra_get(rinew
))->suppress
++;
5665 if (origin
< rinew
->attr
->origin
)
5666 origin
= rinew
->attr
->origin
;
5668 if (aggregate
->as_set
) {
5670 asmerge
= aspath_aggregate(aspath
,
5671 rinew
->attr
->aspath
);
5672 aspath_free(aspath
);
5675 aspath
= aspath_dup(rinew
->attr
->aspath
);
5677 if (rinew
->attr
->community
) {
5679 commerge
= community_merge(
5681 rinew
->attr
->community
);
5683 community_uniq_sort(commerge
);
5684 community_free(commerge
);
5686 community
= community_dup(
5687 rinew
->attr
->community
);
5692 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5693 atomic_aggregate
, aggregate
);
5695 if (aggregate
->count
== 0) {
5697 aspath_free(aspath
);
5699 community_free(community
);
5703 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5704 safi_t safi
, struct bgp_aggregate
*aggregate
)
5706 struct bgp_table
*table
;
5707 struct bgp_node
*top
;
5708 struct bgp_node
*rn
;
5709 struct bgp_info
*ri
;
5710 unsigned long match
;
5712 table
= bgp
->rib
[afi
][safi
];
5714 /* If routes exists below this node, generate aggregate routes. */
5715 top
= bgp_node_get(table
, p
);
5716 for (rn
= bgp_node_get(table
, p
); rn
;
5717 rn
= bgp_route_next_until(rn
, top
)) {
5718 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5722 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5723 if (BGP_INFO_HOLDDOWN(ri
))
5726 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5729 if (aggregate
->summary_only
&& ri
->extra
) {
5730 ri
->extra
->suppress
--;
5732 if (ri
->extra
->suppress
== 0) {
5734 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5741 /* If this node was suppressed, process the change. */
5743 bgp_process(bgp
, rn
, afi
, safi
);
5745 bgp_unlock_node(top
);
5748 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5749 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5751 struct bgp_node
*child
;
5752 struct bgp_node
*rn
;
5753 struct bgp_aggregate
*aggregate
;
5754 struct bgp_table
*table
;
5756 table
= bgp
->aggregate
[afi
][safi
];
5758 /* No aggregates configured. */
5759 if (bgp_table_top_nolock(table
) == NULL
)
5762 if (p
->prefixlen
== 0)
5765 if (BGP_INFO_HOLDDOWN(ri
))
5768 child
= bgp_node_get(table
, p
);
5770 /* Aggregate address configuration check. */
5771 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5772 if ((aggregate
= rn
->info
) != NULL
5773 && rn
->p
.prefixlen
< p
->prefixlen
) {
5774 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5775 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5778 bgp_unlock_node(child
);
5781 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5782 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5784 struct bgp_node
*child
;
5785 struct bgp_node
*rn
;
5786 struct bgp_aggregate
*aggregate
;
5787 struct bgp_table
*table
;
5789 table
= bgp
->aggregate
[afi
][safi
];
5791 /* No aggregates configured. */
5792 if (bgp_table_top_nolock(table
) == NULL
)
5795 if (p
->prefixlen
== 0)
5798 child
= bgp_node_get(table
, p
);
5800 /* Aggregate address configuration check. */
5801 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5802 if ((aggregate
= rn
->info
) != NULL
5803 && rn
->p
.prefixlen
< p
->prefixlen
) {
5804 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5805 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5808 bgp_unlock_node(child
);
5811 /* Aggregate route attribute. */
5812 #define AGGREGATE_SUMMARY_ONLY 1
5813 #define AGGREGATE_AS_SET 1
5815 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5816 afi_t afi
, safi_t safi
)
5818 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5821 struct bgp_node
*rn
;
5822 struct bgp_aggregate
*aggregate
;
5824 /* Convert string to prefix structure. */
5825 ret
= str2prefix(prefix_str
, &p
);
5827 vty_out(vty
, "Malformed prefix\n");
5828 return CMD_WARNING_CONFIG_FAILED
;
5832 /* Old configuration check. */
5833 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5836 "%% There is no aggregate-address configuration.\n");
5837 return CMD_WARNING_CONFIG_FAILED
;
5840 aggregate
= rn
->info
;
5841 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5842 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
, 0, aggregate
);
5844 /* Unlock aggregate address configuration. */
5846 bgp_aggregate_free(aggregate
);
5847 bgp_unlock_node(rn
);
5848 bgp_unlock_node(rn
);
5853 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5854 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5856 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5859 struct bgp_node
*rn
;
5860 struct bgp_aggregate
*aggregate
;
5862 /* Convert string to prefix structure. */
5863 ret
= str2prefix(prefix_str
, &p
);
5865 vty_out(vty
, "Malformed prefix\n");
5866 return CMD_WARNING_CONFIG_FAILED
;
5870 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
5871 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
5872 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
5874 return CMD_WARNING_CONFIG_FAILED
;
5877 /* Old configuration check. */
5878 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5881 vty_out(vty
, "There is already same aggregate network.\n");
5882 /* try to remove the old entry */
5883 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5885 vty_out(vty
, "Error deleting aggregate.\n");
5886 bgp_unlock_node(rn
);
5887 return CMD_WARNING_CONFIG_FAILED
;
5891 /* Make aggregate address structure. */
5892 aggregate
= bgp_aggregate_new();
5893 aggregate
->summary_only
= summary_only
;
5894 aggregate
->as_set
= as_set
;
5895 aggregate
->safi
= safi
;
5896 rn
->info
= aggregate
;
5898 /* Aggregate address insert into BGP routing table. */
5899 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
5904 DEFUN (aggregate_address
,
5905 aggregate_address_cmd
,
5906 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5907 "Configure BGP aggregate entries\n"
5908 "Aggregate prefix\n"
5909 "Generate AS set path information\n"
5910 "Filter more specific routes from updates\n"
5911 "Filter more specific routes from updates\n"
5912 "Generate AS set path information\n")
5915 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5916 char *prefix
= argv
[idx
]->arg
;
5918 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5920 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5921 ? AGGREGATE_SUMMARY_ONLY
5924 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5925 summary_only
, as_set
);
5928 DEFUN (aggregate_address_mask
,
5929 aggregate_address_mask_cmd
,
5930 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5931 "Configure BGP aggregate entries\n"
5932 "Aggregate address\n"
5934 "Generate AS set path information\n"
5935 "Filter more specific routes from updates\n"
5936 "Filter more specific routes from updates\n"
5937 "Generate AS set path information\n")
5940 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5941 char *prefix
= argv
[idx
]->arg
;
5942 char *mask
= argv
[idx
+ 1]->arg
;
5944 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5946 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5947 ? AGGREGATE_SUMMARY_ONLY
5950 char prefix_str
[BUFSIZ
];
5951 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5954 vty_out(vty
, "%% Inconsistent address and mask\n");
5955 return CMD_WARNING_CONFIG_FAILED
;
5958 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5959 summary_only
, as_set
);
5962 DEFUN (no_aggregate_address
,
5963 no_aggregate_address_cmd
,
5964 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5966 "Configure BGP aggregate entries\n"
5967 "Aggregate prefix\n"
5968 "Generate AS set path information\n"
5969 "Filter more specific routes from updates\n"
5970 "Filter more specific routes from updates\n"
5971 "Generate AS set path information\n")
5974 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5975 char *prefix
= argv
[idx
]->arg
;
5976 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5979 DEFUN (no_aggregate_address_mask
,
5980 no_aggregate_address_mask_cmd
,
5981 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5983 "Configure BGP aggregate entries\n"
5984 "Aggregate address\n"
5986 "Generate AS set path information\n"
5987 "Filter more specific routes from updates\n"
5988 "Filter more specific routes from updates\n"
5989 "Generate AS set path information\n")
5992 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5993 char *prefix
= argv
[idx
]->arg
;
5994 char *mask
= argv
[idx
+ 1]->arg
;
5996 char prefix_str
[BUFSIZ
];
5997 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6000 vty_out(vty
, "%% Inconsistent address and mask\n");
6001 return CMD_WARNING_CONFIG_FAILED
;
6004 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6007 DEFUN (ipv6_aggregate_address
,
6008 ipv6_aggregate_address_cmd
,
6009 "aggregate-address X:X::X:X/M [summary-only]",
6010 "Configure BGP aggregate entries\n"
6011 "Aggregate prefix\n"
6012 "Filter more specific routes from updates\n")
6015 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6016 char *prefix
= argv
[idx
]->arg
;
6017 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6018 ? AGGREGATE_SUMMARY_ONLY
6020 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6024 DEFUN (no_ipv6_aggregate_address
,
6025 no_ipv6_aggregate_address_cmd
,
6026 "no aggregate-address X:X::X:X/M [summary-only]",
6028 "Configure BGP aggregate entries\n"
6029 "Aggregate prefix\n"
6030 "Filter more specific routes from updates\n")
6033 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6034 char *prefix
= argv
[idx
]->arg
;
6035 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6038 /* Redistribute route treatment. */
6039 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6040 const union g_addr
*nexthop
, ifindex_t ifindex
,
6041 enum nexthop_types_t nhtype
, uint32_t metric
,
6042 uint8_t type
, unsigned short instance
,
6045 struct bgp_info
*new;
6046 struct bgp_info
*bi
;
6047 struct bgp_info info
;
6048 struct bgp_node
*bn
;
6050 struct attr
*new_attr
;
6053 struct bgp_redist
*red
;
6055 /* Make default attribute. */
6056 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6059 case NEXTHOP_TYPE_IFINDEX
:
6061 case NEXTHOP_TYPE_IPV4
:
6062 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6063 attr
.nexthop
= nexthop
->ipv4
;
6065 case NEXTHOP_TYPE_IPV6
:
6066 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6067 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6068 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6070 case NEXTHOP_TYPE_BLACKHOLE
:
6071 switch (p
->family
) {
6073 attr
.nexthop
.s_addr
= INADDR_ANY
;
6076 memset(&attr
.mp_nexthop_global
, 0,
6077 sizeof(attr
.mp_nexthop_global
));
6078 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6083 attr
.nh_ifindex
= ifindex
;
6086 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6089 afi
= family2afi(p
->family
);
6091 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6093 struct attr attr_new
;
6095 /* Copy attribute for modification. */
6096 bgp_attr_dup(&attr_new
, &attr
);
6098 if (red
->redist_metric_flag
)
6099 attr_new
.med
= red
->redist_metric
;
6101 /* Apply route-map. */
6102 if (red
->rmap
.name
) {
6103 memset(&info
, 0, sizeof(struct bgp_info
));
6104 info
.peer
= bgp
->peer_self
;
6105 info
.attr
= &attr_new
;
6107 SET_FLAG(bgp
->peer_self
->rmap_type
,
6108 PEER_RMAP_TYPE_REDISTRIBUTE
);
6110 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6113 bgp
->peer_self
->rmap_type
= 0;
6115 if (ret
== RMAP_DENYMATCH
) {
6116 /* Free uninterned attribute. */
6117 bgp_attr_flush(&attr_new
);
6119 /* Unintern original. */
6120 aspath_unintern(&attr
.aspath
);
6121 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6126 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6127 bgp_attr_add_gshut_community(&attr_new
);
6129 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6130 SAFI_UNICAST
, p
, NULL
);
6132 new_attr
= bgp_attr_intern(&attr_new
);
6134 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6135 if (bi
->peer
== bgp
->peer_self
6136 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6140 /* Ensure the (source route) type is updated. */
6142 if (attrhash_cmp(bi
->attr
, new_attr
)
6143 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6144 bgp_attr_unintern(&new_attr
);
6145 aspath_unintern(&attr
.aspath
);
6146 bgp_unlock_node(bn
);
6149 /* The attribute is changed. */
6150 bgp_info_set_flag(bn
, bi
,
6151 BGP_INFO_ATTR_CHANGED
);
6153 /* Rewrite BGP route information. */
6154 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6155 bgp_info_restore(bn
, bi
);
6157 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6159 bgp_attr_unintern(&bi
->attr
);
6160 bi
->attr
= new_attr
;
6161 bi
->uptime
= bgp_clock();
6163 /* Process change. */
6164 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6166 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6167 bgp_unlock_node(bn
);
6168 aspath_unintern(&attr
.aspath
);
6170 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6172 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6174 vpn_leak_from_vrf_update(
6175 bgp_get_default(), bgp
, bi
);
6181 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6182 bgp
->peer_self
, new_attr
, bn
);
6183 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6185 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6186 bgp_info_add(bn
, new);
6187 bgp_unlock_node(bn
);
6188 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6190 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6191 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6193 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6197 /* Unintern original. */
6198 aspath_unintern(&attr
.aspath
);
6201 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6202 unsigned short instance
)
6205 struct bgp_node
*rn
;
6206 struct bgp_info
*ri
;
6207 struct bgp_redist
*red
;
6209 afi
= family2afi(p
->family
);
6211 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6213 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6214 SAFI_UNICAST
, p
, NULL
);
6216 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6217 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6221 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6222 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6224 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6227 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6228 bgp_info_delete(rn
, ri
);
6229 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6231 bgp_unlock_node(rn
);
6235 /* Withdraw specified route type's route. */
6236 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6237 unsigned short instance
)
6239 struct bgp_node
*rn
;
6240 struct bgp_info
*ri
;
6241 struct bgp_table
*table
;
6243 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6245 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6246 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6247 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6248 && ri
->instance
== instance
)
6252 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6253 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6255 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6258 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6260 bgp_info_delete(rn
, ri
);
6261 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6266 /* Static function to display route. */
6267 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6273 if (p
->family
== AF_INET
) {
6277 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6280 json_object_string_add(json
, "prefix",
6281 inet_ntop(p
->family
,
6284 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6286 } else if (p
->family
== AF_ETHERNET
) {
6287 prefix2str(p
, buf
, PREFIX_STRLEN
);
6288 len
= vty_out(vty
, "%s", buf
);
6289 } else if (p
->family
== AF_EVPN
) {
6293 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6296 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6297 } else if (p
->family
== AF_FLOWSPEC
) {
6298 route_vty_out_flowspec(vty
, p
, NULL
,
6300 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6301 NLRI_STRING_FORMAT_MIN
, json
);
6306 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6313 vty_out(vty
, "\n%*s", 20, " ");
6315 vty_out(vty
, "%*s", len
, " ");
6319 enum bgp_display_type
{
6323 /* Print the short form route status for a bgp_info */
6324 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6325 json_object
*json_path
)
6329 /* Route status display. */
6330 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6331 json_object_boolean_true_add(json_path
, "removed");
6333 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6334 json_object_boolean_true_add(json_path
, "stale");
6336 if (binfo
->extra
&& binfo
->extra
->suppress
)
6337 json_object_boolean_true_add(json_path
, "suppressed");
6339 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6340 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6341 json_object_boolean_true_add(json_path
, "valid");
6344 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6345 json_object_boolean_true_add(json_path
, "history");
6347 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6348 json_object_boolean_true_add(json_path
, "damped");
6350 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6351 json_object_boolean_true_add(json_path
, "bestpath");
6353 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6354 json_object_boolean_true_add(json_path
, "multipath");
6356 /* Internal route. */
6357 if ((binfo
->peer
->as
)
6358 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6359 json_object_string_add(json_path
, "pathFrom",
6362 json_object_string_add(json_path
, "pathFrom",
6368 /* Route status display. */
6369 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6371 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6373 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6375 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6376 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6382 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6384 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6386 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6388 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6393 /* Internal route. */
6394 if (binfo
->peer
&& (binfo
->peer
->as
)
6395 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6401 /* called from terminal list command */
6402 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6403 int display
, safi_t safi
, json_object
*json_paths
)
6406 json_object
*json_path
= NULL
;
6407 json_object
*json_nexthops
= NULL
;
6408 json_object
*json_nexthop_global
= NULL
;
6409 json_object
*json_nexthop_ll
= NULL
;
6410 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6411 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
6414 bool nexthop_othervrf
= false;
6415 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6416 const char *nexthop_vrfname
= "Default";
6419 json_path
= json_object_new_object();
6421 /* short status lead text */
6422 route_vty_short_status_out(vty
, binfo
, json_path
);
6425 /* print prefix and mask */
6427 route_vty_out_route(p
, vty
, json_path
);
6429 vty_out(vty
, "%*s", 17, " ");
6431 route_vty_out_route(p
, vty
, json_path
);
6434 /* Print attribute */
6438 json_object_array_add(json_paths
, json_path
);
6446 * If vrf id of nexthop is different from that of prefix,
6447 * set up printable string to append
6449 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
6450 const char *self
= "";
6455 nexthop_othervrf
= true;
6456 nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
6458 if (binfo
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6459 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6460 "@%s%s", VRFID_NONE_STR
, self
);
6462 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6463 binfo
->extra
->bgp_orig
->vrf_id
, self
);
6465 if (binfo
->extra
->bgp_orig
->inst_type
!=
6466 BGP_INSTANCE_TYPE_DEFAULT
)
6468 nexthop_vrfname
= binfo
->extra
->bgp_orig
->name
;
6470 const char *self
= "";
6475 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6479 * For ENCAP and EVPN routes, nexthop address family is not
6480 * neccessarily the same as the prefix address family.
6481 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6482 * EVPN routes are also exchanged with a MP nexthop. Currently,
6484 * is only IPv4, the value will be present in either
6486 * attr->mp_nexthop_global_in
6488 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6491 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6495 sprintf(nexthop
, "%s",
6496 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6500 sprintf(nexthop
, "%s",
6501 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6505 sprintf(nexthop
, "?");
6510 json_nexthop_global
= json_object_new_object();
6512 json_object_string_add(json_nexthop_global
, "afi",
6513 (af
== AF_INET
) ? "ip" : "ipv6");
6514 json_object_string_add(json_nexthop_global
,
6515 (af
== AF_INET
) ? "ip" : "ipv6",
6517 json_object_boolean_true_add(json_nexthop_global
,
6520 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6521 } else if (safi
== SAFI_EVPN
) {
6523 json_nexthop_global
= json_object_new_object();
6525 json_object_string_add(json_nexthop_global
, "ip",
6526 inet_ntoa(attr
->nexthop
));
6527 json_object_string_add(json_nexthop_global
, "afi",
6529 json_object_boolean_true_add(json_nexthop_global
,
6532 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6534 } else if (safi
== SAFI_FLOWSPEC
) {
6535 if (attr
->nexthop
.s_addr
!= 0) {
6537 json_nexthop_global
= json_object_new_object();
6538 json_object_string_add(
6539 json_nexthop_global
, "ip",
6540 inet_ntoa(attr
->nexthop
));
6541 json_object_string_add(json_nexthop_global
,
6543 json_object_boolean_true_add(json_nexthop_global
,
6546 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6549 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6551 json_nexthop_global
= json_object_new_object();
6553 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6554 json_object_string_add(
6555 json_nexthop_global
, "ip",
6556 inet_ntoa(attr
->mp_nexthop_global_in
));
6558 json_object_string_add(
6559 json_nexthop_global
, "ip",
6560 inet_ntoa(attr
->nexthop
));
6562 json_object_string_add(json_nexthop_global
, "afi",
6564 json_object_boolean_true_add(json_nexthop_global
,
6569 snprintf(buf
, sizeof(buf
), "%s%s",
6570 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6571 vty_out(vty
, "%-16s", buf
);
6576 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6581 json_nexthop_global
= json_object_new_object();
6582 json_object_string_add(
6583 json_nexthop_global
, "ip",
6584 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6586 json_object_string_add(json_nexthop_global
, "afi",
6588 json_object_string_add(json_nexthop_global
, "scope",
6591 /* We display both LL & GL if both have been
6593 if ((attr
->mp_nexthop_len
== 32)
6594 || (binfo
->peer
->conf_if
)) {
6595 json_nexthop_ll
= json_object_new_object();
6596 json_object_string_add(
6597 json_nexthop_ll
, "ip",
6599 &attr
->mp_nexthop_local
, buf
,
6601 json_object_string_add(json_nexthop_ll
, "afi",
6603 json_object_string_add(json_nexthop_ll
, "scope",
6606 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6607 &attr
->mp_nexthop_local
)
6609 && !attr
->mp_nexthop_prefer_global
)
6610 json_object_boolean_true_add(
6611 json_nexthop_ll
, "used");
6613 json_object_boolean_true_add(
6614 json_nexthop_global
, "used");
6616 json_object_boolean_true_add(
6617 json_nexthop_global
, "used");
6619 /* Display LL if LL/Global both in table unless
6620 * prefer-global is set */
6621 if (((attr
->mp_nexthop_len
== 32)
6622 && !attr
->mp_nexthop_prefer_global
)
6623 || (binfo
->peer
->conf_if
)) {
6624 if (binfo
->peer
->conf_if
) {
6625 len
= vty_out(vty
, "%s",
6626 binfo
->peer
->conf_if
);
6627 len
= 16 - len
; /* len of IPv6
6633 vty_out(vty
, "\n%*s", 36, " ");
6635 vty_out(vty
, "%*s", len
, " ");
6641 &attr
->mp_nexthop_local
,
6647 vty_out(vty
, "\n%*s", 36, " ");
6649 vty_out(vty
, "%*s", len
, " ");
6655 &attr
->mp_nexthop_global
, buf
,
6661 vty_out(vty
, "\n%*s", 36, " ");
6663 vty_out(vty
, "%*s", len
, " ");
6669 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6671 json_object_int_add(json_path
, "med", attr
->med
);
6673 vty_out(vty
, "%10u", attr
->med
);
6674 else if (!json_paths
)
6678 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6680 json_object_int_add(json_path
, "localpref",
6683 vty_out(vty
, "%7u", attr
->local_pref
);
6684 else if (!json_paths
)
6688 json_object_int_add(json_path
, "weight", attr
->weight
);
6690 vty_out(vty
, "%7u ", attr
->weight
);
6694 json_object_string_add(
6695 json_path
, "peerId",
6696 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6702 json_object_string_add(json_path
, "aspath",
6705 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6710 json_object_string_add(json_path
, "origin",
6711 bgp_origin_long_str
[attr
->origin
]);
6713 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6717 json_object_boolean_true_add(json_path
,
6718 "announceNexthopSelf");
6719 if (nexthop_othervrf
) {
6720 json_object_string_add(json_path
, "nhVrfName",
6723 json_object_int_add(json_path
, "nhVrfId",
6724 ((nexthop_vrfid
== VRF_UNKNOWN
)
6726 : (int)nexthop_vrfid
));
6731 if (json_nexthop_global
|| json_nexthop_ll
) {
6732 json_nexthops
= json_object_new_array();
6734 if (json_nexthop_global
)
6735 json_object_array_add(json_nexthops
,
6736 json_nexthop_global
);
6738 if (json_nexthop_ll
)
6739 json_object_array_add(json_nexthops
,
6742 json_object_object_add(json_path
, "nexthops",
6746 json_object_array_add(json_paths
, json_path
);
6750 /* prints an additional line, indented, with VNC info, if
6752 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6753 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6758 /* called from terminal list command */
6759 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6760 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6762 json_object
*json_status
= NULL
;
6763 json_object
*json_net
= NULL
;
6765 /* Route status display. */
6767 json_status
= json_object_new_object();
6768 json_net
= json_object_new_object();
6775 /* print prefix and mask */
6777 json_object_string_add(
6778 json_net
, "addrPrefix",
6779 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6781 route_vty_out_route(p
, vty
, NULL
);
6783 /* Print attribute */
6786 if (p
->family
== AF_INET
6787 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6788 || safi
== SAFI_EVPN
6789 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6790 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6791 || safi
== SAFI_EVPN
)
6792 json_object_string_add(
6793 json_net
, "nextHop",
6795 attr
->mp_nexthop_global_in
));
6797 json_object_string_add(
6798 json_net
, "nextHop",
6799 inet_ntoa(attr
->nexthop
));
6800 } else if (p
->family
== AF_INET6
6801 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6804 json_object_string_add(
6805 json_net
, "netHopGloabal",
6807 &attr
->mp_nexthop_global
, buf
,
6812 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6813 json_object_int_add(json_net
, "metric",
6816 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6817 json_object_int_add(json_net
, "localPref",
6820 json_object_int_add(json_net
, "weight", attr
->weight
);
6824 json_object_string_add(json_net
, "asPath",
6828 json_object_string_add(json_net
, "bgpOriginCode",
6829 bgp_origin_str
[attr
->origin
]);
6831 if (p
->family
== AF_INET
6832 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6833 || safi
== SAFI_EVPN
6834 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6835 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6836 || safi
== SAFI_EVPN
)
6837 vty_out(vty
, "%-16s",
6839 attr
->mp_nexthop_global_in
));
6841 vty_out(vty
, "%-16s",
6842 inet_ntoa(attr
->nexthop
));
6843 } else if (p
->family
== AF_INET6
6844 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6851 &attr
->mp_nexthop_global
, buf
,
6855 vty_out(vty
, "\n%*s", 36, " ");
6857 vty_out(vty
, "%*s", len
, " ");
6860 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6861 vty_out(vty
, "%10u", attr
->med
);
6865 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6866 vty_out(vty
, "%7u", attr
->local_pref
);
6870 vty_out(vty
, "%7u ", attr
->weight
);
6874 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6877 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6881 json_object_boolean_true_add(json_status
, "*");
6882 json_object_boolean_true_add(json_status
, ">");
6883 json_object_object_add(json_net
, "appliedStatusSymbols",
6885 char buf_cut
[BUFSIZ
];
6886 json_object_object_add(
6888 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6894 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6895 struct bgp_info
*binfo
, int display
, safi_t safi
,
6898 json_object
*json_out
= NULL
;
6900 mpls_label_t label
= MPLS_INVALID_LABEL
;
6906 json_out
= json_object_new_object();
6908 /* short status lead text */
6909 route_vty_short_status_out(vty
, binfo
, json_out
);
6911 /* print prefix and mask */
6914 route_vty_out_route(p
, vty
, NULL
);
6916 vty_out(vty
, "%*s", 17, " ");
6919 /* Print attribute */
6922 if (((p
->family
== AF_INET
)
6923 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6924 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6925 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6926 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6927 || safi
== SAFI_EVPN
) {
6929 json_object_string_add(
6930 json_out
, "mpNexthopGlobalIn",
6932 attr
->mp_nexthop_global_in
));
6934 vty_out(vty
, "%-16s",
6936 attr
->mp_nexthop_global_in
));
6939 json_object_string_add(
6940 json_out
, "nexthop",
6941 inet_ntoa(attr
->nexthop
));
6943 vty_out(vty
, "%-16s",
6944 inet_ntoa(attr
->nexthop
));
6946 } else if (((p
->family
== AF_INET6
)
6947 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6948 || (safi
== SAFI_EVPN
6949 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6950 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6954 if (attr
->mp_nexthop_len
6955 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6957 json_object_string_add(
6958 json_out
, "mpNexthopGlobalIn",
6961 &attr
->mp_nexthop_global
,
6962 buf_a
, sizeof(buf_a
)));
6967 &attr
->mp_nexthop_global
,
6968 buf_a
, sizeof(buf_a
)));
6969 } else if (attr
->mp_nexthop_len
6970 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6973 &attr
->mp_nexthop_global
,
6974 buf_a
, sizeof(buf_a
));
6976 &attr
->mp_nexthop_local
,
6977 buf_b
, sizeof(buf_b
));
6978 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6979 json_object_string_add(
6981 "mpNexthopGlobalLocal", buf_c
);
6983 vty_out(vty
, "%s(%s)",
6986 &attr
->mp_nexthop_global
,
6987 buf_a
, sizeof(buf_a
)),
6990 &attr
->mp_nexthop_local
,
6991 buf_b
, sizeof(buf_b
)));
6996 label
= decode_label(&binfo
->extra
->label
[0]);
6998 if (bgp_is_valid_label(&label
)) {
7000 json_object_int_add(json_out
, "notag", label
);
7001 json_object_array_add(json
, json_out
);
7003 vty_out(vty
, "notag/%d", label
);
7009 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7010 struct bgp_info
*binfo
, int display
,
7011 json_object
*json_paths
)
7015 json_object
*json_path
= NULL
;
7018 json_path
= json_object_new_object();
7023 /* short status lead text */
7024 route_vty_short_status_out(vty
, binfo
, json_path
);
7026 /* print prefix and mask */
7028 route_vty_out_route(p
, vty
, NULL
);
7030 vty_out(vty
, "%*s", 17, " ");
7032 /* Print attribute */
7036 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7040 vty_out(vty
, "%-16s",
7041 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7045 vty_out(vty
, "%s(%s)",
7046 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7048 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7055 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7057 vty_out(vty
, "%s", str
);
7058 XFREE(MTYPE_TMP
, str
);
7060 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7062 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7063 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7066 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7069 if (attr
->ecommunity
) {
7071 struct ecommunity_val
*routermac
= ecommunity_lookup(
7072 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7073 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7075 mac
= ecom_mac2str((char *)routermac
->val
);
7077 vty_out(vty
, "/%s", (char *)mac
);
7078 XFREE(MTYPE_TMP
, mac
);
7086 /* dampening route */
7087 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7088 struct bgp_info
*binfo
, int display
, safi_t safi
,
7089 uint8_t use_json
, json_object
*json
)
7093 char timebuf
[BGP_UPTIME_LEN
];
7095 /* short status lead text */
7096 route_vty_short_status_out(vty
, binfo
, json
);
7098 /* print prefix and mask */
7101 route_vty_out_route(p
, vty
, NULL
);
7103 vty_out(vty
, "%*s", 17, " ");
7106 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7110 vty_out(vty
, "\n%*s", 34, " ");
7113 json_object_int_add(json
, "peerHost", len
);
7115 vty_out(vty
, "%*s", len
, " ");
7119 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7122 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7126 /* Print attribute */
7132 json_object_string_add(json
, "asPath",
7135 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7140 json_object_string_add(json
, "origin",
7141 bgp_origin_str
[attr
->origin
]);
7143 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7150 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7151 struct bgp_info
*binfo
, int display
, safi_t safi
,
7152 uint8_t use_json
, json_object
*json
)
7155 struct bgp_damp_info
*bdi
;
7156 char timebuf
[BGP_UPTIME_LEN
];
7162 bdi
= binfo
->extra
->damp_info
;
7164 /* short status lead text */
7165 route_vty_short_status_out(vty
, binfo
, json
);
7167 /* print prefix and mask */
7170 route_vty_out_route(p
, vty
, NULL
);
7172 vty_out(vty
, "%*s", 17, " ");
7175 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7179 vty_out(vty
, "\n%*s", 33, " ");
7182 json_object_int_add(json
, "peerHost", len
);
7184 vty_out(vty
, "%*s", len
, " ");
7187 len
= vty_out(vty
, "%d", bdi
->flap
);
7194 json_object_int_add(json
, "bdiFlap", len
);
7196 vty_out(vty
, "%*s", len
, " ");
7200 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7203 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7204 BGP_UPTIME_LEN
, 0, NULL
));
7206 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7207 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7209 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7210 BGP_UPTIME_LEN
, use_json
, json
);
7213 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7218 vty_out(vty
, "%*s ", 8, " ");
7221 /* Print attribute */
7227 json_object_string_add(json
, "asPath",
7230 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7235 json_object_string_add(json
, "origin",
7236 bgp_origin_str
[attr
->origin
]);
7238 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7244 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7245 int *first
, const char *header
,
7246 json_object
*json_adv_to
)
7248 char buf1
[INET6_ADDRSTRLEN
];
7249 json_object
*json_peer
= NULL
;
7252 /* 'advertised-to' is a dictionary of peers we have advertised
7254 * prefix too. The key is the peer's IP or swpX, the value is
7256 * hostname if we know it and "" if not.
7258 json_peer
= json_object_new_object();
7261 json_object_string_add(json_peer
, "hostname",
7265 json_object_object_add(json_adv_to
, peer
->conf_if
,
7268 json_object_object_add(
7270 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7274 vty_out(vty
, "%s", header
);
7279 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7281 vty_out(vty
, " %s(%s)", peer
->hostname
,
7284 vty_out(vty
, " %s(%s)", peer
->hostname
,
7285 sockunion2str(&peer
->su
, buf1
,
7289 vty_out(vty
, " %s", peer
->conf_if
);
7292 sockunion2str(&peer
->su
, buf1
,
7298 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7299 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7300 json_object
*json_paths
)
7302 char buf
[INET6_ADDRSTRLEN
];
7304 char buf2
[EVPN_ROUTE_STRLEN
];
7306 int sockunion_vty_out(struct vty
*, union sockunion
*);
7308 json_object
*json_bestpath
= NULL
;
7309 json_object
*json_cluster_list
= NULL
;
7310 json_object
*json_cluster_list_list
= NULL
;
7311 json_object
*json_ext_community
= NULL
;
7312 json_object
*json_last_update
= NULL
;
7313 json_object
*json_pmsi
= NULL
;
7314 json_object
*json_nexthop_global
= NULL
;
7315 json_object
*json_nexthop_ll
= NULL
;
7316 json_object
*json_nexthops
= NULL
;
7317 json_object
*json_path
= NULL
;
7318 json_object
*json_peer
= NULL
;
7319 json_object
*json_string
= NULL
;
7320 json_object
*json_adv_to
= NULL
;
7322 struct listnode
*node
, *nnode
;
7324 int addpath_capable
;
7326 unsigned int first_as
;
7327 bool nexthop_self
= CHECK_FLAG(binfo
->flags
, BGP_INFO_ANNC_NH_SELF
)
7332 json_path
= json_object_new_object();
7333 json_peer
= json_object_new_object();
7334 json_nexthop_global
= json_object_new_object();
7337 if (!json_paths
&& safi
== SAFI_EVPN
) {
7340 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7341 vty_out(vty
, " Route %s", buf2
);
7343 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7344 bgp_evpn_label2str(binfo
->extra
->label
,
7345 binfo
->extra
->num_labels
, tag_buf
,
7347 vty_out(vty
, " VNI %s", tag_buf
);
7350 if (binfo
->extra
&& binfo
->extra
->parent
) {
7351 struct bgp_info
*parent_ri
;
7352 struct bgp_node
*rn
, *prn
;
7354 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7355 rn
= parent_ri
->net
;
7356 if (rn
&& rn
->prn
) {
7358 vty_out(vty
, " Imported from %s:%s\n",
7360 (struct prefix_rd
*)&prn
->p
,
7361 buf1
, sizeof(buf1
)),
7370 /* Line1 display AS-path, Aggregator */
7373 if (!attr
->aspath
->json
)
7374 aspath_str_update(attr
->aspath
, true);
7375 json_object_lock(attr
->aspath
->json
);
7376 json_object_object_add(json_path
, "aspath",
7377 attr
->aspath
->json
);
7379 if (attr
->aspath
->segments
)
7380 aspath_print_vty(vty
, " %s",
7383 vty_out(vty
, " Local");
7387 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7389 json_object_boolean_true_add(json_path
,
7392 vty_out(vty
, ", (removed)");
7395 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7397 json_object_boolean_true_add(json_path
,
7400 vty_out(vty
, ", (stale)");
7403 if (CHECK_FLAG(attr
->flag
,
7404 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7406 json_object_int_add(json_path
, "aggregatorAs",
7407 attr
->aggregator_as
);
7408 json_object_string_add(
7409 json_path
, "aggregatorId",
7410 inet_ntoa(attr
->aggregator_addr
));
7412 vty_out(vty
, ", (aggregated by %u %s)",
7413 attr
->aggregator_as
,
7414 inet_ntoa(attr
->aggregator_addr
));
7418 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7419 PEER_FLAG_REFLECTOR_CLIENT
)) {
7421 json_object_boolean_true_add(
7422 json_path
, "rxedFromRrClient");
7424 vty_out(vty
, ", (Received from a RR-client)");
7427 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7428 PEER_FLAG_RSERVER_CLIENT
)) {
7430 json_object_boolean_true_add(
7431 json_path
, "rxedFromRsClient");
7433 vty_out(vty
, ", (Received from a RS-client)");
7436 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7438 json_object_boolean_true_add(
7439 json_path
, "dampeningHistoryEntry");
7441 vty_out(vty
, ", (history entry)");
7442 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7444 json_object_boolean_true_add(
7445 json_path
, "dampeningSuppressed");
7447 vty_out(vty
, ", (suppressed due to dampening)");
7453 /* Line2 display Next-hop, Neighbor, Router-id */
7454 /* Display the nexthop */
7455 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7456 || p
->family
== AF_EVPN
)
7457 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7458 || safi
== SAFI_EVPN
7459 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7460 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7461 || safi
== SAFI_EVPN
) {
7463 json_object_string_add(
7464 json_nexthop_global
, "ip",
7466 attr
->mp_nexthop_global_in
));
7470 attr
->mp_nexthop_global_in
));
7473 json_object_string_add(
7474 json_nexthop_global
, "ip",
7475 inet_ntoa(attr
->nexthop
));
7478 inet_ntoa(attr
->nexthop
));
7482 json_object_string_add(json_nexthop_global
,
7486 json_object_string_add(
7487 json_nexthop_global
, "ip",
7489 &attr
->mp_nexthop_global
, buf
,
7491 json_object_string_add(json_nexthop_global
,
7493 json_object_string_add(json_nexthop_global
,
7498 &attr
->mp_nexthop_global
, buf
,
7503 /* Display the IGP cost or 'inaccessible' */
7504 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7506 json_object_boolean_false_add(
7507 json_nexthop_global
, "accessible");
7509 vty_out(vty
, " (inaccessible)");
7511 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7513 json_object_int_add(
7514 json_nexthop_global
, "metric",
7515 binfo
->extra
->igpmetric
);
7517 vty_out(vty
, " (metric %u)",
7518 binfo
->extra
->igpmetric
);
7521 /* IGP cost is 0, display this only for json */
7524 json_object_int_add(json_nexthop_global
,
7529 json_object_boolean_true_add(
7530 json_nexthop_global
, "accessible");
7533 /* Display peer "from" output */
7534 /* This path was originated locally */
7535 if (binfo
->peer
== bgp
->peer_self
) {
7537 if (safi
== SAFI_EVPN
7538 || (p
->family
== AF_INET
7539 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7541 json_object_string_add(
7542 json_peer
, "peerId", "0.0.0.0");
7544 vty_out(vty
, " from 0.0.0.0 ");
7547 json_object_string_add(json_peer
,
7550 vty_out(vty
, " from :: ");
7554 json_object_string_add(
7555 json_peer
, "routerId",
7556 inet_ntoa(bgp
->router_id
));
7558 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7561 /* We RXed this path from one of our peers */
7565 json_object_string_add(
7566 json_peer
, "peerId",
7567 sockunion2str(&binfo
->peer
->su
, buf
,
7569 json_object_string_add(
7570 json_peer
, "routerId",
7572 &binfo
->peer
->remote_id
, buf1
,
7575 if (binfo
->peer
->hostname
)
7576 json_object_string_add(
7577 json_peer
, "hostname",
7578 binfo
->peer
->hostname
);
7580 if (binfo
->peer
->domainname
)
7581 json_object_string_add(
7582 json_peer
, "domainname",
7583 binfo
->peer
->domainname
);
7585 if (binfo
->peer
->conf_if
)
7586 json_object_string_add(
7587 json_peer
, "interface",
7588 binfo
->peer
->conf_if
);
7590 if (binfo
->peer
->conf_if
) {
7591 if (binfo
->peer
->hostname
7594 BGP_FLAG_SHOW_HOSTNAME
))
7595 vty_out(vty
, " from %s(%s)",
7596 binfo
->peer
->hostname
,
7597 binfo
->peer
->conf_if
);
7599 vty_out(vty
, " from %s",
7600 binfo
->peer
->conf_if
);
7602 if (binfo
->peer
->hostname
7605 BGP_FLAG_SHOW_HOSTNAME
))
7606 vty_out(vty
, " from %s(%s)",
7607 binfo
->peer
->hostname
,
7610 vty_out(vty
, " from %s",
7619 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7620 vty_out(vty
, " (%s)",
7621 inet_ntoa(attr
->originator_id
));
7623 vty_out(vty
, " (%s)",
7626 &binfo
->peer
->remote_id
,
7627 buf1
, sizeof(buf1
)));
7632 * Note when vrfid of nexthop is different from that of prefix
7634 if (binfo
->extra
&& binfo
->extra
->bgp_orig
) {
7635 vrf_id_t nexthop_vrfid
= binfo
->extra
->bgp_orig
->vrf_id
;
7640 if (binfo
->extra
->bgp_orig
->inst_type
==
7641 BGP_INSTANCE_TYPE_DEFAULT
)
7645 vn
= binfo
->extra
->bgp_orig
->name
;
7647 json_object_string_add(json_path
, "nhVrfName",
7650 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7651 json_object_int_add(json_path
,
7654 json_object_int_add(json_path
,
7655 "nhVrfId", (int)nexthop_vrfid
);
7658 if (nexthop_vrfid
== VRF_UNKNOWN
)
7659 vty_out(vty
, " vrf ?");
7661 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7667 json_object_boolean_true_add(json_path
,
7668 "announceNexthopSelf");
7670 vty_out(vty
, " announce-nh-self");
7677 /* display the link-local nexthop */
7678 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7680 json_nexthop_ll
= json_object_new_object();
7681 json_object_string_add(
7682 json_nexthop_ll
, "ip",
7684 &attr
->mp_nexthop_local
, buf
,
7686 json_object_string_add(json_nexthop_ll
, "afi",
7688 json_object_string_add(json_nexthop_ll
, "scope",
7691 json_object_boolean_true_add(json_nexthop_ll
,
7694 if (!attr
->mp_nexthop_prefer_global
)
7695 json_object_boolean_true_add(
7696 json_nexthop_ll
, "used");
7698 json_object_boolean_true_add(
7699 json_nexthop_global
, "used");
7701 vty_out(vty
, " (%s) %s\n",
7703 &attr
->mp_nexthop_local
, buf
,
7705 attr
->mp_nexthop_prefer_global
7710 /* If we do not have a link-local nexthop then we must flag the
7714 json_object_boolean_true_add(
7715 json_nexthop_global
, "used");
7718 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7719 * Int/Ext/Local, Atomic, best */
7721 json_object_string_add(
7722 json_path
, "origin",
7723 bgp_origin_long_str
[attr
->origin
]);
7725 vty_out(vty
, " Origin %s",
7726 bgp_origin_long_str
[attr
->origin
]);
7728 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7730 json_object_int_add(json_path
, "med",
7733 vty_out(vty
, ", metric %u", attr
->med
);
7736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7738 json_object_int_add(json_path
, "localpref",
7741 vty_out(vty
, ", localpref %u",
7745 if (attr
->weight
!= 0) {
7747 json_object_int_add(json_path
, "weight",
7750 vty_out(vty
, ", weight %u", attr
->weight
);
7753 if (attr
->tag
!= 0) {
7755 json_object_int_add(json_path
, "tag",
7758 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7762 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7764 json_object_boolean_false_add(json_path
,
7767 vty_out(vty
, ", invalid");
7768 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7770 json_object_boolean_true_add(json_path
,
7773 vty_out(vty
, ", valid");
7776 if (binfo
->peer
!= bgp
->peer_self
) {
7777 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7778 if (CHECK_FLAG(bgp
->config
,
7779 BGP_CONFIG_CONFEDERATION
)) {
7781 json_object_string_add(
7786 ", confed-internal");
7789 json_object_string_add(
7793 vty_out(vty
, ", internal");
7796 if (bgp_confederation_peers_check(
7797 bgp
, binfo
->peer
->as
)) {
7799 json_object_string_add(
7804 ", confed-external");
7807 json_object_string_add(
7811 vty_out(vty
, ", external");
7814 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7816 json_object_boolean_true_add(json_path
,
7818 json_object_boolean_true_add(json_path
,
7821 vty_out(vty
, ", aggregated, local");
7823 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7825 json_object_boolean_true_add(json_path
,
7828 vty_out(vty
, ", sourced");
7831 json_object_boolean_true_add(json_path
,
7833 json_object_boolean_true_add(json_path
,
7836 vty_out(vty
, ", sourced, local");
7840 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7842 json_object_boolean_true_add(json_path
,
7845 vty_out(vty
, ", atomic-aggregate");
7848 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7849 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7850 && bgp_info_mpath_count(binfo
))) {
7852 json_object_boolean_true_add(json_path
,
7855 vty_out(vty
, ", multipath");
7858 // Mark the bestpath(s)
7859 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7860 first_as
= aspath_get_first_as(attr
->aspath
);
7865 json_object_new_object();
7866 json_object_int_add(json_bestpath
,
7867 "bestpathFromAs", first_as
);
7870 vty_out(vty
, ", bestpath-from-AS %u",
7874 ", bestpath-from-AS Local");
7878 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7882 json_object_new_object();
7883 json_object_boolean_true_add(json_bestpath
,
7886 vty_out(vty
, ", best");
7890 json_object_object_add(json_path
, "bestpath",
7896 /* Line 4 display Community */
7897 if (attr
->community
) {
7899 if (!attr
->community
->json
)
7900 community_str(attr
->community
, true);
7901 json_object_lock(attr
->community
->json
);
7902 json_object_object_add(json_path
, "community",
7903 attr
->community
->json
);
7905 vty_out(vty
, " Community: %s\n",
7906 attr
->community
->str
);
7910 /* Line 5 display Extended-community */
7911 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7913 json_ext_community
= json_object_new_object();
7914 json_object_string_add(json_ext_community
,
7916 attr
->ecommunity
->str
);
7917 json_object_object_add(json_path
,
7918 "extendedCommunity",
7919 json_ext_community
);
7921 vty_out(vty
, " Extended Community: %s\n",
7922 attr
->ecommunity
->str
);
7926 /* Line 6 display Large community */
7927 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7929 if (!attr
->lcommunity
->json
)
7930 lcommunity_str(attr
->lcommunity
, true);
7931 json_object_lock(attr
->lcommunity
->json
);
7932 json_object_object_add(json_path
,
7934 attr
->lcommunity
->json
);
7936 vty_out(vty
, " Large Community: %s\n",
7937 attr
->lcommunity
->str
);
7941 /* Line 7 display Originator, Cluster-id */
7942 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7943 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7945 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7947 json_object_string_add(
7948 json_path
, "originatorId",
7949 inet_ntoa(attr
->originator_id
));
7951 vty_out(vty
, " Originator: %s",
7952 inet_ntoa(attr
->originator_id
));
7955 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7960 json_object_new_object();
7961 json_cluster_list_list
=
7962 json_object_new_array();
7965 i
< attr
->cluster
->length
/ 4;
7967 json_string
= json_object_new_string(
7971 json_object_array_add(
7972 json_cluster_list_list
,
7976 /* struct cluster_list does not have
7978 * aspath and community do. Add this
7981 json_object_string_add(json_cluster_list,
7982 "string", attr->cluster->str);
7984 json_object_object_add(
7985 json_cluster_list
, "list",
7986 json_cluster_list_list
);
7987 json_object_object_add(
7988 json_path
, "clusterList",
7991 vty_out(vty
, ", Cluster list: ");
7994 i
< attr
->cluster
->length
/ 4;
8008 if (binfo
->extra
&& binfo
->extra
->damp_info
)
8009 bgp_damp_info_vty(vty
, binfo
, json_path
);
8012 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
8013 && safi
!= SAFI_EVPN
) {
8014 mpls_label_t label
=
8015 label_pton(&binfo
->extra
->label
[0]);
8017 json_object_int_add(json_path
, "remoteLabel",
8020 vty_out(vty
, " Remote label: %d\n", label
);
8024 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8026 json_object_int_add(json_path
, "labelIndex",
8029 vty_out(vty
, " Label Index: %d\n",
8033 /* Line 8 display Addpath IDs */
8034 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8036 json_object_int_add(json_path
, "addpathRxId",
8037 binfo
->addpath_rx_id
);
8038 json_object_int_add(json_path
, "addpathTxId",
8039 binfo
->addpath_tx_id
);
8041 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8042 binfo
->addpath_rx_id
,
8043 binfo
->addpath_tx_id
);
8047 /* If we used addpath to TX a non-bestpath we need to display
8048 * "Advertised to" on a path-by-path basis */
8049 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8052 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8054 bgp_addpath_encode_tx(peer
, afi
, safi
);
8055 has_adj
= bgp_adj_out_lookup(
8056 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8058 if ((addpath_capable
&& has_adj
)
8059 || (!addpath_capable
&& has_adj
8060 && CHECK_FLAG(binfo
->flags
,
8061 BGP_INFO_SELECTED
))) {
8062 if (json_path
&& !json_adv_to
)
8064 json_object_new_object();
8066 route_vty_out_advertised_to(
8075 json_object_object_add(json_path
,
8086 /* Line 9 display Uptime */
8087 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8089 json_last_update
= json_object_new_object();
8090 json_object_int_add(json_last_update
, "epoch", tbuf
);
8091 json_object_string_add(json_last_update
, "string",
8093 json_object_object_add(json_path
, "lastUpdate",
8096 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8098 /* Line 10 display PMSI tunnel attribute, if present */
8099 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8100 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8101 attr
->pmsi_tnl_type
,
8102 PMSI_TNLTYPE_STR_DEFAULT
);
8105 json_pmsi
= json_object_new_object();
8106 json_object_string_add(json_pmsi
,
8108 json_object_object_add(json_path
, "pmsi",
8111 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8117 /* We've constructed the json object for this path, add it to the json
8121 if (json_nexthop_global
|| json_nexthop_ll
) {
8122 json_nexthops
= json_object_new_array();
8124 if (json_nexthop_global
)
8125 json_object_array_add(json_nexthops
,
8126 json_nexthop_global
);
8128 if (json_nexthop_ll
)
8129 json_object_array_add(json_nexthops
,
8132 json_object_object_add(json_path
, "nexthops",
8136 json_object_object_add(json_path
, "peer", json_peer
);
8137 json_object_array_add(json_paths
, json_path
);
8142 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8143 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8144 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8146 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8147 const char *prefix_list_str
, afi_t afi
,
8148 safi_t safi
, enum bgp_show_type type
);
8149 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8150 const char *filter
, afi_t afi
, safi_t safi
,
8151 enum bgp_show_type type
);
8152 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8153 const char *rmap_str
, afi_t afi
, safi_t safi
,
8154 enum bgp_show_type type
);
8155 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8156 const char *com
, int exact
, afi_t afi
,
8158 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8159 const char *prefix
, afi_t afi
, safi_t safi
,
8160 enum bgp_show_type type
);
8161 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8162 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8163 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8164 const char *comstr
, int exact
, afi_t afi
,
8165 safi_t safi
, uint8_t use_json
);
8168 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8169 struct bgp_table
*table
, enum bgp_show_type type
,
8170 void *output_arg
, uint8_t use_json
, char *rd
,
8171 int is_last
, unsigned long *output_cum
,
8172 unsigned long *total_cum
,
8173 unsigned long *json_header_depth
)
8175 struct bgp_info
*ri
;
8176 struct bgp_node
*rn
;
8179 unsigned long output_count
= 0;
8180 unsigned long total_count
= 0;
8184 json_object
*json_paths
= NULL
;
8187 if (output_cum
&& *output_cum
!= 0)
8190 if (use_json
&& !*json_header_depth
) {
8192 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8193 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8194 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8195 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8197 table
->version
, inet_ntoa(bgp
->router_id
));
8198 *json_header_depth
= 2;
8200 vty_out(vty
, " \"routeDistinguishers\" : {");
8201 ++*json_header_depth
;
8205 if (use_json
&& rd
) {
8206 vty_out(vty
, " \"%s\" : { ", rd
);
8209 /* Start processing of routes. */
8210 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8211 if (rn
->info
== NULL
)
8216 json_paths
= json_object_new_array();
8220 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8222 if (type
== bgp_show_type_flap_statistics
8223 || type
== bgp_show_type_flap_neighbor
8224 || type
== bgp_show_type_dampend_paths
8225 || type
== bgp_show_type_damp_neighbor
) {
8226 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8229 if (type
== bgp_show_type_regexp
) {
8230 regex_t
*regex
= output_arg
;
8232 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8236 if (type
== bgp_show_type_prefix_list
) {
8237 struct prefix_list
*plist
= output_arg
;
8239 if (prefix_list_apply(plist
, &rn
->p
)
8243 if (type
== bgp_show_type_filter_list
) {
8244 struct as_list
*as_list
= output_arg
;
8246 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8247 != AS_FILTER_PERMIT
)
8250 if (type
== bgp_show_type_route_map
) {
8251 struct route_map
*rmap
= output_arg
;
8252 struct bgp_info binfo
;
8253 struct attr dummy_attr
;
8256 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8258 binfo
.peer
= ri
->peer
;
8259 binfo
.attr
= &dummy_attr
;
8261 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8263 if (ret
== RMAP_DENYMATCH
)
8266 if (type
== bgp_show_type_neighbor
8267 || type
== bgp_show_type_flap_neighbor
8268 || type
== bgp_show_type_damp_neighbor
) {
8269 union sockunion
*su
= output_arg
;
8271 if (ri
->peer
== NULL
8272 || ri
->peer
->su_remote
== NULL
8273 || !sockunion_same(ri
->peer
->su_remote
, su
))
8276 if (type
== bgp_show_type_cidr_only
) {
8277 uint32_t destination
;
8279 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8280 if (IN_CLASSC(destination
)
8281 && rn
->p
.prefixlen
== 24)
8283 if (IN_CLASSB(destination
)
8284 && rn
->p
.prefixlen
== 16)
8286 if (IN_CLASSA(destination
)
8287 && rn
->p
.prefixlen
== 8)
8290 if (type
== bgp_show_type_prefix_longer
) {
8291 struct prefix
*p
= output_arg
;
8293 if (!prefix_match(p
, &rn
->p
))
8296 if (type
== bgp_show_type_community_all
) {
8297 if (!ri
->attr
->community
)
8300 if (type
== bgp_show_type_community
) {
8301 struct community
*com
= output_arg
;
8303 if (!ri
->attr
->community
8304 || !community_match(ri
->attr
->community
,
8308 if (type
== bgp_show_type_community_exact
) {
8309 struct community
*com
= output_arg
;
8311 if (!ri
->attr
->community
8312 || !community_cmp(ri
->attr
->community
, com
))
8315 if (type
== bgp_show_type_community_list
) {
8316 struct community_list
*list
= output_arg
;
8318 if (!community_list_match(ri
->attr
->community
,
8322 if (type
== bgp_show_type_community_list_exact
) {
8323 struct community_list
*list
= output_arg
;
8325 if (!community_list_exact_match(
8326 ri
->attr
->community
, list
))
8329 if (type
== bgp_show_type_lcommunity
) {
8330 struct lcommunity
*lcom
= output_arg
;
8332 if (!ri
->attr
->lcommunity
8333 || !lcommunity_match(ri
->attr
->lcommunity
,
8337 if (type
== bgp_show_type_lcommunity_list
) {
8338 struct community_list
*list
= output_arg
;
8340 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8344 if (type
== bgp_show_type_lcommunity_all
) {
8345 if (!ri
->attr
->lcommunity
)
8348 if (type
== bgp_show_type_dampend_paths
8349 || type
== bgp_show_type_damp_neighbor
) {
8350 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8351 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8355 if (!use_json
&& header
) {
8356 vty_out(vty
, "BGP table version is %" PRIu64
8357 ", local router ID is %s, vrf id ",
8359 inet_ntoa(bgp
->router_id
));
8360 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8361 vty_out(vty
, "%s", VRFID_NONE_STR
);
8363 vty_out(vty
, "%u", bgp
->vrf_id
);
8365 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8366 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8367 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8368 if (type
== bgp_show_type_dampend_paths
8369 || type
== bgp_show_type_damp_neighbor
)
8370 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8371 else if (type
== bgp_show_type_flap_statistics
8372 || type
== bgp_show_type_flap_neighbor
)
8373 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8375 vty_out(vty
, BGP_SHOW_HEADER
);
8378 if (rd
!= NULL
&& !display
&& !output_count
) {
8381 "Route Distinguisher: %s\n",
8384 if (type
== bgp_show_type_dampend_paths
8385 || type
== bgp_show_type_damp_neighbor
)
8386 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8387 safi
, use_json
, json_paths
);
8388 else if (type
== bgp_show_type_flap_statistics
8389 || type
== bgp_show_type_flap_neighbor
)
8390 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8391 safi
, use_json
, json_paths
);
8393 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8404 sprintf(buf2
, "%s/%d",
8405 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8408 vty_out(vty
, "\"%s\": ", buf2
);
8410 vty_out(vty
, ",\"%s\": ", buf2
);
8413 json_object_to_json_string(json_paths
));
8414 json_object_free(json_paths
);
8421 output_count
+= *output_cum
;
8422 *output_cum
= output_count
;
8425 total_count
+= *total_cum
;
8426 *total_cum
= total_count
;
8430 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8434 for (i
= 0; i
< *json_header_depth
; ++i
)
8435 vty_out(vty
, " } ");
8439 /* No route is displayed */
8440 if (output_count
== 0) {
8441 if (type
== bgp_show_type_normal
)
8443 "No BGP prefixes displayed, %ld exist\n",
8447 "\nDisplayed %ld routes and %ld total paths\n",
8448 output_count
, total_count
);
8455 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8456 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8457 enum bgp_show_type type
, void *output_arg
,
8460 struct bgp_node
*rn
, *next
;
8461 unsigned long output_cum
= 0;
8462 unsigned long total_cum
= 0;
8463 unsigned long json_header_depth
= 0;
8466 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8468 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8469 next
= bgp_route_next(rn
);
8470 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8472 if (rn
->info
!= NULL
) {
8473 struct prefix_rd prd
;
8474 char rd
[RD_ADDRSTRLEN
];
8476 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8477 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8478 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8479 output_arg
, use_json
, rd
, next
== NULL
,
8480 &output_cum
, &total_cum
,
8481 &json_header_depth
);
8487 if (output_cum
== 0)
8488 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8492 "\nDisplayed %ld routes and %ld total paths\n",
8493 output_cum
, total_cum
);
8497 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8498 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8500 struct bgp_table
*table
;
8501 unsigned long json_header_depth
= 0;
8504 bgp
= bgp_get_default();
8509 vty_out(vty
, "No BGP process is configured\n");
8511 vty_out(vty
, "{}\n");
8515 table
= bgp
->rib
[afi
][safi
];
8516 /* use MPLS and ENCAP specific shows until they are merged */
8517 if (safi
== SAFI_MPLS_VPN
) {
8518 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8519 output_arg
, use_json
);
8522 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8523 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8524 output_arg
, use_json
,
8527 /* labeled-unicast routes live in the unicast table */
8528 else if (safi
== SAFI_LABELED_UNICAST
)
8529 safi
= SAFI_UNICAST
;
8531 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8532 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8535 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8536 safi_t safi
, uint8_t use_json
)
8538 struct listnode
*node
, *nnode
;
8543 vty_out(vty
, "{\n");
8545 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8548 vty_out(vty
, ",\n");
8552 vty_out(vty
, "\"%s\":",
8553 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8557 vty_out(vty
, "\nInstance %s:\n",
8558 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8562 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8567 vty_out(vty
, "}\n");
8570 /* Header of detailed BGP route information */
8571 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8572 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8573 afi_t afi
, safi_t safi
, json_object
*json
)
8575 struct bgp_info
*ri
;
8578 struct listnode
*node
, *nnode
;
8579 char buf1
[RD_ADDRSTRLEN
];
8580 char buf2
[INET6_ADDRSTRLEN
];
8581 char buf3
[EVPN_ROUTE_STRLEN
];
8582 char prefix_str
[BUFSIZ
];
8587 int no_advertise
= 0;
8590 int has_valid_label
= 0;
8591 mpls_label_t label
= 0;
8592 json_object
*json_adv_to
= NULL
;
8595 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8597 if (has_valid_label
)
8598 label
= label_pton(&rn
->local_label
);
8601 if (has_valid_label
)
8602 json_object_int_add(json
, "localLabel", label
);
8604 json_object_string_add(
8606 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8608 if (safi
== SAFI_EVPN
)
8609 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8610 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8613 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8614 buf3
, sizeof(buf3
)));
8616 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8617 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8618 ? prefix_rd2str(prd
, buf1
,
8621 safi
== SAFI_MPLS_VPN
? ":" : "",
8622 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8626 if (has_valid_label
)
8627 vty_out(vty
, "Local label: %d\n", label
);
8628 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8629 vty_out(vty
, "not allocated\n");
8632 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8634 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8636 if (ri
->extra
&& ri
->extra
->suppress
)
8638 if (ri
->attr
->community
!= NULL
) {
8639 if (community_include(ri
->attr
->community
,
8640 COMMUNITY_NO_ADVERTISE
))
8642 if (community_include(ri
->attr
->community
,
8643 COMMUNITY_NO_EXPORT
))
8645 if (community_include(ri
->attr
->community
,
8646 COMMUNITY_LOCAL_AS
))
8653 vty_out(vty
, "Paths: (%d available", count
);
8655 vty_out(vty
, ", best #%d", best
);
8656 if (safi
== SAFI_UNICAST
)
8657 vty_out(vty
, ", table %s",
8659 == BGP_INSTANCE_TYPE_DEFAULT
)
8660 ? "Default-IP-Routing-Table"
8663 vty_out(vty
, ", no best path");
8666 vty_out(vty
, ", not advertised to any peer");
8668 vty_out(vty
, ", not advertised to EBGP peer");
8670 vty_out(vty
, ", not advertised outside local AS");
8674 ", Advertisements suppressed by an aggregate.");
8675 vty_out(vty
, ")\n");
8678 /* If we are not using addpath then we can display Advertised to and
8680 * show what peers we advertised the bestpath to. If we are using
8682 * though then we must display Advertised to on a path-by-path basis. */
8683 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8684 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8685 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8686 if (json
&& !json_adv_to
)
8687 json_adv_to
= json_object_new_object();
8689 route_vty_out_advertised_to(
8691 " Advertised to non peer-group peers:\n ",
8698 json_object_object_add(json
, "advertisedTo",
8703 vty_out(vty
, " Not advertised to any peer");
8709 /* Display specified route of BGP table. */
8710 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8711 struct bgp_table
*rib
, const char *ip_str
,
8712 afi_t afi
, safi_t safi
,
8713 struct prefix_rd
*prd
, int prefix_check
,
8714 enum bgp_path_type pathtype
,
8720 struct prefix match
;
8721 struct bgp_node
*rn
;
8722 struct bgp_node
*rm
;
8723 struct bgp_info
*ri
;
8724 struct bgp_table
*table
;
8725 json_object
*json
= NULL
;
8726 json_object
*json_paths
= NULL
;
8728 /* Check IP address argument. */
8729 ret
= str2prefix(ip_str
, &match
);
8731 vty_out(vty
, "address is malformed\n");
8735 match
.family
= afi2family(afi
);
8738 json
= json_object_new_object();
8739 json_paths
= json_object_new_array();
8742 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8743 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8744 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8747 if ((table
= rn
->info
) == NULL
)
8752 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8756 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8757 bgp_unlock_node(rm
);
8761 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8763 route_vty_out_detail_header(
8765 (struct prefix_rd
*)&rn
->p
,
8766 AFI_IP
, safi
, json
);
8771 if (pathtype
== BGP_PATH_ALL
8772 || (pathtype
== BGP_PATH_BESTPATH
8773 && CHECK_FLAG(ri
->flags
,
8775 || (pathtype
== BGP_PATH_MULTIPATH
8776 && (CHECK_FLAG(ri
->flags
,
8778 || CHECK_FLAG(ri
->flags
,
8779 BGP_INFO_SELECTED
))))
8780 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8785 bgp_unlock_node(rm
);
8787 } else if (safi
== SAFI_FLOWSPEC
) {
8788 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
8789 &match
, prefix_check
,
8796 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8798 || rn
->p
.prefixlen
== match
.prefixlen
) {
8799 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8801 route_vty_out_detail_header(
8802 vty
, bgp
, rn
, NULL
, afi
,
8808 if (pathtype
== BGP_PATH_ALL
8809 || (pathtype
== BGP_PATH_BESTPATH
8813 || (pathtype
== BGP_PATH_MULTIPATH
8819 BGP_INFO_SELECTED
))))
8820 route_vty_out_detail(
8821 vty
, bgp
, &rn
->p
, ri
,
8822 afi
, safi
, json_paths
);
8826 bgp_unlock_node(rn
);
8832 json_object_object_add(json
, "paths", json_paths
);
8834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8835 json
, JSON_C_TO_STRING_PRETTY
));
8836 json_object_free(json
);
8839 vty_out(vty
, "%% Network not in table\n");
8847 /* Display specified route of Main RIB */
8848 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8849 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8850 int prefix_check
, enum bgp_path_type pathtype
,
8854 bgp
= bgp_get_default();
8857 vty_out(vty
, "No BGP process is configured\n");
8859 vty_out(vty
, "{}\n");
8864 /* labeled-unicast routes live in the unicast table */
8865 if (safi
== SAFI_LABELED_UNICAST
)
8866 safi
= SAFI_UNICAST
;
8868 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8869 afi
, safi
, prd
, prefix_check
, pathtype
,
8873 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8874 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8877 struct lcommunity
*lcom
;
8883 b
= buffer_new(1024);
8884 for (i
= 0; i
< argc
; i
++) {
8886 buffer_putc(b
, ' ');
8888 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8890 buffer_putstr(b
, argv
[i
]->arg
);
8894 buffer_putc(b
, '\0');
8896 str
= buffer_getstr(b
);
8899 lcom
= lcommunity_str2com(str
);
8900 XFREE(MTYPE_TMP
, str
);
8902 vty_out(vty
, "%% Large-community malformed\n");
8906 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8910 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8911 const char *lcom
, afi_t afi
, safi_t safi
,
8914 struct community_list
*list
;
8916 list
= community_list_lookup(bgp_clist
, lcom
,
8917 LARGE_COMMUNITY_LIST_MASTER
);
8919 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8924 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8928 DEFUN (show_ip_bgp_large_community_list
,
8929 show_ip_bgp_large_community_list_cmd
,
8930 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8934 BGP_INSTANCE_HELP_STR
8936 BGP_SAFI_WITH_LABEL_HELP_STR
8937 "Display routes matching the large-community-list\n"
8938 "large-community-list number\n"
8939 "large-community-list name\n"
8943 afi_t afi
= AFI_IP6
;
8944 safi_t safi
= SAFI_UNICAST
;
8947 if (argv_find(argv
, argc
, "ip", &idx
))
8949 if (argv_find(argv
, argc
, "view", &idx
)
8950 || argv_find(argv
, argc
, "vrf", &idx
))
8951 vrf
= argv
[++idx
]->arg
;
8952 if (argv_find(argv
, argc
, "ipv4", &idx
)
8953 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8954 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8955 if (argv_find(argv
, argc
, "unicast", &idx
)
8956 || argv_find(argv
, argc
, "multicast", &idx
))
8957 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8960 int uj
= use_json(argc
, argv
);
8962 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8964 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8968 argv_find(argv
, argc
, "large-community-list", &idx
);
8969 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8972 DEFUN (show_ip_bgp_large_community
,
8973 show_ip_bgp_large_community_cmd
,
8974 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8978 BGP_INSTANCE_HELP_STR
8980 BGP_SAFI_WITH_LABEL_HELP_STR
8981 "Display routes matching the large-communities\n"
8982 "List of large-community numbers\n"
8986 afi_t afi
= AFI_IP6
;
8987 safi_t safi
= SAFI_UNICAST
;
8990 if (argv_find(argv
, argc
, "ip", &idx
))
8992 if (argv_find(argv
, argc
, "view", &idx
)
8993 || argv_find(argv
, argc
, "vrf", &idx
))
8994 vrf
= argv
[++idx
]->arg
;
8995 if (argv_find(argv
, argc
, "ipv4", &idx
)
8996 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8997 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8998 if (argv_find(argv
, argc
, "unicast", &idx
)
8999 || argv_find(argv
, argc
, "multicast", &idx
))
9000 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9003 int uj
= use_json(argc
, argv
);
9005 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9007 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9011 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9012 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9014 return bgp_show(vty
, bgp
, afi
, safi
,
9015 bgp_show_type_lcommunity_all
, NULL
, uj
);
9018 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9022 /* BGP route print out function without JSON */
9025 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9026 <dampening <parameters>\
9031 |community-list <(1-500)|WORD> [exact-match]\
9032 |A.B.C.D/M longer-prefixes\
9033 |X:X::X:X/M longer-prefixes\
9038 BGP_INSTANCE_HELP_STR
9040 BGP_SAFI_WITH_LABEL_HELP_STR
9041 "Display detailed information about dampening\n"
9042 "Display detail of configured dampening parameters\n"
9043 "Display routes matching the route-map\n"
9044 "A route-map to match on\n"
9045 "Display routes conforming to the prefix-list\n"
9046 "Prefix-list name\n"
9047 "Display routes conforming to the filter-list\n"
9048 "Regular expression access list name\n"
9049 "BGP RIB advertisement statistics\n"
9050 "Display routes matching the community-list\n"
9051 "community-list number\n"
9052 "community-list name\n"
9053 "Exact match of the communities\n"
9055 "Display route and more specific routes\n"
9057 "Display route and more specific routes\n")
9059 afi_t afi
= AFI_IP6
;
9060 safi_t safi
= SAFI_UNICAST
;
9061 int exact_match
= 0;
9062 struct bgp
*bgp
= NULL
;
9065 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9070 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9071 if (argv_find(argv
, argc
, "parameters", &idx
))
9072 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9075 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9076 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9077 safi
, bgp_show_type_prefix_list
);
9079 if (argv_find(argv
, argc
, "filter-list", &idx
))
9080 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9081 safi
, bgp_show_type_filter_list
);
9083 if (argv_find(argv
, argc
, "statistics", &idx
))
9084 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9086 if (argv_find(argv
, argc
, "route-map", &idx
))
9087 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9088 safi
, bgp_show_type_route_map
);
9090 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9091 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9092 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9094 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9095 exact_match
, afi
, safi
);
9098 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9099 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9100 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9102 bgp_show_type_prefix_longer
);
9107 /* BGP route print out function with JSON */
9108 DEFUN (show_ip_bgp_json
,
9109 show_ip_bgp_json_cmd
,
9110 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9113 |dampening <flap-statistics|dampened-paths>\
9114 |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
9119 BGP_INSTANCE_HELP_STR
9121 BGP_SAFI_WITH_LABEL_HELP_STR
9122 "Display only routes with non-natural netmasks\n"
9123 "Display detailed information about dampening\n"
9124 "Display flap statistics of routes\n"
9125 "Display paths suppressed due to dampening\n"
9126 "Display routes matching the communities\n"
9128 "Do not send outside local AS (well-known community)\n"
9129 "Do not advertise to any peer (well-known community)\n"
9130 "Do not export to next AS (well-known community)\n"
9131 "Graceful shutdown (well-known community)\n"
9132 "Exact match of the communities\n"
9135 afi_t afi
= AFI_IP6
;
9136 safi_t safi
= SAFI_UNICAST
;
9137 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9138 struct bgp
*bgp
= NULL
;
9140 int idx_community_type
= 0;
9141 int exact_match
= 0;
9143 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9148 int uj
= use_json(argc
, argv
);
9152 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9153 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9156 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9157 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9158 return bgp_show(vty
, bgp
, afi
, safi
,
9159 bgp_show_type_dampend_paths
, NULL
, uj
);
9160 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9161 return bgp_show(vty
, bgp
, afi
, safi
,
9162 bgp_show_type_flap_statistics
, NULL
,
9166 if (argv_find(argv
, argc
, "community", &idx
)) {
9168 /* show a specific community */
9169 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
) ||
9170 argv_find(argv
, argc
, "no-advertise",
9171 &idx_community_type
) ||
9172 argv_find(argv
, argc
, "no-export",
9173 &idx_community_type
) ||
9174 argv_find(argv
, argc
, "graceful-shutdown",
9175 &idx_community_type
) ||
9176 argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9177 if (argv_find(argv
, argc
, "exact-match", &idx
))
9180 return (bgp_show_community(vty
, bgp
,
9181 argv
[idx_community_type
]->arg
,
9182 exact_match
, afi
, safi
, uj
));
9185 /* show all communities */
9186 return (bgp_show(vty
, bgp
, afi
, safi
,
9187 bgp_show_type_community_all
, NULL
,
9192 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9195 DEFUN (show_ip_bgp_route
,
9196 show_ip_bgp_route_cmd
,
9197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9198 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9202 BGP_INSTANCE_HELP_STR
9204 BGP_SAFI_WITH_LABEL_HELP_STR
9205 "Network in the BGP routing table to display\n"
9207 "Network in the BGP routing table to display\n"
9209 "Display only the bestpath\n"
9210 "Display only multipaths\n"
9213 int prefix_check
= 0;
9215 afi_t afi
= AFI_IP6
;
9216 safi_t safi
= SAFI_UNICAST
;
9217 char *prefix
= NULL
;
9218 struct bgp
*bgp
= NULL
;
9219 enum bgp_path_type path_type
;
9220 uint8_t uj
= use_json(argc
, argv
);
9224 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9231 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9235 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9236 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9237 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9239 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9240 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9243 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9244 && afi
!= AFI_IP6
) {
9246 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9249 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9252 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9256 prefix
= argv
[idx
]->arg
;
9258 /* [<bestpath|multipath>] */
9259 if (argv_find(argv
, argc
, "bestpath", &idx
))
9260 path_type
= BGP_PATH_BESTPATH
;
9261 else if (argv_find(argv
, argc
, "multipath", &idx
))
9262 path_type
= BGP_PATH_MULTIPATH
;
9264 path_type
= BGP_PATH_ALL
;
9266 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9270 DEFUN (show_ip_bgp_regexp
,
9271 show_ip_bgp_regexp_cmd
,
9272 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9276 BGP_INSTANCE_HELP_STR
9278 BGP_SAFI_WITH_LABEL_HELP_STR
9279 "Display routes matching the AS path regular expression\n"
9280 "A regular-expression to match the BGP AS paths\n")
9282 afi_t afi
= AFI_IP6
;
9283 safi_t safi
= SAFI_UNICAST
;
9284 struct bgp
*bgp
= NULL
;
9287 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9292 // get index of regex
9293 argv_find(argv
, argc
, "regexp", &idx
);
9296 char *regstr
= argv_concat(argv
, argc
, idx
);
9297 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9298 bgp_show_type_regexp
);
9299 XFREE(MTYPE_TMP
, regstr
);
9303 DEFUN (show_ip_bgp_instance_all
,
9304 show_ip_bgp_instance_all_cmd
,
9305 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9309 BGP_INSTANCE_ALL_HELP_STR
9311 BGP_SAFI_WITH_LABEL_HELP_STR
9315 safi_t safi
= SAFI_UNICAST
;
9316 struct bgp
*bgp
= NULL
;
9319 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9324 int uj
= use_json(argc
, argv
);
9328 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9332 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9333 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9338 regex
= bgp_regcomp(regstr
);
9340 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9344 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9345 bgp_regex_free(regex
);
9349 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9350 const char *prefix_list_str
, afi_t afi
,
9351 safi_t safi
, enum bgp_show_type type
)
9353 struct prefix_list
*plist
;
9355 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9356 if (plist
== NULL
) {
9357 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9362 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9365 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9366 const char *filter
, afi_t afi
, safi_t safi
,
9367 enum bgp_show_type type
)
9369 struct as_list
*as_list
;
9371 as_list
= as_list_lookup(filter
);
9372 if (as_list
== NULL
) {
9373 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9378 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9381 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9382 const char *rmap_str
, afi_t afi
, safi_t safi
,
9383 enum bgp_show_type type
)
9385 struct route_map
*rmap
;
9387 rmap
= route_map_lookup_by_name(rmap_str
);
9389 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9393 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9396 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9397 const char *comstr
, int exact
, afi_t afi
,
9398 safi_t safi
, uint8_t use_json
)
9400 struct community
*com
;
9403 com
= community_str2com(comstr
);
9405 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9409 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9410 (exact
? bgp_show_type_community_exact
9411 : bgp_show_type_community
),
9413 community_free(com
);
9418 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9419 const char *com
, int exact
, afi_t afi
,
9422 struct community_list
*list
;
9424 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9426 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9430 return bgp_show(vty
, bgp
, afi
, safi
,
9431 (exact
? bgp_show_type_community_list_exact
9432 : bgp_show_type_community_list
),
9436 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9437 const char *prefix
, afi_t afi
, safi_t safi
,
9438 enum bgp_show_type type
)
9445 ret
= str2prefix(prefix
, p
);
9447 vty_out(vty
, "%% Malformed Prefix\n");
9451 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9456 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9457 const char *ip_str
, uint8_t use_json
)
9463 /* Get peer sockunion. */
9464 ret
= str2sockunion(ip_str
, &su
);
9466 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9468 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9472 json_object
*json_no
= NULL
;
9473 json_no
= json_object_new_object();
9474 json_object_string_add(
9476 "malformedAddressOrName",
9478 vty_out(vty
, "%s\n",
9479 json_object_to_json_string_ext(
9481 JSON_C_TO_STRING_PRETTY
));
9482 json_object_free(json_no
);
9485 "%% Malformed address or name: %s\n",
9493 /* Peer structure lookup. */
9494 peer
= peer_lookup(bgp
, &su
);
9497 json_object
*json_no
= NULL
;
9498 json_no
= json_object_new_object();
9499 json_object_string_add(json_no
, "warning",
9500 "No such neighbor in this view/vrf");
9501 vty_out(vty
, "%s\n",
9502 json_object_to_json_string_ext(
9503 json_no
, JSON_C_TO_STRING_PRETTY
));
9504 json_object_free(json_no
);
9506 vty_out(vty
, "No such neighbor in this view/vrf\n");
9514 BGP_STATS_MAXBITLEN
= 0,
9518 BGP_STATS_UNAGGREGATEABLE
,
9519 BGP_STATS_MAX_AGGREGATEABLE
,
9520 BGP_STATS_AGGREGATES
,
9522 BGP_STATS_ASPATH_COUNT
,
9523 BGP_STATS_ASPATH_MAXHOPS
,
9524 BGP_STATS_ASPATH_TOTHOPS
,
9525 BGP_STATS_ASPATH_MAXSIZE
,
9526 BGP_STATS_ASPATH_TOTSIZE
,
9527 BGP_STATS_ASN_HIGHEST
,
9531 static const char *table_stats_strs
[] = {
9532 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9533 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9534 [BGP_STATS_RIB
] = "Total Advertisements",
9535 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9536 [BGP_STATS_MAX_AGGREGATEABLE
] =
9537 "Maximum aggregateable prefixes",
9538 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9539 [BGP_STATS_SPACE
] = "Address space advertised",
9540 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9541 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9542 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9543 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9544 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9545 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9546 [BGP_STATS_MAX
] = NULL
,
9549 struct bgp_table_stats
{
9550 struct bgp_table
*table
;
9551 unsigned long long counts
[BGP_STATS_MAX
];
9556 #define TALLY_SIGFIG 100000
9557 static unsigned long
9558 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9560 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9561 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9562 unsigned long ret
= newtot
/ count
;
9564 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9571 static int bgp_table_stats_walker(struct thread
*t
)
9573 struct bgp_node
*rn
;
9574 struct bgp_node
*top
;
9575 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9576 unsigned int space
= 0;
9578 if (!(top
= bgp_table_top(ts
->table
)))
9581 switch (top
->p
.family
) {
9583 space
= IPV4_MAX_BITLEN
;
9586 space
= IPV6_MAX_BITLEN
;
9590 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9592 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9593 struct bgp_info
*ri
;
9594 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9595 unsigned int rinum
= 0;
9603 ts
->counts
[BGP_STATS_PREFIXES
]++;
9604 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9607 ts
->counts
[BGP_STATS_AVGPLEN
]
9608 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9609 ts
->counts
[BGP_STATS_AVGPLEN
],
9613 /* check if the prefix is included by any other announcements */
9614 while (prn
&& !prn
->info
)
9615 prn
= bgp_node_parent_nolock(prn
);
9617 if (prn
== NULL
|| prn
== top
) {
9618 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9619 /* announced address space */
9622 pow(2.0, space
- rn
->p
.prefixlen
);
9623 } else if (prn
->info
)
9624 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9626 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9628 ts
->counts
[BGP_STATS_RIB
]++;
9631 && (CHECK_FLAG(ri
->attr
->flag
,
9633 BGP_ATTR_ATOMIC_AGGREGATE
))))
9634 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9637 if (ri
->attr
&& ri
->attr
->aspath
) {
9639 aspath_count_hops(ri
->attr
->aspath
);
9641 aspath_size(ri
->attr
->aspath
);
9642 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9644 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9646 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9647 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9650 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9651 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9654 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9655 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9657 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9658 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9659 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9661 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9662 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9663 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9666 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9667 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9675 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9678 struct bgp_table_stats ts
;
9681 if (!bgp
->rib
[afi
][safi
]) {
9682 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9687 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9689 /* labeled-unicast routes live in the unicast table */
9690 if (safi
== SAFI_LABELED_UNICAST
)
9691 safi
= SAFI_UNICAST
;
9693 memset(&ts
, 0, sizeof(ts
));
9694 ts
.table
= bgp
->rib
[afi
][safi
];
9695 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9697 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9698 if (!table_stats_strs
[i
])
9703 case BGP_STATS_ASPATH_AVGHOPS
:
9704 case BGP_STATS_ASPATH_AVGSIZE
:
9705 case BGP_STATS_AVGPLEN
:
9706 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9707 vty_out (vty
, "%12.2f",
9708 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9711 case BGP_STATS_ASPATH_TOTHOPS
:
9712 case BGP_STATS_ASPATH_TOTSIZE
:
9713 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9714 vty_out(vty
, "%12.2f",
9716 ? (float)ts
.counts
[i
]
9718 [BGP_STATS_ASPATH_COUNT
]
9721 case BGP_STATS_TOTPLEN
:
9722 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9723 vty_out(vty
, "%12.2f",
9725 ? (float)ts
.counts
[i
]
9727 [BGP_STATS_PREFIXES
]
9730 case BGP_STATS_SPACE
:
9731 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9732 vty_out(vty
, "%12g\n", ts
.total_space
);
9734 if (afi
== AFI_IP6
) {
9735 vty_out(vty
, "%30s: ", "/32 equivalent ");
9736 vty_out(vty
, "%12g\n",
9737 ts
.total_space
* pow(2.0, -128 + 32));
9738 vty_out(vty
, "%30s: ", "/48 equivalent ");
9739 vty_out(vty
, "%12g\n",
9740 ts
.total_space
* pow(2.0, -128 + 48));
9742 vty_out(vty
, "%30s: ", "% announced ");
9743 vty_out(vty
, "%12.2f\n",
9744 ts
.total_space
* 100. * pow(2.0, -32));
9745 vty_out(vty
, "%30s: ", "/8 equivalent ");
9746 vty_out(vty
, "%12.2f\n",
9747 ts
.total_space
* pow(2.0, -32 + 8));
9748 vty_out(vty
, "%30s: ", "/24 equivalent ");
9749 vty_out(vty
, "%12.2f\n",
9750 ts
.total_space
* pow(2.0, -32 + 24));
9754 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9755 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9772 PCOUNT_PFCNT
, /* the figure we display to users */
9776 static const char *pcount_strs
[] = {
9777 [PCOUNT_ADJ_IN
] = "Adj-in",
9778 [PCOUNT_DAMPED
] = "Damped",
9779 [PCOUNT_REMOVED
] = "Removed",
9780 [PCOUNT_HISTORY
] = "History",
9781 [PCOUNT_STALE
] = "Stale",
9782 [PCOUNT_VALID
] = "Valid",
9783 [PCOUNT_ALL
] = "All RIB",
9784 [PCOUNT_COUNTED
] = "PfxCt counted",
9785 [PCOUNT_PFCNT
] = "Useable",
9786 [PCOUNT_MAX
] = NULL
,
9789 struct peer_pcounts
{
9790 unsigned int count
[PCOUNT_MAX
];
9791 const struct peer
*peer
;
9792 const struct bgp_table
*table
;
9795 static int bgp_peer_count_walker(struct thread
*t
)
9797 struct bgp_node
*rn
;
9798 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9799 const struct peer
*peer
= pc
->peer
;
9801 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9802 struct bgp_adj_in
*ain
;
9803 struct bgp_info
*ri
;
9805 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9806 if (ain
->peer
== peer
)
9807 pc
->count
[PCOUNT_ADJ_IN
]++;
9809 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9810 char buf
[SU_ADDRSTRLEN
];
9812 if (ri
->peer
!= peer
)
9815 pc
->count
[PCOUNT_ALL
]++;
9817 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9818 pc
->count
[PCOUNT_DAMPED
]++;
9819 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9820 pc
->count
[PCOUNT_HISTORY
]++;
9821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9822 pc
->count
[PCOUNT_REMOVED
]++;
9823 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9824 pc
->count
[PCOUNT_STALE
]++;
9825 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9826 pc
->count
[PCOUNT_VALID
]++;
9827 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9828 pc
->count
[PCOUNT_PFCNT
]++;
9830 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9831 pc
->count
[PCOUNT_COUNTED
]++;
9832 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9834 "%s [pcount] %s/%d is counted but flags 0x%x",
9836 inet_ntop(rn
->p
.family
,
9837 &rn
->p
.u
.prefix
, buf
,
9839 rn
->p
.prefixlen
, ri
->flags
);
9841 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9843 "%s [pcount] %s/%d not counted but flags 0x%x",
9845 inet_ntop(rn
->p
.family
,
9846 &rn
->p
.u
.prefix
, buf
,
9848 rn
->p
.prefixlen
, ri
->flags
);
9855 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9856 safi_t safi
, uint8_t use_json
)
9858 struct peer_pcounts pcounts
= {.peer
= peer
};
9860 json_object
*json
= NULL
;
9861 json_object
*json_loop
= NULL
;
9864 json
= json_object_new_object();
9865 json_loop
= json_object_new_object();
9868 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9869 || !peer
->bgp
->rib
[afi
][safi
]) {
9871 json_object_string_add(
9873 "No such neighbor or address family");
9874 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9875 json_object_free(json
);
9877 vty_out(vty
, "%% No such neighbor or address family\n");
9882 memset(&pcounts
, 0, sizeof(pcounts
));
9883 pcounts
.peer
= peer
;
9884 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9886 /* in-place call via thread subsystem so as to record execution time
9887 * stats for the thread-walk (i.e. ensure this can't be blamed on
9888 * on just vty_read()).
9890 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9893 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9894 json_object_string_add(json
, "multiProtocol",
9895 afi_safi_print(afi
, safi
));
9896 json_object_int_add(json
, "pfxCounter",
9897 peer
->pcount
[afi
][safi
]);
9899 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9900 json_object_int_add(json_loop
, pcount_strs
[i
],
9903 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9905 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9906 json_object_string_add(json
, "pfxctDriftFor",
9908 json_object_string_add(
9909 json
, "recommended",
9910 "Please report this bug, with the above command output");
9912 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9913 json
, JSON_C_TO_STRING_PRETTY
));
9914 json_object_free(json
);
9918 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9919 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9920 peer
->hostname
, peer
->host
,
9921 afi_safi_print(afi
, safi
));
9923 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9924 afi_safi_print(afi
, safi
));
9927 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9928 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9930 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9931 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9934 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9935 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9937 "Please report this bug, with the above command output\n");
9944 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9945 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9946 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9947 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9951 BGP_INSTANCE_HELP_STR
9954 "Detailed information on TCP and BGP neighbor connections\n"
9955 "Neighbor to display information about\n"
9956 "Neighbor to display information about\n"
9957 "Neighbor on BGP configured interface\n"
9958 "Display detailed prefix count information\n"
9961 afi_t afi
= AFI_IP6
;
9962 safi_t safi
= SAFI_UNICAST
;
9965 struct bgp
*bgp
= NULL
;
9967 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9972 int uj
= use_json(argc
, argv
);
9976 argv_find(argv
, argc
, "neighbors", &idx
);
9977 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9981 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9984 #ifdef KEEP_OLD_VPN_COMMANDS
9985 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9986 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9987 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9992 "Display information about all VPNv4 NLRIs\n"
9993 "Detailed information on TCP and BGP neighbor connections\n"
9994 "Neighbor to display information about\n"
9995 "Neighbor to display information about\n"
9996 "Neighbor on BGP configured interface\n"
9997 "Display detailed prefix count information\n"
10002 uint8_t uj
= use_json(argc
, argv
);
10004 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10006 return CMD_WARNING
;
10008 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10011 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10012 show_ip_bgp_vpn_all_route_prefix_cmd
,
10013 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10018 "Display information about all VPNv4 NLRIs\n"
10019 "Network in the BGP routing table to display\n"
10020 "Network in the BGP routing table to display\n"
10024 char *network
= NULL
;
10025 struct bgp
*bgp
= bgp_get_default();
10027 vty_out(vty
, "Can't find default instance\n");
10028 return CMD_WARNING
;
10031 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10032 network
= argv
[idx
]->arg
;
10033 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10034 network
= argv
[idx
]->arg
;
10036 vty_out(vty
, "Unable to figure out Network\n");
10037 return CMD_WARNING
;
10040 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10041 BGP_PATH_ALL
, use_json(argc
, argv
));
10043 #endif /* KEEP_OLD_VPN_COMMANDS */
10045 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10046 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10047 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10053 "Display information about all EVPN NLRIs\n"
10054 "Network in the BGP routing table to display\n"
10055 "Network in the BGP routing table to display\n"
10059 char *network
= NULL
;
10061 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10062 network
= argv
[idx
]->arg
;
10063 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10064 network
= argv
[idx
]->arg
;
10066 vty_out(vty
, "Unable to figure out Network\n");
10067 return CMD_WARNING
;
10069 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10070 BGP_PATH_ALL
, use_json(argc
, argv
));
10073 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10074 safi_t safi
, enum bgp_show_adj_route_type type
,
10075 const char *rmap_name
, uint8_t use_json
,
10078 struct bgp_table
*table
;
10079 struct bgp_adj_in
*ain
;
10080 struct bgp_adj_out
*adj
;
10081 unsigned long output_count
;
10082 unsigned long filtered_count
;
10083 struct bgp_node
*rn
;
10089 struct update_subgroup
*subgrp
;
10090 json_object
*json_scode
= NULL
;
10091 json_object
*json_ocode
= NULL
;
10092 json_object
*json_ar
= NULL
;
10093 struct peer_af
*paf
;
10094 bool route_filtered
;
10097 json_scode
= json_object_new_object();
10098 json_ocode
= json_object_new_object();
10099 json_ar
= json_object_new_object();
10101 json_object_string_add(json_scode
, "suppressed", "s");
10102 json_object_string_add(json_scode
, "damped", "d");
10103 json_object_string_add(json_scode
, "history", "h");
10104 json_object_string_add(json_scode
, "valid", "*");
10105 json_object_string_add(json_scode
, "best", ">");
10106 json_object_string_add(json_scode
, "multipath", "=");
10107 json_object_string_add(json_scode
, "internal", "i");
10108 json_object_string_add(json_scode
, "ribFailure", "r");
10109 json_object_string_add(json_scode
, "stale", "S");
10110 json_object_string_add(json_scode
, "removed", "R");
10112 json_object_string_add(json_ocode
, "igp", "i");
10113 json_object_string_add(json_ocode
, "egp", "e");
10114 json_object_string_add(json_ocode
, "incomplete", "?");
10121 json_object_string_add(json
, "alert", "no BGP");
10122 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10123 json_object_free(json
);
10125 vty_out(vty
, "%% No bgp\n");
10129 table
= bgp
->rib
[afi
][safi
];
10131 output_count
= filtered_count
= 0;
10132 subgrp
= peer_subgroup(peer
, afi
, safi
);
10134 if (type
== bgp_show_adj_route_advertised
&& subgrp
10135 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10137 json_object_int_add(json
, "bgpTableVersion",
10139 json_object_string_add(json
, "bgpLocalRouterId",
10140 inet_ntoa(bgp
->router_id
));
10141 json_object_object_add(json
, "bgpStatusCodes",
10143 json_object_object_add(json
, "bgpOriginCodes",
10145 json_object_string_add(
10146 json
, "bgpOriginatingDefaultNetwork",
10147 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10149 vty_out(vty
, "BGP table version is %" PRIu64
10150 ", local router ID is %s, vrf id ",
10151 table
->version
, inet_ntoa(bgp
->router_id
));
10152 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10153 vty_out(vty
, "%s", VRFID_NONE_STR
);
10155 vty_out(vty
, "%u", bgp
->vrf_id
);
10156 vty_out(vty
, "\n");
10157 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10158 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10159 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10161 vty_out(vty
, "Originating default network %s\n\n",
10162 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10167 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10168 if (type
== bgp_show_adj_route_received
10169 || type
== bgp_show_adj_route_filtered
) {
10170 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10171 if (ain
->peer
!= peer
|| !ain
->attr
)
10176 json_object_int_add(
10177 json
, "bgpTableVersion",
10179 json_object_string_add(
10181 "bgpLocalRouterId",
10184 json_object_object_add(
10185 json
, "bgpStatusCodes",
10187 json_object_object_add(
10188 json
, "bgpOriginCodes",
10192 "BGP table version is 0, local router ID is %s, vrf id ",
10195 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10201 vty_out(vty
, "\n");
10203 BGP_SHOW_SCODE_HEADER
);
10205 BGP_SHOW_NCODE_HEADER
);
10207 BGP_SHOW_OCODE_HEADER
);
10213 vty_out(vty
, BGP_SHOW_HEADER
);
10217 bgp_attr_dup(&attr
, ain
->attr
);
10218 route_filtered
= false;
10220 /* Filter prefix using distribute list,
10221 * filter list or prefix list
10223 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10224 safi
)) == FILTER_DENY
)
10225 route_filtered
= true;
10227 /* Filter prefix using route-map */
10228 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10229 afi
, safi
, rmap_name
);
10231 if (type
== bgp_show_adj_route_filtered
&&
10232 !route_filtered
&& ret
!= RMAP_DENY
) {
10233 bgp_attr_undup(&attr
, ain
->attr
);
10237 if (type
== bgp_show_adj_route_received
&&
10238 (route_filtered
|| ret
== RMAP_DENY
))
10241 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10242 use_json
, json_ar
);
10243 bgp_attr_undup(&attr
, ain
->attr
);
10246 } else if (type
== bgp_show_adj_route_advertised
) {
10247 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10248 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10249 if (paf
->peer
!= peer
|| !adj
->attr
)
10254 json_object_int_add(
10258 json_object_string_add(
10260 "bgpLocalRouterId",
10263 json_object_object_add(
10267 json_object_object_add(
10273 "BGP table version is %" PRIu64
10274 ", local router ID is %s, vrf id ",
10287 vty_out(vty
, "\n");
10289 BGP_SHOW_SCODE_HEADER
);
10291 BGP_SHOW_NCODE_HEADER
);
10293 BGP_SHOW_OCODE_HEADER
);
10304 bgp_attr_dup(&attr
, adj
->attr
);
10305 ret
= bgp_output_modifier(
10306 peer
, &rn
->p
, &attr
, afi
, safi
,
10309 if (ret
!= RMAP_DENY
) {
10310 route_vty_out_tmp(vty
, &rn
->p
,
10319 bgp_attr_undup(&attr
, adj
->attr
);
10325 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10326 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10327 json_object_int_add(json
, "filteredPrefixCounter",
10330 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10331 json
, JSON_C_TO_STRING_PRETTY
));
10332 json_object_free(json
);
10333 } else if (output_count
> 0) {
10334 if (filtered_count
> 0)
10336 "\nTotal number of prefixes %ld (%ld filtered)\n",
10337 output_count
, filtered_count
);
10339 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10344 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10345 safi_t safi
, enum bgp_show_adj_route_type type
,
10346 const char *rmap_name
, uint8_t use_json
)
10348 json_object
*json
= NULL
;
10351 json
= json_object_new_object();
10353 /* labeled-unicast routes live in the unicast table */
10354 if (safi
== SAFI_LABELED_UNICAST
)
10355 safi
= SAFI_UNICAST
;
10357 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10359 json_object_string_add(
10361 "No such neighbor or address family");
10362 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10363 json_object_free(json
);
10365 vty_out(vty
, "%% No such neighbor or address family\n");
10367 return CMD_WARNING
;
10370 if ((type
== bgp_show_adj_route_received
10371 || type
== bgp_show_adj_route_filtered
)
10372 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10373 PEER_FLAG_SOFT_RECONFIG
)) {
10375 json_object_string_add(
10377 "Inbound soft reconfiguration not enabled");
10378 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10379 json_object_free(json
);
10382 "%% Inbound soft reconfiguration not enabled\n");
10384 return CMD_WARNING
;
10387 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10389 return CMD_SUCCESS
;
10392 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10393 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10394 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10395 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10399 BGP_INSTANCE_HELP_STR
10401 BGP_SAFI_WITH_LABEL_HELP_STR
10402 "Detailed information on TCP and BGP neighbor connections\n"
10403 "Neighbor to display information about\n"
10404 "Neighbor to display information about\n"
10405 "Neighbor on BGP configured interface\n"
10406 "Display the routes advertised to a BGP neighbor\n"
10407 "Display the received routes from neighbor\n"
10408 "Display the filtered routes received from neighbor\n"
10409 "Route-map to modify the attributes\n"
10410 "Name of the route map\n"
10413 afi_t afi
= AFI_IP6
;
10414 safi_t safi
= SAFI_UNICAST
;
10415 char *rmap_name
= NULL
;
10416 char *peerstr
= NULL
;
10417 struct bgp
*bgp
= NULL
;
10419 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10425 return CMD_WARNING
;
10427 int uj
= use_json(argc
, argv
);
10432 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10433 argv_find(argv
, argc
, "neighbors", &idx
);
10434 peerstr
= argv
[++idx
]->arg
;
10436 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10438 return CMD_WARNING
;
10440 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10441 type
= bgp_show_adj_route_advertised
;
10442 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10443 type
= bgp_show_adj_route_received
;
10444 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10445 type
= bgp_show_adj_route_filtered
;
10447 if (argv_find(argv
, argc
, "route-map", &idx
))
10448 rmap_name
= argv
[++idx
]->arg
;
10450 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10453 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10454 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10455 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10461 "Address Family modifier\n"
10462 "Detailed information on TCP and BGP neighbor connections\n"
10463 "Neighbor to display information about\n"
10464 "Neighbor to display information about\n"
10465 "Neighbor on BGP configured interface\n"
10466 "Display information received from a BGP neighbor\n"
10467 "Display the prefixlist filter\n"
10470 afi_t afi
= AFI_IP6
;
10471 safi_t safi
= SAFI_UNICAST
;
10472 char *peerstr
= NULL
;
10475 union sockunion su
;
10481 /* show [ip] bgp */
10482 if (argv_find(argv
, argc
, "ip", &idx
))
10484 /* [<ipv4|ipv6> [unicast]] */
10485 if (argv_find(argv
, argc
, "ipv4", &idx
))
10487 if (argv_find(argv
, argc
, "ipv6", &idx
))
10489 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10490 argv_find(argv
, argc
, "neighbors", &idx
);
10491 peerstr
= argv
[++idx
]->arg
;
10493 uint8_t uj
= use_json(argc
, argv
);
10495 ret
= str2sockunion(peerstr
, &su
);
10497 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10500 vty_out(vty
, "{}\n");
10503 "%% Malformed address or name: %s\n",
10505 return CMD_WARNING
;
10508 peer
= peer_lookup(NULL
, &su
);
10511 vty_out(vty
, "{}\n");
10513 vty_out(vty
, "No peer\n");
10514 return CMD_WARNING
;
10518 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10519 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10522 vty_out(vty
, "Address Family: %s\n",
10523 afi_safi_print(afi
, safi
));
10524 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10527 vty_out(vty
, "{}\n");
10529 vty_out(vty
, "No functional output\n");
10532 return CMD_SUCCESS
;
10535 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10536 afi_t afi
, safi_t safi
,
10537 enum bgp_show_type type
, uint8_t use_json
)
10539 /* labeled-unicast routes live in the unicast table */
10540 if (safi
== SAFI_LABELED_UNICAST
)
10541 safi
= SAFI_UNICAST
;
10543 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10545 json_object
*json_no
= NULL
;
10546 json_no
= json_object_new_object();
10547 json_object_string_add(
10548 json_no
, "warning",
10549 "No such neighbor or address family");
10550 vty_out(vty
, "%s\n",
10551 json_object_to_json_string(json_no
));
10552 json_object_free(json_no
);
10554 vty_out(vty
, "%% No such neighbor or address family\n");
10555 return CMD_WARNING
;
10558 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10561 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10562 show_ip_bgp_flowspec_routes_detailed_cmd
,
10563 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10567 BGP_INSTANCE_HELP_STR
10570 "Detailed information on flowspec entries\n"
10573 afi_t afi
= AFI_IP
;
10574 safi_t safi
= SAFI_UNICAST
;
10575 struct bgp
*bgp
= NULL
;
10578 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10581 return CMD_WARNING
;
10583 return bgp_show(vty
, bgp
, afi
, safi
,
10584 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10587 DEFUN (show_ip_bgp_neighbor_routes
,
10588 show_ip_bgp_neighbor_routes_cmd
,
10589 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10590 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10594 BGP_INSTANCE_HELP_STR
10596 BGP_SAFI_WITH_LABEL_HELP_STR
10597 "Detailed information on TCP and BGP neighbor connections\n"
10598 "Neighbor to display information about\n"
10599 "Neighbor to display information about\n"
10600 "Neighbor on BGP configured interface\n"
10601 "Display flap statistics of the routes learned from neighbor\n"
10602 "Display the dampened routes received from neighbor\n"
10603 "Display routes learned from neighbor\n"
10606 char *peerstr
= NULL
;
10607 struct bgp
*bgp
= NULL
;
10608 afi_t afi
= AFI_IP6
;
10609 safi_t safi
= SAFI_UNICAST
;
10611 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10615 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10618 return CMD_WARNING
;
10620 int uj
= use_json(argc
, argv
);
10624 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10625 argv_find(argv
, argc
, "neighbors", &idx
);
10626 peerstr
= argv
[++idx
]->arg
;
10628 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10630 return CMD_WARNING
;
10632 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10633 sh_type
= bgp_show_type_flap_neighbor
;
10634 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10635 sh_type
= bgp_show_type_damp_neighbor
;
10636 else if (argv_find(argv
, argc
, "routes", &idx
))
10637 sh_type
= bgp_show_type_neighbor
;
10639 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10642 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10644 struct bgp_distance
{
10645 /* Distance value for the IP source prefix. */
10648 /* Name of the access-list to be matched. */
10652 DEFUN (show_bgp_afi_vpn_rd_route
,
10653 show_bgp_afi_vpn_rd_route_cmd
,
10654 "show bgp "BGP_AFI_CMD_STR
" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
10658 "Address Family modifier\n"
10659 "Display information for a route distinguisher\n"
10660 "Route Distinguisher\n"
10661 "Network in the BGP routing table to display\n"
10662 "Network in the BGP routing table to display\n"
10666 struct prefix_rd prd
;
10667 afi_t afi
= AFI_MAX
;
10670 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10671 vty_out(vty
, "%% Malformed Address Family\n");
10672 return CMD_WARNING
;
10675 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10677 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10678 return CMD_WARNING
;
10681 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10682 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10685 static struct bgp_distance
*bgp_distance_new(void)
10687 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10690 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10692 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10695 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10696 const char *ip_str
, const char *access_list_str
)
10703 struct bgp_node
*rn
;
10704 struct bgp_distance
*bdistance
;
10706 afi
= bgp_node_afi(vty
);
10707 safi
= bgp_node_safi(vty
);
10709 ret
= str2prefix(ip_str
, &p
);
10711 vty_out(vty
, "Malformed prefix\n");
10712 return CMD_WARNING_CONFIG_FAILED
;
10715 distance
= atoi(distance_str
);
10717 /* Get BGP distance node. */
10718 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10720 bdistance
= rn
->info
;
10721 bgp_unlock_node(rn
);
10723 bdistance
= bgp_distance_new();
10724 rn
->info
= bdistance
;
10727 /* Set distance value. */
10728 bdistance
->distance
= distance
;
10730 /* Reset access-list configuration. */
10731 if (bdistance
->access_list
) {
10732 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10733 bdistance
->access_list
= NULL
;
10735 if (access_list_str
)
10736 bdistance
->access_list
=
10737 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10739 return CMD_SUCCESS
;
10742 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10743 const char *ip_str
, const char *access_list_str
)
10750 struct bgp_node
*rn
;
10751 struct bgp_distance
*bdistance
;
10753 afi
= bgp_node_afi(vty
);
10754 safi
= bgp_node_safi(vty
);
10756 ret
= str2prefix(ip_str
, &p
);
10758 vty_out(vty
, "Malformed prefix\n");
10759 return CMD_WARNING_CONFIG_FAILED
;
10762 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10763 (struct prefix
*)&p
);
10765 vty_out(vty
, "Can't find specified prefix\n");
10766 return CMD_WARNING_CONFIG_FAILED
;
10769 bdistance
= rn
->info
;
10770 distance
= atoi(distance_str
);
10772 if (bdistance
->distance
!= distance
) {
10773 vty_out(vty
, "Distance does not match configured\n");
10774 return CMD_WARNING_CONFIG_FAILED
;
10777 if (bdistance
->access_list
)
10778 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10779 bgp_distance_free(bdistance
);
10782 bgp_unlock_node(rn
);
10783 bgp_unlock_node(rn
);
10785 return CMD_SUCCESS
;
10788 /* Apply BGP information to distance method. */
10789 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10790 safi_t safi
, struct bgp
*bgp
)
10792 struct bgp_node
*rn
;
10795 struct bgp_distance
*bdistance
;
10796 struct access_list
*alist
;
10797 struct bgp_static
*bgp_static
;
10802 peer
= rinfo
->peer
;
10804 /* Check source address. */
10805 sockunion2hostprefix(&peer
->su
, &q
);
10806 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10808 bdistance
= rn
->info
;
10809 bgp_unlock_node(rn
);
10811 if (bdistance
->access_list
) {
10812 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10814 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10815 return bdistance
->distance
;
10817 return bdistance
->distance
;
10820 /* Backdoor check. */
10821 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10823 bgp_static
= rn
->info
;
10824 bgp_unlock_node(rn
);
10826 if (bgp_static
->backdoor
) {
10827 if (bgp
->distance_local
[afi
][safi
])
10828 return bgp
->distance_local
[afi
][safi
];
10830 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10834 if (peer
->sort
== BGP_PEER_EBGP
) {
10835 if (bgp
->distance_ebgp
[afi
][safi
])
10836 return bgp
->distance_ebgp
[afi
][safi
];
10837 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10839 if (bgp
->distance_ibgp
[afi
][safi
])
10840 return bgp
->distance_ibgp
[afi
][safi
];
10841 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10845 DEFUN (bgp_distance
,
10847 "distance bgp (1-255) (1-255) (1-255)",
10848 "Define an administrative distance\n"
10850 "Distance for routes external to the AS\n"
10851 "Distance for routes internal to the AS\n"
10852 "Distance for local routes\n")
10854 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10855 int idx_number
= 2;
10856 int idx_number_2
= 3;
10857 int idx_number_3
= 4;
10861 afi
= bgp_node_afi(vty
);
10862 safi
= bgp_node_safi(vty
);
10864 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10865 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10866 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10867 return CMD_SUCCESS
;
10870 DEFUN (no_bgp_distance
,
10871 no_bgp_distance_cmd
,
10872 "no distance bgp [(1-255) (1-255) (1-255)]",
10874 "Define an administrative distance\n"
10876 "Distance for routes external to the AS\n"
10877 "Distance for routes internal to the AS\n"
10878 "Distance for local routes\n")
10880 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10884 afi
= bgp_node_afi(vty
);
10885 safi
= bgp_node_safi(vty
);
10887 bgp
->distance_ebgp
[afi
][safi
] = 0;
10888 bgp
->distance_ibgp
[afi
][safi
] = 0;
10889 bgp
->distance_local
[afi
][safi
] = 0;
10890 return CMD_SUCCESS
;
10894 DEFUN (bgp_distance_source
,
10895 bgp_distance_source_cmd
,
10896 "distance (1-255) A.B.C.D/M",
10897 "Define an administrative distance\n"
10898 "Administrative distance\n"
10899 "IP source prefix\n")
10901 int idx_number
= 1;
10902 int idx_ipv4_prefixlen
= 2;
10903 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10904 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10905 return CMD_SUCCESS
;
10908 DEFUN (no_bgp_distance_source
,
10909 no_bgp_distance_source_cmd
,
10910 "no distance (1-255) A.B.C.D/M",
10912 "Define an administrative distance\n"
10913 "Administrative distance\n"
10914 "IP source prefix\n")
10916 int idx_number
= 2;
10917 int idx_ipv4_prefixlen
= 3;
10918 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10919 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10920 return CMD_SUCCESS
;
10923 DEFUN (bgp_distance_source_access_list
,
10924 bgp_distance_source_access_list_cmd
,
10925 "distance (1-255) A.B.C.D/M WORD",
10926 "Define an administrative distance\n"
10927 "Administrative distance\n"
10928 "IP source prefix\n"
10929 "Access list name\n")
10931 int idx_number
= 1;
10932 int idx_ipv4_prefixlen
= 2;
10934 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10935 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10936 return CMD_SUCCESS
;
10939 DEFUN (no_bgp_distance_source_access_list
,
10940 no_bgp_distance_source_access_list_cmd
,
10941 "no distance (1-255) A.B.C.D/M WORD",
10943 "Define an administrative distance\n"
10944 "Administrative distance\n"
10945 "IP source prefix\n"
10946 "Access list name\n")
10948 int idx_number
= 2;
10949 int idx_ipv4_prefixlen
= 3;
10951 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10952 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10953 return CMD_SUCCESS
;
10956 DEFUN (ipv6_bgp_distance_source
,
10957 ipv6_bgp_distance_source_cmd
,
10958 "distance (1-255) X:X::X:X/M",
10959 "Define an administrative distance\n"
10960 "Administrative distance\n"
10961 "IP source prefix\n")
10963 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10964 return CMD_SUCCESS
;
10967 DEFUN (no_ipv6_bgp_distance_source
,
10968 no_ipv6_bgp_distance_source_cmd
,
10969 "no distance (1-255) X:X::X:X/M",
10971 "Define an administrative distance\n"
10972 "Administrative distance\n"
10973 "IP source prefix\n")
10975 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10976 return CMD_SUCCESS
;
10979 DEFUN (ipv6_bgp_distance_source_access_list
,
10980 ipv6_bgp_distance_source_access_list_cmd
,
10981 "distance (1-255) X:X::X:X/M WORD",
10982 "Define an administrative distance\n"
10983 "Administrative distance\n"
10984 "IP source prefix\n"
10985 "Access list name\n")
10987 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10988 return CMD_SUCCESS
;
10991 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10992 no_ipv6_bgp_distance_source_access_list_cmd
,
10993 "no distance (1-255) X:X::X:X/M WORD",
10995 "Define an administrative distance\n"
10996 "Administrative distance\n"
10997 "IP source prefix\n"
10998 "Access list name\n")
11000 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11001 return CMD_SUCCESS
;
11004 DEFUN (bgp_damp_set
,
11006 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11007 "BGP Specific commands\n"
11008 "Enable route-flap dampening\n"
11009 "Half-life time for the penalty\n"
11010 "Value to start reusing a route\n"
11011 "Value to start suppressing a route\n"
11012 "Maximum duration to suppress a stable route\n")
11014 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11015 int idx_half_life
= 2;
11017 int idx_suppress
= 4;
11018 int idx_max_suppress
= 5;
11019 int half
= DEFAULT_HALF_LIFE
* 60;
11020 int reuse
= DEFAULT_REUSE
;
11021 int suppress
= DEFAULT_SUPPRESS
;
11022 int max
= 4 * half
;
11025 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11026 reuse
= atoi(argv
[idx_reuse
]->arg
);
11027 suppress
= atoi(argv
[idx_suppress
]->arg
);
11028 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11029 } else if (argc
== 3) {
11030 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11034 if (suppress
< reuse
) {
11036 "Suppress value cannot be less than reuse value \n");
11040 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11041 reuse
, suppress
, max
);
11044 DEFUN (bgp_damp_unset
,
11045 bgp_damp_unset_cmd
,
11046 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11048 "BGP Specific commands\n"
11049 "Enable route-flap dampening\n"
11050 "Half-life time for the penalty\n"
11051 "Value to start reusing a route\n"
11052 "Value to start suppressing a route\n"
11053 "Maximum duration to suppress a stable route\n")
11055 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11056 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11059 /* Display specified route of BGP table. */
11060 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11061 const char *ip_str
, afi_t afi
, safi_t safi
,
11062 struct prefix_rd
*prd
, int prefix_check
)
11065 struct prefix match
;
11066 struct bgp_node
*rn
;
11067 struct bgp_node
*rm
;
11068 struct bgp_info
*ri
;
11069 struct bgp_info
*ri_temp
;
11071 struct bgp_table
*table
;
11073 /* BGP structure lookup. */
11075 bgp
= bgp_lookup_by_name(view_name
);
11077 vty_out(vty
, "%% Can't find BGP instance %s\n",
11079 return CMD_WARNING
;
11082 bgp
= bgp_get_default();
11084 vty_out(vty
, "%% No BGP process is configured\n");
11085 return CMD_WARNING
;
11089 /* Check IP address argument. */
11090 ret
= str2prefix(ip_str
, &match
);
11092 vty_out(vty
, "%% address is malformed\n");
11093 return CMD_WARNING
;
11096 match
.family
= afi2family(afi
);
11098 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11099 || (safi
== SAFI_EVPN
)) {
11100 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11101 rn
= bgp_route_next(rn
)) {
11102 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11104 if ((table
= rn
->info
) == NULL
)
11106 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11110 || rm
->p
.prefixlen
== match
.prefixlen
) {
11113 if (ri
->extra
&& ri
->extra
->damp_info
) {
11114 ri_temp
= ri
->next
;
11115 bgp_damp_info_free(
11116 ri
->extra
->damp_info
,
11124 bgp_unlock_node(rm
);
11127 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11130 || rn
->p
.prefixlen
== match
.prefixlen
) {
11133 if (ri
->extra
&& ri
->extra
->damp_info
) {
11134 ri_temp
= ri
->next
;
11135 bgp_damp_info_free(
11136 ri
->extra
->damp_info
,
11144 bgp_unlock_node(rn
);
11148 return CMD_SUCCESS
;
11151 DEFUN (clear_ip_bgp_dampening
,
11152 clear_ip_bgp_dampening_cmd
,
11153 "clear ip bgp dampening",
11157 "Clear route flap dampening information\n")
11159 bgp_damp_info_clean();
11160 return CMD_SUCCESS
;
11163 DEFUN (clear_ip_bgp_dampening_prefix
,
11164 clear_ip_bgp_dampening_prefix_cmd
,
11165 "clear ip bgp dampening A.B.C.D/M",
11169 "Clear route flap dampening information\n"
11172 int idx_ipv4_prefixlen
= 4;
11173 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11174 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11177 DEFUN (clear_ip_bgp_dampening_address
,
11178 clear_ip_bgp_dampening_address_cmd
,
11179 "clear ip bgp dampening A.B.C.D",
11183 "Clear route flap dampening information\n"
11184 "Network to clear damping information\n")
11187 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11188 SAFI_UNICAST
, NULL
, 0);
11191 DEFUN (clear_ip_bgp_dampening_address_mask
,
11192 clear_ip_bgp_dampening_address_mask_cmd
,
11193 "clear ip bgp dampening A.B.C.D A.B.C.D",
11197 "Clear route flap dampening information\n"
11198 "Network to clear damping information\n"
11202 int idx_ipv4_2
= 5;
11204 char prefix_str
[BUFSIZ
];
11206 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11209 vty_out(vty
, "%% Inconsistent address and mask\n");
11210 return CMD_WARNING
;
11213 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11217 /* also used for encap safi */
11218 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11219 afi_t afi
, safi_t safi
)
11221 struct bgp_node
*prn
;
11222 struct bgp_node
*rn
;
11223 struct bgp_table
*table
;
11225 struct prefix_rd
*prd
;
11226 struct bgp_static
*bgp_static
;
11227 mpls_label_t label
;
11228 char buf
[SU_ADDRSTRLEN
];
11229 char rdbuf
[RD_ADDRSTRLEN
];
11231 /* Network configuration. */
11232 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11233 prn
= bgp_route_next(prn
)) {
11234 if ((table
= prn
->info
) == NULL
)
11237 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11238 if ((bgp_static
= rn
->info
) == NULL
)
11242 prd
= (struct prefix_rd
*)&prn
->p
;
11244 /* "network" configuration display. */
11245 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11246 label
= decode_label(&bgp_static
->label
);
11248 vty_out(vty
, " network %s/%d rd %s",
11249 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11251 p
->prefixlen
, rdbuf
);
11252 if (safi
== SAFI_MPLS_VPN
)
11253 vty_out(vty
, " label %u", label
);
11255 if (bgp_static
->rmap
.name
)
11256 vty_out(vty
, " route-map %s",
11257 bgp_static
->rmap
.name
);
11259 if (bgp_static
->backdoor
)
11260 vty_out(vty
, " backdoor");
11262 vty_out(vty
, "\n");
11267 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11268 afi_t afi
, safi_t safi
)
11270 struct bgp_node
*prn
;
11271 struct bgp_node
*rn
;
11272 struct bgp_table
*table
;
11274 struct prefix_rd
*prd
;
11275 struct bgp_static
*bgp_static
;
11276 char buf
[PREFIX_STRLEN
* 2];
11277 char buf2
[SU_ADDRSTRLEN
];
11278 char rdbuf
[RD_ADDRSTRLEN
];
11280 /* Network configuration. */
11281 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11282 prn
= bgp_route_next(prn
)) {
11283 if ((table
= prn
->info
) == NULL
)
11286 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11287 if ((bgp_static
= rn
->info
) == NULL
)
11290 char *macrouter
= NULL
;
11293 if (bgp_static
->router_mac
)
11294 macrouter
= prefix_mac2str(
11295 bgp_static
->router_mac
, NULL
, 0);
11296 if (bgp_static
->eth_s_id
)
11297 esi
= esi2str(bgp_static
->eth_s_id
);
11299 prd
= (struct prefix_rd
*)&prn
->p
;
11301 /* "network" configuration display. */
11302 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11303 if (p
->u
.prefix_evpn
.route_type
== 5) {
11304 char local_buf
[PREFIX_STRLEN
];
11305 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11306 struct prefix_evpn
*)p
)
11310 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11311 local_buf
, PREFIX_STRLEN
);
11312 sprintf(buf
, "%s/%u", local_buf
,
11313 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11315 prefix2str(p
, buf
, sizeof(buf
));
11318 if (bgp_static
->gatewayIp
.family
== AF_INET
11319 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11320 inet_ntop(bgp_static
->gatewayIp
.family
,
11321 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11324 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11326 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11327 decode_label(&bgp_static
->label
), esi
, buf2
,
11331 XFREE(MTYPE_TMP
, macrouter
);
11333 XFREE(MTYPE_TMP
, esi
);
11338 /* Configuration of static route announcement and aggregate
11340 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11343 struct bgp_node
*rn
;
11345 struct bgp_static
*bgp_static
;
11346 struct bgp_aggregate
*bgp_aggregate
;
11347 char buf
[SU_ADDRSTRLEN
];
11349 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11350 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11354 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11355 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11359 /* Network configuration. */
11360 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11361 rn
= bgp_route_next(rn
)) {
11362 if ((bgp_static
= rn
->info
) == NULL
)
11367 /* "network" configuration display. */
11368 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11369 uint32_t destination
;
11370 struct in_addr netmask
;
11372 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11373 masklen2ip(p
->prefixlen
, &netmask
);
11374 vty_out(vty
, " network %s",
11375 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11378 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11379 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11380 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11381 || p
->u
.prefix4
.s_addr
== 0) {
11382 /* Natural mask is not display. */
11384 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11386 vty_out(vty
, " network %s/%d",
11387 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11392 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11393 vty_out(vty
, " label-index %u",
11394 bgp_static
->label_index
);
11396 if (bgp_static
->rmap
.name
)
11397 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11399 if (bgp_static
->backdoor
)
11400 vty_out(vty
, " backdoor");
11402 vty_out(vty
, "\n");
11405 /* Aggregate-address configuration. */
11406 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11407 rn
= bgp_route_next(rn
)) {
11408 if ((bgp_aggregate
= rn
->info
) == NULL
)
11413 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11414 struct in_addr netmask
;
11416 masklen2ip(p
->prefixlen
, &netmask
);
11417 vty_out(vty
, " aggregate-address %s %s",
11418 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11420 inet_ntoa(netmask
));
11422 vty_out(vty
, " aggregate-address %s/%d",
11423 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11428 if (bgp_aggregate
->as_set
)
11429 vty_out(vty
, " as-set");
11431 if (bgp_aggregate
->summary_only
)
11432 vty_out(vty
, " summary-only");
11434 vty_out(vty
, "\n");
11438 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11441 struct bgp_node
*rn
;
11442 struct bgp_distance
*bdistance
;
11444 /* Distance configuration. */
11445 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11446 && bgp
->distance_local
[afi
][safi
]
11447 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11448 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11449 || bgp
->distance_local
[afi
][safi
]
11450 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11451 vty_out(vty
, " distance bgp %d %d %d\n",
11452 bgp
->distance_ebgp
[afi
][safi
],
11453 bgp
->distance_ibgp
[afi
][safi
],
11454 bgp
->distance_local
[afi
][safi
]);
11457 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11458 rn
= bgp_route_next(rn
))
11459 if ((bdistance
= rn
->info
) != NULL
) {
11460 char buf
[PREFIX_STRLEN
];
11462 vty_out(vty
, " distance %d %s %s\n",
11463 bdistance
->distance
,
11464 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11465 bdistance
->access_list
? bdistance
->access_list
11470 /* Allocate routing table structure and install commands. */
11471 void bgp_route_init(void)
11476 /* Init BGP distance table. */
11477 FOREACH_AFI_SAFI (afi
, safi
)
11478 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11480 /* IPv4 BGP commands. */
11481 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11482 install_element(BGP_NODE
, &bgp_network_cmd
);
11483 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11485 install_element(BGP_NODE
, &aggregate_address_cmd
);
11486 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11487 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11488 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11490 /* IPv4 unicast configuration. */
11491 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11492 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11493 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11495 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11496 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11497 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11498 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11500 /* IPv4 multicast configuration. */
11501 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11502 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11503 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11504 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11505 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11506 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11507 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11509 /* IPv4 labeled-unicast configuration. */
11510 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11511 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11512 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11513 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11514 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11516 install_element(VIEW_NODE
,
11517 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11518 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11519 install_element(VIEW_NODE
,
11520 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11521 #ifdef KEEP_OLD_VPN_COMMANDS
11522 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11523 #endif /* KEEP_OLD_VPN_COMMANDS */
11524 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11525 install_element(VIEW_NODE
,
11526 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11528 /* BGP dampening clear commands */
11529 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11530 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11532 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11533 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11536 install_element(ENABLE_NODE
,
11537 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11538 #ifdef KEEP_OLD_VPN_COMMANDS
11539 install_element(ENABLE_NODE
,
11540 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11541 #endif /* KEEP_OLD_VPN_COMMANDS */
11543 /* New config IPv6 BGP commands. */
11544 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11545 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11546 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11548 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11549 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11551 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11553 install_element(BGP_NODE
, &bgp_distance_cmd
);
11554 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11555 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11556 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11557 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11558 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11559 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11560 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11561 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11562 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11563 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11564 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11565 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11566 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11567 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11568 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11569 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11570 install_element(BGP_IPV4M_NODE
,
11571 &no_bgp_distance_source_access_list_cmd
);
11572 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11573 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11574 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11575 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11576 install_element(BGP_IPV6_NODE
,
11577 &ipv6_bgp_distance_source_access_list_cmd
);
11578 install_element(BGP_IPV6_NODE
,
11579 &no_ipv6_bgp_distance_source_access_list_cmd
);
11580 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11581 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11582 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11583 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11584 install_element(BGP_IPV6M_NODE
,
11585 &ipv6_bgp_distance_source_access_list_cmd
);
11586 install_element(BGP_IPV6M_NODE
,
11587 &no_ipv6_bgp_distance_source_access_list_cmd
);
11589 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11590 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11591 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11592 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11594 /* IPv4 Multicast Mode */
11595 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11596 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11598 /* Large Communities */
11599 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11600 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11602 /* show bgp ipv4 flowspec detailed */
11603 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11607 void bgp_route_finish(void)
11612 FOREACH_AFI_SAFI (afi
, safi
) {
11613 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11614 bgp_distance_table
[afi
][safi
] = NULL
;