1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
79 #ifndef VTYSH_EXTRACT_PL
80 #include "bgpd/bgp_route_clippy.c"
83 /* Extern from bgp_dump.c */
84 extern const char *bgp_origin_str
[];
85 extern const char *bgp_origin_long_str
[];
88 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
89 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
90 static const struct message bgp_pmsi_tnltype_str
[] = {
91 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
92 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
93 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
94 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
95 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
96 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
97 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
98 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
102 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
103 safi_t safi
, struct prefix
*p
,
104 struct prefix_rd
*prd
)
107 struct bgp_node
*prn
= NULL
;
113 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
114 || (safi
== SAFI_EVPN
)) {
115 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
117 if (prn
->info
== NULL
)
118 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
120 bgp_unlock_node(prn
);
124 rn
= bgp_node_get(table
, p
);
126 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
127 || (safi
== SAFI_EVPN
))
133 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
134 safi_t safi
, struct prefix
*p
,
135 struct prefix_rd
*prd
)
138 struct bgp_node
*prn
= NULL
;
143 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
144 || (safi
== SAFI_EVPN
)) {
145 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
149 if (prn
->info
== NULL
) {
150 bgp_unlock_node(prn
);
157 rn
= bgp_node_lookup(table
, p
);
162 /* Allocate bgp_info_extra */
163 static struct bgp_info_extra
*bgp_info_extra_new(void)
165 struct bgp_info_extra
*new;
166 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
167 new->label
[0] = MPLS_INVALID_LABEL
;
172 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
174 if (extra
&& *extra
) {
175 if ((*extra
)->damp_info
)
176 bgp_damp_info_free((*extra
)->damp_info
, 0);
178 (*extra
)->damp_info
= NULL
;
180 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
186 /* Get bgp_info extra information for the given bgp_info, lazy allocated
189 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
192 ri
->extra
= bgp_info_extra_new();
196 /* Allocate new bgp info structure. */
197 struct bgp_info
*bgp_info_new(void)
199 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
202 /* Free bgp route information. */
203 static void bgp_info_free(struct bgp_info
*binfo
)
206 bgp_attr_unintern(&binfo
->attr
);
208 bgp_unlink_nexthop(binfo
);
209 bgp_info_extra_free(&binfo
->extra
);
210 bgp_info_mpath_free(&binfo
->mpath
);
212 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
214 XFREE(MTYPE_BGP_ROUTE
, binfo
);
217 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
223 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
225 assert(binfo
&& binfo
->lock
> 0);
228 if (binfo
->lock
== 0) {
230 zlog_debug ("%s: unlocked and freeing", __func__
);
231 zlog_backtrace (LOG_DEBUG
);
233 bgp_info_free(binfo
);
238 if (binfo
->lock
== 1)
240 zlog_debug ("%s: unlocked to 1", __func__
);
241 zlog_backtrace (LOG_DEBUG
);
248 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
250 struct bgp_info
*top
;
262 peer_lock(ri
->peer
); /* bgp_info peer reference */
265 /* Do the actual removal of info from RIB, for use by bgp_process
266 completion callback *only* */
267 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
270 ri
->next
->prev
= ri
->prev
;
272 ri
->prev
->next
= ri
->next
;
276 bgp_info_mpath_dequeue(ri
);
281 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
283 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
284 /* set of previous already took care of pcount */
285 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
288 /* undo the effects of a previous call to bgp_info_delete; typically
289 called when a route is deleted and then quickly re-added before the
290 deletion has been processed */
291 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
293 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
294 /* unset of previous already took care of pcount */
295 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
298 /* Adjust pcount as required */
299 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
301 struct bgp_table
*table
;
303 assert(rn
&& bgp_node_table(rn
));
304 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
306 table
= bgp_node_table(rn
);
308 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
311 if (!BGP_INFO_COUNTABLE(ri
)
312 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
314 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
316 /* slight hack, but more robust against errors. */
317 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
318 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
321 "%s: Asked to decrement 0 prefix count for peer %s",
322 __func__
, ri
->peer
->host
);
323 zlog_backtrace(LOG_WARNING
);
324 zlog_warn("%s: Please report to Quagga bugzilla",
327 } else if (BGP_INFO_COUNTABLE(ri
)
328 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
329 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
330 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
334 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
336 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
339 /* Set/unset bgp_info flags, adjusting any other state as needed.
340 * This is here primarily to keep prefix-count in check.
342 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
344 SET_FLAG(ri
->flags
, flag
);
346 /* early bath if we know it's not a flag that changes countability state
348 if (!CHECK_FLAG(flag
,
349 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
352 bgp_pcount_adjust(rn
, ri
);
355 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
358 UNSET_FLAG(ri
->flags
, flag
);
360 /* early bath if we know it's not a flag that changes countability state
362 if (!CHECK_FLAG(flag
,
363 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
366 bgp_pcount_adjust(rn
, ri
);
369 /* Get MED value. If MED value is missing and "bgp bestpath
370 missing-as-worst" is specified, treat it as the worst value. */
371 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
373 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
376 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
383 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
385 if (ri
->addpath_rx_id
)
386 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
389 sprintf(buf
, "path %s", ri
->peer
->host
);
392 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
394 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
395 struct bgp_info
*exist
, int *paths_eq
,
396 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
397 char *pfx_buf
, afi_t afi
, safi_t safi
)
399 struct attr
*newattr
, *existattr
;
400 bgp_peer_sort_t new_sort
;
401 bgp_peer_sort_t exist_sort
;
407 uint32_t exist_weight
;
408 uint32_t newm
, existm
;
409 struct in_addr new_id
;
410 struct in_addr exist_id
;
413 int internal_as_route
;
416 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
417 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
419 uint32_t exist_mm_seq
;
426 zlog_debug("%s: new is NULL", pfx_buf
);
431 bgp_info_path_with_addpath_rx_str(new, new_buf
);
435 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
441 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
442 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
443 pfx_buf
, new_buf
, new->flags
, exist_buf
,
448 existattr
= exist
->attr
;
450 /* For EVPN routes, we cannot just go by local vs remote, we have to
451 * look at the MAC mobility sequence number, if present.
453 if (safi
== SAFI_EVPN
) {
454 /* This is an error condition described in RFC 7432 Section
456 * states that in this scenario "the PE MUST alert the operator"
458 * does not state what other action to take. In order to provide
460 * consistency in this scenario we are going to prefer the path
464 if (newattr
->sticky
!= existattr
->sticky
) {
466 prefix2str(&new->net
->p
, pfx_buf
,
468 * PREFIX2STR_BUFFER
);
469 bgp_info_path_with_addpath_rx_str(new, new_buf
);
470 bgp_info_path_with_addpath_rx_str(exist
,
474 if (newattr
->sticky
&& !existattr
->sticky
) {
476 "%s: %s wins over %s due to sticky MAC flag",
477 pfx_buf
, new_buf
, exist_buf
);
481 if (!newattr
->sticky
&& existattr
->sticky
) {
483 "%s: %s loses to %s due to sticky MAC flag",
484 pfx_buf
, new_buf
, exist_buf
);
489 new_mm_seq
= mac_mobility_seqnum(newattr
);
490 exist_mm_seq
= mac_mobility_seqnum(existattr
);
492 if (new_mm_seq
> exist_mm_seq
) {
495 "%s: %s wins over %s due to MM seq %u > %u",
496 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
501 if (new_mm_seq
< exist_mm_seq
) {
504 "%s: %s loses to %s due to MM seq %u < %u",
505 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
511 /* 1. Weight check. */
512 new_weight
= newattr
->weight
;
513 exist_weight
= existattr
->weight
;
515 if (new_weight
> exist_weight
) {
517 zlog_debug("%s: %s wins over %s due to weight %d > %d",
518 pfx_buf
, new_buf
, exist_buf
, new_weight
,
523 if (new_weight
< exist_weight
) {
525 zlog_debug("%s: %s loses to %s due to weight %d < %d",
526 pfx_buf
, new_buf
, exist_buf
, new_weight
,
531 /* 2. Local preference check. */
532 new_pref
= exist_pref
= bgp
->default_local_pref
;
534 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
535 new_pref
= newattr
->local_pref
;
536 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
537 exist_pref
= existattr
->local_pref
;
539 if (new_pref
> exist_pref
) {
542 "%s: %s wins over %s due to localpref %d > %d",
543 pfx_buf
, new_buf
, exist_buf
, new_pref
,
548 if (new_pref
< exist_pref
) {
551 "%s: %s loses to %s due to localpref %d < %d",
552 pfx_buf
, new_buf
, exist_buf
, new_pref
,
557 /* 3. Local route check. We prefer:
559 * - BGP_ROUTE_AGGREGATE
560 * - BGP_ROUTE_REDISTRIBUTE
562 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
563 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
566 "%s: %s wins over %s due to preferred BGP_ROUTE type",
567 pfx_buf
, new_buf
, exist_buf
);
571 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
572 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
575 "%s: %s loses to %s due to preferred BGP_ROUTE type",
576 pfx_buf
, new_buf
, exist_buf
);
580 /* 4. AS path length check. */
581 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
582 int exist_hops
= aspath_count_hops(existattr
->aspath
);
583 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
585 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
588 aspath_hops
= aspath_count_hops(newattr
->aspath
);
589 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
591 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
594 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
595 pfx_buf
, new_buf
, exist_buf
,
597 (exist_hops
+ exist_confeds
));
601 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
604 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
605 pfx_buf
, new_buf
, exist_buf
,
607 (exist_hops
+ exist_confeds
));
611 int newhops
= aspath_count_hops(newattr
->aspath
);
613 if (newhops
< exist_hops
) {
616 "%s: %s wins over %s due to aspath hopcount %d < %d",
617 pfx_buf
, new_buf
, exist_buf
,
618 newhops
, exist_hops
);
622 if (newhops
> exist_hops
) {
625 "%s: %s loses to %s due to aspath hopcount %d > %d",
626 pfx_buf
, new_buf
, exist_buf
,
627 newhops
, exist_hops
);
633 /* 5. Origin check. */
634 if (newattr
->origin
< existattr
->origin
) {
636 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
637 pfx_buf
, new_buf
, exist_buf
,
638 bgp_origin_long_str
[newattr
->origin
],
639 bgp_origin_long_str
[existattr
->origin
]);
643 if (newattr
->origin
> existattr
->origin
) {
645 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
646 pfx_buf
, new_buf
, exist_buf
,
647 bgp_origin_long_str
[newattr
->origin
],
648 bgp_origin_long_str
[existattr
->origin
]);
653 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
654 && aspath_count_hops(existattr
->aspath
) == 0);
655 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
656 && aspath_count_confeds(existattr
->aspath
) > 0
657 && aspath_count_hops(newattr
->aspath
) == 0
658 && aspath_count_hops(existattr
->aspath
) == 0);
660 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
661 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
662 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
663 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
664 || internal_as_route
) {
665 new_med
= bgp_med_value(new->attr
, bgp
);
666 exist_med
= bgp_med_value(exist
->attr
, bgp
);
668 if (new_med
< exist_med
) {
671 "%s: %s wins over %s due to MED %d < %d",
672 pfx_buf
, new_buf
, exist_buf
, new_med
,
677 if (new_med
> exist_med
) {
680 "%s: %s loses to %s due to MED %d > %d",
681 pfx_buf
, new_buf
, exist_buf
, new_med
,
687 /* 7. Peer type check. */
688 new_sort
= new->peer
->sort
;
689 exist_sort
= exist
->peer
->sort
;
691 if (new_sort
== BGP_PEER_EBGP
692 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
695 "%s: %s wins over %s due to eBGP peer > iBGP peer",
696 pfx_buf
, new_buf
, exist_buf
);
700 if (exist_sort
== BGP_PEER_EBGP
701 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
704 "%s: %s loses to %s due to iBGP peer < eBGP peer",
705 pfx_buf
, new_buf
, exist_buf
);
709 /* 8. IGP metric check. */
713 newm
= new->extra
->igpmetric
;
715 existm
= exist
->extra
->igpmetric
;
720 "%s: %s wins over %s due to IGP metric %d < %d",
721 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
728 "%s: %s loses to %s due to IGP metric %d > %d",
729 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
733 /* 9. Same IGP metric. Compare the cluster list length as
734 representative of IGP hops metric. Rewrite the metric value
735 pair (newm, existm) with the cluster list length. Prefer the
736 path with smaller cluster list length. */
737 if (newm
== existm
) {
738 if (peer_sort(new->peer
) == BGP_PEER_IBGP
739 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
740 && (mpath_cfg
== NULL
742 mpath_cfg
->ibgp_flags
,
743 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
744 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
745 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
750 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
751 pfx_buf
, new_buf
, exist_buf
,
759 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
760 pfx_buf
, new_buf
, exist_buf
,
767 /* 10. confed-external vs. confed-internal */
768 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
769 if (new_sort
== BGP_PEER_CONFED
770 && exist_sort
== BGP_PEER_IBGP
) {
773 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
774 pfx_buf
, new_buf
, exist_buf
);
778 if (exist_sort
== BGP_PEER_CONFED
779 && new_sort
== BGP_PEER_IBGP
) {
782 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
783 pfx_buf
, new_buf
, exist_buf
);
788 /* 11. Maximum path check. */
789 if (newm
== existm
) {
790 /* If one path has a label but the other does not, do not treat
791 * them as equals for multipath
793 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
795 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
798 "%s: %s and %s cannot be multipath, one has a label while the other does not",
799 pfx_buf
, new_buf
, exist_buf
);
800 } else if (bgp_flag_check(bgp
,
801 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
804 * For the two paths, all comparison steps till IGP
806 * have succeeded - including AS_PATH hop count. Since
808 * bestpath as-path multipath-relax' knob is on, we
810 * an exact match of AS_PATH. Thus, mark the paths are
812 * That will trigger both these paths to get into the
820 "%s: %s and %s are equal via multipath-relax",
821 pfx_buf
, new_buf
, exist_buf
);
822 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
823 if (aspath_cmp(new->attr
->aspath
,
824 exist
->attr
->aspath
)) {
829 "%s: %s and %s are equal via matching aspaths",
830 pfx_buf
, new_buf
, exist_buf
);
832 } else if (new->peer
->as
== exist
->peer
->as
) {
837 "%s: %s and %s are equal via same remote-as",
838 pfx_buf
, new_buf
, exist_buf
);
842 * TODO: If unequal cost ibgp multipath is enabled we can
843 * mark the paths as equal here instead of returning
848 "%s: %s wins over %s after IGP metric comparison",
849 pfx_buf
, new_buf
, exist_buf
);
852 "%s: %s loses to %s after IGP metric comparison",
853 pfx_buf
, new_buf
, exist_buf
);
858 /* 12. If both paths are external, prefer the path that was received
859 first (the oldest one). This step minimizes route-flap, since a
860 newer path won't displace an older one, even if it was the
861 preferred route based on the additional decision criteria below. */
862 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
863 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
864 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
867 "%s: %s wins over %s due to oldest external",
868 pfx_buf
, new_buf
, exist_buf
);
872 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
875 "%s: %s loses to %s due to oldest external",
876 pfx_buf
, new_buf
, exist_buf
);
881 /* 13. Router-ID comparision. */
882 /* If one of the paths is "stale", the corresponding peer router-id will
883 * be 0 and would always win over the other path. If originator id is
884 * used for the comparision, it will decide which path is better.
886 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
887 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
889 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
890 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
891 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
893 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
895 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
898 "%s: %s wins over %s due to Router-ID comparison",
899 pfx_buf
, new_buf
, exist_buf
);
903 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
906 "%s: %s loses to %s due to Router-ID comparison",
907 pfx_buf
, new_buf
, exist_buf
);
911 /* 14. Cluster length comparision. */
912 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
913 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
915 if (new_cluster
< exist_cluster
) {
918 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
919 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
924 if (new_cluster
> exist_cluster
) {
927 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
928 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
933 /* 15. Neighbor address comparision. */
934 /* Do this only if neither path is "stale" as stale paths do not have
935 * valid peer information (as the connection may or may not be up).
937 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
940 "%s: %s wins over %s due to latter path being STALE",
941 pfx_buf
, new_buf
, exist_buf
);
945 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
948 "%s: %s loses to %s due to former path being STALE",
949 pfx_buf
, new_buf
, exist_buf
);
953 /* locally configured routes to advertise do not have su_remote */
954 if (new->peer
->su_remote
== NULL
)
956 if (exist
->peer
->su_remote
== NULL
)
959 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
964 "%s: %s loses to %s due to Neighor IP comparison",
965 pfx_buf
, new_buf
, exist_buf
);
972 "%s: %s wins over %s due to Neighor IP comparison",
973 pfx_buf
, new_buf
, exist_buf
);
978 zlog_debug("%s: %s wins over %s due to nothing left to compare",
979 pfx_buf
, new_buf
, exist_buf
);
984 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
985 * is preferred, or 0 if they are the same (usually will only occur if
986 * multipath is enabled
987 * This version is compatible with */
988 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
989 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
994 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1008 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1009 struct attr
*attr
, afi_t afi
,
1012 struct bgp_filter
*filter
;
1014 filter
= &peer
->filter
[afi
][safi
];
1016 #define FILTER_EXIST_WARN(F, f, filter) \
1017 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1018 zlog_warn("%s: Could not find configured input %s-list %s!", \
1019 peer->host, #f, F##_IN_NAME(filter));
1021 if (DISTRIBUTE_IN_NAME(filter
)) {
1022 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1024 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1028 if (PREFIX_LIST_IN_NAME(filter
)) {
1029 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1031 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1035 if (FILTER_LIST_IN_NAME(filter
)) {
1036 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1038 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1043 return FILTER_PERMIT
;
1044 #undef FILTER_EXIST_WARN
1047 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1048 struct attr
*attr
, afi_t afi
,
1051 struct bgp_filter
*filter
;
1053 filter
= &peer
->filter
[afi
][safi
];
1055 #define FILTER_EXIST_WARN(F, f, filter) \
1056 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1057 zlog_warn("%s: Could not find configured output %s-list %s!", \
1058 peer->host, #f, F##_OUT_NAME(filter));
1060 if (DISTRIBUTE_OUT_NAME(filter
)) {
1061 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1063 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1067 if (PREFIX_LIST_OUT_NAME(filter
)) {
1068 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1070 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1075 if (FILTER_LIST_OUT_NAME(filter
)) {
1076 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1078 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1083 return FILTER_PERMIT
;
1084 #undef FILTER_EXIST_WARN
1087 /* If community attribute includes no_export then return 1. */
1088 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1090 if (attr
->community
) {
1091 /* NO_ADVERTISE check. */
1092 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1095 /* NO_EXPORT check. */
1096 if (peer
->sort
== BGP_PEER_EBGP
1097 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1100 /* NO_EXPORT_SUBCONFED check. */
1101 if (peer
->sort
== BGP_PEER_EBGP
1102 || peer
->sort
== BGP_PEER_CONFED
)
1103 if (community_include(attr
->community
,
1104 COMMUNITY_NO_EXPORT_SUBCONFED
))
1110 /* Route reflection loop check. */
1111 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1113 struct in_addr cluster_id
;
1115 if (attr
->cluster
) {
1116 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1117 cluster_id
= peer
->bgp
->cluster_id
;
1119 cluster_id
= peer
->bgp
->router_id
;
1121 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1127 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1128 struct attr
*attr
, afi_t afi
, safi_t safi
,
1129 const char *rmap_name
)
1131 struct bgp_filter
*filter
;
1132 struct bgp_info info
;
1133 route_map_result_t ret
;
1134 struct route_map
*rmap
= NULL
;
1136 filter
= &peer
->filter
[afi
][safi
];
1138 /* Apply default weight value. */
1139 if (peer
->weight
[afi
][safi
])
1140 attr
->weight
= peer
->weight
[afi
][safi
];
1143 rmap
= route_map_lookup_by_name(rmap_name
);
1148 if (ROUTE_MAP_IN_NAME(filter
)) {
1149 rmap
= ROUTE_MAP_IN(filter
);
1156 /* Route map apply. */
1158 /* Duplicate current value to new strucutre for modification. */
1162 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1164 /* Apply BGP route map to the attribute. */
1165 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1167 peer
->rmap_type
= 0;
1169 if (ret
== RMAP_DENYMATCH
) {
1170 /* Free newly generated AS path and community by
1172 bgp_attr_flush(attr
);
1179 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1180 struct attr
*attr
, afi_t afi
, safi_t safi
,
1181 const char *rmap_name
)
1183 struct bgp_info info
;
1184 route_map_result_t ret
;
1185 struct route_map
*rmap
= NULL
;
1189 * So if we get to this point and have no rmap_name
1190 * we want to just show the output as it currently
1196 /* Apply default weight value. */
1197 if (peer
->weight
[afi
][safi
])
1198 attr
->weight
= peer
->weight
[afi
][safi
];
1200 rmap
= route_map_lookup_by_name(rmap_name
);
1203 * If we have a route map name and we do not find
1204 * the routemap that means we have an implicit
1210 /* Route map apply. */
1211 /* Duplicate current value to new strucutre for modification. */
1215 rmap_type
= peer
->rmap_type
;
1216 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1218 /* Apply BGP route map to the attribute. */
1219 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1221 peer
->rmap_type
= rmap_type
;
1223 if (ret
== RMAP_DENYMATCH
)
1225 * caller has multiple error paths with bgp_attr_flush()
1232 /* If this is an EBGP peer with remove-private-AS */
1233 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1234 struct peer
*peer
, struct attr
*attr
)
1236 if (peer
->sort
== BGP_PEER_EBGP
1237 && (peer_af_flag_check(peer
, afi
, safi
,
1238 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1239 || peer_af_flag_check(peer
, afi
, safi
,
1240 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1241 || peer_af_flag_check(peer
, afi
, safi
,
1242 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1243 || peer_af_flag_check(peer
, afi
, safi
,
1244 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1245 // Take action on the entire aspath
1246 if (peer_af_flag_check(peer
, afi
, safi
,
1247 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1248 || peer_af_flag_check(peer
, afi
, safi
,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1250 if (peer_af_flag_check(
1252 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1253 attr
->aspath
= aspath_replace_private_asns(
1254 attr
->aspath
, bgp
->as
);
1256 // The entire aspath consists of private ASNs so create
1258 else if (aspath_private_as_check(attr
->aspath
))
1259 attr
->aspath
= aspath_empty_get();
1261 // There are some public and some private ASNs, remove
1264 attr
->aspath
= aspath_remove_private_asns(
1268 // 'all' was not specified so the entire aspath must be private
1270 // for us to do anything
1271 else if (aspath_private_as_check(attr
->aspath
)) {
1272 if (peer_af_flag_check(
1274 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1275 attr
->aspath
= aspath_replace_private_asns(
1276 attr
->aspath
, bgp
->as
);
1278 attr
->aspath
= aspath_empty_get();
1283 /* If this is an EBGP peer with as-override */
1284 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1285 struct peer
*peer
, struct attr
*attr
)
1287 if (peer
->sort
== BGP_PEER_EBGP
1288 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1289 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1290 attr
->aspath
= aspath_replace_specific_asn(
1291 attr
->aspath
, peer
->as
, bgp
->as
);
1295 void bgp_attr_add_gshut_community(struct attr
*attr
)
1297 struct community
*old
;
1298 struct community
*new;
1299 struct community
*merge
;
1300 struct community
*gshut
;
1302 old
= attr
->community
;
1303 gshut
= community_str2com("graceful-shutdown");
1306 merge
= community_merge(community_dup(old
), gshut
);
1308 if (old
->refcnt
== 0)
1309 community_free(old
);
1311 new = community_uniq_sort(merge
);
1312 community_free(merge
);
1314 new = community_dup(gshut
);
1317 community_free(gshut
);
1318 attr
->community
= new;
1319 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1321 /* When we add the graceful-shutdown community we must also
1322 * lower the local-preference */
1323 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1324 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1328 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1330 if (family
== AF_INET
) {
1331 attr
->nexthop
.s_addr
= 0;
1332 attr
->mp_nexthop_global_in
.s_addr
= 0;
1334 if (family
== AF_INET6
)
1335 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1338 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1339 struct update_subgroup
*subgrp
, struct prefix
*p
,
1342 struct bgp_filter
*filter
;
1345 struct peer
*onlypeer
;
1347 struct attr
*riattr
;
1348 char buf
[PREFIX_STRLEN
];
1354 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1356 if (DISABLE_BGP_ANNOUNCE
)
1359 afi
= SUBGRP_AFI(subgrp
);
1360 safi
= SUBGRP_SAFI(subgrp
);
1361 peer
= SUBGRP_PEER(subgrp
);
1363 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1364 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1367 filter
= &peer
->filter
[afi
][safi
];
1368 bgp
= SUBGRP_INST(subgrp
);
1369 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1372 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1373 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1374 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1377 * direct and direct_ext type routes originate internally even
1378 * though they can have peer pointers that reference other
1381 prefix2str(p
, buf
, PREFIX_STRLEN
);
1382 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1388 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1389 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1390 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1391 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1393 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1398 /* With addpath we may be asked to TX all kinds of paths so make sure
1400 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1401 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1402 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1406 /* If this is not the bestpath then check to see if there is an enabled
1408 * feature that requires us to advertise it */
1409 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1410 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1415 /* Aggregate-address suppress check. */
1416 if (ri
->extra
&& ri
->extra
->suppress
)
1417 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1421 /* If it's labeled safi, make sure the route has a valid label. */
1422 if (safi
== SAFI_LABELED_UNICAST
) {
1423 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1424 if (!bgp_is_valid_label(&label
)) {
1425 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1426 zlog_debug("u%" PRIu64
":s%" PRIu64
1427 " %s/%d is filtered - no label (%p)",
1428 subgrp
->update_group
->id
, subgrp
->id
,
1429 inet_ntop(p
->family
, &p
->u
.prefix
,
1430 buf
, SU_ADDRSTRLEN
),
1431 p
->prefixlen
, &label
);
1436 /* Do not send back route to sender. */
1437 if (onlypeer
&& from
== onlypeer
) {
1441 /* Do not send the default route in the BGP table if the neighbor is
1442 * configured for default-originate */
1443 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1444 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1445 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1447 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1451 /* Transparency check. */
1452 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1453 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1458 /* If community is not disabled check the no-export and local. */
1459 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1460 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1462 "subgrpannouncecheck: community filter check fail");
1466 /* If the attribute has originator-id and it is same as remote
1468 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1469 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1470 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1472 "%s [Update:SEND] %s originator-id is same as "
1475 prefix2str(p
, buf
, sizeof(buf
)));
1479 /* ORF prefix-list filter check */
1480 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1481 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1482 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1483 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1484 if (peer
->orf_plist
[afi
][safi
]) {
1485 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1487 if (bgp_debug_update(NULL
, p
,
1488 subgrp
->update_group
, 0))
1490 "%s [Update:SEND] %s is filtered via ORF",
1498 /* Output filter check. */
1499 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1500 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1501 zlog_debug("%s [Update:SEND] %s is filtered",
1502 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1506 #ifdef BGP_SEND_ASPATH_CHECK
1507 /* AS path loop check. */
1508 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1509 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1511 "%s [Update:SEND] suppress announcement to peer AS %u "
1512 "that is part of AS path.",
1513 onlypeer
->host
, onlypeer
->as
);
1516 #endif /* BGP_SEND_ASPATH_CHECK */
1518 /* If we're a CONFED we need to loop check the CONFED ID too */
1519 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1520 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1521 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1523 "%s [Update:SEND] suppress announcement to peer AS %u"
1525 peer
->host
, bgp
->confed_id
);
1530 /* Route-Reflect check. */
1531 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1536 /* IBGP reflection check. */
1537 if (reflect
&& !samepeer_safe
) {
1538 /* A route from a Client peer. */
1539 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1540 PEER_FLAG_REFLECTOR_CLIENT
)) {
1541 /* Reflect to all the Non-Client peers and also to the
1542 Client peers other than the originator. Originator
1544 is already done. So there is noting to do. */
1545 /* no bgp client-to-client reflection check. */
1546 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1547 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1548 PEER_FLAG_REFLECTOR_CLIENT
))
1551 /* A route from a Non-client peer. Reflect to all other
1553 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1554 PEER_FLAG_REFLECTOR_CLIENT
))
1559 /* For modify attribute, copy it to temporary structure. */
1560 bgp_attr_dup(attr
, riattr
);
1562 /* If local-preference is not set. */
1563 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1564 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1565 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1566 attr
->local_pref
= bgp
->default_local_pref
;
1569 /* If originator-id is not set and the route is to be reflected,
1570 set the originator id */
1572 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1573 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1574 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1577 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1579 if (peer
->sort
== BGP_PEER_EBGP
1580 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1581 if (from
!= bgp
->peer_self
&& !transparent
1582 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1583 PEER_FLAG_MED_UNCHANGED
))
1585 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1588 /* Since the nexthop attribute can vary per peer, it is not explicitly
1590 * in announce check, only certain flags and length (or number of
1592 * -- for IPv6/MP_REACH) are set here in order to guide the update
1594 * code in setting the nexthop(s) on a per peer basis in
1596 * Typically, the source nexthop in the attribute is preserved but in
1598 * scenarios where we know it will always be overwritten, we reset the
1599 * nexthop to "0" in an attempt to achieve better Update packing. An
1600 * example of this is when a prefix from each of 2 IBGP peers needs to
1602 * announced to an EBGP peer (and they have the same attributes barring
1606 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1608 #define NEXTHOP_IS_V6 \
1609 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1610 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1611 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1612 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1614 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1616 * the peer (group) is configured to receive link-local nexthop
1618 * and it is available in the prefix OR we're not reflecting the route
1620 * the peer (group) to whom we're going to announce is on a shared
1622 * and this is either a self-originated route or the peer is EBGP.
1624 if (NEXTHOP_IS_V6
) {
1625 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1626 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1627 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1628 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1629 || (!reflect
&& peer
->shared_network
1630 && (from
== bgp
->peer_self
1631 || peer
->sort
== BGP_PEER_EBGP
))) {
1632 attr
->mp_nexthop_len
=
1633 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1636 /* Clear off link-local nexthop in source, whenever it is not
1638 * ensure more prefixes share the same attribute for
1641 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1642 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1643 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1646 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1647 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1649 /* Route map & unsuppress-map apply. */
1650 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1651 struct bgp_info info
;
1652 struct bgp_info_extra dummy_info_extra
;
1653 struct attr dummy_attr
;
1659 memcpy(&dummy_info_extra
, ri
->extra
,
1660 sizeof(struct bgp_info_extra
));
1661 info
.extra
= &dummy_info_extra
;
1664 /* don't confuse inbound and outbound setting */
1665 RESET_FLAG(attr
->rmap_change_flags
);
1668 * The route reflector is not allowed to modify the attributes
1669 * of the reflected IBGP routes unless explicitly allowed.
1671 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1672 && !bgp_flag_check(bgp
,
1673 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1674 bgp_attr_dup(&dummy_attr
, attr
);
1675 info
.attr
= &dummy_attr
;
1678 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1680 if (ri
->extra
&& ri
->extra
->suppress
)
1681 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1684 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1687 peer
->rmap_type
= 0;
1689 if (ret
== RMAP_DENYMATCH
) {
1690 bgp_attr_flush(attr
);
1695 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1696 if (peer
->sort
== BGP_PEER_IBGP
1697 || peer
->sort
== BGP_PEER_CONFED
) {
1698 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1699 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1701 bgp_attr_add_gshut_community(attr
);
1705 /* After route-map has been applied, we check to see if the nexthop to
1706 * be carried in the attribute (that is used for the announcement) can
1707 * be cleared off or not. We do this in all cases where we would be
1708 * setting the nexthop to "ourselves". For IPv6, we only need to
1710 * the global nexthop here; the link-local nexthop would have been
1712 * already, and if not, it is required by the update formation code.
1713 * Also see earlier comments in this function.
1716 * If route-map has performed some operation on the nexthop or the peer
1717 * configuration says to pass it unchanged, we cannot reset the nexthop
1718 * here, so only attempt to do it if these aren't true. Note that the
1719 * route-map handler itself might have cleared the nexthop, if for
1721 * it is configured as 'peer-address'.
1723 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1724 riattr
->rmap_change_flags
)
1726 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1727 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1728 /* We can reset the nexthop, if setting (or forcing) it to
1730 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1731 PEER_FLAG_NEXTHOP_SELF
)
1732 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1733 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1735 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1736 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1737 subgroup_announce_reset_nhop(
1738 (peer_cap_enhe(peer
, afi
, safi
)
1742 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1743 /* Can also reset the nexthop if announcing to EBGP, but
1745 * no peer in the subgroup is on a shared subnet.
1746 * Note: 3rd party nexthop currently implemented for
1749 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1751 subgroup_announce_reset_nhop(
1752 (peer_cap_enhe(peer
, afi
, safi
)
1756 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1758 * This flag is used for leaked vpn-vrf routes
1760 int family
= p
->family
;
1762 if (peer_cap_enhe(peer
, afi
, safi
))
1765 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1767 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1768 __func__
, family2str(family
));
1769 subgroup_announce_reset_nhop(family
, attr
);
1772 /* If IPv6/MP and nexthop does not have any override and happens
1774 * be a link-local address, reset it so that we don't pass along
1776 * source's link-local IPv6 address to recipients who may not be
1778 * the same interface.
1780 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1781 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1782 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1789 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1790 struct bgp_maxpaths_cfg
*mpath_cfg
,
1791 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1793 struct bgp_info
*new_select
;
1794 struct bgp_info
*old_select
;
1795 struct bgp_info
*ri
;
1796 struct bgp_info
*ri1
;
1797 struct bgp_info
*ri2
;
1798 struct bgp_info
*nextri
= NULL
;
1799 int paths_eq
, do_mpath
, debug
;
1800 struct list mp_list
;
1801 char pfx_buf
[PREFIX2STR_BUFFER
];
1802 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1804 bgp_mp_list_init(&mp_list
);
1806 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1808 debug
= bgp_debug_bestpath(&rn
->p
);
1811 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1813 /* bgp deterministic-med */
1815 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1817 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1818 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1819 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1821 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1822 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1824 if (BGP_INFO_HOLDDOWN(ri1
))
1826 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1827 if (ri1
->peer
->status
!= Established
)
1832 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1833 if (CHECK_FLAG(ri2
->flags
,
1834 BGP_INFO_DMED_CHECK
))
1836 if (BGP_INFO_HOLDDOWN(ri2
))
1839 && ri2
->peer
!= bgp
->peer_self
1842 PEER_STATUS_NSF_WAIT
))
1843 if (ri2
->peer
->status
1847 if (aspath_cmp_left(ri1
->attr
->aspath
,
1849 || aspath_cmp_left_confed(
1851 ri2
->attr
->aspath
)) {
1852 if (bgp_info_cmp(bgp
, ri2
,
1858 bgp_info_unset_flag(
1860 BGP_INFO_DMED_SELECTED
);
1866 BGP_INFO_DMED_CHECK
);
1870 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1871 bgp_info_set_flag(rn
, new_select
,
1872 BGP_INFO_DMED_SELECTED
);
1875 bgp_info_path_with_addpath_rx_str(new_select
,
1877 zlog_debug("%s: %s is the bestpath from AS %u",
1879 aspath_get_first_as(
1880 new_select
->attr
->aspath
));
1885 /* Check old selected route and new selected route. */
1888 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1890 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1893 if (BGP_INFO_HOLDDOWN(ri
)) {
1894 /* reap REMOVED routes, if needs be
1895 * selected route must stay for a while longer though
1897 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1898 && (ri
!= old_select
))
1899 bgp_info_reap(rn
, ri
);
1902 zlog_debug("%s: ri %p in holddown", __func__
,
1908 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1909 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1910 if (ri
->peer
->status
!= Established
) {
1914 "%s: ri %p non self peer %s not estab state",
1915 __func__
, ri
, ri
->peer
->host
);
1920 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1921 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1922 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1924 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1928 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1930 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1931 debug
, pfx_buf
, afi
, safi
)) {
1936 /* Now that we know which path is the bestpath see if any of the other
1938 * qualify as multipaths
1942 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1944 sprintf(path_buf
, "NONE");
1946 "%s: After path selection, newbest is %s oldbest was %s",
1948 old_select
? old_select
->peer
->host
: "NONE");
1951 if (do_mpath
&& new_select
) {
1952 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1956 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1958 if (ri
== new_select
) {
1961 "%s: %s is the bestpath, add to the multipath list",
1963 bgp_mp_list_add(&mp_list
, ri
);
1967 if (BGP_INFO_HOLDDOWN(ri
))
1970 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1971 && !CHECK_FLAG(ri
->peer
->sflags
,
1972 PEER_STATUS_NSF_WAIT
))
1973 if (ri
->peer
->status
!= Established
)
1976 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1979 "%s: %s has the same nexthop as the bestpath, skip it",
1984 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1985 debug
, pfx_buf
, afi
, safi
);
1990 "%s: %s is equivalent to the bestpath, add to the multipath list",
1992 bgp_mp_list_add(&mp_list
, ri
);
1997 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1998 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1999 bgp_mp_list_clear(&mp_list
);
2001 result
->old
= old_select
;
2002 result
->new = new_select
;
2008 * A new route/change in bestpath of an existing route. Evaluate the path
2009 * for advertisement to the subgroup.
2011 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2012 struct bgp_info
*selected
,
2013 struct bgp_node
*rn
,
2014 uint32_t addpath_tx_id
)
2017 struct peer
*onlypeer
;
2023 afi
= SUBGRP_AFI(subgrp
);
2024 safi
= SUBGRP_SAFI(subgrp
);
2025 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2028 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2029 char buf_prefix
[PREFIX_STRLEN
];
2030 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2031 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2035 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2036 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2037 PEER_STATUS_ORF_WAIT_REFRESH
))
2040 memset(&attr
, 0, sizeof(struct attr
));
2041 /* It's initialized in bgp_announce_check() */
2043 /* Announcement to the subgroup. If the route is filtered withdraw it.
2046 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2047 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2049 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2050 selected
->addpath_tx_id
);
2053 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2055 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2062 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2063 * This is called at the end of route processing.
2065 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2067 struct bgp_info
*ri
;
2069 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2070 if (BGP_INFO_HOLDDOWN(ri
))
2072 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2073 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2078 * Has the route changed from the RIB's perspective? This is invoked only
2079 * if the route selection returns the same best route as earlier - to
2080 * determine if we need to update zebra or not.
2082 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2084 struct bgp_info
*mpinfo
;
2086 /* If this is multipath, check all selected paths for any nexthop change
2088 * attribute change. Some attribute changes (e.g., community) aren't of
2089 * relevance to the RIB, but we'll update zebra to ensure we handle the
2090 * case of BGP nexthop change. This is the behavior when the best path
2092 * an attribute change anyway.
2094 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2095 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2098 /* If this is multipath, check all selected paths for any nexthop change
2100 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2101 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2102 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2103 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2107 /* Nothing has changed from the RIB's perspective. */
2111 struct bgp_process_queue
{
2113 STAILQ_HEAD(, bgp_node
) pqueue
;
2114 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2116 unsigned int queued
;
2120 * old_select = The old best path
2121 * new_select = the new best path
2123 * if (!old_select && new_select)
2124 * We are sending new information on.
2126 * if (old_select && new_select) {
2127 * if (new_select != old_select)
2128 * We have a new best path send a change
2130 * We've received a update with new attributes that needs
2134 * if (old_select && !new_select)
2135 * We have no eligible route that we can announce or the rn
2138 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2139 afi_t afi
, safi_t safi
)
2141 struct prefix
*p
= &rn
->p
;
2142 struct bgp_info
*new_select
;
2143 struct bgp_info
*old_select
;
2144 struct bgp_info_pair old_and_new
;
2145 char pfx_buf
[PREFIX2STR_BUFFER
];
2148 /* Is it end of initial update? (after startup) */
2150 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2151 sizeof(bgp
->update_delay_zebra_resume_time
));
2153 bgp
->main_zebra_update_hold
= 0;
2154 FOREACH_AFI_SAFI (afi
, safi
) {
2155 if (bgp_fibupd_safi(safi
))
2156 bgp_zebra_announce_table(bgp
, afi
, safi
);
2158 bgp
->main_peers_update_hold
= 0;
2160 bgp_start_routeadv(bgp
);
2164 debug
= bgp_debug_bestpath(&rn
->p
);
2166 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2167 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2168 afi2str(afi
), safi2str(safi
));
2171 /* Best path selection. */
2172 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2174 old_select
= old_and_new
.old
;
2175 new_select
= old_and_new
.new;
2177 /* Do we need to allocate or free labels?
2178 * Right now, since we only deal with per-prefix labels, it is not
2179 * necessary to do this upon changes to best path except if the label
2182 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2185 || bgp_label_index_differs(new_select
, old_select
)
2186 || new_select
->sub_type
!= old_select
->sub_type
) {
2187 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2188 && new_select
->attr
->flag
2190 BGP_ATTR_PREFIX_SID
)
2191 && new_select
->attr
->label_index
2192 != BGP_INVALID_LABEL_INDEX
) {
2195 BGP_NODE_REGISTERED_FOR_LABEL
))
2196 bgp_unregister_for_label(rn
);
2197 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2199 bgp_set_valid_label(&rn
->local_label
);
2201 bgp_register_for_label(rn
, new_select
);
2203 } else if (CHECK_FLAG(rn
->flags
,
2204 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2205 bgp_unregister_for_label(rn
);
2207 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2208 bgp_unregister_for_label(rn
);
2212 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2214 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2215 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2216 old_select
, new_select
);
2219 /* If best route remains the same and this is not due to user-initiated
2220 * clear, see exactly what needs to be done.
2223 if (old_select
&& old_select
== new_select
2224 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2225 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2226 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2227 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2229 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2230 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2232 if (bgp_fibupd_safi(safi
)
2233 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2235 if (new_select
->type
== ZEBRA_ROUTE_BGP
2236 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2237 || new_select
->sub_type
2238 == BGP_ROUTE_IMPORTED
))
2240 bgp_zebra_announce(rn
, p
, old_select
,
2244 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2245 bgp_zebra_clear_route_change_flags(rn
);
2247 /* If there is a change of interest to peers, reannounce the
2249 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2250 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2251 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2253 /* unicast routes must also be annouced to
2254 * labeled-unicast update-groups */
2255 if (safi
== SAFI_UNICAST
)
2256 group_announce_route(bgp
, afi
,
2257 SAFI_LABELED_UNICAST
, rn
,
2260 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2261 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2264 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2268 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2270 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2272 /* bestpath has changed; bump version */
2273 if (old_select
|| new_select
) {
2274 bgp_bump_version(rn
);
2276 if (!bgp
->t_rmap_def_originate_eval
) {
2280 update_group_refresh_default_originate_route_map
,
2281 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2282 &bgp
->t_rmap_def_originate_eval
);
2287 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2290 zlog_debug("%s: setting SELECTED flag", __func__
);
2291 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2292 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2293 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2297 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2298 if (old_select
!= new_select
) {
2300 vnc_import_bgp_exterior_del_route(bgp
, p
,
2302 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2305 vnc_import_bgp_exterior_add_route(bgp
, p
,
2307 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2313 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2315 /* unicast routes must also be annouced to labeled-unicast update-groups
2317 if (safi
== SAFI_UNICAST
)
2318 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2322 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2323 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2324 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2325 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2326 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2327 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2329 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2331 /* Withdraw the route from the kernel. */
2332 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2333 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2334 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2335 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2337 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2341 /* advertise/withdraw type-5 routes */
2342 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2343 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2344 (!new_select
->extra
|| !new_select
->extra
->parent
))
2345 bgp_evpn_advertise_type5_route(bgp
, &rn
->p
,
2348 else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2349 (!old_select
->extra
|| !old_select
->extra
->parent
))
2350 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2353 /* Clear any route change flags. */
2354 bgp_zebra_clear_route_change_flags(rn
);
2356 /* Reap old select bgp_info, if it has been removed */
2357 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2358 bgp_info_reap(rn
, old_select
);
2360 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2364 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2366 struct bgp_process_queue
*pqnode
= data
;
2367 struct bgp
*bgp
= pqnode
->bgp
;
2368 struct bgp_table
*table
;
2369 struct bgp_node
*rn
;
2372 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2373 bgp_process_main_one(bgp
, NULL
, 0, 0);
2374 /* should always have dedicated wq call */
2375 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2379 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2380 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2381 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2382 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2383 table
= bgp_node_table(rn
);
2384 /* note, new RNs may be added as part of processing */
2385 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2387 bgp_unlock_node(rn
);
2388 bgp_table_unlock(table
);
2394 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2396 struct bgp_process_queue
*pqnode
= data
;
2398 bgp_unlock(pqnode
->bgp
);
2400 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2403 void bgp_process_queue_init(void)
2405 if (!bm
->process_main_queue
) {
2406 bm
->process_main_queue
=
2407 work_queue_new(bm
->master
, "process_main_queue");
2409 if (!bm
->process_main_queue
) {
2410 zlog_err("%s: Failed to allocate work queue", __func__
);
2415 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2416 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2417 bm
->process_main_queue
->spec
.max_retries
= 0;
2418 bm
->process_main_queue
->spec
.hold
= 50;
2419 /* Use a higher yield value of 50ms for main queue processing */
2420 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2423 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2425 struct bgp_process_queue
*pqnode
;
2427 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2428 sizeof(struct bgp_process_queue
));
2430 /* unlocked in bgp_processq_del */
2431 pqnode
->bgp
= bgp_lock(bgp
);
2432 STAILQ_INIT(&pqnode
->pqueue
);
2437 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2439 #define ARBITRARY_PROCESS_QLEN 10000
2440 struct work_queue
*wq
= bm
->process_main_queue
;
2441 struct bgp_process_queue
*pqnode
;
2442 int pqnode_reuse
= 0;
2444 /* already scheduled for processing? */
2445 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2451 /* Add route nodes to an existing work queue item until reaching the
2452 limit only if is from the same BGP view and it's not an EOIU marker
2454 if (work_queue_item_count(wq
)) {
2455 struct work_queue_item
*item
= work_queue_last_item(wq
);
2456 pqnode
= item
->data
;
2458 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2459 || pqnode
->bgp
!= bgp
2460 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2461 pqnode
= bgp_processq_alloc(bgp
);
2465 pqnode
= bgp_processq_alloc(bgp
);
2466 /* all unlocked in bgp_process_wq */
2467 bgp_table_lock(bgp_node_table(rn
));
2469 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2472 /* can't be enqueued twice */
2473 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2474 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2478 work_queue_add(wq
, pqnode
);
2483 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2485 struct bgp_process_queue
*pqnode
;
2487 if (bm
->process_main_queue
== NULL
)
2490 pqnode
= bgp_processq_alloc(bgp
);
2492 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2493 work_queue_add(bm
->process_main_queue
, pqnode
);
2496 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2500 peer
= THREAD_ARG(thread
);
2501 peer
->t_pmax_restart
= NULL
;
2503 if (bgp_debug_neighbor_events(peer
))
2505 "%s Maximum-prefix restart timer expired, restore peering",
2508 peer_clear(peer
, NULL
);
2513 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2517 iana_safi_t pkt_safi
;
2519 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2522 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2523 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2524 PEER_STATUS_PREFIX_LIMIT
)
2529 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2531 afi_safi_print(afi
, safi
), peer
->host
,
2532 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2533 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2535 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2536 PEER_FLAG_MAX_PREFIX_WARNING
))
2539 /* Convert AFI, SAFI to values for packet. */
2540 pkt_afi
= afi_int2iana(afi
);
2541 pkt_safi
= safi_int2iana(safi
);
2545 ndata
[0] = (pkt_afi
>> 8);
2547 ndata
[2] = pkt_safi
;
2548 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2549 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2550 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2551 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2553 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2554 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2555 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2559 /* Dynamic peers will just close their connection. */
2560 if (peer_dynamic_neighbor(peer
))
2563 /* restart timer start */
2564 if (peer
->pmax_restart
[afi
][safi
]) {
2565 peer
->v_pmax_restart
=
2566 peer
->pmax_restart
[afi
][safi
] * 60;
2568 if (bgp_debug_neighbor_events(peer
))
2570 "%s Maximum-prefix restart timer started for %d secs",
2571 peer
->host
, peer
->v_pmax_restart
);
2573 BGP_TIMER_ON(peer
->t_pmax_restart
,
2574 bgp_maximum_prefix_restart_timer
,
2575 peer
->v_pmax_restart
);
2580 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2581 PEER_STATUS_PREFIX_LIMIT
);
2583 if (peer
->pcount
[afi
][safi
]
2584 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2585 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2586 PEER_STATUS_PREFIX_THRESHOLD
)
2591 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2592 afi_safi_print(afi
, safi
), peer
->host
,
2593 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2594 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2595 PEER_STATUS_PREFIX_THRESHOLD
);
2597 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2598 PEER_STATUS_PREFIX_THRESHOLD
);
2602 /* Unconditionally remove the route from the RIB, without taking
2603 * damping into consideration (eg, because the session went down)
2605 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2606 afi_t afi
, safi_t safi
)
2608 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2610 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2611 bgp_info_delete(rn
, ri
); /* keep historical info */
2613 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2616 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2617 struct peer
*peer
, afi_t afi
, safi_t safi
,
2618 struct prefix_rd
*prd
)
2620 int status
= BGP_DAMP_NONE
;
2622 /* apply dampening, if result is suppressed, we'll be retaining
2623 * the bgp_info in the RIB for historical reference.
2625 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2626 && peer
->sort
== BGP_PEER_EBGP
)
2627 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2628 == BGP_DAMP_SUPPRESSED
) {
2629 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2635 if (safi
== SAFI_MPLS_VPN
) {
2636 struct bgp_node
*prn
= NULL
;
2637 struct bgp_table
*table
= NULL
;
2639 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2640 (struct prefix
*)prd
);
2642 table
= (struct bgp_table
*)(prn
->info
);
2644 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2645 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2647 bgp_unlock_node(prn
);
2649 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2650 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2652 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2653 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2659 /* If this is an EVPN route, process for un-import. */
2660 if (safi
== SAFI_EVPN
)
2661 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2663 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2666 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2667 struct peer
*peer
, struct attr
*attr
,
2668 struct bgp_node
*rn
)
2670 struct bgp_info
*new;
2672 /* Make new BGP info. */
2673 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2675 new->instance
= instance
;
2676 new->sub_type
= sub_type
;
2679 new->uptime
= bgp_clock();
2681 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2685 static void overlay_index_update(struct attr
*attr
,
2686 struct eth_segment_id
*eth_s_id
,
2687 union gw_addr
*gw_ip
)
2692 if (eth_s_id
== NULL
) {
2693 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2694 sizeof(struct eth_segment_id
));
2696 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2697 sizeof(struct eth_segment_id
));
2699 if (gw_ip
== NULL
) {
2700 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2702 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2703 sizeof(union gw_addr
));
2707 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2708 struct eth_segment_id
*eth_s_id
,
2709 union gw_addr
*gw_ip
)
2711 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2712 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2715 if (afi
!= AFI_L2VPN
)
2718 memset(&temp
, 0, 16);
2719 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2720 info_gw_ip
= (union gw_addr
*)&temp
;
2721 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2724 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2725 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2728 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2730 info_gw_ip_remote
= gw_ip
;
2731 if (eth_s_id
== NULL
)
2732 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2734 info_eth_s_id_remote
= eth_s_id
;
2735 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2737 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2738 sizeof(struct eth_segment_id
));
2741 /* Check if received nexthop is valid or not. */
2742 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2747 /* Only validated for unicast and multicast currently. */
2748 /* Also valid for EVPN where the nexthop is an IP address. */
2749 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2752 /* If NEXT_HOP is present, validate it. */
2753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2754 if (attr
->nexthop
.s_addr
== 0
2755 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2756 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2760 /* If MP_NEXTHOP is present, validate it. */
2761 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2762 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2763 * it is not an IPv6 link-local address.
2765 if (attr
->mp_nexthop_len
) {
2766 switch (attr
->mp_nexthop_len
) {
2767 case BGP_ATTR_NHLEN_IPV4
:
2768 case BGP_ATTR_NHLEN_VPNV4
:
2769 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2770 || IPV4_CLASS_DE(ntohl(
2771 attr
->mp_nexthop_global_in
.s_addr
))
2772 || bgp_nexthop_self(bgp
,
2773 attr
->mp_nexthop_global_in
));
2776 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2777 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2778 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2779 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2780 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2781 || IN6_IS_ADDR_MULTICAST(
2782 &attr
->mp_nexthop_global
));
2794 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2795 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2796 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2797 uint32_t num_labels
, int soft_reconfig
,
2798 struct bgp_route_evpn
*evpn
)
2801 int aspath_loop_count
= 0;
2802 struct bgp_node
*rn
;
2804 struct attr new_attr
;
2805 struct attr
*attr_new
;
2806 struct bgp_info
*ri
;
2807 struct bgp_info
*new;
2808 struct bgp_info_extra
*extra
;
2810 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2812 int do_loop_check
= 1;
2813 int has_valid_label
= 0;
2815 int vnc_implicit_withdraw
= 0;
2819 memset(&new_attr
, 0, sizeof(struct attr
));
2820 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2821 new_attr
.label
= MPLS_INVALID_LABEL
;
2824 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2825 /* TODO: Check to see if we can get rid of "is_valid_label" */
2826 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2827 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2829 has_valid_label
= bgp_is_valid_label(label
);
2831 /* When peer's soft reconfiguration enabled. Record input packet in
2834 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2835 && peer
!= bgp
->peer_self
)
2836 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2838 /* Check previously received route. */
2839 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2840 if (ri
->peer
== peer
&& ri
->type
== type
2841 && ri
->sub_type
== sub_type
2842 && ri
->addpath_rx_id
== addpath_id
)
2845 /* AS path local-as loop check. */
2846 if (peer
->change_local_as
) {
2847 if (peer
->allowas_in
[afi
][safi
])
2848 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2849 else if (!CHECK_FLAG(peer
->flags
,
2850 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2851 aspath_loop_count
= 1;
2853 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2854 > aspath_loop_count
) {
2855 reason
= "as-path contains our own AS;";
2860 /* If the peer is configured for "allowas-in origin" and the last ASN in
2862 * as-path is our ASN then we do not need to call aspath_loop_check
2864 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2865 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2868 /* AS path loop check. */
2869 if (do_loop_check
) {
2870 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2871 > peer
->allowas_in
[afi
][safi
]
2872 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2873 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2874 > peer
->allowas_in
[afi
][safi
])) {
2875 reason
= "as-path contains our own AS;";
2880 /* Route reflector originator ID check. */
2881 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2882 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2883 reason
= "originator is us;";
2887 /* Route reflector cluster ID check. */
2888 if (bgp_cluster_filter(peer
, attr
)) {
2889 reason
= "reflected from the same cluster;";
2893 /* Apply incoming filter. */
2894 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2899 bgp_attr_dup(&new_attr
, attr
);
2901 /* Apply incoming route-map.
2902 * NB: new_attr may now contain newly allocated values from route-map
2904 * commands, so we need bgp_attr_flush in the error paths, until we
2906 * the attr (which takes over the memory references) */
2907 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2909 reason
= "route-map;";
2910 bgp_attr_flush(&new_attr
);
2914 if (peer
->sort
== BGP_PEER_EBGP
) {
2916 /* If we receive the graceful-shutdown community from an eBGP
2917 * peer we must lower local-preference */
2918 if (new_attr
.community
2919 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2920 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2921 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2923 /* If graceful-shutdown is configured then add the GSHUT
2924 * community to all paths received from eBGP peers */
2925 } else if (bgp_flag_check(peer
->bgp
,
2926 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2927 bgp_attr_add_gshut_community(&new_attr
);
2931 /* next hop check. */
2932 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2933 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2934 reason
= "martian or self next-hop;";
2935 bgp_attr_flush(&new_attr
);
2939 attr_new
= bgp_attr_intern(&new_attr
);
2941 /* If the update is implicit withdraw. */
2943 ri
->uptime
= bgp_clock();
2944 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2946 /* Same attribute comes in. */
2947 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2948 && attrhash_cmp(ri
->attr
, attr_new
)
2949 && (!has_valid_label
2950 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2951 num_labels
* sizeof(mpls_label_t
))
2953 && (overlay_index_equal(
2954 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2955 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2956 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2957 BGP_CONFIG_DAMPENING
)
2958 && peer
->sort
== BGP_PEER_EBGP
2959 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2960 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2961 bgp_debug_rdpfxpath2str(
2962 afi
, safi
, prd
, p
, label
,
2963 num_labels
, addpath_id
? 1 : 0,
2964 addpath_id
, pfx_buf
,
2966 zlog_debug("%s rcvd %s", peer
->host
,
2970 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2971 != BGP_DAMP_SUPPRESSED
) {
2972 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2974 bgp_process(bgp
, rn
, afi
, safi
);
2976 } else /* Duplicate - odd */
2978 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2979 if (!peer
->rcvd_attr_printed
) {
2981 "%s rcvd UPDATE w/ attr: %s",
2983 peer
->rcvd_attr_str
);
2984 peer
->rcvd_attr_printed
= 1;
2987 bgp_debug_rdpfxpath2str(
2988 afi
, safi
, prd
, p
, label
,
2989 num_labels
, addpath_id
? 1 : 0,
2990 addpath_id
, pfx_buf
,
2993 "%s rcvd %s...duplicate ignored",
2994 peer
->host
, pfx_buf
);
2997 /* graceful restart STALE flag unset. */
2998 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2999 bgp_info_unset_flag(rn
, ri
,
3001 bgp_process(bgp
, rn
, afi
, safi
);
3005 bgp_unlock_node(rn
);
3006 bgp_attr_unintern(&attr_new
);
3011 /* Withdraw/Announce before we fully processed the withdraw */
3012 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3013 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3014 bgp_debug_rdpfxpath2str(
3015 afi
, safi
, prd
, p
, label
, num_labels
,
3016 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3019 "%s rcvd %s, flapped quicker than processing",
3020 peer
->host
, pfx_buf
);
3023 bgp_info_restore(rn
, ri
);
3026 /* Received Logging. */
3027 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3028 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3029 num_labels
, addpath_id
? 1 : 0,
3030 addpath_id
, pfx_buf
,
3032 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3035 /* graceful restart STALE flag unset. */
3036 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3037 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3039 /* The attribute is changed. */
3040 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3042 /* implicit withdraw, decrement aggregate and pcount here.
3043 * only if update is accepted, they'll increment below.
3045 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3047 /* Update bgp route dampening information. */
3048 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3049 && peer
->sort
== BGP_PEER_EBGP
) {
3050 /* This is implicit withdraw so we should update
3053 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3054 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3057 if (safi
== SAFI_MPLS_VPN
) {
3058 struct bgp_node
*prn
= NULL
;
3059 struct bgp_table
*table
= NULL
;
3061 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3062 (struct prefix
*)prd
);
3064 table
= (struct bgp_table
*)(prn
->info
);
3066 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3067 bgp
, prd
, table
, p
, ri
);
3069 bgp_unlock_node(prn
);
3071 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3072 && (safi
== SAFI_UNICAST
)) {
3073 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3075 * Implicit withdraw case.
3077 ++vnc_implicit_withdraw
;
3078 vnc_import_bgp_del_route(bgp
, p
, ri
);
3079 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3084 /* Special handling for EVPN update of an existing route. If the
3085 * extended community attribute has changed, we need to
3087 * the route using its existing extended community. It will be
3088 * subsequently processed for import with the new extended
3091 if (safi
== SAFI_EVPN
&& !same_attr
) {
3093 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3095 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3098 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3099 attr_new
->ecommunity
);
3101 if (bgp_debug_update(peer
, p
, NULL
, 1))
3103 "Change in EXT-COMM, existing %s new %s",
3105 ri
->attr
->ecommunity
),
3107 attr_new
->ecommunity
));
3108 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3114 /* Update to new attribute. */
3115 bgp_attr_unintern(&ri
->attr
);
3116 ri
->attr
= attr_new
;
3118 /* Update MPLS label */
3119 if (has_valid_label
) {
3120 extra
= bgp_info_extra_get(ri
);
3121 memcpy(&extra
->label
, label
,
3122 num_labels
* sizeof(mpls_label_t
));
3123 extra
->num_labels
= num_labels
;
3124 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3125 bgp_set_valid_label(&extra
->label
[0]);
3129 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3130 && (safi
== SAFI_UNICAST
)) {
3131 if (vnc_implicit_withdraw
) {
3133 * Add back the route with its new attributes
3135 * The route is still selected, until the route
3137 * queued by bgp_process actually runs. We have
3139 * update to the VNC side immediately to avoid
3141 * configuration changes (e.g., route-map
3143 * trigger re-importation of the entire RIB.
3145 vnc_import_bgp_add_route(bgp
, p
, ri
);
3146 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3150 /* Update Overlay Index */
3151 if (afi
== AFI_L2VPN
) {
3152 overlay_index_update(
3153 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3154 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3157 /* Update bgp route dampening information. */
3158 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3159 && peer
->sort
== BGP_PEER_EBGP
) {
3160 /* Now we do normal update dampening. */
3161 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3162 if (ret
== BGP_DAMP_SUPPRESSED
) {
3163 bgp_unlock_node(rn
);
3168 /* Nexthop reachability check - for unicast and
3169 * labeled-unicast.. */
3170 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3171 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3172 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3173 && !CHECK_FLAG(peer
->flags
,
3174 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3176 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3181 struct bgp
*bgp_nexthop
= bgp
;
3183 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3184 bgp_nexthop
= ri
->extra
->bgp_orig
;
3186 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3187 ri
, NULL
, connected
)
3188 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3189 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3191 if (BGP_DEBUG(nht
, NHT
)) {
3192 char buf1
[INET6_ADDRSTRLEN
];
3194 (const void *)&attr_new
3196 buf1
, INET6_ADDRSTRLEN
);
3197 zlog_debug("%s(%s): NH unresolved",
3198 __FUNCTION__
, buf1
);
3200 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3203 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3206 if (safi
== SAFI_MPLS_VPN
) {
3207 struct bgp_node
*prn
= NULL
;
3208 struct bgp_table
*table
= NULL
;
3210 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3211 (struct prefix
*)prd
);
3213 table
= (struct bgp_table
*)(prn
->info
);
3215 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3216 bgp
, prd
, table
, p
, ri
);
3218 bgp_unlock_node(prn
);
3222 /* If this is an EVPN route and some attribute has changed,
3224 * route for import. If the extended community has changed, we
3226 * have done the un-import earlier and the import would result
3228 * route getting injected into appropriate L2 VNIs. If it is
3230 * some other attribute change, the import will result in
3232 * the attributes for the route in the VNI(s).
3234 if (safi
== SAFI_EVPN
&& !same_attr
)
3235 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3237 /* Process change. */
3238 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3240 bgp_process(bgp
, rn
, afi
, safi
);
3241 bgp_unlock_node(rn
);
3243 if (SAFI_UNICAST
== safi
3244 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3245 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3247 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3249 if ((SAFI_MPLS_VPN
== safi
)
3250 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3252 vpn_leak_to_vrf_update(bgp
, ri
);
3256 if (SAFI_MPLS_VPN
== safi
) {
3257 mpls_label_t label_decoded
= decode_label(label
);
3259 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3260 type
, sub_type
, &label_decoded
);
3262 if (SAFI_ENCAP
== safi
) {
3263 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3264 type
, sub_type
, NULL
);
3269 } // End of implicit withdraw
3271 /* Received Logging. */
3272 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3273 if (!peer
->rcvd_attr_printed
) {
3274 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3275 peer
->rcvd_attr_str
);
3276 peer
->rcvd_attr_printed
= 1;
3279 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3280 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3282 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3285 /* Make new BGP info. */
3286 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3288 /* Update MPLS label */
3289 if (has_valid_label
) {
3290 extra
= bgp_info_extra_get(new);
3291 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3292 extra
->num_labels
= num_labels
;
3293 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3294 bgp_set_valid_label(&extra
->label
[0]);
3297 /* Update Overlay Index */
3298 if (afi
== AFI_L2VPN
) {
3299 overlay_index_update(new->attr
,
3300 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3301 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3303 /* Nexthop reachability check. */
3304 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3305 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3306 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3307 && !CHECK_FLAG(peer
->flags
,
3308 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3309 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3314 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3315 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3316 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3318 if (BGP_DEBUG(nht
, NHT
)) {
3319 char buf1
[INET6_ADDRSTRLEN
];
3321 (const void *)&attr_new
->nexthop
,
3322 buf1
, INET6_ADDRSTRLEN
);
3323 zlog_debug("%s(%s): NH unresolved",
3324 __FUNCTION__
, buf1
);
3326 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3329 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3332 new->addpath_rx_id
= addpath_id
;
3334 /* Increment prefix */
3335 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3337 /* Register new BGP information. */
3338 bgp_info_add(rn
, new);
3340 /* route_node_get lock */
3341 bgp_unlock_node(rn
);
3344 if (safi
== SAFI_MPLS_VPN
) {
3345 struct bgp_node
*prn
= NULL
;
3346 struct bgp_table
*table
= NULL
;
3348 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3350 table
= (struct bgp_table
*)(prn
->info
);
3352 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3353 bgp
, prd
, table
, p
, new);
3355 bgp_unlock_node(prn
);
3359 /* If maximum prefix count is configured and current prefix
3361 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3364 /* If this is an EVPN route, process for import. */
3365 if (safi
== SAFI_EVPN
)
3366 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3368 /* Process change. */
3369 bgp_process(bgp
, rn
, afi
, safi
);
3371 if (SAFI_UNICAST
== safi
3372 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3373 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3374 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3376 if ((SAFI_MPLS_VPN
== safi
)
3377 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3379 vpn_leak_to_vrf_update(bgp
, new);
3382 if (SAFI_MPLS_VPN
== safi
) {
3383 mpls_label_t label_decoded
= decode_label(label
);
3385 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3386 sub_type
, &label_decoded
);
3388 if (SAFI_ENCAP
== safi
) {
3389 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3396 /* This BGP update is filtered. Log the reason then update BGP
3399 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3400 if (!peer
->rcvd_attr_printed
) {
3401 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3402 peer
->rcvd_attr_str
);
3403 peer
->rcvd_attr_printed
= 1;
3406 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3407 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3409 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3410 peer
->host
, pfx_buf
, reason
);
3414 /* If this is an EVPN route, un-import it as it is now filtered.
3416 if (safi
== SAFI_EVPN
)
3417 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3419 if (SAFI_UNICAST
== safi
3420 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3421 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3423 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3425 if ((SAFI_MPLS_VPN
== safi
)
3426 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3428 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3431 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3434 bgp_unlock_node(rn
);
3438 * Filtered update is treated as an implicit withdrawal (see
3440 * a few lines above)
3442 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3443 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3451 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3452 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3453 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3454 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3457 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3458 struct bgp_node
*rn
;
3459 struct bgp_info
*ri
;
3462 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3463 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3471 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3473 /* If peer is soft reconfiguration enabled. Record input packet for
3474 * further calculation.
3476 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3477 * routes that are filtered. This tanks out Quagga RS pretty badly due
3479 * the iteration over all RS clients.
3480 * Since we need to remove the entry from adj_in anyway, do that first
3482 * if there was no entry, we don't need to do anything more.
3484 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3485 && peer
!= bgp
->peer_self
)
3486 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3487 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3488 bgp_debug_rdpfxpath2str(
3489 afi
, safi
, prd
, p
, label
, num_labels
,
3490 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3493 "%s withdrawing route %s not in adj-in",
3494 peer
->host
, pfx_buf
);
3496 bgp_unlock_node(rn
);
3500 /* Lookup withdrawn route. */
3501 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3502 if (ri
->peer
== peer
&& ri
->type
== type
3503 && ri
->sub_type
== sub_type
3504 && ri
->addpath_rx_id
== addpath_id
)
3508 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3509 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3510 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3512 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3516 /* Withdraw specified route from routing table. */
3517 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3518 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3519 if (SAFI_UNICAST
== safi
3520 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3521 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3522 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3524 if ((SAFI_MPLS_VPN
== safi
)
3525 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3527 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3529 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3530 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3531 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3533 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3536 /* Unlock bgp_node_get() lock. */
3537 bgp_unlock_node(rn
);
3542 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3545 struct update_subgroup
*subgrp
;
3546 subgrp
= peer_subgroup(peer
, afi
, safi
);
3547 subgroup_default_originate(subgrp
, withdraw
);
3552 * bgp_stop_announce_route_timer
3554 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3556 if (!paf
->t_announce_route
)
3559 THREAD_TIMER_OFF(paf
->t_announce_route
);
3563 * bgp_announce_route_timer_expired
3565 * Callback that is invoked when the route announcement timer for a
3568 static int bgp_announce_route_timer_expired(struct thread
*t
)
3570 struct peer_af
*paf
;
3573 paf
= THREAD_ARG(t
);
3576 if (peer
->status
!= Established
)
3579 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3582 peer_af_announce_route(paf
, 1);
3587 * bgp_announce_route
3589 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3591 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3593 struct peer_af
*paf
;
3594 struct update_subgroup
*subgrp
;
3596 paf
= peer_af_find(peer
, afi
, safi
);
3599 subgrp
= PAF_SUBGRP(paf
);
3602 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3603 * or a refresh has already been triggered.
3605 if (!subgrp
|| paf
->t_announce_route
)
3609 * Start a timer to stagger/delay the announce. This serves
3610 * two purposes - announcement can potentially be combined for
3611 * multiple peers and the announcement doesn't happen in the
3614 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3615 (subgrp
->peer_count
== 1)
3616 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3617 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3618 &paf
->t_announce_route
);
3622 * Announce routes from all AF tables to a peer.
3624 * This should ONLY be called when there is a need to refresh the
3625 * routes to the peer based on a policy change for this peer alone
3626 * or a route refresh request received from the peer.
3627 * The operation will result in splitting the peer from its existing
3628 * subgroups and putting it in new subgroups.
3630 void bgp_announce_route_all(struct peer
*peer
)
3635 FOREACH_AFI_SAFI (afi
, safi
)
3636 bgp_announce_route(peer
, afi
, safi
);
3639 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3640 struct bgp_table
*table
,
3641 struct prefix_rd
*prd
)
3644 struct bgp_node
*rn
;
3645 struct bgp_adj_in
*ain
;
3648 table
= peer
->bgp
->rib
[afi
][safi
];
3650 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3651 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3652 if (ain
->peer
!= peer
)
3655 struct bgp_info
*ri
= rn
->info
;
3656 uint32_t num_labels
= 0;
3657 mpls_label_t
*label_pnt
= NULL
;
3659 if (ri
&& ri
->extra
)
3660 num_labels
= ri
->extra
->num_labels
;
3662 label_pnt
= &ri
->extra
->label
[0];
3664 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3665 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3666 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3667 num_labels
, 1, NULL
);
3670 bgp_unlock_node(rn
);
3676 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3678 struct bgp_node
*rn
;
3679 struct bgp_table
*table
;
3681 if (peer
->status
!= Established
)
3684 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3685 && (safi
!= SAFI_EVPN
))
3686 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3688 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3689 rn
= bgp_route_next(rn
))
3690 if ((table
= rn
->info
) != NULL
) {
3691 struct prefix_rd prd
;
3692 prd
.family
= AF_UNSPEC
;
3694 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3696 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3702 struct bgp_clear_node_queue
{
3703 struct bgp_node
*rn
;
3706 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3708 struct bgp_clear_node_queue
*cnq
= data
;
3709 struct bgp_node
*rn
= cnq
->rn
;
3710 struct peer
*peer
= wq
->spec
.data
;
3711 struct bgp_info
*ri
;
3713 afi_t afi
= bgp_node_table(rn
)->afi
;
3714 safi_t safi
= bgp_node_table(rn
)->safi
;
3719 /* It is possible that we have multiple paths for a prefix from a peer
3720 * if that peer is using AddPath.
3722 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3723 if (ri
->peer
!= peer
)
3726 /* graceful restart STALE flag set. */
3727 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3728 && peer
->nsf
[afi
][safi
]
3729 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3730 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3731 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3733 /* If this is an EVPN route, process for
3735 if (safi
== SAFI_EVPN
)
3736 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3738 /* Handle withdraw for VRF route-leaking and L3VPN */
3739 if (SAFI_UNICAST
== safi
3740 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3741 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3742 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3745 if (SAFI_MPLS_VPN
== safi
&&
3746 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3747 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3750 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3756 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3758 struct bgp_clear_node_queue
*cnq
= data
;
3759 struct bgp_node
*rn
= cnq
->rn
;
3760 struct bgp_table
*table
= bgp_node_table(rn
);
3762 bgp_unlock_node(rn
);
3763 bgp_table_unlock(table
);
3764 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3767 static void bgp_clear_node_complete(struct work_queue
*wq
)
3769 struct peer
*peer
= wq
->spec
.data
;
3771 /* Tickle FSM to start moving again */
3772 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3774 peer_unlock(peer
); /* bgp_clear_route */
3777 static void bgp_clear_node_queue_init(struct peer
*peer
)
3779 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3781 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3782 #undef CLEAR_QUEUE_NAME_LEN
3784 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3786 zlog_err("%s: Failed to allocate work queue", __func__
);
3789 peer
->clear_node_queue
->spec
.hold
= 10;
3790 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3791 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3792 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3793 peer
->clear_node_queue
->spec
.max_retries
= 0;
3795 /* we only 'lock' this peer reference when the queue is actually active
3797 peer
->clear_node_queue
->spec
.data
= peer
;
3800 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3801 struct bgp_table
*table
)
3803 struct bgp_node
*rn
;
3804 int force
= bm
->process_main_queue
? 0 : 1;
3807 table
= peer
->bgp
->rib
[afi
][safi
];
3809 /* If still no table => afi/safi isn't configured at all or smth. */
3813 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3814 struct bgp_info
*ri
, *next
;
3815 struct bgp_adj_in
*ain
;
3816 struct bgp_adj_in
*ain_next
;
3818 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3819 * queued for every clearing peer, regardless of whether it is
3820 * relevant to the peer at hand.
3822 * Overview: There are 3 different indices which need to be
3823 * scrubbed, potentially, when a peer is removed:
3825 * 1 peer's routes visible via the RIB (ie accepted routes)
3826 * 2 peer's routes visible by the (optional) peer's adj-in index
3827 * 3 other routes visible by the peer's adj-out index
3829 * 3 there is no hurry in scrubbing, once the struct peer is
3830 * removed from bgp->peer, we could just GC such deleted peer's
3831 * adj-outs at our leisure.
3833 * 1 and 2 must be 'scrubbed' in some way, at least made
3834 * invisible via RIB index before peer session is allowed to be
3835 * brought back up. So one needs to know when such a 'search' is
3840 * - there'd be a single global queue or a single RIB walker
3841 * - rather than tracking which route_nodes still need to be
3842 * examined on a peer basis, we'd track which peers still
3845 * Given that our per-peer prefix-counts now should be reliable,
3846 * this may actually be achievable. It doesn't seem to be a huge
3847 * problem at this time,
3849 * It is possible that we have multiple paths for a prefix from
3851 * if that peer is using AddPath.
3855 ain_next
= ain
->next
;
3857 if (ain
->peer
== peer
) {
3858 bgp_adj_in_remove(rn
, ain
);
3859 bgp_unlock_node(rn
);
3865 for (ri
= rn
->info
; ri
; ri
= next
) {
3867 if (ri
->peer
!= peer
)
3871 bgp_info_reap(rn
, ri
);
3873 struct bgp_clear_node_queue
*cnq
;
3875 /* both unlocked in bgp_clear_node_queue_del */
3876 bgp_table_lock(bgp_node_table(rn
));
3879 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3880 sizeof(struct bgp_clear_node_queue
));
3882 work_queue_add(peer
->clear_node_queue
, cnq
);
3890 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3892 struct bgp_node
*rn
;
3893 struct bgp_table
*table
;
3895 if (peer
->clear_node_queue
== NULL
)
3896 bgp_clear_node_queue_init(peer
);
3898 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3899 * Idle until it receives a Clearing_Completed event. This protects
3900 * against peers which flap faster than we can we clear, which could
3903 * a) race with routes from the new session being installed before
3904 * clear_route_node visits the node (to delete the route of that
3906 * b) resource exhaustion, clear_route_node likely leads to an entry
3907 * on the process_main queue. Fast-flapping could cause that queue
3911 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3912 * the unlock will happen upon work-queue completion; other wise, the
3913 * unlock happens at the end of this function.
3915 if (!peer
->clear_node_queue
->thread
)
3918 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3919 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3921 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3922 rn
= bgp_route_next(rn
))
3923 if ((table
= rn
->info
) != NULL
)
3924 bgp_clear_route_table(peer
, afi
, safi
, table
);
3926 /* unlock if no nodes got added to the clear-node-queue. */
3927 if (!peer
->clear_node_queue
->thread
)
3931 void bgp_clear_route_all(struct peer
*peer
)
3936 FOREACH_AFI_SAFI (afi
, safi
)
3937 bgp_clear_route(peer
, afi
, safi
);
3940 rfapiProcessPeerDown(peer
);
3944 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3946 struct bgp_table
*table
;
3947 struct bgp_node
*rn
;
3948 struct bgp_adj_in
*ain
;
3949 struct bgp_adj_in
*ain_next
;
3951 table
= peer
->bgp
->rib
[afi
][safi
];
3953 /* It is possible that we have multiple paths for a prefix from a peer
3954 * if that peer is using AddPath.
3956 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3960 ain_next
= ain
->next
;
3962 if (ain
->peer
== peer
) {
3963 bgp_adj_in_remove(rn
, ain
);
3964 bgp_unlock_node(rn
);
3972 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3974 struct bgp_node
*rn
;
3975 struct bgp_info
*ri
;
3976 struct bgp_table
*table
;
3978 if (safi
== SAFI_MPLS_VPN
) {
3979 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3980 rn
= bgp_route_next(rn
)) {
3981 struct bgp_node
*rm
;
3982 struct bgp_info
*ri
;
3984 /* look for neighbor in tables */
3985 if ((table
= rn
->info
) == NULL
)
3988 for (rm
= bgp_table_top(table
); rm
;
3989 rm
= bgp_route_next(rm
))
3990 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3991 if (ri
->peer
!= peer
)
3993 if (!CHECK_FLAG(ri
->flags
,
3997 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4002 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4003 rn
= bgp_route_next(rn
))
4004 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4005 if (ri
->peer
!= peer
)
4007 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4009 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4015 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4018 struct bgp_node
*rn
;
4019 struct bgp_info
*ri
;
4020 struct bgp_info
*next
;
4022 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4023 for (ri
= rn
->info
; ri
; ri
= next
) {
4025 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4026 && ri
->type
== ZEBRA_ROUTE_BGP
4027 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4028 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4029 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4031 if (bgp_fibupd_safi(safi
))
4032 bgp_zebra_withdraw(&rn
->p
, ri
,
4034 bgp_info_reap(rn
, ri
);
4039 /* Delete all kernel routes. */
4040 void bgp_cleanup_routes(struct bgp
*bgp
)
4043 struct bgp_node
*rn
;
4045 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4046 if (afi
== AFI_L2VPN
)
4048 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4051 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4053 if (afi
!= AFI_L2VPN
) {
4055 safi
= SAFI_MPLS_VPN
;
4056 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4057 rn
= bgp_route_next(rn
)) {
4059 bgp_cleanup_table(bgp
,
4060 (struct bgp_table
*)(rn
->info
),
4062 bgp_table_finish((struct bgp_table
**)&(
4065 bgp_unlock_node(rn
);
4069 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4070 rn
= bgp_route_next(rn
)) {
4072 bgp_cleanup_table(bgp
,
4073 (struct bgp_table
*)(rn
->info
),
4075 bgp_table_finish((struct bgp_table
**)&(
4078 bgp_unlock_node(rn
);
4083 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4084 rn
= bgp_route_next(rn
)) {
4086 bgp_cleanup_table(bgp
,
4087 (struct bgp_table
*)(rn
->info
),
4089 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4091 bgp_unlock_node(rn
);
4096 void bgp_reset(void)
4099 bgp_zclient_reset();
4100 access_list_reset();
4101 prefix_list_reset();
4104 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4106 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4107 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4108 PEER_CAP_ADDPATH_AF_TX_RCV
));
4111 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4113 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4114 struct bgp_nlri
*packet
)
4123 int addpath_encoded
;
4124 uint32_t addpath_id
;
4127 lim
= pnt
+ packet
->length
;
4129 safi
= packet
->safi
;
4131 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4133 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4134 syntactic validity. If the field is syntactically incorrect,
4135 then the Error Subcode is set to Invalid Network Field. */
4136 for (; pnt
< lim
; pnt
+= psize
) {
4137 /* Clear prefix structure. */
4138 memset(&p
, 0, sizeof(struct prefix
));
4140 if (addpath_encoded
) {
4142 /* When packet overflow occurs return immediately. */
4143 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4146 addpath_id
= ntohl(*((uint32_t *)pnt
));
4147 pnt
+= BGP_ADDPATH_ID_LEN
;
4150 /* Fetch prefix length. */
4151 p
.prefixlen
= *pnt
++;
4152 /* afi/safi validity already verified by caller,
4153 * bgp_update_receive */
4154 p
.family
= afi2family(afi
);
4156 /* Prefix length check. */
4157 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4159 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4160 peer
->host
, p
.prefixlen
, packet
->afi
);
4164 /* Packet size overflow check. */
4165 psize
= PSIZE(p
.prefixlen
);
4167 /* When packet overflow occur return immediately. */
4168 if (pnt
+ psize
> lim
) {
4170 "%s [Error] Update packet error (prefix length %d overflows packet)",
4171 peer
->host
, p
.prefixlen
);
4175 /* Defensive coding, double-check the psize fits in a struct
4177 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4179 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4180 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4184 /* Fetch prefix from NLRI packet. */
4185 memcpy(&p
.u
.prefix
, pnt
, psize
);
4187 /* Check address. */
4188 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4189 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4190 /* From RFC4271 Section 6.3:
4192 * If a prefix in the NLRI field is semantically
4194 * (e.g., an unexpected multicast IP address),
4196 * be logged locally, and the prefix SHOULD be
4200 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4201 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4206 /* Check address. */
4207 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4208 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4212 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4214 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4219 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4223 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4225 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4232 /* Normal process. */
4234 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4235 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4236 NULL
, NULL
, 0, 0, NULL
);
4238 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4239 safi
, ZEBRA_ROUTE_BGP
,
4240 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4243 /* Address family configuration mismatch or maximum-prefix count
4249 /* Packet length consistency check. */
4252 "%s [Error] Update packet error (prefix length mismatch with total length)",
4260 static struct bgp_static
*bgp_static_new(void)
4262 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4265 static void bgp_static_free(struct bgp_static
*bgp_static
)
4267 if (bgp_static
->rmap
.name
)
4268 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4269 if (bgp_static
->eth_s_id
)
4270 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4271 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4274 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4275 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4277 struct bgp_node
*rn
;
4278 struct bgp_info
*ri
;
4279 struct bgp_info
*new;
4280 struct bgp_info info
;
4282 struct attr
*attr_new
;
4285 int vnc_implicit_withdraw
= 0;
4292 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4294 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4296 attr
.nexthop
= bgp_static
->igpnexthop
;
4297 attr
.med
= bgp_static
->igpmetric
;
4298 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4300 if (bgp_static
->atomic
)
4301 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4303 /* Store label index, if required. */
4304 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4305 attr
.label_index
= bgp_static
->label_index
;
4306 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4309 /* Apply route-map. */
4310 if (bgp_static
->rmap
.name
) {
4311 struct attr attr_tmp
= attr
;
4312 info
.peer
= bgp
->peer_self
;
4313 info
.attr
= &attr_tmp
;
4315 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4317 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4319 bgp
->peer_self
->rmap_type
= 0;
4321 if (ret
== RMAP_DENYMATCH
) {
4322 /* Free uninterned attribute. */
4323 bgp_attr_flush(&attr_tmp
);
4325 /* Unintern original. */
4326 aspath_unintern(&attr
.aspath
);
4327 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4331 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4332 bgp_attr_add_gshut_community(&attr_tmp
);
4334 attr_new
= bgp_attr_intern(&attr_tmp
);
4337 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4338 bgp_attr_add_gshut_community(&attr
);
4340 attr_new
= bgp_attr_intern(&attr
);
4343 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4344 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4345 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4349 if (attrhash_cmp(ri
->attr
, attr_new
)
4350 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4351 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4352 bgp_unlock_node(rn
);
4353 bgp_attr_unintern(&attr_new
);
4354 aspath_unintern(&attr
.aspath
);
4357 /* The attribute is changed. */
4358 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4360 /* Rewrite BGP route information. */
4361 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4362 bgp_info_restore(rn
, ri
);
4364 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4366 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4367 && (safi
== SAFI_UNICAST
)) {
4368 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4370 * Implicit withdraw case.
4371 * We have to do this before ri is
4374 ++vnc_implicit_withdraw
;
4375 vnc_import_bgp_del_route(bgp
, p
, ri
);
4376 vnc_import_bgp_exterior_del_route(
4381 bgp_attr_unintern(&ri
->attr
);
4382 ri
->attr
= attr_new
;
4383 ri
->uptime
= bgp_clock();
4385 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4386 && (safi
== SAFI_UNICAST
)) {
4387 if (vnc_implicit_withdraw
) {
4388 vnc_import_bgp_add_route(bgp
, p
, ri
);
4389 vnc_import_bgp_exterior_add_route(
4395 /* Nexthop reachability check. */
4396 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4397 && (safi
== SAFI_UNICAST
4398 || safi
== SAFI_LABELED_UNICAST
)) {
4400 struct bgp
*bgp_nexthop
= bgp
;
4402 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4403 bgp_nexthop
= ri
->extra
->bgp_orig
;
4405 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4407 bgp_info_set_flag(rn
, ri
,
4410 if (BGP_DEBUG(nht
, NHT
)) {
4411 char buf1
[INET6_ADDRSTRLEN
];
4412 inet_ntop(p
->family
,
4416 "%s(%s): Route not in table, not advertising",
4417 __FUNCTION__
, buf1
);
4419 bgp_info_unset_flag(rn
, ri
,
4423 /* Delete the NHT structure if any, if we're
4425 * enabling/disabling import check. We
4426 * deregister the route
4427 * from NHT to avoid overloading NHT and the
4428 * process interaction
4430 bgp_unlink_nexthop(ri
);
4431 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4433 /* Process change. */
4434 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4435 bgp_process(bgp
, rn
, afi
, safi
);
4437 if (SAFI_UNICAST
== safi
4438 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4440 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4441 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4445 bgp_unlock_node(rn
);
4446 aspath_unintern(&attr
.aspath
);
4451 /* Make new BGP info. */
4452 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4454 /* Nexthop reachability check. */
4455 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4456 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4457 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4458 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4460 if (BGP_DEBUG(nht
, NHT
)) {
4461 char buf1
[INET6_ADDRSTRLEN
];
4462 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4465 "%s(%s): Route not in table, not advertising",
4466 __FUNCTION__
, buf1
);
4468 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4471 /* Delete the NHT structure if any, if we're toggling between
4472 * enabling/disabling import check. We deregister the route
4473 * from NHT to avoid overloading NHT and the process interaction
4475 bgp_unlink_nexthop(new);
4477 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4480 /* Aggregate address increment. */
4481 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4483 /* Register new BGP information. */
4484 bgp_info_add(rn
, new);
4486 /* route_node_get lock */
4487 bgp_unlock_node(rn
);
4489 /* Process change. */
4490 bgp_process(bgp
, rn
, afi
, safi
);
4492 if (SAFI_UNICAST
== safi
4493 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4494 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4495 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4498 /* Unintern original. */
4499 aspath_unintern(&attr
.aspath
);
4502 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4505 struct bgp_node
*rn
;
4506 struct bgp_info
*ri
;
4508 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4510 /* Check selected route and self inserted route. */
4511 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4512 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4513 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4516 /* Withdraw static BGP route from routing table. */
4518 if (SAFI_UNICAST
== safi
4519 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4520 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4521 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4523 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4524 bgp_unlink_nexthop(ri
);
4525 bgp_info_delete(rn
, ri
);
4526 bgp_process(bgp
, rn
, afi
, safi
);
4529 /* Unlock bgp_node_lookup. */
4530 bgp_unlock_node(rn
);
4534 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4536 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4537 afi_t afi
, safi_t safi
,
4538 struct prefix_rd
*prd
)
4540 struct bgp_node
*rn
;
4541 struct bgp_info
*ri
;
4543 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4545 /* Check selected route and self inserted route. */
4546 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4547 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4548 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4551 /* Withdraw static BGP route from routing table. */
4554 rfapiProcessWithdraw(
4555 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4556 1); /* Kill, since it is an administrative change */
4558 if (SAFI_MPLS_VPN
== safi
4559 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4560 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4562 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4563 bgp_info_delete(rn
, ri
);
4564 bgp_process(bgp
, rn
, afi
, safi
);
4567 /* Unlock bgp_node_lookup. */
4568 bgp_unlock_node(rn
);
4571 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4572 struct bgp_static
*bgp_static
, afi_t afi
,
4575 struct bgp_node
*rn
;
4576 struct bgp_info
*new;
4577 struct attr
*attr_new
;
4578 struct attr attr
= {0};
4579 struct bgp_info
*ri
;
4581 mpls_label_t label
= 0;
4583 uint32_t num_labels
= 0;
4588 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4590 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4593 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4595 attr
.nexthop
= bgp_static
->igpnexthop
;
4596 attr
.med
= bgp_static
->igpmetric
;
4597 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4599 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4600 || (safi
== SAFI_ENCAP
)) {
4601 if (afi
== AFI_IP
) {
4602 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4603 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4606 if (afi
== AFI_L2VPN
) {
4607 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4609 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4610 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4611 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4612 sizeof(struct in6_addr
));
4613 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4614 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4615 struct bgp_encap_type_vxlan bet
;
4616 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4617 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4618 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4620 if (bgp_static
->router_mac
) {
4621 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4624 /* Apply route-map. */
4625 if (bgp_static
->rmap
.name
) {
4626 struct attr attr_tmp
= attr
;
4627 struct bgp_info info
;
4630 info
.peer
= bgp
->peer_self
;
4631 info
.attr
= &attr_tmp
;
4633 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4635 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4637 bgp
->peer_self
->rmap_type
= 0;
4639 if (ret
== RMAP_DENYMATCH
) {
4640 /* Free uninterned attribute. */
4641 bgp_attr_flush(&attr_tmp
);
4643 /* Unintern original. */
4644 aspath_unintern(&attr
.aspath
);
4645 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4650 attr_new
= bgp_attr_intern(&attr_tmp
);
4652 attr_new
= bgp_attr_intern(&attr
);
4655 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4656 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4657 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4662 memset(&add
, 0, sizeof(union gw_addr
));
4663 if (attrhash_cmp(ri
->attr
, attr_new
)
4664 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4665 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4666 bgp_unlock_node(rn
);
4667 bgp_attr_unintern(&attr_new
);
4668 aspath_unintern(&attr
.aspath
);
4671 /* The attribute is changed. */
4672 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4674 /* Rewrite BGP route information. */
4675 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4676 bgp_info_restore(rn
, ri
);
4678 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4679 bgp_attr_unintern(&ri
->attr
);
4680 ri
->attr
= attr_new
;
4681 ri
->uptime
= bgp_clock();
4684 label
= decode_label(&ri
->extra
->label
[0]);
4687 /* Process change. */
4688 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4689 bgp_process(bgp
, rn
, afi
, safi
);
4691 if (SAFI_MPLS_VPN
== safi
4692 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4693 vpn_leak_to_vrf_update(bgp
, ri
);
4696 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4697 ri
->attr
, afi
, safi
, ri
->type
,
4698 ri
->sub_type
, &label
);
4700 bgp_unlock_node(rn
);
4701 aspath_unintern(&attr
.aspath
);
4707 /* Make new BGP info. */
4708 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4710 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4711 new->extra
= bgp_info_extra_new();
4713 new->extra
->label
[0] = bgp_static
->label
;
4714 new->extra
->num_labels
= num_labels
;
4717 label
= decode_label(&bgp_static
->label
);
4720 /* Aggregate address increment. */
4721 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4723 /* Register new BGP information. */
4724 bgp_info_add(rn
, new);
4725 /* route_node_get lock */
4726 bgp_unlock_node(rn
);
4728 /* Process change. */
4729 bgp_process(bgp
, rn
, afi
, safi
);
4731 if (SAFI_MPLS_VPN
== safi
4732 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4733 vpn_leak_to_vrf_update(bgp
, new);
4736 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4737 safi
, new->type
, new->sub_type
, &label
);
4740 /* Unintern original. */
4741 aspath_unintern(&attr
.aspath
);
4744 /* Configure static BGP network. When user don't run zebra, static
4745 route should be installed as valid. */
4746 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4747 const char *ip_str
, afi_t afi
, safi_t safi
,
4748 const char *rmap
, int backdoor
, uint32_t label_index
)
4750 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4753 struct bgp_static
*bgp_static
;
4754 struct bgp_node
*rn
;
4755 uint8_t need_update
= 0;
4757 /* Convert IP prefix string to struct prefix. */
4758 ret
= str2prefix(ip_str
, &p
);
4760 vty_out(vty
, "%% Malformed prefix\n");
4761 return CMD_WARNING_CONFIG_FAILED
;
4763 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4764 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4765 return CMD_WARNING_CONFIG_FAILED
;
4772 /* Set BGP static route configuration. */
4773 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4776 vty_out(vty
, "%% Can't find static route specified\n");
4777 return CMD_WARNING_CONFIG_FAILED
;
4780 bgp_static
= rn
->info
;
4782 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4783 && (label_index
!= bgp_static
->label_index
)) {
4785 "%% label-index doesn't match static route\n");
4786 return CMD_WARNING_CONFIG_FAILED
;
4789 if ((rmap
&& bgp_static
->rmap
.name
)
4790 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4792 "%% route-map name doesn't match static route\n");
4793 return CMD_WARNING_CONFIG_FAILED
;
4796 /* Update BGP RIB. */
4797 if (!bgp_static
->backdoor
)
4798 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4800 /* Clear configuration. */
4801 bgp_static_free(bgp_static
);
4803 bgp_unlock_node(rn
);
4804 bgp_unlock_node(rn
);
4807 /* Set BGP static route configuration. */
4808 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4811 /* Configuration change. */
4812 bgp_static
= rn
->info
;
4814 /* Label index cannot be changed. */
4815 if (bgp_static
->label_index
!= label_index
) {
4816 vty_out(vty
, "%% cannot change label-index\n");
4817 return CMD_WARNING_CONFIG_FAILED
;
4820 /* Check previous routes are installed into BGP. */
4821 if (bgp_static
->valid
4822 && bgp_static
->backdoor
!= backdoor
)
4825 bgp_static
->backdoor
= backdoor
;
4828 if (bgp_static
->rmap
.name
)
4829 XFREE(MTYPE_ROUTE_MAP_NAME
,
4830 bgp_static
->rmap
.name
);
4831 bgp_static
->rmap
.name
=
4832 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4833 bgp_static
->rmap
.map
=
4834 route_map_lookup_by_name(rmap
);
4836 if (bgp_static
->rmap
.name
)
4837 XFREE(MTYPE_ROUTE_MAP_NAME
,
4838 bgp_static
->rmap
.name
);
4839 bgp_static
->rmap
.name
= NULL
;
4840 bgp_static
->rmap
.map
= NULL
;
4841 bgp_static
->valid
= 0;
4843 bgp_unlock_node(rn
);
4845 /* New configuration. */
4846 bgp_static
= bgp_static_new();
4847 bgp_static
->backdoor
= backdoor
;
4848 bgp_static
->valid
= 0;
4849 bgp_static
->igpmetric
= 0;
4850 bgp_static
->igpnexthop
.s_addr
= 0;
4851 bgp_static
->label_index
= label_index
;
4854 if (bgp_static
->rmap
.name
)
4855 XFREE(MTYPE_ROUTE_MAP_NAME
,
4856 bgp_static
->rmap
.name
);
4857 bgp_static
->rmap
.name
=
4858 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4859 bgp_static
->rmap
.map
=
4860 route_map_lookup_by_name(rmap
);
4862 rn
->info
= bgp_static
;
4865 bgp_static
->valid
= 1;
4867 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4869 if (!bgp_static
->backdoor
)
4870 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4876 void bgp_static_add(struct bgp
*bgp
)
4880 struct bgp_node
*rn
;
4881 struct bgp_node
*rm
;
4882 struct bgp_table
*table
;
4883 struct bgp_static
*bgp_static
;
4885 FOREACH_AFI_SAFI (afi
, safi
)
4886 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4887 rn
= bgp_route_next(rn
)) {
4888 if (rn
->info
== NULL
)
4891 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4892 || (safi
== SAFI_EVPN
)) {
4895 for (rm
= bgp_table_top(table
); rm
;
4896 rm
= bgp_route_next(rm
)) {
4897 bgp_static
= rm
->info
;
4898 bgp_static_update_safi(bgp
, &rm
->p
,
4903 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4909 /* Called from bgp_delete(). Delete all static routes from the BGP
4911 void bgp_static_delete(struct bgp
*bgp
)
4915 struct bgp_node
*rn
;
4916 struct bgp_node
*rm
;
4917 struct bgp_table
*table
;
4918 struct bgp_static
*bgp_static
;
4920 FOREACH_AFI_SAFI (afi
, safi
)
4921 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4922 rn
= bgp_route_next(rn
)) {
4923 if (rn
->info
== NULL
)
4926 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4927 || (safi
== SAFI_EVPN
)) {
4930 for (rm
= bgp_table_top(table
); rm
;
4931 rm
= bgp_route_next(rm
)) {
4932 bgp_static
= rm
->info
;
4933 bgp_static_withdraw_safi(
4934 bgp
, &rm
->p
, AFI_IP
, safi
,
4935 (struct prefix_rd
*)&rn
->p
);
4936 bgp_static_free(bgp_static
);
4938 bgp_unlock_node(rn
);
4941 bgp_static
= rn
->info
;
4942 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4943 bgp_static_free(bgp_static
);
4945 bgp_unlock_node(rn
);
4950 void bgp_static_redo_import_check(struct bgp
*bgp
)
4954 struct bgp_node
*rn
;
4955 struct bgp_node
*rm
;
4956 struct bgp_table
*table
;
4957 struct bgp_static
*bgp_static
;
4959 /* Use this flag to force reprocessing of the route */
4960 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4961 FOREACH_AFI_SAFI (afi
, safi
) {
4962 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4963 rn
= bgp_route_next(rn
)) {
4964 if (rn
->info
== NULL
)
4967 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4968 || (safi
== SAFI_EVPN
)) {
4971 for (rm
= bgp_table_top(table
); rm
;
4972 rm
= bgp_route_next(rm
)) {
4973 bgp_static
= rm
->info
;
4974 bgp_static_update_safi(bgp
, &rm
->p
,
4979 bgp_static
= rn
->info
;
4980 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4985 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4988 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4991 struct bgp_table
*table
;
4992 struct bgp_node
*rn
;
4993 struct bgp_info
*ri
;
4995 table
= bgp
->rib
[afi
][safi
];
4996 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4997 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4998 if (ri
->peer
== bgp
->peer_self
4999 && ((ri
->type
== ZEBRA_ROUTE_BGP
5000 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5001 || (ri
->type
!= ZEBRA_ROUTE_BGP
5003 == BGP_ROUTE_REDISTRIBUTE
))) {
5004 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5006 bgp_unlink_nexthop(ri
);
5007 bgp_info_delete(rn
, ri
);
5008 bgp_process(bgp
, rn
, afi
, safi
);
5015 * Purge all networks and redistributed routes from routing table.
5016 * Invoked upon the instance going down.
5018 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5023 FOREACH_AFI_SAFI (afi
, safi
)
5024 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5029 * Currently this is used to set static routes for VPN and ENCAP.
5030 * I think it can probably be factored with bgp_static_set.
5032 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5033 const char *ip_str
, const char *rd_str
,
5034 const char *label_str
, const char *rmap_str
,
5035 int evpn_type
, const char *esi
, const char *gwip
,
5036 const char *ethtag
, const char *routermac
)
5038 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5041 struct prefix_rd prd
;
5042 struct bgp_node
*prn
;
5043 struct bgp_node
*rn
;
5044 struct bgp_table
*table
;
5045 struct bgp_static
*bgp_static
;
5046 mpls_label_t label
= MPLS_INVALID_LABEL
;
5047 struct prefix gw_ip
;
5049 /* validate ip prefix */
5050 ret
= str2prefix(ip_str
, &p
);
5052 vty_out(vty
, "%% Malformed prefix\n");
5053 return CMD_WARNING_CONFIG_FAILED
;
5056 if ((afi
== AFI_L2VPN
)
5057 && (bgp_build_evpn_prefix(evpn_type
,
5058 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5059 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5060 return CMD_WARNING_CONFIG_FAILED
;
5063 ret
= str2prefix_rd(rd_str
, &prd
);
5065 vty_out(vty
, "%% Malformed rd\n");
5066 return CMD_WARNING_CONFIG_FAILED
;
5070 unsigned long label_val
;
5071 label_val
= strtoul(label_str
, NULL
, 10);
5072 encode_label(label_val
, &label
);
5075 if (safi
== SAFI_EVPN
) {
5076 if (esi
&& str2esi(esi
, NULL
) == 0) {
5077 vty_out(vty
, "%% Malformed ESI\n");
5078 return CMD_WARNING_CONFIG_FAILED
;
5080 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5081 vty_out(vty
, "%% Malformed Router MAC\n");
5082 return CMD_WARNING_CONFIG_FAILED
;
5085 memset(&gw_ip
, 0, sizeof(struct prefix
));
5086 ret
= str2prefix(gwip
, &gw_ip
);
5088 vty_out(vty
, "%% Malformed GatewayIp\n");
5089 return CMD_WARNING_CONFIG_FAILED
;
5091 if ((gw_ip
.family
== AF_INET
5092 && IS_EVPN_PREFIX_IPADDR_V6(
5093 (struct prefix_evpn
*)&p
))
5094 || (gw_ip
.family
== AF_INET6
5095 && IS_EVPN_PREFIX_IPADDR_V4(
5096 (struct prefix_evpn
*)&p
))) {
5098 "%% GatewayIp family differs with IP prefix\n");
5099 return CMD_WARNING_CONFIG_FAILED
;
5103 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5104 if (prn
->info
== NULL
)
5105 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5107 bgp_unlock_node(prn
);
5110 rn
= bgp_node_get(table
, &p
);
5113 vty_out(vty
, "%% Same network configuration exists\n");
5114 bgp_unlock_node(rn
);
5116 /* New configuration. */
5117 bgp_static
= bgp_static_new();
5118 bgp_static
->backdoor
= 0;
5119 bgp_static
->valid
= 0;
5120 bgp_static
->igpmetric
= 0;
5121 bgp_static
->igpnexthop
.s_addr
= 0;
5122 bgp_static
->label
= label
;
5123 bgp_static
->prd
= prd
;
5126 if (bgp_static
->rmap
.name
)
5127 XFREE(MTYPE_ROUTE_MAP_NAME
,
5128 bgp_static
->rmap
.name
);
5129 bgp_static
->rmap
.name
=
5130 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5131 bgp_static
->rmap
.map
=
5132 route_map_lookup_by_name(rmap_str
);
5135 if (safi
== SAFI_EVPN
) {
5137 bgp_static
->eth_s_id
=
5139 sizeof(struct eth_segment_id
));
5140 str2esi(esi
, bgp_static
->eth_s_id
);
5143 bgp_static
->router_mac
=
5144 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5145 prefix_str2mac(routermac
,
5146 bgp_static
->router_mac
);
5149 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5151 rn
->info
= bgp_static
;
5153 bgp_static
->valid
= 1;
5154 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5160 /* Configure static BGP network. */
5161 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5162 const char *ip_str
, const char *rd_str
,
5163 const char *label_str
, int evpn_type
, const char *esi
,
5164 const char *gwip
, const char *ethtag
)
5166 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5169 struct prefix_rd prd
;
5170 struct bgp_node
*prn
;
5171 struct bgp_node
*rn
;
5172 struct bgp_table
*table
;
5173 struct bgp_static
*bgp_static
;
5174 mpls_label_t label
= MPLS_INVALID_LABEL
;
5176 /* Convert IP prefix string to struct prefix. */
5177 ret
= str2prefix(ip_str
, &p
);
5179 vty_out(vty
, "%% Malformed prefix\n");
5180 return CMD_WARNING_CONFIG_FAILED
;
5183 if ((afi
== AFI_L2VPN
)
5184 && (bgp_build_evpn_prefix(evpn_type
,
5185 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5186 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5187 return CMD_WARNING_CONFIG_FAILED
;
5189 ret
= str2prefix_rd(rd_str
, &prd
);
5191 vty_out(vty
, "%% Malformed rd\n");
5192 return CMD_WARNING_CONFIG_FAILED
;
5196 unsigned long label_val
;
5197 label_val
= strtoul(label_str
, NULL
, 10);
5198 encode_label(label_val
, &label
);
5201 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5202 if (prn
->info
== NULL
)
5203 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5205 bgp_unlock_node(prn
);
5208 rn
= bgp_node_lookup(table
, &p
);
5211 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5213 bgp_static
= rn
->info
;
5214 bgp_static_free(bgp_static
);
5216 bgp_unlock_node(rn
);
5217 bgp_unlock_node(rn
);
5219 vty_out(vty
, "%% Can't find the route\n");
5224 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5225 const char *rmap_name
)
5227 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5228 struct bgp_rmap
*rmap
;
5230 rmap
= &bgp
->table_map
[afi
][safi
];
5233 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5234 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5235 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5238 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5243 if (bgp_fibupd_safi(safi
))
5244 bgp_zebra_announce_table(bgp
, afi
, safi
);
5249 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5250 const char *rmap_name
)
5252 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5253 struct bgp_rmap
*rmap
;
5255 rmap
= &bgp
->table_map
[afi
][safi
];
5257 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5261 if (bgp_fibupd_safi(safi
))
5262 bgp_zebra_announce_table(bgp
, afi
, safi
);
5267 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5270 if (bgp
->table_map
[afi
][safi
].name
) {
5271 vty_out(vty
, " table-map %s\n",
5272 bgp
->table_map
[afi
][safi
].name
);
5276 DEFUN (bgp_table_map
,
5279 "BGP table to RIB route download filter\n"
5280 "Name of the route map\n")
5283 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5284 argv
[idx_word
]->arg
);
5286 DEFUN (no_bgp_table_map
,
5287 no_bgp_table_map_cmd
,
5288 "no table-map WORD",
5290 "BGP table to RIB route download filter\n"
5291 "Name of the route map\n")
5294 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5295 argv
[idx_word
]->arg
);
5301 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5302 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5303 backdoor$backdoor}]",
5305 "Specify a network to announce via BGP\n"
5310 "Route-map to modify the attributes\n"
5311 "Name of the route map\n"
5312 "Label index to associate with the prefix\n"
5313 "Label index value\n"
5314 "Specify a BGP backdoor route\n")
5316 char addr_prefix_str
[BUFSIZ
];
5321 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5324 vty_out(vty
, "%% Inconsistent address and mask\n");
5325 return CMD_WARNING_CONFIG_FAILED
;
5329 return bgp_static_set(
5330 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5331 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5332 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5335 DEFPY(ipv6_bgp_network
,
5336 ipv6_bgp_network_cmd
,
5337 "[no] network X:X::X:X/M$prefix \
5338 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5340 "Specify a network to announce via BGP\n"
5342 "Route-map to modify the attributes\n"
5343 "Name of the route map\n"
5344 "Label index to associate with the prefix\n"
5345 "Label index value\n")
5347 return bgp_static_set(
5348 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5349 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5352 /* Aggreagete address:
5354 advertise-map Set condition to advertise attribute
5355 as-set Generate AS set path information
5356 attribute-map Set attributes of aggregate
5357 route-map Set parameters of aggregate
5358 summary-only Filter more specific routes from updates
5359 suppress-map Conditionally filter more specific routes from updates
5362 struct bgp_aggregate
{
5363 /* Summary-only flag. */
5364 uint8_t summary_only
;
5366 /* AS set generation. */
5369 /* Route-map for aggregated route. */
5370 struct route_map
*map
;
5372 /* Suppress-count. */
5373 unsigned long count
;
5375 /* SAFI configuration. */
5379 static struct bgp_aggregate
*bgp_aggregate_new(void)
5381 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5384 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5386 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5389 /* Update an aggregate as routes are added/removed from the BGP table */
5390 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5391 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5392 struct bgp_info
*del
,
5393 struct bgp_aggregate
*aggregate
)
5395 struct bgp_table
*table
;
5396 struct bgp_node
*top
;
5397 struct bgp_node
*rn
;
5399 struct aspath
*aspath
= NULL
;
5400 struct aspath
*asmerge
= NULL
;
5401 struct community
*community
= NULL
;
5402 struct community
*commerge
= NULL
;
5403 #if defined(AGGREGATE_NEXTHOP_CHECK)
5404 struct in_addr nexthop
;
5407 struct bgp_info
*ri
;
5408 struct bgp_info
*new;
5410 unsigned long match
= 0;
5411 uint8_t atomic_aggregate
= 0;
5413 /* Record adding route's nexthop and med. */
5415 #if defined(AGGREGATE_NEXTHOP_CHECK)
5416 nexthop
= rinew
->attr
->nexthop
;
5417 med
= rinew
->attr
->med
;
5421 /* ORIGIN attribute: If at least one route among routes that are
5422 aggregated has ORIGIN with the value INCOMPLETE, then the
5423 aggregated route must have the ORIGIN attribute with the value
5424 INCOMPLETE. Otherwise, if at least one route among routes that
5425 are aggregated has ORIGIN with the value EGP, then the aggregated
5426 route must have the origin attribute with the value EGP. In all
5427 other case the value of the ORIGIN attribute of the aggregated
5428 route is INTERNAL. */
5429 origin
= BGP_ORIGIN_IGP
;
5431 table
= bgp
->rib
[afi
][safi
];
5433 top
= bgp_node_get(table
, p
);
5434 for (rn
= bgp_node_get(table
, p
); rn
;
5435 rn
= bgp_route_next_until(rn
, top
))
5436 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5439 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5440 if (BGP_INFO_HOLDDOWN(ri
))
5443 if (del
&& ri
== del
)
5446 if (!rinew
&& first
) {
5447 #if defined(AGGREGATE_NEXTHOP_CHECK)
5448 nexthop
= ri
->attr
->nexthop
;
5449 med
= ri
->attr
->med
;
5454 #ifdef AGGREGATE_NEXTHOP_CHECK
5455 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5457 || ri
->attr
->med
!= med
) {
5459 aspath_free(aspath
);
5461 community_free(community
);
5462 bgp_unlock_node(rn
);
5463 bgp_unlock_node(top
);
5466 #endif /* AGGREGATE_NEXTHOP_CHECK */
5469 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5470 atomic_aggregate
= 1;
5472 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5473 if (aggregate
->summary_only
) {
5474 (bgp_info_extra_get(ri
))
5478 BGP_INFO_ATTR_CHANGED
);
5484 if (origin
< ri
->attr
->origin
)
5485 origin
= ri
->attr
->origin
;
5487 if (aggregate
->as_set
) {
5489 asmerge
= aspath_aggregate(
5492 aspath_free(aspath
);
5495 aspath
= aspath_dup(
5498 if (ri
->attr
->community
) {
5500 commerge
= community_merge(
5502 ri
->attr
->community
);
5503 community
= community_uniq_sort(
5508 community
= community_dup(
5509 ri
->attr
->community
);
5515 bgp_process(bgp
, rn
, afi
, safi
);
5517 bgp_unlock_node(top
);
5522 if (aggregate
->summary_only
)
5523 (bgp_info_extra_get(rinew
))->suppress
++;
5525 if (origin
< rinew
->attr
->origin
)
5526 origin
= rinew
->attr
->origin
;
5528 if (aggregate
->as_set
) {
5530 asmerge
= aspath_aggregate(aspath
,
5531 rinew
->attr
->aspath
);
5532 aspath_free(aspath
);
5535 aspath
= aspath_dup(rinew
->attr
->aspath
);
5537 if (rinew
->attr
->community
) {
5539 commerge
= community_merge(
5541 rinew
->attr
->community
);
5543 community_uniq_sort(commerge
);
5544 community_free(commerge
);
5546 community
= community_dup(
5547 rinew
->attr
->community
);
5552 if (aggregate
->count
> 0) {
5553 rn
= bgp_node_get(table
, p
);
5555 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5556 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5557 community
, aggregate
->as_set
,
5560 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5562 bgp_info_add(rn
, new);
5563 bgp_unlock_node(rn
);
5564 bgp_process(bgp
, rn
, afi
, safi
);
5567 aspath_free(aspath
);
5569 community_free(community
);
5573 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5574 struct bgp_aggregate
*);
5576 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5577 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5579 struct bgp_node
*child
;
5580 struct bgp_node
*rn
;
5581 struct bgp_aggregate
*aggregate
;
5582 struct bgp_table
*table
;
5584 /* MPLS-VPN aggregation is not yet supported. */
5585 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5586 || (safi
== SAFI_EVPN
)
5587 || (safi
== SAFI_FLOWSPEC
))
5590 table
= bgp
->aggregate
[afi
][safi
];
5592 /* No aggregates configured. */
5593 if (bgp_table_top_nolock(table
) == NULL
)
5596 if (p
->prefixlen
== 0)
5599 if (BGP_INFO_HOLDDOWN(ri
))
5602 child
= bgp_node_get(table
, p
);
5604 /* Aggregate address configuration check. */
5605 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5606 if ((aggregate
= rn
->info
) != NULL
5607 && rn
->p
.prefixlen
< p
->prefixlen
) {
5608 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5609 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5612 bgp_unlock_node(child
);
5615 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5616 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5618 struct bgp_node
*child
;
5619 struct bgp_node
*rn
;
5620 struct bgp_aggregate
*aggregate
;
5621 struct bgp_table
*table
;
5623 /* MPLS-VPN aggregation is not yet supported. */
5624 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5625 || (safi
== SAFI_EVPN
)
5626 || (safi
== SAFI_FLOWSPEC
))
5629 table
= bgp
->aggregate
[afi
][safi
];
5631 /* No aggregates configured. */
5632 if (bgp_table_top_nolock(table
) == NULL
)
5635 if (p
->prefixlen
== 0)
5638 child
= bgp_node_get(table
, p
);
5640 /* Aggregate address configuration check. */
5641 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5642 if ((aggregate
= rn
->info
) != NULL
5643 && rn
->p
.prefixlen
< p
->prefixlen
) {
5644 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5645 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5648 bgp_unlock_node(child
);
5651 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5652 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5653 safi_t safi
, struct bgp_aggregate
*aggregate
)
5655 struct bgp_table
*table
;
5656 struct bgp_node
*top
;
5657 struct bgp_node
*rn
;
5658 struct bgp_info
*new;
5659 struct bgp_info
*ri
;
5660 unsigned long match
;
5661 uint8_t origin
= BGP_ORIGIN_IGP
;
5662 struct aspath
*aspath
= NULL
;
5663 struct aspath
*asmerge
= NULL
;
5664 struct community
*community
= NULL
;
5665 struct community
*commerge
= NULL
;
5666 uint8_t atomic_aggregate
= 0;
5668 table
= bgp
->rib
[afi
][safi
];
5671 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5673 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5676 /* If routes exists below this node, generate aggregate routes. */
5677 top
= bgp_node_get(table
, p
);
5678 for (rn
= bgp_node_get(table
, p
); rn
;
5679 rn
= bgp_route_next_until(rn
, top
)) {
5680 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5685 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5686 if (BGP_INFO_HOLDDOWN(ri
))
5690 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5691 atomic_aggregate
= 1;
5693 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5696 /* summary-only aggregate route suppress
5697 * aggregated route announcement. */
5698 if (aggregate
->summary_only
) {
5699 (bgp_info_extra_get(ri
))->suppress
++;
5700 bgp_info_set_flag(rn
, ri
,
5701 BGP_INFO_ATTR_CHANGED
);
5705 /* If at least one route among routes that are
5706 * aggregated has ORIGIN with the value INCOMPLETE,
5707 * then the aggregated route MUST have the ORIGIN
5708 * attribute with the value INCOMPLETE. Otherwise, if
5709 * at least one route among routes that are aggregated
5710 * has ORIGIN with the value EGP, then the aggregated
5711 * route MUST have the ORIGIN attribute with the value
5714 if (origin
< ri
->attr
->origin
)
5715 origin
= ri
->attr
->origin
;
5717 /* as-set aggregate route generate origin, as path,
5718 * community aggregation. */
5719 if (aggregate
->as_set
) {
5721 asmerge
= aspath_aggregate(
5722 aspath
, ri
->attr
->aspath
);
5723 aspath_free(aspath
);
5726 aspath
= aspath_dup(ri
->attr
->aspath
);
5728 if (ri
->attr
->community
) {
5730 commerge
= community_merge(
5732 ri
->attr
->community
);
5733 community
= community_uniq_sort(
5735 community_free(commerge
);
5737 community
= community_dup(
5738 ri
->attr
->community
);
5744 /* If this node is suppressed, process the change. */
5746 bgp_process(bgp
, rn
, afi
, safi
);
5748 bgp_unlock_node(top
);
5750 /* Add aggregate route to BGP table. */
5751 if (aggregate
->count
) {
5752 rn
= bgp_node_get(table
, p
);
5754 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5755 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5756 community
, aggregate
->as_set
,
5759 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5761 bgp_info_add(rn
, new);
5762 bgp_unlock_node(rn
);
5764 /* Process change. */
5765 bgp_process(bgp
, rn
, afi
, safi
);
5768 aspath_free(aspath
);
5770 community_free(community
);
5774 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5775 safi_t safi
, struct bgp_aggregate
*aggregate
)
5777 struct bgp_table
*table
;
5778 struct bgp_node
*top
;
5779 struct bgp_node
*rn
;
5780 struct bgp_info
*ri
;
5781 unsigned long match
;
5783 table
= bgp
->rib
[afi
][safi
];
5785 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5787 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5790 /* If routes exists below this node, generate aggregate routes. */
5791 top
= bgp_node_get(table
, p
);
5792 for (rn
= bgp_node_get(table
, p
); rn
;
5793 rn
= bgp_route_next_until(rn
, top
)) {
5794 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5798 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5799 if (BGP_INFO_HOLDDOWN(ri
))
5802 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5805 if (aggregate
->summary_only
&& ri
->extra
) {
5806 ri
->extra
->suppress
--;
5808 if (ri
->extra
->suppress
== 0) {
5810 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5817 /* If this node was suppressed, process the change. */
5819 bgp_process(bgp
, rn
, afi
, safi
);
5821 bgp_unlock_node(top
);
5823 /* Delete aggregate route from BGP table. */
5824 rn
= bgp_node_get(table
, p
);
5826 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5827 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5828 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5831 /* Withdraw static BGP route from routing table. */
5833 bgp_info_delete(rn
, ri
);
5834 bgp_process(bgp
, rn
, afi
, safi
);
5837 /* Unlock bgp_node_lookup. */
5838 bgp_unlock_node(rn
);
5841 /* Aggregate route attribute. */
5842 #define AGGREGATE_SUMMARY_ONLY 1
5843 #define AGGREGATE_AS_SET 1
5845 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5846 afi_t afi
, safi_t safi
)
5848 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5851 struct bgp_node
*rn
;
5852 struct bgp_aggregate
*aggregate
;
5854 if (safi
== SAFI_FLOWSPEC
)
5855 return CMD_WARNING_CONFIG_FAILED
;
5857 /* Convert string to prefix structure. */
5858 ret
= str2prefix(prefix_str
, &p
);
5860 vty_out(vty
, "Malformed prefix\n");
5861 return CMD_WARNING_CONFIG_FAILED
;
5865 /* Old configuration check. */
5866 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5869 "%% There is no aggregate-address configuration.\n");
5870 return CMD_WARNING_CONFIG_FAILED
;
5873 aggregate
= rn
->info
;
5874 if (aggregate
->safi
== SAFI_UNICAST
)
5875 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5876 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5877 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5879 if (aggregate
->safi
== SAFI_MULTICAST
)
5880 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5882 /* Unlock aggregate address configuration. */
5884 bgp_aggregate_free(aggregate
);
5885 bgp_unlock_node(rn
);
5886 bgp_unlock_node(rn
);
5891 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5892 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5894 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5897 struct bgp_node
*rn
;
5898 struct bgp_aggregate
*aggregate
;
5900 if (safi
== SAFI_FLOWSPEC
)
5901 return CMD_WARNING_CONFIG_FAILED
;
5903 /* Convert string to prefix structure. */
5904 ret
= str2prefix(prefix_str
, &p
);
5906 vty_out(vty
, "Malformed prefix\n");
5907 return CMD_WARNING_CONFIG_FAILED
;
5911 /* Old configuration check. */
5912 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5915 vty_out(vty
, "There is already same aggregate network.\n");
5916 /* try to remove the old entry */
5917 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5919 vty_out(vty
, "Error deleting aggregate.\n");
5920 bgp_unlock_node(rn
);
5921 return CMD_WARNING_CONFIG_FAILED
;
5925 /* Make aggregate address structure. */
5926 aggregate
= bgp_aggregate_new();
5927 aggregate
->summary_only
= summary_only
;
5928 aggregate
->as_set
= as_set
;
5929 aggregate
->safi
= safi
;
5930 rn
->info
= aggregate
;
5932 /* Aggregate address insert into BGP routing table. */
5933 if (safi
== SAFI_UNICAST
)
5934 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5935 if (safi
== SAFI_LABELED_UNICAST
)
5936 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5938 if (safi
== SAFI_MULTICAST
)
5939 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5944 DEFUN (aggregate_address
,
5945 aggregate_address_cmd
,
5946 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5947 "Configure BGP aggregate entries\n"
5948 "Aggregate prefix\n"
5949 "Generate AS set path information\n"
5950 "Filter more specific routes from updates\n"
5951 "Filter more specific routes from updates\n"
5952 "Generate AS set path information\n")
5955 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5956 char *prefix
= argv
[idx
]->arg
;
5958 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5960 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5961 ? AGGREGATE_SUMMARY_ONLY
5964 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5965 summary_only
, as_set
);
5968 DEFUN (aggregate_address_mask
,
5969 aggregate_address_mask_cmd
,
5970 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5971 "Configure BGP aggregate entries\n"
5972 "Aggregate address\n"
5974 "Generate AS set path information\n"
5975 "Filter more specific routes from updates\n"
5976 "Filter more specific routes from updates\n"
5977 "Generate AS set path information\n")
5980 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5981 char *prefix
= argv
[idx
]->arg
;
5982 char *mask
= argv
[idx
+ 1]->arg
;
5984 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5986 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5987 ? AGGREGATE_SUMMARY_ONLY
5990 char prefix_str
[BUFSIZ
];
5991 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5994 vty_out(vty
, "%% Inconsistent address and mask\n");
5995 return CMD_WARNING_CONFIG_FAILED
;
5998 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5999 summary_only
, as_set
);
6002 DEFUN (no_aggregate_address
,
6003 no_aggregate_address_cmd
,
6004 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6006 "Configure BGP aggregate entries\n"
6007 "Aggregate prefix\n"
6008 "Generate AS set path information\n"
6009 "Filter more specific routes from updates\n"
6010 "Filter more specific routes from updates\n"
6011 "Generate AS set path information\n")
6014 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6015 char *prefix
= argv
[idx
]->arg
;
6016 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6019 DEFUN (no_aggregate_address_mask
,
6020 no_aggregate_address_mask_cmd
,
6021 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6023 "Configure BGP aggregate entries\n"
6024 "Aggregate address\n"
6026 "Generate AS set path information\n"
6027 "Filter more specific routes from updates\n"
6028 "Filter more specific routes from updates\n"
6029 "Generate AS set path information\n")
6032 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6033 char *prefix
= argv
[idx
]->arg
;
6034 char *mask
= argv
[idx
+ 1]->arg
;
6036 char prefix_str
[BUFSIZ
];
6037 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6040 vty_out(vty
, "%% Inconsistent address and mask\n");
6041 return CMD_WARNING_CONFIG_FAILED
;
6044 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6047 DEFUN (ipv6_aggregate_address
,
6048 ipv6_aggregate_address_cmd
,
6049 "aggregate-address X:X::X:X/M [summary-only]",
6050 "Configure BGP aggregate entries\n"
6051 "Aggregate prefix\n"
6052 "Filter more specific routes from updates\n")
6055 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6056 char *prefix
= argv
[idx
]->arg
;
6057 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6058 ? AGGREGATE_SUMMARY_ONLY
6060 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6064 DEFUN (no_ipv6_aggregate_address
,
6065 no_ipv6_aggregate_address_cmd
,
6066 "no aggregate-address X:X::X:X/M [summary-only]",
6068 "Configure BGP aggregate entries\n"
6069 "Aggregate prefix\n"
6070 "Filter more specific routes from updates\n")
6073 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6074 char *prefix
= argv
[idx
]->arg
;
6075 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6078 /* Redistribute route treatment. */
6079 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6080 const union g_addr
*nexthop
, ifindex_t ifindex
,
6081 enum nexthop_types_t nhtype
, uint32_t metric
,
6082 uint8_t type
, unsigned short instance
,
6085 struct bgp_info
*new;
6086 struct bgp_info
*bi
;
6087 struct bgp_info info
;
6088 struct bgp_node
*bn
;
6090 struct attr
*new_attr
;
6093 struct bgp_redist
*red
;
6095 /* Make default attribute. */
6096 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6099 case NEXTHOP_TYPE_IFINDEX
:
6101 case NEXTHOP_TYPE_IPV4
:
6102 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6103 attr
.nexthop
= nexthop
->ipv4
;
6105 case NEXTHOP_TYPE_IPV6
:
6106 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6107 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6108 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6110 case NEXTHOP_TYPE_BLACKHOLE
:
6111 switch (p
->family
) {
6113 attr
.nexthop
.s_addr
= INADDR_ANY
;
6116 memset(&attr
.mp_nexthop_global
, 0,
6117 sizeof(attr
.mp_nexthop_global
));
6118 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6123 attr
.nh_ifindex
= ifindex
;
6126 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6129 afi
= family2afi(p
->family
);
6131 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6133 struct attr attr_new
;
6135 /* Copy attribute for modification. */
6136 bgp_attr_dup(&attr_new
, &attr
);
6138 if (red
->redist_metric_flag
)
6139 attr_new
.med
= red
->redist_metric
;
6141 /* Apply route-map. */
6142 if (red
->rmap
.name
) {
6143 info
.peer
= bgp
->peer_self
;
6144 info
.attr
= &attr_new
;
6146 SET_FLAG(bgp
->peer_self
->rmap_type
,
6147 PEER_RMAP_TYPE_REDISTRIBUTE
);
6149 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6152 bgp
->peer_self
->rmap_type
= 0;
6154 if (ret
== RMAP_DENYMATCH
) {
6155 /* Free uninterned attribute. */
6156 bgp_attr_flush(&attr_new
);
6158 /* Unintern original. */
6159 aspath_unintern(&attr
.aspath
);
6160 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6165 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6166 bgp_attr_add_gshut_community(&attr_new
);
6168 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6169 SAFI_UNICAST
, p
, NULL
);
6171 new_attr
= bgp_attr_intern(&attr_new
);
6173 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6174 if (bi
->peer
== bgp
->peer_self
6175 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6179 /* Ensure the (source route) type is updated. */
6181 if (attrhash_cmp(bi
->attr
, new_attr
)
6182 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6183 bgp_attr_unintern(&new_attr
);
6184 aspath_unintern(&attr
.aspath
);
6185 bgp_unlock_node(bn
);
6188 /* The attribute is changed. */
6189 bgp_info_set_flag(bn
, bi
,
6190 BGP_INFO_ATTR_CHANGED
);
6192 /* Rewrite BGP route information. */
6193 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6194 bgp_info_restore(bn
, bi
);
6196 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6198 bgp_attr_unintern(&bi
->attr
);
6199 bi
->attr
= new_attr
;
6200 bi
->uptime
= bgp_clock();
6202 /* Process change. */
6203 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6205 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6206 bgp_unlock_node(bn
);
6207 aspath_unintern(&attr
.aspath
);
6209 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6211 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6213 vpn_leak_from_vrf_update(
6214 bgp_get_default(), bgp
, bi
);
6220 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6221 bgp
->peer_self
, new_attr
, bn
);
6222 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6224 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6225 bgp_info_add(bn
, new);
6226 bgp_unlock_node(bn
);
6227 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6229 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6230 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6232 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6236 /* Unintern original. */
6237 aspath_unintern(&attr
.aspath
);
6240 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6241 unsigned short instance
)
6244 struct bgp_node
*rn
;
6245 struct bgp_info
*ri
;
6246 struct bgp_redist
*red
;
6248 afi
= family2afi(p
->family
);
6250 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6252 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6253 SAFI_UNICAST
, p
, NULL
);
6255 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6256 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6260 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6261 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6263 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6266 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6267 bgp_info_delete(rn
, ri
);
6268 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6270 bgp_unlock_node(rn
);
6274 /* Withdraw specified route type's route. */
6275 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6276 unsigned short instance
)
6278 struct bgp_node
*rn
;
6279 struct bgp_info
*ri
;
6280 struct bgp_table
*table
;
6282 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6284 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6285 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6286 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6287 && ri
->instance
== instance
)
6291 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6292 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6294 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6297 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6299 bgp_info_delete(rn
, ri
);
6300 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6305 /* Static function to display route. */
6306 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6310 uint32_t destination
;
6313 if (p
->family
== AF_INET
) {
6315 len
= vty_out(vty
, "%s",
6316 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6318 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6320 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6321 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6322 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6323 || p
->u
.prefix4
.s_addr
== 0) {
6324 /* When mask is natural,
6325 mask is not displayed. */
6327 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6329 json_object_string_add(json
, "prefix",
6330 inet_ntop(p
->family
,
6333 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6335 } else if (p
->family
== AF_ETHERNET
) {
6336 prefix2str(p
, buf
, PREFIX_STRLEN
);
6337 len
= vty_out(vty
, "%s", buf
);
6338 } else if (p
->family
== AF_EVPN
) {
6339 #if defined(HAVE_CUMULUS)
6343 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6346 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6348 prefix2str(p
, buf
, PREFIX_STRLEN
);
6349 len
= vty_out(vty
, "%s", buf
);
6351 } else if (p
->family
== AF_FLOWSPEC
) {
6352 route_vty_out_flowspec(vty
, p
, NULL
,
6354 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6355 NLRI_STRING_FORMAT_MIN
, json
);
6360 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6367 vty_out(vty
, "\n%*s", 20, " ");
6369 vty_out(vty
, "%*s", len
, " ");
6373 enum bgp_display_type
{
6377 /* Print the short form route status for a bgp_info */
6378 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6379 json_object
*json_path
)
6383 /* Route status display. */
6384 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6385 json_object_boolean_true_add(json_path
, "removed");
6387 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6388 json_object_boolean_true_add(json_path
, "stale");
6390 if (binfo
->extra
&& binfo
->extra
->suppress
)
6391 json_object_boolean_true_add(json_path
, "suppressed");
6393 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6394 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6395 json_object_boolean_true_add(json_path
, "valid");
6398 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6399 json_object_boolean_true_add(json_path
, "history");
6401 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6402 json_object_boolean_true_add(json_path
, "damped");
6404 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6405 json_object_boolean_true_add(json_path
, "bestpath");
6407 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6408 json_object_boolean_true_add(json_path
, "multipath");
6410 /* Internal route. */
6411 if ((binfo
->peer
->as
)
6412 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6413 json_object_string_add(json_path
, "pathFrom",
6416 json_object_string_add(json_path
, "pathFrom",
6422 /* Route status display. */
6423 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6425 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6427 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6429 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6430 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6436 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6438 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6440 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6442 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6447 /* Internal route. */
6448 if (binfo
->peer
&& (binfo
->peer
->as
)
6449 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6455 /* called from terminal list command */
6456 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6457 int display
, safi_t safi
, json_object
*json_paths
)
6460 json_object
*json_path
= NULL
;
6461 json_object
*json_nexthops
= NULL
;
6462 json_object
*json_nexthop_global
= NULL
;
6463 json_object
*json_nexthop_ll
= NULL
;
6466 json_path
= json_object_new_object();
6468 /* short status lead text */
6469 route_vty_short_status_out(vty
, binfo
, json_path
);
6472 /* print prefix and mask */
6474 route_vty_out_route(p
, vty
, json_path
);
6476 vty_out(vty
, "%*s", 17, " ");
6478 route_vty_out_route(p
, vty
, json_path
);
6481 /* Print attribute */
6485 json_object_array_add(json_paths
, json_path
);
6493 * For ENCAP and EVPN routes, nexthop address family is not
6494 * neccessarily the same as the prefix address family.
6495 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6496 * EVPN routes are also exchanged with a MP nexthop. Currently,
6498 * is only IPv4, the value will be present in either
6500 * attr->mp_nexthop_global_in
6502 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6505 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6509 sprintf(nexthop
, "%s",
6510 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6514 sprintf(nexthop
, "%s",
6515 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6519 sprintf(nexthop
, "?");
6524 json_nexthop_global
= json_object_new_object();
6526 json_object_string_add(json_nexthop_global
, "afi",
6527 (af
== AF_INET
) ? "ip" : "ipv6");
6528 json_object_string_add(json_nexthop_global
,
6529 (af
== AF_INET
) ? "ip" : "ipv6",
6531 json_object_boolean_true_add(json_nexthop_global
,
6534 vty_out(vty
, "%s", nexthop
);
6535 } else if (safi
== SAFI_EVPN
) {
6537 json_nexthop_global
= json_object_new_object();
6539 json_object_string_add(json_nexthop_global
, "ip",
6540 inet_ntoa(attr
->nexthop
));
6541 json_object_string_add(json_nexthop_global
, "afi",
6543 json_object_boolean_true_add(json_nexthop_global
,
6546 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6547 } else if (safi
== SAFI_FLOWSPEC
) {
6548 if (attr
->nexthop
.s_addr
!= 0) {
6550 json_nexthop_global
= json_object_new_object();
6551 json_object_string_add(
6552 json_nexthop_global
, "ip",
6553 inet_ntoa(attr
->nexthop
));
6554 json_object_string_add(json_nexthop_global
,
6556 json_object_boolean_true_add(json_nexthop_global
,
6559 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6562 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6564 json_nexthop_global
= json_object_new_object();
6566 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6567 json_object_string_add(
6568 json_nexthop_global
, "ip",
6569 inet_ntoa(attr
->mp_nexthop_global_in
));
6571 json_object_string_add(
6572 json_nexthop_global
, "ip",
6573 inet_ntoa(attr
->nexthop
));
6575 json_object_string_add(json_nexthop_global
, "afi",
6577 json_object_boolean_true_add(json_nexthop_global
,
6580 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6581 vty_out(vty
, "%-16s",
6582 inet_ntoa(attr
->mp_nexthop_global_in
));
6584 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6589 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6594 json_nexthop_global
= json_object_new_object();
6595 json_object_string_add(
6596 json_nexthop_global
, "ip",
6597 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6599 json_object_string_add(json_nexthop_global
, "afi",
6601 json_object_string_add(json_nexthop_global
, "scope",
6604 /* We display both LL & GL if both have been
6606 if ((attr
->mp_nexthop_len
== 32)
6607 || (binfo
->peer
->conf_if
)) {
6608 json_nexthop_ll
= json_object_new_object();
6609 json_object_string_add(
6610 json_nexthop_ll
, "ip",
6612 &attr
->mp_nexthop_local
, buf
,
6614 json_object_string_add(json_nexthop_ll
, "afi",
6616 json_object_string_add(json_nexthop_ll
, "scope",
6619 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6620 &attr
->mp_nexthop_local
)
6622 && !attr
->mp_nexthop_prefer_global
)
6623 json_object_boolean_true_add(
6624 json_nexthop_ll
, "used");
6626 json_object_boolean_true_add(
6627 json_nexthop_global
, "used");
6629 json_object_boolean_true_add(
6630 json_nexthop_global
, "used");
6632 /* Display LL if LL/Global both in table unless
6633 * prefer-global is set */
6634 if (((attr
->mp_nexthop_len
== 32)
6635 && !attr
->mp_nexthop_prefer_global
)
6636 || (binfo
->peer
->conf_if
)) {
6637 if (binfo
->peer
->conf_if
) {
6638 len
= vty_out(vty
, "%s",
6639 binfo
->peer
->conf_if
);
6640 len
= 16 - len
; /* len of IPv6
6646 vty_out(vty
, "\n%*s", 36, " ");
6648 vty_out(vty
, "%*s", len
, " ");
6654 &attr
->mp_nexthop_local
,
6659 vty_out(vty
, "\n%*s", 36, " ");
6661 vty_out(vty
, "%*s", len
, " ");
6667 &attr
->mp_nexthop_global
, buf
,
6672 vty_out(vty
, "\n%*s", 36, " ");
6674 vty_out(vty
, "%*s", len
, " ");
6680 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6682 json_object_int_add(json_path
, "med", attr
->med
);
6684 vty_out(vty
, "%10u", attr
->med
);
6685 else if (!json_paths
)
6689 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6691 json_object_int_add(json_path
, "localpref",
6694 vty_out(vty
, "%7u", attr
->local_pref
);
6695 else if (!json_paths
)
6699 json_object_int_add(json_path
, "weight", attr
->weight
);
6701 vty_out(vty
, "%7u ", attr
->weight
);
6705 json_object_string_add(
6706 json_path
, "peerId",
6707 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6713 json_object_string_add(json_path
, "aspath",
6716 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6721 json_object_string_add(json_path
, "origin",
6722 bgp_origin_long_str
[attr
->origin
]);
6724 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6727 if (json_nexthop_global
|| json_nexthop_ll
) {
6728 json_nexthops
= json_object_new_array();
6730 if (json_nexthop_global
)
6731 json_object_array_add(json_nexthops
,
6732 json_nexthop_global
);
6734 if (json_nexthop_ll
)
6735 json_object_array_add(json_nexthops
,
6738 json_object_object_add(json_path
, "nexthops",
6742 json_object_array_add(json_paths
, json_path
);
6746 /* prints an additional line, indented, with VNC info, if
6748 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6749 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6754 /* called from terminal list command */
6755 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6756 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6758 json_object
*json_status
= NULL
;
6759 json_object
*json_net
= NULL
;
6761 /* Route status display. */
6763 json_status
= json_object_new_object();
6764 json_net
= json_object_new_object();
6771 /* print prefix and mask */
6773 json_object_string_add(
6774 json_net
, "addrPrefix",
6775 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6777 route_vty_out_route(p
, vty
, NULL
);
6779 /* Print attribute */
6782 if (p
->family
== AF_INET
6783 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6784 || safi
== SAFI_EVPN
6785 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6786 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6787 || safi
== SAFI_EVPN
)
6788 json_object_string_add(
6789 json_net
, "nextHop",
6791 attr
->mp_nexthop_global_in
));
6793 json_object_string_add(
6794 json_net
, "nextHop",
6795 inet_ntoa(attr
->nexthop
));
6796 } else if (p
->family
== AF_INET6
6797 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6800 json_object_string_add(
6801 json_net
, "netHopGloabal",
6803 &attr
->mp_nexthop_global
, buf
,
6808 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6809 json_object_int_add(json_net
, "metric",
6812 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6813 json_object_int_add(json_net
, "localPref",
6816 json_object_int_add(json_net
, "weight", attr
->weight
);
6820 json_object_string_add(json_net
, "asPath",
6824 json_object_string_add(json_net
, "bgpOriginCode",
6825 bgp_origin_str
[attr
->origin
]);
6827 if (p
->family
== AF_INET
6828 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6829 || safi
== SAFI_EVPN
6830 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6831 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6832 || safi
== SAFI_EVPN
)
6833 vty_out(vty
, "%-16s",
6835 attr
->mp_nexthop_global_in
));
6837 vty_out(vty
, "%-16s",
6838 inet_ntoa(attr
->nexthop
));
6839 } else if (p
->family
== AF_INET6
6840 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6847 &attr
->mp_nexthop_global
, buf
,
6851 vty_out(vty
, "\n%*s", 36, " ");
6853 vty_out(vty
, "%*s", len
, " ");
6856 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6857 vty_out(vty
, "%10u", attr
->med
);
6861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6862 vty_out(vty
, "%7u", attr
->local_pref
);
6866 vty_out(vty
, "%7u ", attr
->weight
);
6870 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6873 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6877 json_object_boolean_true_add(json_status
, "*");
6878 json_object_boolean_true_add(json_status
, ">");
6879 json_object_object_add(json_net
, "appliedStatusSymbols",
6881 char buf_cut
[BUFSIZ
];
6882 json_object_object_add(
6884 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6890 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6891 struct bgp_info
*binfo
, int display
, safi_t safi
,
6894 json_object
*json_out
= NULL
;
6896 mpls_label_t label
= MPLS_INVALID_LABEL
;
6902 json_out
= json_object_new_object();
6904 /* short status lead text */
6905 route_vty_short_status_out(vty
, binfo
, json_out
);
6907 /* print prefix and mask */
6910 route_vty_out_route(p
, vty
, NULL
);
6912 vty_out(vty
, "%*s", 17, " ");
6915 /* Print attribute */
6918 if (((p
->family
== AF_INET
)
6919 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6920 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6921 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6922 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6923 || safi
== SAFI_EVPN
) {
6925 json_object_string_add(
6926 json_out
, "mpNexthopGlobalIn",
6928 attr
->mp_nexthop_global_in
));
6930 vty_out(vty
, "%-16s",
6932 attr
->mp_nexthop_global_in
));
6935 json_object_string_add(
6936 json_out
, "nexthop",
6937 inet_ntoa(attr
->nexthop
));
6939 vty_out(vty
, "%-16s",
6940 inet_ntoa(attr
->nexthop
));
6942 } else if (((p
->family
== AF_INET6
)
6943 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6944 || (safi
== SAFI_EVPN
6945 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6946 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6950 if (attr
->mp_nexthop_len
6951 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6953 json_object_string_add(
6954 json_out
, "mpNexthopGlobalIn",
6957 &attr
->mp_nexthop_global
,
6963 &attr
->mp_nexthop_global
,
6965 } else if (attr
->mp_nexthop_len
6966 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6969 &attr
->mp_nexthop_global
,
6972 &attr
->mp_nexthop_local
,
6974 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6975 json_object_string_add(
6977 "mpNexthopGlobalLocal", buf_c
);
6979 vty_out(vty
, "%s(%s)",
6982 &attr
->mp_nexthop_global
,
6986 &attr
->mp_nexthop_local
,
6992 label
= decode_label(&binfo
->extra
->label
[0]);
6994 if (bgp_is_valid_label(&label
)) {
6996 json_object_int_add(json_out
, "notag", label
);
6997 json_object_array_add(json
, json_out
);
6999 vty_out(vty
, "notag/%d", label
);
7005 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7006 struct bgp_info
*binfo
, int display
,
7007 json_object
*json_paths
)
7011 json_object
*json_path
= NULL
;
7014 json_path
= json_object_new_object();
7019 /* short status lead text */
7020 route_vty_short_status_out(vty
, binfo
, json_path
);
7022 /* print prefix and mask */
7024 route_vty_out_route(p
, vty
, NULL
);
7026 vty_out(vty
, "%*s", 17, " ");
7028 /* Print attribute */
7032 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7036 vty_out(vty
, "%-16s",
7037 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7041 vty_out(vty
, "%s(%s)",
7042 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7044 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7051 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7053 vty_out(vty
, "%s", str
);
7054 XFREE(MTYPE_TMP
, str
);
7056 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7058 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7059 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7062 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7065 if (attr
->ecommunity
) {
7067 struct ecommunity_val
*routermac
= ecommunity_lookup(
7068 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7069 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7071 mac
= ecom_mac2str((char *)routermac
->val
);
7073 vty_out(vty
, "/%s", (char *)mac
);
7074 XFREE(MTYPE_TMP
, mac
);
7082 /* dampening route */
7083 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7084 struct bgp_info
*binfo
, int display
, safi_t safi
,
7085 uint8_t use_json
, json_object
*json
)
7089 char timebuf
[BGP_UPTIME_LEN
];
7091 /* short status lead text */
7092 route_vty_short_status_out(vty
, binfo
, json
);
7094 /* print prefix and mask */
7097 route_vty_out_route(p
, vty
, NULL
);
7099 vty_out(vty
, "%*s", 17, " ");
7102 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7106 vty_out(vty
, "\n%*s", 34, " ");
7109 json_object_int_add(json
, "peerHost", len
);
7111 vty_out(vty
, "%*s", len
, " ");
7115 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7118 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7122 /* Print attribute */
7128 json_object_string_add(json
, "asPath",
7131 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7136 json_object_string_add(json
, "origin",
7137 bgp_origin_str
[attr
->origin
]);
7139 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7146 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7147 struct bgp_info
*binfo
, int display
, safi_t safi
,
7148 uint8_t use_json
, json_object
*json
)
7151 struct bgp_damp_info
*bdi
;
7152 char timebuf
[BGP_UPTIME_LEN
];
7158 bdi
= binfo
->extra
->damp_info
;
7160 /* short status lead text */
7161 route_vty_short_status_out(vty
, binfo
, json
);
7163 /* print prefix and mask */
7166 route_vty_out_route(p
, vty
, NULL
);
7168 vty_out(vty
, "%*s", 17, " ");
7171 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7175 vty_out(vty
, "\n%*s", 33, " ");
7178 json_object_int_add(json
, "peerHost", len
);
7180 vty_out(vty
, "%*s", len
, " ");
7183 len
= vty_out(vty
, "%d", bdi
->flap
);
7190 json_object_int_add(json
, "bdiFlap", len
);
7192 vty_out(vty
, "%*s", len
, " ");
7196 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7199 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7200 BGP_UPTIME_LEN
, 0, NULL
));
7202 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7203 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7205 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7206 BGP_UPTIME_LEN
, use_json
, json
);
7209 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7214 vty_out(vty
, "%*s ", 8, " ");
7217 /* Print attribute */
7223 json_object_string_add(json
, "asPath",
7226 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7231 json_object_string_add(json
, "origin",
7232 bgp_origin_str
[attr
->origin
]);
7234 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7240 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7241 int *first
, const char *header
,
7242 json_object
*json_adv_to
)
7244 char buf1
[INET6_ADDRSTRLEN
];
7245 json_object
*json_peer
= NULL
;
7248 /* 'advertised-to' is a dictionary of peers we have advertised
7250 * prefix too. The key is the peer's IP or swpX, the value is
7252 * hostname if we know it and "" if not.
7254 json_peer
= json_object_new_object();
7257 json_object_string_add(json_peer
, "hostname",
7261 json_object_object_add(json_adv_to
, peer
->conf_if
,
7264 json_object_object_add(
7266 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7270 vty_out(vty
, "%s", header
);
7275 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7277 vty_out(vty
, " %s(%s)", peer
->hostname
,
7280 vty_out(vty
, " %s(%s)", peer
->hostname
,
7281 sockunion2str(&peer
->su
, buf1
,
7285 vty_out(vty
, " %s", peer
->conf_if
);
7288 sockunion2str(&peer
->su
, buf1
,
7294 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7295 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7296 json_object
*json_paths
)
7298 char buf
[INET6_ADDRSTRLEN
];
7300 #if defined(HAVE_CUMULUS)
7301 char buf2
[EVPN_ROUTE_STRLEN
];
7304 int sockunion_vty_out(struct vty
*, union sockunion
*);
7306 json_object
*json_bestpath
= NULL
;
7307 json_object
*json_cluster_list
= NULL
;
7308 json_object
*json_cluster_list_list
= NULL
;
7309 json_object
*json_ext_community
= NULL
;
7310 json_object
*json_lcommunity
= NULL
;
7311 json_object
*json_last_update
= NULL
;
7312 json_object
*json_pmsi
= NULL
;
7313 json_object
*json_nexthop_global
= NULL
;
7314 json_object
*json_nexthop_ll
= NULL
;
7315 json_object
*json_nexthops
= NULL
;
7316 json_object
*json_path
= NULL
;
7317 json_object
*json_peer
= NULL
;
7318 json_object
*json_string
= NULL
;
7319 json_object
*json_adv_to
= NULL
;
7321 struct listnode
*node
, *nnode
;
7323 int addpath_capable
;
7325 unsigned int first_as
;
7328 json_path
= json_object_new_object();
7329 json_peer
= json_object_new_object();
7330 json_nexthop_global
= json_object_new_object();
7333 #if defined(HAVE_CUMULUS)
7334 if (!json_paths
&& safi
== SAFI_EVPN
) {
7337 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7338 vty_out(vty
, " Route %s", buf2
);
7340 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7341 bgp_evpn_label2str(binfo
->extra
->label
,
7342 binfo
->extra
->num_labels
, tag_buf
,
7344 vty_out(vty
, " VNI %s", tag_buf
);
7347 if (binfo
->extra
&& binfo
->extra
->parent
) {
7348 struct bgp_info
*parent_ri
;
7349 struct bgp_node
*rn
, *prn
;
7351 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7352 rn
= parent_ri
->net
;
7353 if (rn
&& rn
->prn
) {
7355 vty_out(vty
, " Imported from %s:%s\n",
7357 (struct prefix_rd
*)&prn
->p
,
7358 buf1
, sizeof(buf1
)),
7368 /* Line1 display AS-path, Aggregator */
7371 if (!attr
->aspath
->json
)
7372 aspath_str_update(attr
->aspath
, true);
7373 json_object_lock(attr
->aspath
->json
);
7374 json_object_object_add(json_path
, "aspath",
7375 attr
->aspath
->json
);
7377 if (attr
->aspath
->segments
)
7378 aspath_print_vty(vty
, " %s",
7381 vty_out(vty
, " Local");
7385 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7387 json_object_boolean_true_add(json_path
,
7390 vty_out(vty
, ", (removed)");
7393 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7395 json_object_boolean_true_add(json_path
,
7398 vty_out(vty
, ", (stale)");
7401 if (CHECK_FLAG(attr
->flag
,
7402 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7404 json_object_int_add(json_path
, "aggregatorAs",
7405 attr
->aggregator_as
);
7406 json_object_string_add(
7407 json_path
, "aggregatorId",
7408 inet_ntoa(attr
->aggregator_addr
));
7410 vty_out(vty
, ", (aggregated by %u %s)",
7411 attr
->aggregator_as
,
7412 inet_ntoa(attr
->aggregator_addr
));
7416 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7417 PEER_FLAG_REFLECTOR_CLIENT
)) {
7419 json_object_boolean_true_add(
7420 json_path
, "rxedFromRrClient");
7422 vty_out(vty
, ", (Received from a RR-client)");
7425 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7426 PEER_FLAG_RSERVER_CLIENT
)) {
7428 json_object_boolean_true_add(
7429 json_path
, "rxedFromRsClient");
7431 vty_out(vty
, ", (Received from a RS-client)");
7434 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7436 json_object_boolean_true_add(
7437 json_path
, "dampeningHistoryEntry");
7439 vty_out(vty
, ", (history entry)");
7440 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7442 json_object_boolean_true_add(
7443 json_path
, "dampeningSuppressed");
7445 vty_out(vty
, ", (suppressed due to dampening)");
7451 /* Line2 display Next-hop, Neighbor, Router-id */
7452 /* Display the nexthop */
7453 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7454 || p
->family
== AF_EVPN
)
7455 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7456 || safi
== SAFI_EVPN
7457 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7458 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7459 || safi
== SAFI_EVPN
) {
7461 json_object_string_add(
7462 json_nexthop_global
, "ip",
7464 attr
->mp_nexthop_global_in
));
7468 attr
->mp_nexthop_global_in
));
7471 json_object_string_add(
7472 json_nexthop_global
, "ip",
7473 inet_ntoa(attr
->nexthop
));
7476 inet_ntoa(attr
->nexthop
));
7480 json_object_string_add(json_nexthop_global
,
7484 json_object_string_add(
7485 json_nexthop_global
, "ip",
7487 &attr
->mp_nexthop_global
, buf
,
7489 json_object_string_add(json_nexthop_global
,
7491 json_object_string_add(json_nexthop_global
,
7496 &attr
->mp_nexthop_global
, buf
,
7501 /* Display the IGP cost or 'inaccessible' */
7502 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7504 json_object_boolean_false_add(
7505 json_nexthop_global
, "accessible");
7507 vty_out(vty
, " (inaccessible)");
7509 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7511 json_object_int_add(
7512 json_nexthop_global
, "metric",
7513 binfo
->extra
->igpmetric
);
7515 vty_out(vty
, " (metric %u)",
7516 binfo
->extra
->igpmetric
);
7519 /* IGP cost is 0, display this only for json */
7522 json_object_int_add(json_nexthop_global
,
7527 json_object_boolean_true_add(
7528 json_nexthop_global
, "accessible");
7531 /* Display peer "from" output */
7532 /* This path was originated locally */
7533 if (binfo
->peer
== bgp
->peer_self
) {
7535 if (safi
== SAFI_EVPN
7536 || (p
->family
== AF_INET
7537 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7539 json_object_string_add(
7540 json_peer
, "peerId", "0.0.0.0");
7542 vty_out(vty
, " from 0.0.0.0 ");
7545 json_object_string_add(json_peer
,
7548 vty_out(vty
, " from :: ");
7552 json_object_string_add(
7553 json_peer
, "routerId",
7554 inet_ntoa(bgp
->router_id
));
7556 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7559 /* We RXed this path from one of our peers */
7563 json_object_string_add(
7564 json_peer
, "peerId",
7565 sockunion2str(&binfo
->peer
->su
, buf
,
7567 json_object_string_add(
7568 json_peer
, "routerId",
7570 &binfo
->peer
->remote_id
, buf1
,
7573 if (binfo
->peer
->hostname
)
7574 json_object_string_add(
7575 json_peer
, "hostname",
7576 binfo
->peer
->hostname
);
7578 if (binfo
->peer
->domainname
)
7579 json_object_string_add(
7580 json_peer
, "domainname",
7581 binfo
->peer
->domainname
);
7583 if (binfo
->peer
->conf_if
)
7584 json_object_string_add(
7585 json_peer
, "interface",
7586 binfo
->peer
->conf_if
);
7588 if (binfo
->peer
->conf_if
) {
7589 if (binfo
->peer
->hostname
7592 BGP_FLAG_SHOW_HOSTNAME
))
7593 vty_out(vty
, " from %s(%s)",
7594 binfo
->peer
->hostname
,
7595 binfo
->peer
->conf_if
);
7597 vty_out(vty
, " from %s",
7598 binfo
->peer
->conf_if
);
7600 if (binfo
->peer
->hostname
7603 BGP_FLAG_SHOW_HOSTNAME
))
7604 vty_out(vty
, " from %s(%s)",
7605 binfo
->peer
->hostname
,
7608 vty_out(vty
, " from %s",
7617 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7618 vty_out(vty
, " (%s)",
7619 inet_ntoa(attr
->originator_id
));
7621 vty_out(vty
, " (%s)",
7624 &binfo
->peer
->remote_id
,
7625 buf1
, sizeof(buf1
)));
7632 /* display the link-local nexthop */
7633 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7635 json_nexthop_ll
= json_object_new_object();
7636 json_object_string_add(
7637 json_nexthop_ll
, "ip",
7639 &attr
->mp_nexthop_local
, buf
,
7641 json_object_string_add(json_nexthop_ll
, "afi",
7643 json_object_string_add(json_nexthop_ll
, "scope",
7646 json_object_boolean_true_add(json_nexthop_ll
,
7649 if (!attr
->mp_nexthop_prefer_global
)
7650 json_object_boolean_true_add(
7651 json_nexthop_ll
, "used");
7653 json_object_boolean_true_add(
7654 json_nexthop_global
, "used");
7656 vty_out(vty
, " (%s) %s\n",
7658 &attr
->mp_nexthop_local
, buf
,
7660 attr
->mp_nexthop_prefer_global
7665 /* If we do not have a link-local nexthop then we must flag the
7669 json_object_boolean_true_add(
7670 json_nexthop_global
, "used");
7673 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7674 * Int/Ext/Local, Atomic, best */
7676 json_object_string_add(
7677 json_path
, "origin",
7678 bgp_origin_long_str
[attr
->origin
]);
7680 vty_out(vty
, " Origin %s",
7681 bgp_origin_long_str
[attr
->origin
]);
7683 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7685 json_object_int_add(json_path
, "med",
7688 vty_out(vty
, ", metric %u", attr
->med
);
7691 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7693 json_object_int_add(json_path
, "localpref",
7696 vty_out(vty
, ", localpref %u",
7700 json_object_int_add(json_path
, "localpref",
7701 bgp
->default_local_pref
);
7703 vty_out(vty
, ", localpref %u",
7704 bgp
->default_local_pref
);
7707 if (attr
->weight
!= 0) {
7709 json_object_int_add(json_path
, "weight",
7712 vty_out(vty
, ", weight %u", attr
->weight
);
7715 if (attr
->tag
!= 0) {
7717 json_object_int_add(json_path
, "tag",
7720 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7724 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7726 json_object_boolean_false_add(json_path
,
7729 vty_out(vty
, ", invalid");
7730 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7732 json_object_boolean_true_add(json_path
,
7735 vty_out(vty
, ", valid");
7738 if (binfo
->peer
!= bgp
->peer_self
) {
7739 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7740 if (CHECK_FLAG(bgp
->config
,
7741 BGP_CONFIG_CONFEDERATION
)) {
7743 json_object_string_add(
7748 ", confed-internal");
7751 json_object_string_add(
7755 vty_out(vty
, ", internal");
7758 if (bgp_confederation_peers_check(
7759 bgp
, binfo
->peer
->as
)) {
7761 json_object_string_add(
7766 ", confed-external");
7769 json_object_string_add(
7773 vty_out(vty
, ", external");
7776 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7778 json_object_boolean_true_add(json_path
,
7780 json_object_boolean_true_add(json_path
,
7783 vty_out(vty
, ", aggregated, local");
7785 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7787 json_object_boolean_true_add(json_path
,
7790 vty_out(vty
, ", sourced");
7793 json_object_boolean_true_add(json_path
,
7795 json_object_boolean_true_add(json_path
,
7798 vty_out(vty
, ", sourced, local");
7802 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7804 json_object_boolean_true_add(json_path
,
7807 vty_out(vty
, ", atomic-aggregate");
7810 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7811 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7812 && bgp_info_mpath_count(binfo
))) {
7814 json_object_boolean_true_add(json_path
,
7817 vty_out(vty
, ", multipath");
7820 // Mark the bestpath(s)
7821 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7822 first_as
= aspath_get_first_as(attr
->aspath
);
7827 json_object_new_object();
7828 json_object_int_add(json_bestpath
,
7829 "bestpathFromAs", first_as
);
7832 vty_out(vty
, ", bestpath-from-AS %u",
7836 ", bestpath-from-AS Local");
7840 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7844 json_object_new_object();
7845 json_object_boolean_true_add(json_bestpath
,
7848 vty_out(vty
, ", best");
7852 json_object_object_add(json_path
, "bestpath",
7858 /* Line 4 display Community */
7859 if (attr
->community
) {
7861 if (!attr
->community
->json
)
7862 community_str(attr
->community
, true);
7863 json_object_lock(attr
->community
->json
);
7864 json_object_object_add(json_path
, "community",
7865 attr
->community
->json
);
7867 vty_out(vty
, " Community: %s\n",
7868 attr
->community
->str
);
7872 /* Line 5 display Extended-community */
7873 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7875 json_ext_community
= json_object_new_object();
7876 json_object_string_add(json_ext_community
,
7878 attr
->ecommunity
->str
);
7879 json_object_object_add(json_path
,
7880 "extendedCommunity",
7881 json_ext_community
);
7883 vty_out(vty
, " Extended Community: %s\n",
7884 attr
->ecommunity
->str
);
7888 /* Line 6 display Large community */
7889 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7891 json_lcommunity
= json_object_new_object();
7892 json_object_string_add(json_lcommunity
,
7894 attr
->lcommunity
->str
);
7895 json_object_object_add(json_path
,
7899 vty_out(vty
, " Large Community: %s\n",
7900 attr
->lcommunity
->str
);
7904 /* Line 7 display Originator, Cluster-id */
7905 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7906 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7908 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7910 json_object_string_add(
7911 json_path
, "originatorId",
7912 inet_ntoa(attr
->originator_id
));
7914 vty_out(vty
, " Originator: %s",
7915 inet_ntoa(attr
->originator_id
));
7918 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7923 json_object_new_object();
7924 json_cluster_list_list
=
7925 json_object_new_array();
7928 i
< attr
->cluster
->length
/ 4;
7930 json_string
= json_object_new_string(
7934 json_object_array_add(
7935 json_cluster_list_list
,
7939 /* struct cluster_list does not have
7941 * aspath and community do. Add this
7944 json_object_string_add(json_cluster_list,
7945 "string", attr->cluster->str);
7947 json_object_object_add(
7948 json_cluster_list
, "list",
7949 json_cluster_list_list
);
7950 json_object_object_add(
7951 json_path
, "clusterList",
7954 vty_out(vty
, ", Cluster list: ");
7957 i
< attr
->cluster
->length
/ 4;
7971 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7972 bgp_damp_info_vty(vty
, binfo
, json_path
);
7975 #if defined(HAVE_CUMULUS)
7976 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
7977 && safi
!= SAFI_EVPN
)
7979 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
7982 mpls_label_t label
=
7983 label_pton(&binfo
->extra
->label
[0]);
7985 json_object_int_add(json_path
, "remoteLabel",
7988 vty_out(vty
, " Remote label: %d\n", label
);
7992 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7994 json_object_int_add(json_path
, "labelIndex",
7997 vty_out(vty
, " Label Index: %d\n",
8001 /* Line 8 display Addpath IDs */
8002 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8004 json_object_int_add(json_path
, "addpathRxId",
8005 binfo
->addpath_rx_id
);
8006 json_object_int_add(json_path
, "addpathTxId",
8007 binfo
->addpath_tx_id
);
8009 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8010 binfo
->addpath_rx_id
,
8011 binfo
->addpath_tx_id
);
8015 /* If we used addpath to TX a non-bestpath we need to display
8016 * "Advertised to" on a path-by-path basis */
8017 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8020 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8022 bgp_addpath_encode_tx(peer
, afi
, safi
);
8023 has_adj
= bgp_adj_out_lookup(
8024 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8026 if ((addpath_capable
&& has_adj
)
8027 || (!addpath_capable
&& has_adj
8028 && CHECK_FLAG(binfo
->flags
,
8029 BGP_INFO_SELECTED
))) {
8030 if (json_path
&& !json_adv_to
)
8032 json_object_new_object();
8034 route_vty_out_advertised_to(
8043 json_object_object_add(json_path
,
8054 /* Line 9 display Uptime */
8055 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8057 json_last_update
= json_object_new_object();
8058 json_object_int_add(json_last_update
, "epoch", tbuf
);
8059 json_object_string_add(json_last_update
, "string",
8061 json_object_object_add(json_path
, "lastUpdate",
8064 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8066 /* Line 10 display PMSI tunnel attribute, if present */
8067 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8068 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8069 attr
->pmsi_tnl_type
,
8070 PMSI_TNLTYPE_STR_DEFAULT
);
8073 json_pmsi
= json_object_new_object();
8074 json_object_string_add(json_pmsi
,
8076 json_object_object_add(json_path
, "pmsi",
8079 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8085 /* We've constructed the json object for this path, add it to the json
8089 if (json_nexthop_global
|| json_nexthop_ll
) {
8090 json_nexthops
= json_object_new_array();
8092 if (json_nexthop_global
)
8093 json_object_array_add(json_nexthops
,
8094 json_nexthop_global
);
8096 if (json_nexthop_ll
)
8097 json_object_array_add(json_nexthops
,
8100 json_object_object_add(json_path
, "nexthops",
8104 json_object_object_add(json_path
, "peer", json_peer
);
8105 json_object_array_add(json_paths
, json_path
);
8110 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8111 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8112 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8114 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8115 const char *prefix_list_str
, afi_t afi
,
8116 safi_t safi
, enum bgp_show_type type
);
8117 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8118 const char *filter
, afi_t afi
, safi_t safi
,
8119 enum bgp_show_type type
);
8120 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8121 const char *rmap_str
, afi_t afi
, safi_t safi
,
8122 enum bgp_show_type type
);
8123 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8124 const char *com
, int exact
, afi_t afi
,
8126 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8127 const char *prefix
, afi_t afi
, safi_t safi
,
8128 enum bgp_show_type type
);
8129 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8130 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8131 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8132 const char *comstr
, int exact
, afi_t afi
,
8136 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8137 struct bgp_table
*table
, enum bgp_show_type type
,
8138 void *output_arg
, uint8_t use_json
, char *rd
,
8139 int is_last
, unsigned long *output_cum
,
8140 unsigned long *total_cum
,
8141 unsigned long *json_header_depth
)
8143 struct bgp_info
*ri
;
8144 struct bgp_node
*rn
;
8147 unsigned long output_count
= 0;
8148 unsigned long total_count
= 0;
8152 json_object
*json_paths
= NULL
;
8155 if (output_cum
&& *output_cum
!= 0)
8158 if (use_json
&& !*json_header_depth
) {
8160 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8161 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8162 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8163 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8165 table
->version
, inet_ntoa(bgp
->router_id
));
8166 *json_header_depth
= 2;
8168 vty_out(vty
, " \"routeDistinguishers\" : {");
8169 ++*json_header_depth
;
8171 json_paths
= json_object_new_object();
8174 if (use_json
&& rd
) {
8175 vty_out(vty
, " \"%s\" : { ", rd
);
8178 /* Start processing of routes. */
8179 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8180 if (rn
->info
== NULL
)
8185 json_paths
= json_object_new_array();
8189 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8191 if (type
== bgp_show_type_flap_statistics
8192 || type
== bgp_show_type_flap_neighbor
8193 || type
== bgp_show_type_dampend_paths
8194 || type
== bgp_show_type_damp_neighbor
) {
8195 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8198 if (type
== bgp_show_type_regexp
) {
8199 regex_t
*regex
= output_arg
;
8201 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8205 if (type
== bgp_show_type_prefix_list
) {
8206 struct prefix_list
*plist
= output_arg
;
8208 if (prefix_list_apply(plist
, &rn
->p
)
8212 if (type
== bgp_show_type_filter_list
) {
8213 struct as_list
*as_list
= output_arg
;
8215 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8216 != AS_FILTER_PERMIT
)
8219 if (type
== bgp_show_type_route_map
) {
8220 struct route_map
*rmap
= output_arg
;
8221 struct bgp_info binfo
;
8222 struct attr dummy_attr
;
8225 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8227 binfo
.peer
= ri
->peer
;
8228 binfo
.attr
= &dummy_attr
;
8230 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8232 if (ret
== RMAP_DENYMATCH
)
8235 if (type
== bgp_show_type_neighbor
8236 || type
== bgp_show_type_flap_neighbor
8237 || type
== bgp_show_type_damp_neighbor
) {
8238 union sockunion
*su
= output_arg
;
8240 if (ri
->peer
== NULL
8241 || ri
->peer
->su_remote
== NULL
8242 || !sockunion_same(ri
->peer
->su_remote
, su
))
8245 if (type
== bgp_show_type_cidr_only
) {
8246 uint32_t destination
;
8248 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8249 if (IN_CLASSC(destination
)
8250 && rn
->p
.prefixlen
== 24)
8252 if (IN_CLASSB(destination
)
8253 && rn
->p
.prefixlen
== 16)
8255 if (IN_CLASSA(destination
)
8256 && rn
->p
.prefixlen
== 8)
8259 if (type
== bgp_show_type_prefix_longer
) {
8260 struct prefix
*p
= output_arg
;
8262 if (!prefix_match(p
, &rn
->p
))
8265 if (type
== bgp_show_type_community_all
) {
8266 if (!ri
->attr
->community
)
8269 if (type
== bgp_show_type_community
) {
8270 struct community
*com
= output_arg
;
8272 if (!ri
->attr
->community
8273 || !community_match(ri
->attr
->community
,
8277 if (type
== bgp_show_type_community_exact
) {
8278 struct community
*com
= output_arg
;
8280 if (!ri
->attr
->community
8281 || !community_cmp(ri
->attr
->community
, com
))
8284 if (type
== bgp_show_type_community_list
) {
8285 struct community_list
*list
= output_arg
;
8287 if (!community_list_match(ri
->attr
->community
,
8291 if (type
== bgp_show_type_community_list_exact
) {
8292 struct community_list
*list
= output_arg
;
8294 if (!community_list_exact_match(
8295 ri
->attr
->community
, list
))
8298 if (type
== bgp_show_type_lcommunity
) {
8299 struct lcommunity
*lcom
= output_arg
;
8301 if (!ri
->attr
->lcommunity
8302 || !lcommunity_match(ri
->attr
->lcommunity
,
8306 if (type
== bgp_show_type_lcommunity_list
) {
8307 struct community_list
*list
= output_arg
;
8309 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8313 if (type
== bgp_show_type_lcommunity_all
) {
8314 if (!ri
->attr
->lcommunity
)
8317 if (type
== bgp_show_type_dampend_paths
8318 || type
== bgp_show_type_damp_neighbor
) {
8319 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8320 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8324 if (!use_json
&& header
) {
8325 vty_out(vty
, "BGP table version is %" PRIu64
8326 ", local router ID is %s\n",
8328 inet_ntoa(bgp
->router_id
));
8329 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8330 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8331 if (type
== bgp_show_type_dampend_paths
8332 || type
== bgp_show_type_damp_neighbor
)
8333 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8334 else if (type
== bgp_show_type_flap_statistics
8335 || type
== bgp_show_type_flap_neighbor
)
8336 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8338 vty_out(vty
, BGP_SHOW_HEADER
);
8341 if (rd
!= NULL
&& !display
&& !output_count
) {
8344 "Route Distinguisher: %s\n",
8347 if (type
== bgp_show_type_dampend_paths
8348 || type
== bgp_show_type_damp_neighbor
)
8349 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8350 safi
, use_json
, json_paths
);
8351 else if (type
== bgp_show_type_flap_statistics
8352 || type
== bgp_show_type_flap_neighbor
)
8353 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8354 safi
, use_json
, json_paths
);
8356 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8367 sprintf(buf2
, "%s/%d",
8368 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8371 vty_out(vty
, "\"%s\": ", buf2
);
8373 vty_out(vty
, ",\"%s\": ", buf2
);
8376 json_object_to_json_string(json_paths
));
8377 json_object_free(json_paths
);
8384 output_count
+= *output_cum
;
8385 *output_cum
= output_count
;
8388 total_count
+= *total_cum
;
8389 *total_cum
= total_count
;
8393 json_object_free(json_paths
);
8395 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8399 for (i
= 0; i
< *json_header_depth
; ++i
)
8400 vty_out(vty
, " } ");
8404 /* No route is displayed */
8405 if (output_count
== 0) {
8406 if (type
== bgp_show_type_normal
)
8408 "No BGP prefixes displayed, %ld exist\n",
8412 "\nDisplayed %ld routes and %ld total paths\n",
8413 output_count
, total_count
);
8420 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8421 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8422 enum bgp_show_type type
, void *output_arg
,
8425 struct bgp_node
*rn
, *next
;
8426 unsigned long output_cum
= 0;
8427 unsigned long total_cum
= 0;
8428 unsigned long json_header_depth
= 0;
8431 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8433 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8434 next
= bgp_route_next(rn
);
8435 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8437 if (rn
->info
!= NULL
) {
8438 struct prefix_rd prd
;
8439 char rd
[RD_ADDRSTRLEN
];
8441 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8442 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8443 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8444 output_arg
, use_json
, rd
, next
== NULL
,
8445 &output_cum
, &total_cum
,
8446 &json_header_depth
);
8452 if (output_cum
== 0)
8453 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8457 "\nDisplayed %ld routes and %ld total paths\n",
8458 output_cum
, total_cum
);
8462 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8463 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8465 struct bgp_table
*table
;
8466 unsigned long json_header_depth
= 0;
8469 bgp
= bgp_get_default();
8474 vty_out(vty
, "No BGP process is configured\n");
8476 vty_out(vty
, "{}\n");
8480 table
= bgp
->rib
[afi
][safi
];
8481 /* use MPLS and ENCAP specific shows until they are merged */
8482 if (safi
== SAFI_MPLS_VPN
) {
8483 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8484 output_arg
, use_json
);
8487 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8488 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8489 output_arg
, use_json
,
8492 /* labeled-unicast routes live in the unicast table */
8493 else if (safi
== SAFI_LABELED_UNICAST
)
8494 safi
= SAFI_UNICAST
;
8496 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8497 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8500 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8501 safi_t safi
, uint8_t use_json
)
8503 struct listnode
*node
, *nnode
;
8508 vty_out(vty
, "{\n");
8510 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8513 vty_out(vty
, ",\n");
8517 vty_out(vty
, "\"%s\":",
8518 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8522 vty_out(vty
, "\nInstance %s:\n",
8523 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8527 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8532 vty_out(vty
, "}\n");
8535 /* Header of detailed BGP route information */
8536 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8537 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8538 afi_t afi
, safi_t safi
, json_object
*json
)
8540 struct bgp_info
*ri
;
8543 struct listnode
*node
, *nnode
;
8544 char buf1
[RD_ADDRSTRLEN
];
8545 char buf2
[INET6_ADDRSTRLEN
];
8546 #if defined(HAVE_CUMULUS)
8547 char buf3
[EVPN_ROUTE_STRLEN
];
8549 char prefix_str
[BUFSIZ
];
8554 int no_advertise
= 0;
8557 int has_valid_label
= 0;
8558 mpls_label_t label
= 0;
8559 json_object
*json_adv_to
= NULL
;
8562 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8564 if (has_valid_label
)
8565 label
= label_pton(&rn
->local_label
);
8568 if (has_valid_label
)
8569 json_object_int_add(json
, "localLabel", label
);
8571 json_object_string_add(
8573 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8575 #if defined(HAVE_CUMULUS)
8576 if (safi
== SAFI_EVPN
)
8577 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8578 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8581 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8582 buf3
, sizeof(buf3
)));
8584 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8585 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8586 ? prefix_rd2str(prd
, buf1
,
8589 safi
== SAFI_MPLS_VPN
? ":" : "",
8590 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8594 if (p
->family
== AF_ETHERNET
)
8595 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8597 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8599 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8600 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8601 || safi
== SAFI_EVPN
)
8602 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8604 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8606 buf2
, p
->prefixlen
);
8609 if (has_valid_label
)
8610 vty_out(vty
, "Local label: %d\n", label
);
8611 #if defined(HAVE_CUMULUS)
8612 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8614 if (bgp_labeled_safi(safi
))
8616 vty_out(vty
, "not allocated\n");
8619 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8621 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8623 if (ri
->extra
&& ri
->extra
->suppress
)
8625 if (ri
->attr
->community
!= NULL
) {
8626 if (community_include(ri
->attr
->community
,
8627 COMMUNITY_NO_ADVERTISE
))
8629 if (community_include(ri
->attr
->community
,
8630 COMMUNITY_NO_EXPORT
))
8632 if (community_include(ri
->attr
->community
,
8633 COMMUNITY_LOCAL_AS
))
8640 vty_out(vty
, "Paths: (%d available", count
);
8642 vty_out(vty
, ", best #%d", best
);
8643 if (safi
== SAFI_UNICAST
)
8644 vty_out(vty
, ", table %s",
8646 == BGP_INSTANCE_TYPE_DEFAULT
)
8647 ? "Default-IP-Routing-Table"
8650 vty_out(vty
, ", no best path");
8653 vty_out(vty
, ", not advertised to any peer");
8655 vty_out(vty
, ", not advertised to EBGP peer");
8657 vty_out(vty
, ", not advertised outside local AS");
8661 ", Advertisements suppressed by an aggregate.");
8662 vty_out(vty
, ")\n");
8665 /* If we are not using addpath then we can display Advertised to and
8667 * show what peers we advertised the bestpath to. If we are using
8669 * though then we must display Advertised to on a path-by-path basis. */
8670 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8671 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8672 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8673 if (json
&& !json_adv_to
)
8674 json_adv_to
= json_object_new_object();
8676 route_vty_out_advertised_to(
8678 " Advertised to non peer-group peers:\n ",
8685 json_object_object_add(json
, "advertisedTo",
8690 vty_out(vty
, " Not advertised to any peer");
8696 /* Display specified route of BGP table. */
8697 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8698 struct bgp_table
*rib
, const char *ip_str
,
8699 afi_t afi
, safi_t safi
,
8700 struct prefix_rd
*prd
, int prefix_check
,
8701 enum bgp_path_type pathtype
,
8707 struct prefix match
;
8708 struct bgp_node
*rn
;
8709 struct bgp_node
*rm
;
8710 struct bgp_info
*ri
;
8711 struct bgp_table
*table
;
8712 json_object
*json
= NULL
;
8713 json_object
*json_paths
= NULL
;
8715 /* Check IP address argument. */
8716 ret
= str2prefix(ip_str
, &match
);
8718 vty_out(vty
, "address is malformed\n");
8722 match
.family
= afi2family(afi
);
8725 json
= json_object_new_object();
8726 json_paths
= json_object_new_array();
8729 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8730 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8731 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8734 if ((table
= rn
->info
) == NULL
)
8739 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8743 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8744 bgp_unlock_node(rm
);
8748 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8750 route_vty_out_detail_header(
8752 (struct prefix_rd
*)&rn
->p
,
8753 AFI_IP
, safi
, json
);
8758 if (pathtype
== BGP_PATH_ALL
8759 || (pathtype
== BGP_PATH_BESTPATH
8760 && CHECK_FLAG(ri
->flags
,
8762 || (pathtype
== BGP_PATH_MULTIPATH
8763 && (CHECK_FLAG(ri
->flags
,
8765 || CHECK_FLAG(ri
->flags
,
8766 BGP_INFO_SELECTED
))))
8767 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8772 bgp_unlock_node(rm
);
8774 } else if (safi
== SAFI_FLOWSPEC
) {
8775 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8776 &match
, prefix_check
);
8778 route_vty_out_flowspec(vty
, &rn
->p
,
8779 rn
->info
, use_json
?
8780 NLRI_STRING_FORMAT_JSON
:
8781 NLRI_STRING_FORMAT_LARGE
,
8784 bgp_unlock_node(rn
);
8789 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8791 || rn
->p
.prefixlen
== match
.prefixlen
) {
8792 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8794 route_vty_out_detail_header(
8795 vty
, bgp
, rn
, NULL
, afi
,
8801 if (pathtype
== BGP_PATH_ALL
8802 || (pathtype
== BGP_PATH_BESTPATH
8806 || (pathtype
== BGP_PATH_MULTIPATH
8812 BGP_INFO_SELECTED
))))
8813 route_vty_out_detail(
8814 vty
, bgp
, &rn
->p
, ri
,
8815 afi
, safi
, json_paths
);
8819 bgp_unlock_node(rn
);
8825 json_object_object_add(json
, "paths", json_paths
);
8827 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8828 json
, JSON_C_TO_STRING_PRETTY
));
8829 json_object_free(json
);
8832 vty_out(vty
, "%% Network not in table\n");
8840 /* Display specified route of Main RIB */
8841 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8842 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8843 int prefix_check
, enum bgp_path_type pathtype
,
8847 bgp
= bgp_get_default();
8850 vty_out(vty
, "No BGP process is configured\n");
8852 vty_out(vty
, "{}\n");
8857 /* labeled-unicast routes live in the unicast table */
8858 if (safi
== SAFI_LABELED_UNICAST
)
8859 safi
= SAFI_UNICAST
;
8861 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8862 afi
, safi
, prd
, prefix_check
, pathtype
,
8866 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8867 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8870 struct lcommunity
*lcom
;
8876 b
= buffer_new(1024);
8877 for (i
= 0; i
< argc
; i
++) {
8879 buffer_putc(b
, ' ');
8881 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8883 buffer_putstr(b
, argv
[i
]->arg
);
8887 buffer_putc(b
, '\0');
8889 str
= buffer_getstr(b
);
8892 lcom
= lcommunity_str2com(str
);
8893 XFREE(MTYPE_TMP
, str
);
8895 vty_out(vty
, "%% Large-community malformed\n");
8899 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8903 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8904 const char *lcom
, afi_t afi
, safi_t safi
,
8907 struct community_list
*list
;
8909 list
= community_list_lookup(bgp_clist
, lcom
,
8910 LARGE_COMMUNITY_LIST_MASTER
);
8912 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8917 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8921 DEFUN (show_ip_bgp_large_community_list
,
8922 show_ip_bgp_large_community_list_cmd
,
8923 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8927 BGP_INSTANCE_HELP_STR
8929 BGP_SAFI_WITH_LABEL_HELP_STR
8930 "Display routes matching the large-community-list\n"
8931 "large-community-list number\n"
8932 "large-community-list name\n"
8936 afi_t afi
= AFI_IP6
;
8937 safi_t safi
= SAFI_UNICAST
;
8940 if (argv_find(argv
, argc
, "ip", &idx
))
8942 if (argv_find(argv
, argc
, "view", &idx
)
8943 || argv_find(argv
, argc
, "vrf", &idx
))
8944 vrf
= argv
[++idx
]->arg
;
8945 if (argv_find(argv
, argc
, "ipv4", &idx
)
8946 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8947 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8948 if (argv_find(argv
, argc
, "unicast", &idx
)
8949 || argv_find(argv
, argc
, "multicast", &idx
))
8950 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8953 int uj
= use_json(argc
, argv
);
8955 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8957 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8961 argv_find(argv
, argc
, "large-community-list", &idx
);
8962 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8965 DEFUN (show_ip_bgp_large_community
,
8966 show_ip_bgp_large_community_cmd
,
8967 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8971 BGP_INSTANCE_HELP_STR
8973 BGP_SAFI_WITH_LABEL_HELP_STR
8974 "Display routes matching the large-communities\n"
8975 "List of large-community numbers\n"
8979 afi_t afi
= AFI_IP6
;
8980 safi_t safi
= SAFI_UNICAST
;
8983 if (argv_find(argv
, argc
, "ip", &idx
))
8985 if (argv_find(argv
, argc
, "view", &idx
)
8986 || argv_find(argv
, argc
, "vrf", &idx
))
8987 vrf
= argv
[++idx
]->arg
;
8988 if (argv_find(argv
, argc
, "ipv4", &idx
)
8989 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8990 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8991 if (argv_find(argv
, argc
, "unicast", &idx
)
8992 || argv_find(argv
, argc
, "multicast", &idx
))
8993 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8996 int uj
= use_json(argc
, argv
);
8998 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9000 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9004 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9005 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9007 return bgp_show(vty
, bgp
, afi
, safi
,
9008 bgp_show_type_lcommunity_all
, NULL
, uj
);
9011 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9015 /* BGP route print out function without JSON */
9018 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9019 <dampening <parameters>\
9024 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9025 |community-list <(1-500)|WORD> [exact-match]\
9026 |A.B.C.D/M longer-prefixes\
9027 |X:X::X:X/M longer-prefixes\
9032 BGP_INSTANCE_HELP_STR
9034 BGP_SAFI_WITH_LABEL_HELP_STR
9035 "Display detailed information about dampening\n"
9036 "Display detail of configured dampening parameters\n"
9037 "Display routes matching the route-map\n"
9038 "A route-map to match on\n"
9039 "Display routes conforming to the prefix-list\n"
9040 "Prefix-list name\n"
9041 "Display routes conforming to the filter-list\n"
9042 "Regular expression access list name\n"
9043 "BGP RIB advertisement statistics\n"
9044 "Display routes matching the communities\n"
9046 "Do not send outside local AS (well-known community)\n"
9047 "Do not advertise to any peer (well-known community)\n"
9048 "Do not export to next AS (well-known community)\n"
9049 "Graceful shutdown (well-known community)\n"
9050 "Exact match of the communities\n"
9051 "Display routes matching the community-list\n"
9052 "community-list number\n"
9053 "community-list name\n"
9054 "Exact match of the communities\n"
9056 "Display route and more specific routes\n"
9058 "Display route and more specific routes\n")
9060 afi_t afi
= AFI_IP6
;
9061 safi_t safi
= SAFI_UNICAST
;
9062 int exact_match
= 0;
9063 struct bgp
*bgp
= NULL
;
9065 int idx_community_type
= 0;
9067 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9072 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9073 if (argv_find(argv
, argc
, "parameters", &idx
))
9074 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9077 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9078 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9079 safi
, bgp_show_type_prefix_list
);
9081 if (argv_find(argv
, argc
, "filter-list", &idx
))
9082 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9083 safi
, bgp_show_type_filter_list
);
9085 if (argv_find(argv
, argc
, "statistics", &idx
))
9086 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9088 if (argv_find(argv
, argc
, "route-map", &idx
))
9089 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9090 safi
, bgp_show_type_route_map
);
9092 if (argv_find(argv
, argc
, "community", &idx
)) {
9093 /* show a specific community */
9094 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9095 || argv_find(argv
, argc
, "no-advertise",
9096 &idx_community_type
)
9097 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9098 || argv_find(argv
, argc
, "graceful-shutdown",
9099 &idx_community_type
)
9100 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9102 if (argv_find(argv
, argc
, "exact-match", &idx
))
9104 return bgp_show_community(vty
, bgp
,
9105 argv
[idx_community_type
]->arg
,
9106 exact_match
, afi
, safi
);
9110 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9111 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9112 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9114 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9115 exact_match
, afi
, safi
);
9118 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9119 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9120 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9122 bgp_show_type_prefix_longer
);
9127 /* BGP route print out function with JSON */
9128 DEFUN (show_ip_bgp_json
,
9129 show_ip_bgp_json_cmd
,
9130 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9133 |dampening <flap-statistics|dampened-paths>\
9139 BGP_INSTANCE_HELP_STR
9141 BGP_SAFI_WITH_LABEL_HELP_STR
9142 "Display only routes with non-natural netmasks\n"
9143 "Display detailed information about dampening\n"
9144 "Display flap statistics of routes\n"
9145 "Display paths suppressed due to dampening\n"
9146 "Display routes matching the communities\n"
9149 afi_t afi
= AFI_IP6
;
9150 safi_t safi
= SAFI_UNICAST
;
9151 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9152 struct bgp
*bgp
= NULL
;
9155 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9160 int uj
= use_json(argc
, argv
);
9164 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9165 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9168 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9169 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9170 return bgp_show(vty
, bgp
, afi
, safi
,
9171 bgp_show_type_dampend_paths
, NULL
, uj
);
9172 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9173 return bgp_show(vty
, bgp
, afi
, safi
,
9174 bgp_show_type_flap_statistics
, NULL
,
9178 if (argv_find(argv
, argc
, "community", &idx
)) {
9179 /* show all communities */
9180 return bgp_show(vty
, bgp
, afi
, safi
,
9181 bgp_show_type_community_all
, NULL
, uj
);
9183 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9186 DEFUN (show_ip_bgp_route
,
9187 show_ip_bgp_route_cmd
,
9188 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9189 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9193 BGP_INSTANCE_HELP_STR
9195 BGP_SAFI_WITH_LABEL_HELP_STR
9196 "Network in the BGP routing table to display\n"
9198 "Network in the BGP routing table to display\n"
9200 "Display only the bestpath\n"
9201 "Display only multipaths\n"
9204 int prefix_check
= 0;
9206 afi_t afi
= AFI_IP6
;
9207 safi_t safi
= SAFI_UNICAST
;
9208 char *prefix
= NULL
;
9209 struct bgp
*bgp
= NULL
;
9210 enum bgp_path_type path_type
;
9211 uint8_t uj
= use_json(argc
, argv
);
9215 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9222 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9226 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9227 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9228 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9230 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9231 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9234 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9235 && afi
!= AFI_IP6
) {
9237 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9240 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9243 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9247 prefix
= argv
[idx
]->arg
;
9249 /* [<bestpath|multipath>] */
9250 if (argv_find(argv
, argc
, "bestpath", &idx
))
9251 path_type
= BGP_PATH_BESTPATH
;
9252 else if (argv_find(argv
, argc
, "multipath", &idx
))
9253 path_type
= BGP_PATH_MULTIPATH
;
9255 path_type
= BGP_PATH_ALL
;
9257 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9261 DEFUN (show_ip_bgp_regexp
,
9262 show_ip_bgp_regexp_cmd
,
9263 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9267 BGP_INSTANCE_HELP_STR
9269 BGP_SAFI_WITH_LABEL_HELP_STR
9270 "Display routes matching the AS path regular expression\n"
9271 "A regular-expression to match the BGP AS paths\n")
9273 afi_t afi
= AFI_IP6
;
9274 safi_t safi
= SAFI_UNICAST
;
9275 struct bgp
*bgp
= NULL
;
9278 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9283 // get index of regex
9284 argv_find(argv
, argc
, "regexp", &idx
);
9287 char *regstr
= argv_concat(argv
, argc
, idx
);
9288 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9289 bgp_show_type_regexp
);
9290 XFREE(MTYPE_TMP
, regstr
);
9294 DEFUN (show_ip_bgp_instance_all
,
9295 show_ip_bgp_instance_all_cmd
,
9296 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9300 BGP_INSTANCE_ALL_HELP_STR
9302 BGP_SAFI_WITH_LABEL_HELP_STR
9306 safi_t safi
= SAFI_UNICAST
;
9307 struct bgp
*bgp
= NULL
;
9310 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9315 int uj
= use_json(argc
, argv
);
9319 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9323 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9324 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9329 regex
= bgp_regcomp(regstr
);
9331 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9335 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9336 bgp_regex_free(regex
);
9340 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9341 const char *prefix_list_str
, afi_t afi
,
9342 safi_t safi
, enum bgp_show_type type
)
9344 struct prefix_list
*plist
;
9346 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9347 if (plist
== NULL
) {
9348 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9353 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9356 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9357 const char *filter
, afi_t afi
, safi_t safi
,
9358 enum bgp_show_type type
)
9360 struct as_list
*as_list
;
9362 as_list
= as_list_lookup(filter
);
9363 if (as_list
== NULL
) {
9364 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9369 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9372 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9373 const char *rmap_str
, afi_t afi
, safi_t safi
,
9374 enum bgp_show_type type
)
9376 struct route_map
*rmap
;
9378 rmap
= route_map_lookup_by_name(rmap_str
);
9380 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9384 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9387 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9388 const char *comstr
, int exact
, afi_t afi
,
9391 struct community
*com
;
9394 com
= community_str2com(comstr
);
9396 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9400 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9401 (exact
? bgp_show_type_community_exact
9402 : bgp_show_type_community
),
9404 community_free(com
);
9409 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9410 const char *com
, int exact
, afi_t afi
,
9413 struct community_list
*list
;
9415 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9417 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9421 return bgp_show(vty
, bgp
, afi
, safi
,
9422 (exact
? bgp_show_type_community_list_exact
9423 : bgp_show_type_community_list
),
9427 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9428 const char *prefix
, afi_t afi
, safi_t safi
,
9429 enum bgp_show_type type
)
9436 ret
= str2prefix(prefix
, p
);
9438 vty_out(vty
, "%% Malformed Prefix\n");
9442 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9447 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9448 const char *ip_str
, uint8_t use_json
)
9454 /* Get peer sockunion. */
9455 ret
= str2sockunion(ip_str
, &su
);
9457 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9459 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9463 json_object
*json_no
= NULL
;
9464 json_no
= json_object_new_object();
9465 json_object_string_add(
9467 "malformedAddressOrName",
9469 vty_out(vty
, "%s\n",
9470 json_object_to_json_string_ext(
9472 JSON_C_TO_STRING_PRETTY
));
9473 json_object_free(json_no
);
9476 "%% Malformed address or name: %s\n",
9484 /* Peer structure lookup. */
9485 peer
= peer_lookup(bgp
, &su
);
9488 json_object
*json_no
= NULL
;
9489 json_no
= json_object_new_object();
9490 json_object_string_add(json_no
, "warning",
9491 "No such neighbor");
9492 vty_out(vty
, "%s\n",
9493 json_object_to_json_string_ext(
9494 json_no
, JSON_C_TO_STRING_PRETTY
));
9495 json_object_free(json_no
);
9497 vty_out(vty
, "No such neighbor\n");
9505 BGP_STATS_MAXBITLEN
= 0,
9509 BGP_STATS_UNAGGREGATEABLE
,
9510 BGP_STATS_MAX_AGGREGATEABLE
,
9511 BGP_STATS_AGGREGATES
,
9513 BGP_STATS_ASPATH_COUNT
,
9514 BGP_STATS_ASPATH_MAXHOPS
,
9515 BGP_STATS_ASPATH_TOTHOPS
,
9516 BGP_STATS_ASPATH_MAXSIZE
,
9517 BGP_STATS_ASPATH_TOTSIZE
,
9518 BGP_STATS_ASN_HIGHEST
,
9522 static const char *table_stats_strs
[] = {
9523 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9524 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9525 [BGP_STATS_RIB
] = "Total Advertisements",
9526 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9527 [BGP_STATS_MAX_AGGREGATEABLE
] =
9528 "Maximum aggregateable prefixes",
9529 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9530 [BGP_STATS_SPACE
] = "Address space advertised",
9531 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9532 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9533 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9534 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9535 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9536 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9537 [BGP_STATS_MAX
] = NULL
,
9540 struct bgp_table_stats
{
9541 struct bgp_table
*table
;
9542 unsigned long long counts
[BGP_STATS_MAX
];
9547 #define TALLY_SIGFIG 100000
9548 static unsigned long
9549 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9551 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9552 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9553 unsigned long ret
= newtot
/ count
;
9555 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9562 static int bgp_table_stats_walker(struct thread
*t
)
9564 struct bgp_node
*rn
;
9565 struct bgp_node
*top
;
9566 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9567 unsigned int space
= 0;
9569 if (!(top
= bgp_table_top(ts
->table
)))
9572 switch (top
->p
.family
) {
9574 space
= IPV4_MAX_BITLEN
;
9577 space
= IPV6_MAX_BITLEN
;
9581 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9583 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9584 struct bgp_info
*ri
;
9585 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9586 unsigned int rinum
= 0;
9594 ts
->counts
[BGP_STATS_PREFIXES
]++;
9595 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9598 ts
->counts
[BGP_STATS_AVGPLEN
]
9599 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9600 ts
->counts
[BGP_STATS_AVGPLEN
],
9604 /* check if the prefix is included by any other announcements */
9605 while (prn
&& !prn
->info
)
9606 prn
= bgp_node_parent_nolock(prn
);
9608 if (prn
== NULL
|| prn
== top
) {
9609 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9610 /* announced address space */
9613 pow(2.0, space
- rn
->p
.prefixlen
);
9614 } else if (prn
->info
)
9615 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9617 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9619 ts
->counts
[BGP_STATS_RIB
]++;
9622 && (CHECK_FLAG(ri
->attr
->flag
,
9624 BGP_ATTR_ATOMIC_AGGREGATE
))))
9625 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9628 if (ri
->attr
&& ri
->attr
->aspath
) {
9630 aspath_count_hops(ri
->attr
->aspath
);
9632 aspath_size(ri
->attr
->aspath
);
9633 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9635 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9637 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9638 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9641 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9642 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9645 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9646 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9648 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9649 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9650 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9652 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9653 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9654 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9657 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9658 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9666 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9669 struct bgp_table_stats ts
;
9672 if (!bgp
->rib
[afi
][safi
]) {
9673 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9678 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9680 /* labeled-unicast routes live in the unicast table */
9681 if (safi
== SAFI_LABELED_UNICAST
)
9682 safi
= SAFI_UNICAST
;
9684 memset(&ts
, 0, sizeof(ts
));
9685 ts
.table
= bgp
->rib
[afi
][safi
];
9686 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9688 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9689 if (!table_stats_strs
[i
])
9694 case BGP_STATS_ASPATH_AVGHOPS
:
9695 case BGP_STATS_ASPATH_AVGSIZE
:
9696 case BGP_STATS_AVGPLEN
:
9697 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9698 vty_out (vty
, "%12.2f",
9699 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9702 case BGP_STATS_ASPATH_TOTHOPS
:
9703 case BGP_STATS_ASPATH_TOTSIZE
:
9704 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9705 vty_out(vty
, "%12.2f",
9707 ? (float)ts
.counts
[i
]
9709 [BGP_STATS_ASPATH_COUNT
]
9712 case BGP_STATS_TOTPLEN
:
9713 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9714 vty_out(vty
, "%12.2f",
9716 ? (float)ts
.counts
[i
]
9718 [BGP_STATS_PREFIXES
]
9721 case BGP_STATS_SPACE
:
9722 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9723 vty_out(vty
, "%12g\n", ts
.total_space
);
9725 if (afi
== AFI_IP6
) {
9726 vty_out(vty
, "%30s: ", "/32 equivalent ");
9727 vty_out(vty
, "%12g\n",
9728 ts
.total_space
* pow(2.0, -128 + 32));
9729 vty_out(vty
, "%30s: ", "/48 equivalent ");
9730 vty_out(vty
, "%12g\n",
9731 ts
.total_space
* pow(2.0, -128 + 48));
9733 vty_out(vty
, "%30s: ", "% announced ");
9734 vty_out(vty
, "%12.2f\n",
9735 ts
.total_space
* 100. * pow(2.0, -32));
9736 vty_out(vty
, "%30s: ", "/8 equivalent ");
9737 vty_out(vty
, "%12.2f\n",
9738 ts
.total_space
* pow(2.0, -32 + 8));
9739 vty_out(vty
, "%30s: ", "/24 equivalent ");
9740 vty_out(vty
, "%12.2f\n",
9741 ts
.total_space
* pow(2.0, -32 + 24));
9745 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9746 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9763 PCOUNT_PFCNT
, /* the figure we display to users */
9767 static const char *pcount_strs
[] = {
9768 [PCOUNT_ADJ_IN
] = "Adj-in",
9769 [PCOUNT_DAMPED
] = "Damped",
9770 [PCOUNT_REMOVED
] = "Removed",
9771 [PCOUNT_HISTORY
] = "History",
9772 [PCOUNT_STALE
] = "Stale",
9773 [PCOUNT_VALID
] = "Valid",
9774 [PCOUNT_ALL
] = "All RIB",
9775 [PCOUNT_COUNTED
] = "PfxCt counted",
9776 [PCOUNT_PFCNT
] = "Useable",
9777 [PCOUNT_MAX
] = NULL
,
9780 struct peer_pcounts
{
9781 unsigned int count
[PCOUNT_MAX
];
9782 const struct peer
*peer
;
9783 const struct bgp_table
*table
;
9786 static int bgp_peer_count_walker(struct thread
*t
)
9788 struct bgp_node
*rn
;
9789 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9790 const struct peer
*peer
= pc
->peer
;
9792 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9793 struct bgp_adj_in
*ain
;
9794 struct bgp_info
*ri
;
9796 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9797 if (ain
->peer
== peer
)
9798 pc
->count
[PCOUNT_ADJ_IN
]++;
9800 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9801 char buf
[SU_ADDRSTRLEN
];
9803 if (ri
->peer
!= peer
)
9806 pc
->count
[PCOUNT_ALL
]++;
9808 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9809 pc
->count
[PCOUNT_DAMPED
]++;
9810 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9811 pc
->count
[PCOUNT_HISTORY
]++;
9812 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9813 pc
->count
[PCOUNT_REMOVED
]++;
9814 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9815 pc
->count
[PCOUNT_STALE
]++;
9816 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9817 pc
->count
[PCOUNT_VALID
]++;
9818 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9819 pc
->count
[PCOUNT_PFCNT
]++;
9821 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9822 pc
->count
[PCOUNT_COUNTED
]++;
9823 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9825 "%s [pcount] %s/%d is counted but flags 0x%x",
9827 inet_ntop(rn
->p
.family
,
9828 &rn
->p
.u
.prefix
, buf
,
9830 rn
->p
.prefixlen
, ri
->flags
);
9832 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9834 "%s [pcount] %s/%d not counted but flags 0x%x",
9836 inet_ntop(rn
->p
.family
,
9837 &rn
->p
.u
.prefix
, buf
,
9839 rn
->p
.prefixlen
, ri
->flags
);
9846 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9847 safi_t safi
, uint8_t use_json
)
9849 struct peer_pcounts pcounts
= {.peer
= peer
};
9851 json_object
*json
= NULL
;
9852 json_object
*json_loop
= NULL
;
9855 json
= json_object_new_object();
9856 json_loop
= json_object_new_object();
9859 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9860 || !peer
->bgp
->rib
[afi
][safi
]) {
9862 json_object_string_add(
9864 "No such neighbor or address family");
9865 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9866 json_object_free(json
);
9868 vty_out(vty
, "%% No such neighbor or address family\n");
9873 memset(&pcounts
, 0, sizeof(pcounts
));
9874 pcounts
.peer
= peer
;
9875 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9877 /* in-place call via thread subsystem so as to record execution time
9878 * stats for the thread-walk (i.e. ensure this can't be blamed on
9879 * on just vty_read()).
9881 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9884 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9885 json_object_string_add(json
, "multiProtocol",
9886 afi_safi_print(afi
, safi
));
9887 json_object_int_add(json
, "pfxCounter",
9888 peer
->pcount
[afi
][safi
]);
9890 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9891 json_object_int_add(json_loop
, pcount_strs
[i
],
9894 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9896 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9897 json_object_string_add(json
, "pfxctDriftFor",
9899 json_object_string_add(
9900 json
, "recommended",
9901 "Please report this bug, with the above command output");
9903 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9904 json
, JSON_C_TO_STRING_PRETTY
));
9905 json_object_free(json
);
9909 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9910 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9911 peer
->hostname
, peer
->host
,
9912 afi_safi_print(afi
, safi
));
9914 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9915 afi_safi_print(afi
, safi
));
9918 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9919 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9921 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9922 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9925 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9926 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9928 "Please report this bug, with the above command output\n");
9935 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9936 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9937 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9938 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9942 BGP_INSTANCE_HELP_STR
9945 "Detailed information on TCP and BGP neighbor connections\n"
9946 "Neighbor to display information about\n"
9947 "Neighbor to display information about\n"
9948 "Neighbor on BGP configured interface\n"
9949 "Display detailed prefix count information\n"
9952 afi_t afi
= AFI_IP6
;
9953 safi_t safi
= SAFI_UNICAST
;
9956 struct bgp
*bgp
= NULL
;
9958 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9963 int uj
= use_json(argc
, argv
);
9967 argv_find(argv
, argc
, "neighbors", &idx
);
9968 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9972 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9975 #ifdef KEEP_OLD_VPN_COMMANDS
9976 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9977 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9978 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9983 "Display information about all VPNv4 NLRIs\n"
9984 "Detailed information on TCP and BGP neighbor connections\n"
9985 "Neighbor to display information about\n"
9986 "Neighbor to display information about\n"
9987 "Neighbor on BGP configured interface\n"
9988 "Display detailed prefix count information\n"
9993 uint8_t uj
= use_json(argc
, argv
);
9995 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9999 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10002 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10003 show_ip_bgp_vpn_all_route_prefix_cmd
,
10004 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10009 "Display information about all VPNv4 NLRIs\n"
10010 "Network in the BGP routing table to display\n"
10011 "Network in the BGP routing table to display\n"
10015 char *network
= NULL
;
10016 struct bgp
*bgp
= bgp_get_default();
10018 vty_out(vty
, "Can't find default instance\n");
10019 return CMD_WARNING
;
10022 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10023 network
= argv
[idx
]->arg
;
10024 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10025 network
= argv
[idx
]->arg
;
10027 vty_out(vty
, "Unable to figure out Network\n");
10028 return CMD_WARNING
;
10031 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10032 BGP_PATH_ALL
, use_json(argc
, argv
));
10034 #endif /* KEEP_OLD_VPN_COMMANDS */
10036 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10037 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10038 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10044 "Display information about all EVPN NLRIs\n"
10045 "Network in the BGP routing table to display\n"
10046 "Network in the BGP routing table to display\n"
10050 char *network
= NULL
;
10052 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10053 network
= argv
[idx
]->arg
;
10054 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10055 network
= argv
[idx
]->arg
;
10057 vty_out(vty
, "Unable to figure out Network\n");
10058 return CMD_WARNING
;
10060 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10061 BGP_PATH_ALL
, use_json(argc
, argv
));
10064 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10065 safi_t safi
, int in
, const char *rmap_name
,
10066 uint8_t use_json
, json_object
*json
)
10068 struct bgp_table
*table
;
10069 struct bgp_adj_in
*ain
;
10070 struct bgp_adj_out
*adj
;
10071 unsigned long output_count
;
10072 unsigned long filtered_count
;
10073 struct bgp_node
*rn
;
10079 struct update_subgroup
*subgrp
;
10080 json_object
*json_scode
= NULL
;
10081 json_object
*json_ocode
= NULL
;
10082 json_object
*json_ar
= NULL
;
10083 struct peer_af
*paf
;
10086 json_scode
= json_object_new_object();
10087 json_ocode
= json_object_new_object();
10088 json_ar
= json_object_new_object();
10090 json_object_string_add(json_scode
, "suppressed", "s");
10091 json_object_string_add(json_scode
, "damped", "d");
10092 json_object_string_add(json_scode
, "history", "h");
10093 json_object_string_add(json_scode
, "valid", "*");
10094 json_object_string_add(json_scode
, "best", ">");
10095 json_object_string_add(json_scode
, "multipath", "=");
10096 json_object_string_add(json_scode
, "internal", "i");
10097 json_object_string_add(json_scode
, "ribFailure", "r");
10098 json_object_string_add(json_scode
, "stale", "S");
10099 json_object_string_add(json_scode
, "removed", "R");
10101 json_object_string_add(json_ocode
, "igp", "i");
10102 json_object_string_add(json_ocode
, "egp", "e");
10103 json_object_string_add(json_ocode
, "incomplete", "?");
10110 json_object_string_add(json
, "alert", "no BGP");
10111 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10112 json_object_free(json
);
10114 vty_out(vty
, "%% No bgp\n");
10118 table
= bgp
->rib
[afi
][safi
];
10120 output_count
= filtered_count
= 0;
10121 subgrp
= peer_subgroup(peer
, afi
, safi
);
10124 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10126 json_object_int_add(json
, "bgpTableVersion",
10128 json_object_string_add(json
, "bgpLocalRouterId",
10129 inet_ntoa(bgp
->router_id
));
10130 json_object_object_add(json
, "bgpStatusCodes",
10132 json_object_object_add(json
, "bgpOriginCodes",
10134 json_object_string_add(json
,
10135 "bgpOriginatingDefaultNetwork",
10138 vty_out(vty
, "BGP table version is %" PRIu64
10139 ", local router ID is %s\n",
10140 table
->version
, inet_ntoa(bgp
->router_id
));
10141 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10142 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10144 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10149 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10151 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10152 if (ain
->peer
!= peer
)
10156 json_object_int_add(
10157 json
, "bgpTableVersion",
10159 json_object_string_add(
10161 "bgpLocalRouterId",
10164 json_object_object_add(
10165 json
, "bgpStatusCodes",
10167 json_object_object_add(
10168 json
, "bgpOriginCodes",
10172 "BGP table version is 0, local router ID is %s\n",
10176 BGP_SHOW_SCODE_HEADER
);
10178 BGP_SHOW_OCODE_HEADER
);
10184 vty_out(vty
, BGP_SHOW_HEADER
);
10188 bgp_attr_dup(&attr
, ain
->attr
);
10189 if (bgp_input_modifier(peer
, &rn
->p
,
10193 route_vty_out_tmp(vty
, &rn
->p
,
10203 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10204 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10205 if (paf
->peer
!= peer
)
10210 json_object_int_add(
10214 json_object_string_add(
10216 "bgpLocalRouterId",
10219 json_object_object_add(
10223 json_object_object_add(
10229 "BGP table version is %" PRIu64
10230 ", local router ID is %s\n",
10235 BGP_SHOW_SCODE_HEADER
);
10237 BGP_SHOW_OCODE_HEADER
);
10250 bgp_attr_dup(&attr
, adj
->attr
);
10251 ret
= bgp_output_modifier(
10252 peer
, &rn
->p
, &attr
,
10253 afi
, safi
, rmap_name
);
10254 if (ret
!= RMAP_DENY
) {
10264 bgp_attr_undup(&attr
,
10271 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10273 if (output_count
!= 0) {
10275 json_object_int_add(json
, "totalPrefixCounter",
10278 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10282 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10283 json
, JSON_C_TO_STRING_PRETTY
));
10284 json_object_free(json
);
10288 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10289 safi_t safi
, int in
, const char *rmap_name
,
10292 json_object
*json
= NULL
;
10295 json
= json_object_new_object();
10297 /* labeled-unicast routes live in the unicast table */
10298 if (safi
== SAFI_LABELED_UNICAST
)
10299 safi
= SAFI_UNICAST
;
10301 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10303 json_object_string_add(
10305 "No such neighbor or address family");
10306 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10307 json_object_free(json
);
10309 vty_out(vty
, "%% No such neighbor or address family\n");
10311 return CMD_WARNING
;
10315 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10316 PEER_FLAG_SOFT_RECONFIG
)) {
10318 json_object_string_add(
10320 "Inbound soft reconfiguration not enabled");
10321 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10322 json_object_free(json
);
10325 "%% Inbound soft reconfiguration not enabled\n");
10327 return CMD_WARNING
;
10330 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10332 return CMD_SUCCESS
;
10335 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10336 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10337 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10338 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10342 BGP_INSTANCE_HELP_STR
10344 BGP_SAFI_WITH_LABEL_HELP_STR
10345 "Detailed information on TCP and BGP neighbor connections\n"
10346 "Neighbor to display information about\n"
10347 "Neighbor to display information about\n"
10348 "Neighbor on BGP configured interface\n"
10349 "Display the received routes from neighbor\n"
10350 "Display the routes advertised to a BGP neighbor\n"
10351 "Route-map to modify the attributes\n"
10352 "Name of the route map\n"
10355 afi_t afi
= AFI_IP6
;
10356 safi_t safi
= SAFI_UNICAST
;
10357 char *rmap_name
= NULL
;
10358 char *peerstr
= NULL
;
10360 struct bgp
*bgp
= NULL
;
10365 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10368 return CMD_WARNING
;
10370 int uj
= use_json(argc
, argv
);
10374 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10375 argv_find(argv
, argc
, "neighbors", &idx
);
10376 peerstr
= argv
[++idx
]->arg
;
10378 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10380 return CMD_WARNING
;
10382 if (argv_find(argv
, argc
, "received-routes", &idx
))
10384 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10386 if (argv_find(argv
, argc
, "route-map", &idx
))
10387 rmap_name
= argv
[++idx
]->arg
;
10389 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10392 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10393 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10394 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10400 "Address Family modifier\n"
10401 "Detailed information on TCP and BGP neighbor connections\n"
10402 "Neighbor to display information about\n"
10403 "Neighbor to display information about\n"
10404 "Neighbor on BGP configured interface\n"
10405 "Display information received from a BGP neighbor\n"
10406 "Display the prefixlist filter\n"
10409 afi_t afi
= AFI_IP6
;
10410 safi_t safi
= SAFI_UNICAST
;
10411 char *peerstr
= NULL
;
10414 union sockunion su
;
10420 /* show [ip] bgp */
10421 if (argv_find(argv
, argc
, "ip", &idx
))
10423 /* [<ipv4|ipv6> [unicast]] */
10424 if (argv_find(argv
, argc
, "ipv4", &idx
))
10426 if (argv_find(argv
, argc
, "ipv6", &idx
))
10428 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10429 argv_find(argv
, argc
, "neighbors", &idx
);
10430 peerstr
= argv
[++idx
]->arg
;
10432 uint8_t uj
= use_json(argc
, argv
);
10434 ret
= str2sockunion(peerstr
, &su
);
10436 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10439 vty_out(vty
, "{}\n");
10442 "%% Malformed address or name: %s\n",
10444 return CMD_WARNING
;
10447 peer
= peer_lookup(NULL
, &su
);
10450 vty_out(vty
, "{}\n");
10452 vty_out(vty
, "No peer\n");
10453 return CMD_WARNING
;
10457 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10458 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10461 vty_out(vty
, "Address Family: %s\n",
10462 afi_safi_print(afi
, safi
));
10463 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10466 vty_out(vty
, "{}\n");
10468 vty_out(vty
, "No functional output\n");
10471 return CMD_SUCCESS
;
10474 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10475 afi_t afi
, safi_t safi
,
10476 enum bgp_show_type type
, uint8_t use_json
)
10478 /* labeled-unicast routes live in the unicast table */
10479 if (safi
== SAFI_LABELED_UNICAST
)
10480 safi
= SAFI_UNICAST
;
10482 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10484 json_object
*json_no
= NULL
;
10485 json_no
= json_object_new_object();
10486 json_object_string_add(
10487 json_no
, "warning",
10488 "No such neighbor or address family");
10489 vty_out(vty
, "%s\n",
10490 json_object_to_json_string(json_no
));
10491 json_object_free(json_no
);
10493 vty_out(vty
, "%% No such neighbor or address family\n");
10494 return CMD_WARNING
;
10497 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10500 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10501 show_ip_bgp_flowspec_routes_detailed_cmd
,
10502 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10506 BGP_INSTANCE_HELP_STR
10509 "Detailed information on flowspec entries\n"
10512 afi_t afi
= AFI_IP
;
10513 safi_t safi
= SAFI_UNICAST
;
10514 struct bgp
*bgp
= NULL
;
10517 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10520 return CMD_WARNING
;
10522 return bgp_show(vty
, bgp
, afi
, safi
,
10523 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10526 DEFUN (show_ip_bgp_neighbor_routes
,
10527 show_ip_bgp_neighbor_routes_cmd
,
10528 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10529 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10533 BGP_INSTANCE_HELP_STR
10535 BGP_SAFI_WITH_LABEL_HELP_STR
10536 "Detailed information on TCP and BGP neighbor connections\n"
10537 "Neighbor to display information about\n"
10538 "Neighbor to display information about\n"
10539 "Neighbor on BGP configured interface\n"
10540 "Display flap statistics of the routes learned from neighbor\n"
10541 "Display the dampened routes received from neighbor\n"
10542 "Display routes learned from neighbor\n"
10545 char *peerstr
= NULL
;
10546 struct bgp
*bgp
= NULL
;
10547 afi_t afi
= AFI_IP6
;
10548 safi_t safi
= SAFI_UNICAST
;
10550 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10554 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10557 return CMD_WARNING
;
10559 int uj
= use_json(argc
, argv
);
10563 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10564 argv_find(argv
, argc
, "neighbors", &idx
);
10565 peerstr
= argv
[++idx
]->arg
;
10567 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10569 vty_out(vty
, "No such neighbor\n");
10570 return CMD_WARNING
;
10573 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10574 sh_type
= bgp_show_type_flap_neighbor
;
10575 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10576 sh_type
= bgp_show_type_damp_neighbor
;
10577 else if (argv_find(argv
, argc
, "routes", &idx
))
10578 sh_type
= bgp_show_type_neighbor
;
10580 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10583 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10585 struct bgp_distance
{
10586 /* Distance value for the IP source prefix. */
10589 /* Name of the access-list to be matched. */
10593 DEFUN (show_bgp_afi_vpn_rd_route
,
10594 show_bgp_afi_vpn_rd_route_cmd
,
10595 "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]",
10599 "Address Family modifier\n"
10600 "Display information for a route distinguisher\n"
10601 "Route Distinguisher\n"
10602 "Network in the BGP routing table to display\n"
10603 "Network in the BGP routing table to display\n"
10607 struct prefix_rd prd
;
10608 afi_t afi
= AFI_MAX
;
10611 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10612 vty_out(vty
, "%% Malformed Address Family\n");
10613 return CMD_WARNING
;
10616 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10618 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10619 return CMD_WARNING
;
10622 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10623 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10626 static struct bgp_distance
*bgp_distance_new(void)
10628 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10631 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10633 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10636 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10637 const char *ip_str
, const char *access_list_str
)
10644 struct bgp_node
*rn
;
10645 struct bgp_distance
*bdistance
;
10647 afi
= bgp_node_afi(vty
);
10648 safi
= bgp_node_safi(vty
);
10650 ret
= str2prefix(ip_str
, &p
);
10652 vty_out(vty
, "Malformed prefix\n");
10653 return CMD_WARNING_CONFIG_FAILED
;
10656 distance
= atoi(distance_str
);
10658 /* Get BGP distance node. */
10659 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10661 bdistance
= rn
->info
;
10662 bgp_unlock_node(rn
);
10664 bdistance
= bgp_distance_new();
10665 rn
->info
= bdistance
;
10668 /* Set distance value. */
10669 bdistance
->distance
= distance
;
10671 /* Reset access-list configuration. */
10672 if (bdistance
->access_list
) {
10673 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10674 bdistance
->access_list
= NULL
;
10676 if (access_list_str
)
10677 bdistance
->access_list
=
10678 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10680 return CMD_SUCCESS
;
10683 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10684 const char *ip_str
, const char *access_list_str
)
10691 struct bgp_node
*rn
;
10692 struct bgp_distance
*bdistance
;
10694 afi
= bgp_node_afi(vty
);
10695 safi
= bgp_node_safi(vty
);
10697 ret
= str2prefix(ip_str
, &p
);
10699 vty_out(vty
, "Malformed prefix\n");
10700 return CMD_WARNING_CONFIG_FAILED
;
10703 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10704 (struct prefix
*)&p
);
10706 vty_out(vty
, "Can't find specified prefix\n");
10707 return CMD_WARNING_CONFIG_FAILED
;
10710 bdistance
= rn
->info
;
10711 distance
= atoi(distance_str
);
10713 if (bdistance
->distance
!= distance
) {
10714 vty_out(vty
, "Distance does not match configured\n");
10715 return CMD_WARNING_CONFIG_FAILED
;
10718 if (bdistance
->access_list
)
10719 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10720 bgp_distance_free(bdistance
);
10723 bgp_unlock_node(rn
);
10724 bgp_unlock_node(rn
);
10726 return CMD_SUCCESS
;
10729 /* Apply BGP information to distance method. */
10730 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10731 safi_t safi
, struct bgp
*bgp
)
10733 struct bgp_node
*rn
;
10736 struct bgp_distance
*bdistance
;
10737 struct access_list
*alist
;
10738 struct bgp_static
*bgp_static
;
10743 peer
= rinfo
->peer
;
10745 /* Check source address. */
10746 sockunion2hostprefix(&peer
->su
, &q
);
10747 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10749 bdistance
= rn
->info
;
10750 bgp_unlock_node(rn
);
10752 if (bdistance
->access_list
) {
10753 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10755 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10756 return bdistance
->distance
;
10758 return bdistance
->distance
;
10761 /* Backdoor check. */
10762 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10764 bgp_static
= rn
->info
;
10765 bgp_unlock_node(rn
);
10767 if (bgp_static
->backdoor
) {
10768 if (bgp
->distance_local
[afi
][safi
])
10769 return bgp
->distance_local
[afi
][safi
];
10771 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10775 if (peer
->sort
== BGP_PEER_EBGP
) {
10776 if (bgp
->distance_ebgp
[afi
][safi
])
10777 return bgp
->distance_ebgp
[afi
][safi
];
10778 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10780 if (bgp
->distance_ibgp
[afi
][safi
])
10781 return bgp
->distance_ibgp
[afi
][safi
];
10782 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10786 DEFUN (bgp_distance
,
10788 "distance bgp (1-255) (1-255) (1-255)",
10789 "Define an administrative distance\n"
10791 "Distance for routes external to the AS\n"
10792 "Distance for routes internal to the AS\n"
10793 "Distance for local routes\n")
10795 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10796 int idx_number
= 2;
10797 int idx_number_2
= 3;
10798 int idx_number_3
= 4;
10802 afi
= bgp_node_afi(vty
);
10803 safi
= bgp_node_safi(vty
);
10805 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10806 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10807 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10808 return CMD_SUCCESS
;
10811 DEFUN (no_bgp_distance
,
10812 no_bgp_distance_cmd
,
10813 "no distance bgp [(1-255) (1-255) (1-255)]",
10815 "Define an administrative distance\n"
10817 "Distance for routes external to the AS\n"
10818 "Distance for routes internal to the AS\n"
10819 "Distance for local routes\n")
10821 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10825 afi
= bgp_node_afi(vty
);
10826 safi
= bgp_node_safi(vty
);
10828 bgp
->distance_ebgp
[afi
][safi
] = 0;
10829 bgp
->distance_ibgp
[afi
][safi
] = 0;
10830 bgp
->distance_local
[afi
][safi
] = 0;
10831 return CMD_SUCCESS
;
10835 DEFUN (bgp_distance_source
,
10836 bgp_distance_source_cmd
,
10837 "distance (1-255) A.B.C.D/M",
10838 "Define an administrative distance\n"
10839 "Administrative distance\n"
10840 "IP source prefix\n")
10842 int idx_number
= 1;
10843 int idx_ipv4_prefixlen
= 2;
10844 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10845 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10846 return CMD_SUCCESS
;
10849 DEFUN (no_bgp_distance_source
,
10850 no_bgp_distance_source_cmd
,
10851 "no distance (1-255) A.B.C.D/M",
10853 "Define an administrative distance\n"
10854 "Administrative distance\n"
10855 "IP source prefix\n")
10857 int idx_number
= 2;
10858 int idx_ipv4_prefixlen
= 3;
10859 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10860 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10861 return CMD_SUCCESS
;
10864 DEFUN (bgp_distance_source_access_list
,
10865 bgp_distance_source_access_list_cmd
,
10866 "distance (1-255) A.B.C.D/M WORD",
10867 "Define an administrative distance\n"
10868 "Administrative distance\n"
10869 "IP source prefix\n"
10870 "Access list name\n")
10872 int idx_number
= 1;
10873 int idx_ipv4_prefixlen
= 2;
10875 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10876 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10877 return CMD_SUCCESS
;
10880 DEFUN (no_bgp_distance_source_access_list
,
10881 no_bgp_distance_source_access_list_cmd
,
10882 "no distance (1-255) A.B.C.D/M WORD",
10884 "Define an administrative distance\n"
10885 "Administrative distance\n"
10886 "IP source prefix\n"
10887 "Access list name\n")
10889 int idx_number
= 2;
10890 int idx_ipv4_prefixlen
= 3;
10892 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10893 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10894 return CMD_SUCCESS
;
10897 DEFUN (ipv6_bgp_distance_source
,
10898 ipv6_bgp_distance_source_cmd
,
10899 "distance (1-255) X:X::X:X/M",
10900 "Define an administrative distance\n"
10901 "Administrative distance\n"
10902 "IP source prefix\n")
10904 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10905 return CMD_SUCCESS
;
10908 DEFUN (no_ipv6_bgp_distance_source
,
10909 no_ipv6_bgp_distance_source_cmd
,
10910 "no distance (1-255) X:X::X:X/M",
10912 "Define an administrative distance\n"
10913 "Administrative distance\n"
10914 "IP source prefix\n")
10916 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10917 return CMD_SUCCESS
;
10920 DEFUN (ipv6_bgp_distance_source_access_list
,
10921 ipv6_bgp_distance_source_access_list_cmd
,
10922 "distance (1-255) X:X::X:X/M WORD",
10923 "Define an administrative distance\n"
10924 "Administrative distance\n"
10925 "IP source prefix\n"
10926 "Access list name\n")
10928 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10929 return CMD_SUCCESS
;
10932 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10933 no_ipv6_bgp_distance_source_access_list_cmd
,
10934 "no distance (1-255) X:X::X:X/M WORD",
10936 "Define an administrative distance\n"
10937 "Administrative distance\n"
10938 "IP source prefix\n"
10939 "Access list name\n")
10941 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10942 return CMD_SUCCESS
;
10945 DEFUN (bgp_damp_set
,
10947 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10948 "BGP Specific commands\n"
10949 "Enable route-flap dampening\n"
10950 "Half-life time for the penalty\n"
10951 "Value to start reusing a route\n"
10952 "Value to start suppressing a route\n"
10953 "Maximum duration to suppress a stable route\n")
10955 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10956 int idx_half_life
= 2;
10958 int idx_suppress
= 4;
10959 int idx_max_suppress
= 5;
10960 int half
= DEFAULT_HALF_LIFE
* 60;
10961 int reuse
= DEFAULT_REUSE
;
10962 int suppress
= DEFAULT_SUPPRESS
;
10963 int max
= 4 * half
;
10966 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10967 reuse
= atoi(argv
[idx_reuse
]->arg
);
10968 suppress
= atoi(argv
[idx_suppress
]->arg
);
10969 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10970 } else if (argc
== 3) {
10971 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10975 if (suppress
< reuse
) {
10977 "Suppress value cannot be less than reuse value \n");
10981 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10982 reuse
, suppress
, max
);
10985 DEFUN (bgp_damp_unset
,
10986 bgp_damp_unset_cmd
,
10987 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10989 "BGP Specific commands\n"
10990 "Enable route-flap dampening\n"
10991 "Half-life time for the penalty\n"
10992 "Value to start reusing a route\n"
10993 "Value to start suppressing a route\n"
10994 "Maximum duration to suppress a stable route\n")
10996 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10997 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11000 /* Display specified route of BGP table. */
11001 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11002 const char *ip_str
, afi_t afi
, safi_t safi
,
11003 struct prefix_rd
*prd
, int prefix_check
)
11006 struct prefix match
;
11007 struct bgp_node
*rn
;
11008 struct bgp_node
*rm
;
11009 struct bgp_info
*ri
;
11010 struct bgp_info
*ri_temp
;
11012 struct bgp_table
*table
;
11014 /* BGP structure lookup. */
11016 bgp
= bgp_lookup_by_name(view_name
);
11018 vty_out(vty
, "%% Can't find BGP instance %s\n",
11020 return CMD_WARNING
;
11023 bgp
= bgp_get_default();
11025 vty_out(vty
, "%% No BGP process is configured\n");
11026 return CMD_WARNING
;
11030 /* Check IP address argument. */
11031 ret
= str2prefix(ip_str
, &match
);
11033 vty_out(vty
, "%% address is malformed\n");
11034 return CMD_WARNING
;
11037 match
.family
= afi2family(afi
);
11039 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11040 || (safi
== SAFI_EVPN
)) {
11041 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11042 rn
= bgp_route_next(rn
)) {
11043 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11045 if ((table
= rn
->info
) == NULL
)
11047 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11051 || rm
->p
.prefixlen
== match
.prefixlen
) {
11054 if (ri
->extra
&& ri
->extra
->damp_info
) {
11055 ri_temp
= ri
->next
;
11056 bgp_damp_info_free(
11057 ri
->extra
->damp_info
,
11065 bgp_unlock_node(rm
);
11068 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11071 || rn
->p
.prefixlen
== match
.prefixlen
) {
11074 if (ri
->extra
&& ri
->extra
->damp_info
) {
11075 ri_temp
= ri
->next
;
11076 bgp_damp_info_free(
11077 ri
->extra
->damp_info
,
11085 bgp_unlock_node(rn
);
11089 return CMD_SUCCESS
;
11092 DEFUN (clear_ip_bgp_dampening
,
11093 clear_ip_bgp_dampening_cmd
,
11094 "clear ip bgp dampening",
11098 "Clear route flap dampening information\n")
11100 bgp_damp_info_clean();
11101 return CMD_SUCCESS
;
11104 DEFUN (clear_ip_bgp_dampening_prefix
,
11105 clear_ip_bgp_dampening_prefix_cmd
,
11106 "clear ip bgp dampening A.B.C.D/M",
11110 "Clear route flap dampening information\n"
11113 int idx_ipv4_prefixlen
= 4;
11114 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11115 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11118 DEFUN (clear_ip_bgp_dampening_address
,
11119 clear_ip_bgp_dampening_address_cmd
,
11120 "clear ip bgp dampening A.B.C.D",
11124 "Clear route flap dampening information\n"
11125 "Network to clear damping information\n")
11128 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11129 SAFI_UNICAST
, NULL
, 0);
11132 DEFUN (clear_ip_bgp_dampening_address_mask
,
11133 clear_ip_bgp_dampening_address_mask_cmd
,
11134 "clear ip bgp dampening A.B.C.D A.B.C.D",
11138 "Clear route flap dampening information\n"
11139 "Network to clear damping information\n"
11143 int idx_ipv4_2
= 5;
11145 char prefix_str
[BUFSIZ
];
11147 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11150 vty_out(vty
, "%% Inconsistent address and mask\n");
11151 return CMD_WARNING
;
11154 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11158 /* also used for encap safi */
11159 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11160 afi_t afi
, safi_t safi
)
11162 struct bgp_node
*prn
;
11163 struct bgp_node
*rn
;
11164 struct bgp_table
*table
;
11166 struct prefix_rd
*prd
;
11167 struct bgp_static
*bgp_static
;
11168 mpls_label_t label
;
11169 char buf
[SU_ADDRSTRLEN
];
11170 char rdbuf
[RD_ADDRSTRLEN
];
11172 /* Network configuration. */
11173 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11174 prn
= bgp_route_next(prn
)) {
11175 if ((table
= prn
->info
) == NULL
)
11178 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11179 if ((bgp_static
= rn
->info
) == NULL
)
11183 prd
= (struct prefix_rd
*)&prn
->p
;
11185 /* "network" configuration display. */
11186 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11187 label
= decode_label(&bgp_static
->label
);
11189 vty_out(vty
, " network %s/%d rd %s",
11190 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11192 p
->prefixlen
, rdbuf
);
11193 if (safi
== SAFI_MPLS_VPN
)
11194 vty_out(vty
, " label %u", label
);
11196 if (bgp_static
->rmap
.name
)
11197 vty_out(vty
, " route-map %s",
11198 bgp_static
->rmap
.name
);
11200 if (bgp_static
->backdoor
)
11201 vty_out(vty
, " backdoor");
11203 vty_out(vty
, "\n");
11208 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11209 afi_t afi
, safi_t safi
)
11211 struct bgp_node
*prn
;
11212 struct bgp_node
*rn
;
11213 struct bgp_table
*table
;
11215 struct prefix_rd
*prd
;
11216 struct bgp_static
*bgp_static
;
11217 char buf
[PREFIX_STRLEN
];
11218 char buf2
[SU_ADDRSTRLEN
];
11219 char rdbuf
[RD_ADDRSTRLEN
];
11221 /* Network configuration. */
11222 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11223 prn
= bgp_route_next(prn
)) {
11224 if ((table
= prn
->info
) == NULL
)
11227 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11228 if ((bgp_static
= rn
->info
) == NULL
)
11231 char *macrouter
= NULL
;
11234 if (bgp_static
->router_mac
)
11235 macrouter
= prefix_mac2str(
11236 bgp_static
->router_mac
, NULL
, 0);
11237 if (bgp_static
->eth_s_id
)
11238 esi
= esi2str(bgp_static
->eth_s_id
);
11240 prd
= (struct prefix_rd
*)&prn
->p
;
11242 /* "network" configuration display. */
11243 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11244 if (p
->u
.prefix_evpn
.route_type
== 5) {
11245 char local_buf
[PREFIX_STRLEN
];
11246 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((
11247 struct prefix_evpn
*)p
)
11250 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
,
11251 local_buf
, PREFIX_STRLEN
);
11252 sprintf(buf
, "%s/%u", local_buf
,
11253 p
->u
.prefix_evpn
.ip_prefix_length
);
11255 prefix2str(p
, buf
, sizeof(buf
));
11258 if (bgp_static
->gatewayIp
.family
== AF_INET
11259 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11260 inet_ntop(bgp_static
->gatewayIp
.family
,
11261 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11264 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11265 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11266 decode_label(&bgp_static
->label
), esi
, buf2
,
11270 XFREE(MTYPE_TMP
, macrouter
);
11272 XFREE(MTYPE_TMP
, esi
);
11277 /* Configuration of static route announcement and aggregate
11279 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11282 struct bgp_node
*rn
;
11284 struct bgp_static
*bgp_static
;
11285 struct bgp_aggregate
*bgp_aggregate
;
11286 char buf
[SU_ADDRSTRLEN
];
11288 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11289 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11293 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11294 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11298 /* Network configuration. */
11299 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11300 rn
= bgp_route_next(rn
)) {
11301 if ((bgp_static
= rn
->info
) == NULL
)
11306 /* "network" configuration display. */
11307 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11308 uint32_t destination
;
11309 struct in_addr netmask
;
11311 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11312 masklen2ip(p
->prefixlen
, &netmask
);
11313 vty_out(vty
, " network %s",
11314 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11317 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11318 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11319 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11320 || p
->u
.prefix4
.s_addr
== 0) {
11321 /* Natural mask is not display. */
11323 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11325 vty_out(vty
, " network %s/%d",
11326 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11331 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11332 vty_out(vty
, " label-index %u",
11333 bgp_static
->label_index
);
11335 if (bgp_static
->rmap
.name
)
11336 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11338 if (bgp_static
->backdoor
)
11339 vty_out(vty
, " backdoor");
11341 vty_out(vty
, "\n");
11344 /* Aggregate-address configuration. */
11345 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11346 rn
= bgp_route_next(rn
)) {
11347 if ((bgp_aggregate
= rn
->info
) == NULL
)
11352 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11353 struct in_addr netmask
;
11355 masklen2ip(p
->prefixlen
, &netmask
);
11356 vty_out(vty
, " aggregate-address %s %s",
11357 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11359 inet_ntoa(netmask
));
11361 vty_out(vty
, " aggregate-address %s/%d",
11362 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11367 if (bgp_aggregate
->as_set
)
11368 vty_out(vty
, " as-set");
11370 if (bgp_aggregate
->summary_only
)
11371 vty_out(vty
, " summary-only");
11373 vty_out(vty
, "\n");
11377 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11380 struct bgp_node
*rn
;
11381 struct bgp_distance
*bdistance
;
11383 /* Distance configuration. */
11384 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11385 && bgp
->distance_local
[afi
][safi
]
11386 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11387 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11388 || bgp
->distance_local
[afi
][safi
]
11389 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11390 vty_out(vty
, " distance bgp %d %d %d\n",
11391 bgp
->distance_ebgp
[afi
][safi
],
11392 bgp
->distance_ibgp
[afi
][safi
],
11393 bgp
->distance_local
[afi
][safi
]);
11396 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11397 rn
= bgp_route_next(rn
))
11398 if ((bdistance
= rn
->info
) != NULL
) {
11399 char buf
[PREFIX_STRLEN
];
11401 vty_out(vty
, " distance %d %s %s\n",
11402 bdistance
->distance
,
11403 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11404 bdistance
->access_list
? bdistance
->access_list
11409 /* Allocate routing table structure and install commands. */
11410 void bgp_route_init(void)
11415 /* Init BGP distance table. */
11416 FOREACH_AFI_SAFI (afi
, safi
)
11417 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11419 /* IPv4 BGP commands. */
11420 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11421 install_element(BGP_NODE
, &bgp_network_cmd
);
11422 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11424 install_element(BGP_NODE
, &aggregate_address_cmd
);
11425 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11426 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11427 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11429 /* IPv4 unicast configuration. */
11430 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11431 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11432 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11434 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11435 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11436 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11437 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11439 /* IPv4 multicast configuration. */
11440 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11441 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11442 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11443 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11444 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11445 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11446 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11448 /* IPv4 labeled-unicast configuration. */
11449 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11450 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11451 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11452 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11453 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11455 install_element(VIEW_NODE
,
11456 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11457 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11458 install_element(VIEW_NODE
,
11459 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11460 #ifdef KEEP_OLD_VPN_COMMANDS
11461 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11462 #endif /* KEEP_OLD_VPN_COMMANDS */
11463 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11464 install_element(VIEW_NODE
,
11465 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11467 /* BGP dampening clear commands */
11468 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11469 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11471 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11472 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11475 install_element(ENABLE_NODE
,
11476 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11477 #ifdef KEEP_OLD_VPN_COMMANDS
11478 install_element(ENABLE_NODE
,
11479 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11480 #endif /* KEEP_OLD_VPN_COMMANDS */
11482 /* New config IPv6 BGP commands. */
11483 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11484 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11485 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11487 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11488 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11490 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11492 install_element(BGP_NODE
, &bgp_distance_cmd
);
11493 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11494 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11495 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11496 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11497 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11498 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11499 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11500 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11501 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11502 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11503 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11504 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11505 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11506 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11507 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11508 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11509 install_element(BGP_IPV4M_NODE
,
11510 &no_bgp_distance_source_access_list_cmd
);
11511 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11512 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11513 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11514 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11515 install_element(BGP_IPV6_NODE
,
11516 &ipv6_bgp_distance_source_access_list_cmd
);
11517 install_element(BGP_IPV6_NODE
,
11518 &no_ipv6_bgp_distance_source_access_list_cmd
);
11519 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11520 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11521 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11522 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11523 install_element(BGP_IPV6M_NODE
,
11524 &ipv6_bgp_distance_source_access_list_cmd
);
11525 install_element(BGP_IPV6M_NODE
,
11526 &no_ipv6_bgp_distance_source_access_list_cmd
);
11528 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11529 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11530 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11531 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11533 /* IPv4 Multicast Mode */
11534 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11535 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11537 /* Large Communities */
11538 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11539 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11541 /* show bgp ipv4 flowspec detailed */
11542 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11546 void bgp_route_finish(void)
11551 FOREACH_AFI_SAFI (afi
, safi
) {
11552 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11553 bgp_distance_table
[afi
][safi
] = NULL
;