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(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 new->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 if (family
== AF_INET6
)
1333 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1336 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1337 struct update_subgroup
*subgrp
, struct prefix
*p
,
1340 struct bgp_filter
*filter
;
1343 struct peer
*onlypeer
;
1345 struct attr
*riattr
;
1346 char buf
[PREFIX_STRLEN
];
1352 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1354 if (DISABLE_BGP_ANNOUNCE
)
1357 afi
= SUBGRP_AFI(subgrp
);
1358 safi
= SUBGRP_SAFI(subgrp
);
1359 peer
= SUBGRP_PEER(subgrp
);
1361 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1362 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1365 filter
= &peer
->filter
[afi
][safi
];
1366 bgp
= SUBGRP_INST(subgrp
);
1367 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1370 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1371 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1372 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1375 * direct and direct_ext type routes originate internally even
1376 * though they can have peer pointers that reference other
1379 prefix2str(p
, buf
, PREFIX_STRLEN
);
1380 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1386 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1387 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1388 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1389 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1391 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1396 /* With addpath we may be asked to TX all kinds of paths so make sure
1398 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1399 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1400 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1404 /* If this is not the bestpath then check to see if there is an enabled
1406 * feature that requires us to advertise it */
1407 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1408 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1413 /* Aggregate-address suppress check. */
1414 if (ri
->extra
&& ri
->extra
->suppress
)
1415 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1419 /* If it's labeled safi, make sure the route has a valid label. */
1420 if (safi
== SAFI_LABELED_UNICAST
) {
1421 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1422 if (!bgp_is_valid_label(&label
)) {
1423 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1424 zlog_debug("u%" PRIu64
":s%" PRIu64
1425 " %s/%d is filtered - no label (%p)",
1426 subgrp
->update_group
->id
, subgrp
->id
,
1427 inet_ntop(p
->family
, &p
->u
.prefix
,
1428 buf
, SU_ADDRSTRLEN
),
1429 p
->prefixlen
, &label
);
1434 /* Do not send back route to sender. */
1435 if (onlypeer
&& from
== onlypeer
) {
1439 /* Do not send the default route in the BGP table if the neighbor is
1440 * configured for default-originate */
1441 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1442 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1443 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1445 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1449 /* Transparency check. */
1450 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1451 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1456 /* If community is not disabled check the no-export and local. */
1457 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1458 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1460 "subgrpannouncecheck: community filter check fail");
1464 /* If the attribute has originator-id and it is same as remote
1466 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1467 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1468 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1470 "%s [Update:SEND] %s originator-id is same as "
1473 prefix2str(p
, buf
, sizeof(buf
)));
1477 /* ORF prefix-list filter check */
1478 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1479 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1480 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1481 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1482 if (peer
->orf_plist
[afi
][safi
]) {
1483 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1485 if (bgp_debug_update(NULL
, p
,
1486 subgrp
->update_group
, 0))
1488 "%s [Update:SEND] %s is filtered via ORF",
1496 /* Output filter check. */
1497 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1498 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1499 zlog_debug("%s [Update:SEND] %s is filtered",
1500 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1504 #ifdef BGP_SEND_ASPATH_CHECK
1505 /* AS path loop check. */
1506 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1507 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1509 "%s [Update:SEND] suppress announcement to peer AS %u "
1510 "that is part of AS path.",
1511 onlypeer
->host
, onlypeer
->as
);
1514 #endif /* BGP_SEND_ASPATH_CHECK */
1516 /* If we're a CONFED we need to loop check the CONFED ID too */
1517 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1518 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1519 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1521 "%s [Update:SEND] suppress announcement to peer AS %u"
1523 peer
->host
, bgp
->confed_id
);
1528 /* Route-Reflect check. */
1529 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1534 /* IBGP reflection check. */
1535 if (reflect
&& !samepeer_safe
) {
1536 /* A route from a Client peer. */
1537 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1538 PEER_FLAG_REFLECTOR_CLIENT
)) {
1539 /* Reflect to all the Non-Client peers and also to the
1540 Client peers other than the originator. Originator
1542 is already done. So there is noting to do. */
1543 /* no bgp client-to-client reflection check. */
1544 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1545 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1546 PEER_FLAG_REFLECTOR_CLIENT
))
1549 /* A route from a Non-client peer. Reflect to all other
1551 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1552 PEER_FLAG_REFLECTOR_CLIENT
))
1557 /* For modify attribute, copy it to temporary structure. */
1558 bgp_attr_dup(attr
, riattr
);
1560 /* If local-preference is not set. */
1561 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1562 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1563 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1564 attr
->local_pref
= bgp
->default_local_pref
;
1567 /* If originator-id is not set and the route is to be reflected,
1568 set the originator id */
1570 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1571 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1572 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1575 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1577 if (peer
->sort
== BGP_PEER_EBGP
1578 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1579 if (from
!= bgp
->peer_self
&& !transparent
1580 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1581 PEER_FLAG_MED_UNCHANGED
))
1583 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1586 /* Since the nexthop attribute can vary per peer, it is not explicitly
1588 * in announce check, only certain flags and length (or number of
1590 * -- for IPv6/MP_REACH) are set here in order to guide the update
1592 * code in setting the nexthop(s) on a per peer basis in
1594 * Typically, the source nexthop in the attribute is preserved but in
1596 * scenarios where we know it will always be overwritten, we reset the
1597 * nexthop to "0" in an attempt to achieve better Update packing. An
1598 * example of this is when a prefix from each of 2 IBGP peers needs to
1600 * announced to an EBGP peer (and they have the same attributes barring
1604 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1606 #define NEXTHOP_IS_V6 \
1607 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1608 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1609 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1610 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1612 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1614 * the peer (group) is configured to receive link-local nexthop
1616 * and it is available in the prefix OR we're not reflecting the route
1618 * the peer (group) to whom we're going to announce is on a shared
1620 * and this is either a self-originated route or the peer is EBGP.
1622 if (NEXTHOP_IS_V6
) {
1623 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1624 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1625 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1626 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1627 || (!reflect
&& peer
->shared_network
1628 && (from
== bgp
->peer_self
1629 || peer
->sort
== BGP_PEER_EBGP
))) {
1630 attr
->mp_nexthop_len
=
1631 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1634 /* Clear off link-local nexthop in source, whenever it is not
1636 * ensure more prefixes share the same attribute for
1639 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1640 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1641 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1644 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1645 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1647 /* Route map & unsuppress-map apply. */
1648 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1649 struct bgp_info info
;
1650 struct bgp_info_extra dummy_info_extra
;
1651 struct attr dummy_attr
;
1657 memcpy(&dummy_info_extra
, ri
->extra
,
1658 sizeof(struct bgp_info_extra
));
1659 info
.extra
= &dummy_info_extra
;
1662 /* don't confuse inbound and outbound setting */
1663 RESET_FLAG(attr
->rmap_change_flags
);
1666 * The route reflector is not allowed to modify the attributes
1667 * of the reflected IBGP routes unless explicitly allowed.
1669 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1670 && !bgp_flag_check(bgp
,
1671 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1672 bgp_attr_dup(&dummy_attr
, attr
);
1673 info
.attr
= &dummy_attr
;
1676 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1678 if (ri
->extra
&& ri
->extra
->suppress
)
1679 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1682 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1685 peer
->rmap_type
= 0;
1687 if (ret
== RMAP_DENYMATCH
) {
1688 bgp_attr_flush(attr
);
1693 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1694 if (peer
->sort
== BGP_PEER_IBGP
1695 || peer
->sort
== BGP_PEER_CONFED
) {
1696 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1697 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1699 bgp_attr_add_gshut_community(attr
);
1703 /* After route-map has been applied, we check to see if the nexthop to
1704 * be carried in the attribute (that is used for the announcement) can
1705 * be cleared off or not. We do this in all cases where we would be
1706 * setting the nexthop to "ourselves". For IPv6, we only need to
1708 * the global nexthop here; the link-local nexthop would have been
1710 * already, and if not, it is required by the update formation code.
1711 * Also see earlier comments in this function.
1714 * If route-map has performed some operation on the nexthop or the peer
1715 * configuration says to pass it unchanged, we cannot reset the nexthop
1716 * here, so only attempt to do it if these aren't true. Note that the
1717 * route-map handler itself might have cleared the nexthop, if for
1719 * it is configured as 'peer-address'.
1721 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1722 riattr
->rmap_change_flags
)
1724 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1725 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1726 /* We can reset the nexthop, if setting (or forcing) it to
1728 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1729 PEER_FLAG_NEXTHOP_SELF
)
1730 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1731 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1733 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1734 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1735 subgroup_announce_reset_nhop(
1736 (peer_cap_enhe(peer
, afi
, safi
)
1740 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1741 /* Can also reset the nexthop if announcing to EBGP, but
1743 * no peer in the subgroup is on a shared subnet.
1744 * Note: 3rd party nexthop currently implemented for
1747 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1749 subgroup_announce_reset_nhop(
1750 (peer_cap_enhe(peer
, afi
, safi
)
1755 /* If IPv6/MP and nexthop does not have any override and happens
1757 * be a link-local address, reset it so that we don't pass along
1759 * source's link-local IPv6 address to recipients who may not be
1761 * the same interface.
1763 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1764 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1765 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1772 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1773 struct bgp_maxpaths_cfg
*mpath_cfg
,
1774 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1776 struct bgp_info
*new_select
;
1777 struct bgp_info
*old_select
;
1778 struct bgp_info
*ri
;
1779 struct bgp_info
*ri1
;
1780 struct bgp_info
*ri2
;
1781 struct bgp_info
*nextri
= NULL
;
1782 int paths_eq
, do_mpath
, debug
;
1783 struct list mp_list
;
1784 char pfx_buf
[PREFIX2STR_BUFFER
];
1785 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1787 bgp_mp_list_init(&mp_list
);
1789 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1791 debug
= bgp_debug_bestpath(&rn
->p
);
1794 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1796 /* bgp deterministic-med */
1798 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1800 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1801 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1802 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1804 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1805 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1807 if (BGP_INFO_HOLDDOWN(ri1
))
1809 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1810 if (ri1
->peer
->status
!= Established
)
1815 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1816 if (CHECK_FLAG(ri2
->flags
,
1817 BGP_INFO_DMED_CHECK
))
1819 if (BGP_INFO_HOLDDOWN(ri2
))
1822 && ri2
->peer
!= bgp
->peer_self
1825 PEER_STATUS_NSF_WAIT
))
1826 if (ri2
->peer
->status
1830 if (aspath_cmp_left(ri1
->attr
->aspath
,
1832 || aspath_cmp_left_confed(
1834 ri2
->attr
->aspath
)) {
1835 if (bgp_info_cmp(bgp
, ri2
,
1841 bgp_info_unset_flag(
1843 BGP_INFO_DMED_SELECTED
);
1849 BGP_INFO_DMED_CHECK
);
1853 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1854 bgp_info_set_flag(rn
, new_select
,
1855 BGP_INFO_DMED_SELECTED
);
1858 bgp_info_path_with_addpath_rx_str(new_select
,
1860 zlog_debug("%s: %s is the bestpath from AS %d",
1862 aspath_get_first_as(
1863 new_select
->attr
->aspath
));
1868 /* Check old selected route and new selected route. */
1871 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1873 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1876 if (BGP_INFO_HOLDDOWN(ri
)) {
1877 /* reap REMOVED routes, if needs be
1878 * selected route must stay for a while longer though
1880 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1881 && (ri
!= old_select
))
1882 bgp_info_reap(rn
, ri
);
1885 zlog_debug("%s: ri %p in holddown", __func__
,
1891 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1892 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1893 if (ri
->peer
->status
!= Established
) {
1897 "%s: ri %p non self peer %s not estab state",
1898 __func__
, ri
, ri
->peer
->host
);
1903 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1904 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1905 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1907 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1911 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1913 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1914 debug
, pfx_buf
, afi
, safi
)) {
1919 /* Now that we know which path is the bestpath see if any of the other
1921 * qualify as multipaths
1925 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1927 sprintf(path_buf
, "NONE");
1929 "%s: After path selection, newbest is %s oldbest was %s",
1931 old_select
? old_select
->peer
->host
: "NONE");
1934 if (do_mpath
&& new_select
) {
1935 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1939 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1941 if (ri
== new_select
) {
1944 "%s: %s is the bestpath, add to the multipath list",
1946 bgp_mp_list_add(&mp_list
, ri
);
1950 if (BGP_INFO_HOLDDOWN(ri
))
1953 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1954 && !CHECK_FLAG(ri
->peer
->sflags
,
1955 PEER_STATUS_NSF_WAIT
))
1956 if (ri
->peer
->status
!= Established
)
1959 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1962 "%s: %s has the same nexthop as the bestpath, skip it",
1967 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1968 debug
, pfx_buf
, afi
, safi
);
1973 "%s: %s is equivalent to the bestpath, add to the multipath list",
1975 bgp_mp_list_add(&mp_list
, ri
);
1980 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1981 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1982 bgp_mp_list_clear(&mp_list
);
1984 result
->old
= old_select
;
1985 result
->new = new_select
;
1991 * A new route/change in bestpath of an existing route. Evaluate the path
1992 * for advertisement to the subgroup.
1994 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1995 struct bgp_info
*selected
,
1996 struct bgp_node
*rn
,
1997 uint32_t addpath_tx_id
)
2000 struct peer
*onlypeer
;
2006 afi
= SUBGRP_AFI(subgrp
);
2007 safi
= SUBGRP_SAFI(subgrp
);
2008 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2011 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2012 char buf_prefix
[PREFIX_STRLEN
];
2013 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2014 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2018 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2019 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2020 PEER_STATUS_ORF_WAIT_REFRESH
))
2023 memset(&attr
, 0, sizeof(struct attr
));
2024 /* It's initialized in bgp_announce_check() */
2026 /* Announcement to the subgroup. If the route is filtered withdraw it.
2029 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2030 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2032 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2033 selected
->addpath_tx_id
);
2036 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2038 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2045 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2046 * This is called at the end of route processing.
2048 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2050 struct bgp_info
*ri
;
2052 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2053 if (BGP_INFO_HOLDDOWN(ri
))
2055 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2056 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2061 * Has the route changed from the RIB's perspective? This is invoked only
2062 * if the route selection returns the same best route as earlier - to
2063 * determine if we need to update zebra or not.
2065 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2067 struct bgp_info
*mpinfo
;
2069 /* If this is multipath, check all selected paths for any nexthop change
2071 * attribute change. Some attribute changes (e.g., community) aren't of
2072 * relevance to the RIB, but we'll update zebra to ensure we handle the
2073 * case of BGP nexthop change. This is the behavior when the best path
2075 * an attribute change anyway.
2077 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2078 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2081 /* If this is multipath, check all selected paths for any nexthop change
2083 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2084 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2085 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2086 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2090 /* Nothing has changed from the RIB's perspective. */
2094 struct bgp_process_queue
{
2096 STAILQ_HEAD(, bgp_node
) pqueue
;
2097 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2099 unsigned int queued
;
2103 * old_select = The old best path
2104 * new_select = the new best path
2106 * if (!old_select && new_select)
2107 * We are sending new information on.
2109 * if (old_select && new_select) {
2110 * if (new_select != old_select)
2111 * We have a new best path send a change
2113 * We've received a update with new attributes that needs
2117 * if (old_select && !new_select)
2118 * We have no eligible route that we can announce or the rn
2121 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2122 afi_t afi
, safi_t safi
)
2124 struct prefix
*p
= &rn
->p
;
2125 struct bgp_info
*new_select
;
2126 struct bgp_info
*old_select
;
2127 struct bgp_info_pair old_and_new
;
2128 char pfx_buf
[PREFIX2STR_BUFFER
];
2131 /* Is it end of initial update? (after startup) */
2133 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2134 sizeof(bgp
->update_delay_zebra_resume_time
));
2136 bgp
->main_zebra_update_hold
= 0;
2137 FOREACH_AFI_SAFI (afi
, safi
) {
2138 if (bgp_fibupd_safi(safi
))
2139 bgp_zebra_announce_table(bgp
, afi
, safi
);
2141 bgp
->main_peers_update_hold
= 0;
2143 bgp_start_routeadv(bgp
);
2147 debug
= bgp_debug_bestpath(&rn
->p
);
2149 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2150 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2151 afi2str(afi
), safi2str(safi
));
2154 /* Best path selection. */
2155 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2157 old_select
= old_and_new
.old
;
2158 new_select
= old_and_new
.new;
2160 /* Do we need to allocate or free labels?
2161 * Right now, since we only deal with per-prefix labels, it is not
2162 * necessary to do this upon changes to best path except if the label
2165 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2168 || bgp_label_index_differs(new_select
, old_select
)
2169 || new_select
->sub_type
!= old_select
->sub_type
) {
2170 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2171 && new_select
->attr
->flag
2173 BGP_ATTR_PREFIX_SID
)
2174 && new_select
->attr
->label_index
2175 != BGP_INVALID_LABEL_INDEX
) {
2178 BGP_NODE_REGISTERED_FOR_LABEL
))
2179 bgp_unregister_for_label(rn
);
2180 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2182 bgp_set_valid_label(&rn
->local_label
);
2184 bgp_register_for_label(rn
, new_select
);
2186 } else if (CHECK_FLAG(rn
->flags
,
2187 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2188 bgp_unregister_for_label(rn
);
2190 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2191 bgp_unregister_for_label(rn
);
2195 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2197 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2198 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2199 old_select
, new_select
);
2202 /* If best route remains the same and this is not due to user-initiated
2203 * clear, see exactly what needs to be done.
2206 if (old_select
&& old_select
== new_select
2207 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2208 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2209 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2210 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2212 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2213 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2215 if (bgp_fibupd_safi(safi
)
2216 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2218 if (new_select
->type
== ZEBRA_ROUTE_BGP
2219 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2220 || new_select
->sub_type
2221 == BGP_ROUTE_IMPORTED
))
2223 bgp_zebra_announce(rn
, p
, old_select
,
2227 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2228 bgp_zebra_clear_route_change_flags(rn
);
2230 /* If there is a change of interest to peers, reannounce the
2232 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2233 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2234 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2236 /* unicast routes must also be annouced to
2237 * labeled-unicast update-groups */
2238 if (safi
== SAFI_UNICAST
)
2239 group_announce_route(bgp
, afi
,
2240 SAFI_LABELED_UNICAST
, rn
,
2243 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2244 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2247 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2251 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2253 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2255 /* bestpath has changed; bump version */
2256 if (old_select
|| new_select
) {
2257 bgp_bump_version(rn
);
2259 if (!bgp
->t_rmap_def_originate_eval
) {
2263 update_group_refresh_default_originate_route_map
,
2264 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2265 &bgp
->t_rmap_def_originate_eval
);
2270 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2273 zlog_debug("%s: setting SELECTED flag", __func__
);
2274 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2275 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2276 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2280 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2281 if (old_select
!= new_select
) {
2283 vnc_import_bgp_exterior_del_route(bgp
, p
,
2285 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2288 vnc_import_bgp_exterior_add_route(bgp
, p
,
2290 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2296 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2298 /* unicast routes must also be annouced to labeled-unicast update-groups
2300 if (safi
== SAFI_UNICAST
)
2301 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2305 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2306 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2307 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2308 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2309 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2310 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2312 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2314 /* Withdraw the route from the kernel. */
2315 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2316 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2317 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2318 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2320 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2324 /* advertise/withdraw type-5 routes */
2325 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2326 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2327 (!new_select
->extra
|| !new_select
->extra
->parent
))
2328 bgp_evpn_advertise_type5_route(bgp
, &rn
->p
,
2331 else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2332 (!old_select
->extra
|| !old_select
->extra
->parent
))
2333 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2336 /* Clear any route change flags. */
2337 bgp_zebra_clear_route_change_flags(rn
);
2339 /* Reap old select bgp_info, if it has been removed */
2340 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2341 bgp_info_reap(rn
, old_select
);
2343 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2347 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2349 struct bgp_process_queue
*pqnode
= data
;
2350 struct bgp
*bgp
= pqnode
->bgp
;
2351 struct bgp_table
*table
;
2352 struct bgp_node
*rn
;
2355 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2356 bgp_process_main_one(bgp
, NULL
, 0, 0);
2357 /* should always have dedicated wq call */
2358 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2362 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2363 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2364 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2365 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2366 table
= bgp_node_table(rn
);
2367 /* note, new RNs may be added as part of processing */
2368 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2370 bgp_unlock_node(rn
);
2371 bgp_table_unlock(table
);
2377 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2379 struct bgp_process_queue
*pqnode
= data
;
2381 bgp_unlock(pqnode
->bgp
);
2383 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2386 void bgp_process_queue_init(void)
2388 if (!bm
->process_main_queue
) {
2389 bm
->process_main_queue
=
2390 work_queue_new(bm
->master
, "process_main_queue");
2392 if (!bm
->process_main_queue
) {
2393 zlog_err("%s: Failed to allocate work queue", __func__
);
2398 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2399 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2400 bm
->process_main_queue
->spec
.max_retries
= 0;
2401 bm
->process_main_queue
->spec
.hold
= 50;
2402 /* Use a higher yield value of 50ms for main queue processing */
2403 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2406 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2408 struct bgp_process_queue
*pqnode
;
2410 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2411 sizeof(struct bgp_process_queue
));
2413 /* unlocked in bgp_processq_del */
2414 pqnode
->bgp
= bgp_lock(bgp
);
2415 STAILQ_INIT(&pqnode
->pqueue
);
2420 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2422 #define ARBITRARY_PROCESS_QLEN 10000
2423 struct work_queue
*wq
= bm
->process_main_queue
;
2424 struct bgp_process_queue
*pqnode
;
2425 int pqnode_reuse
= 0;
2427 /* already scheduled for processing? */
2428 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2434 /* Add route nodes to an existing work queue item until reaching the
2435 limit only if is from the same BGP view and it's not an EOIU marker
2437 if (work_queue_item_count(wq
)) {
2438 struct work_queue_item
*item
= work_queue_last_item(wq
);
2439 pqnode
= item
->data
;
2441 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2442 || pqnode
->bgp
!= bgp
2443 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2444 pqnode
= bgp_processq_alloc(bgp
);
2448 pqnode
= bgp_processq_alloc(bgp
);
2449 /* all unlocked in bgp_process_wq */
2450 bgp_table_lock(bgp_node_table(rn
));
2452 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2455 /* can't be enqueued twice */
2456 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2457 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2461 work_queue_add(wq
, pqnode
);
2466 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2468 struct bgp_process_queue
*pqnode
;
2470 if (bm
->process_main_queue
== NULL
)
2473 pqnode
= bgp_processq_alloc(bgp
);
2475 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2476 work_queue_add(bm
->process_main_queue
, pqnode
);
2479 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2483 peer
= THREAD_ARG(thread
);
2484 peer
->t_pmax_restart
= NULL
;
2486 if (bgp_debug_neighbor_events(peer
))
2488 "%s Maximum-prefix restart timer expired, restore peering",
2491 peer_clear(peer
, NULL
);
2496 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2500 iana_safi_t pkt_safi
;
2502 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2505 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2506 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2507 PEER_STATUS_PREFIX_LIMIT
)
2512 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2514 afi_safi_print(afi
, safi
), peer
->host
,
2515 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2516 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2518 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2519 PEER_FLAG_MAX_PREFIX_WARNING
))
2522 /* Convert AFI, SAFI to values for packet. */
2523 pkt_afi
= afi_int2iana(afi
);
2524 pkt_safi
= safi_int2iana(safi
);
2528 ndata
[0] = (pkt_afi
>> 8);
2530 ndata
[2] = pkt_safi
;
2531 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2532 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2533 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2534 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2536 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2537 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2538 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2542 /* Dynamic peers will just close their connection. */
2543 if (peer_dynamic_neighbor(peer
))
2546 /* restart timer start */
2547 if (peer
->pmax_restart
[afi
][safi
]) {
2548 peer
->v_pmax_restart
=
2549 peer
->pmax_restart
[afi
][safi
] * 60;
2551 if (bgp_debug_neighbor_events(peer
))
2553 "%s Maximum-prefix restart timer started for %d secs",
2554 peer
->host
, peer
->v_pmax_restart
);
2556 BGP_TIMER_ON(peer
->t_pmax_restart
,
2557 bgp_maximum_prefix_restart_timer
,
2558 peer
->v_pmax_restart
);
2563 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2564 PEER_STATUS_PREFIX_LIMIT
);
2566 if (peer
->pcount
[afi
][safi
]
2567 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2568 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2569 PEER_STATUS_PREFIX_THRESHOLD
)
2574 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2575 afi_safi_print(afi
, safi
), peer
->host
,
2576 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2577 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2578 PEER_STATUS_PREFIX_THRESHOLD
);
2580 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2581 PEER_STATUS_PREFIX_THRESHOLD
);
2585 /* Unconditionally remove the route from the RIB, without taking
2586 * damping into consideration (eg, because the session went down)
2588 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2589 afi_t afi
, safi_t safi
)
2591 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2593 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2594 bgp_info_delete(rn
, ri
); /* keep historical info */
2596 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2599 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2600 struct peer
*peer
, afi_t afi
, safi_t safi
,
2601 struct prefix_rd
*prd
)
2603 int status
= BGP_DAMP_NONE
;
2605 /* apply dampening, if result is suppressed, we'll be retaining
2606 * the bgp_info in the RIB for historical reference.
2608 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2609 && peer
->sort
== BGP_PEER_EBGP
)
2610 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2611 == BGP_DAMP_SUPPRESSED
) {
2612 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2618 if (safi
== SAFI_MPLS_VPN
) {
2619 struct bgp_node
*prn
= NULL
;
2620 struct bgp_table
*table
= NULL
;
2622 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2623 (struct prefix
*)prd
);
2625 table
= (struct bgp_table
*)(prn
->info
);
2627 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2628 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2630 bgp_unlock_node(prn
);
2632 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2633 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2635 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2636 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2642 /* If this is an EVPN route, process for un-import. */
2643 if (safi
== SAFI_EVPN
)
2644 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2646 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2649 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2650 struct peer
*peer
, struct attr
*attr
,
2651 struct bgp_node
*rn
)
2653 struct bgp_info
*new;
2655 /* Make new BGP info. */
2656 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2658 new->instance
= instance
;
2659 new->sub_type
= sub_type
;
2662 new->uptime
= bgp_clock();
2664 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2668 static void overlay_index_update(struct attr
*attr
,
2669 struct eth_segment_id
*eth_s_id
,
2670 union gw_addr
*gw_ip
)
2675 if (eth_s_id
== NULL
) {
2676 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2677 sizeof(struct eth_segment_id
));
2679 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2680 sizeof(struct eth_segment_id
));
2682 if (gw_ip
== NULL
) {
2683 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2685 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2686 sizeof(union gw_addr
));
2690 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2691 struct eth_segment_id
*eth_s_id
,
2692 union gw_addr
*gw_ip
)
2694 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2695 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2698 if (afi
!= AFI_L2VPN
)
2701 memset(&temp
, 0, 16);
2702 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2703 info_gw_ip
= (union gw_addr
*)&temp
;
2704 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2707 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2708 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2711 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2713 info_gw_ip_remote
= gw_ip
;
2714 if (eth_s_id
== NULL
)
2715 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2717 info_eth_s_id_remote
= eth_s_id
;
2718 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2720 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2721 sizeof(struct eth_segment_id
));
2724 /* Check if received nexthop is valid or not. */
2725 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2730 /* Only validated for unicast and multicast currently. */
2731 /* Also valid for EVPN where the nexthop is an IP address. */
2732 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2735 /* If NEXT_HOP is present, validate it. */
2736 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2737 if (attr
->nexthop
.s_addr
== 0
2738 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2739 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2743 /* If MP_NEXTHOP is present, validate it. */
2744 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2745 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2746 * it is not an IPv6 link-local address.
2748 if (attr
->mp_nexthop_len
) {
2749 switch (attr
->mp_nexthop_len
) {
2750 case BGP_ATTR_NHLEN_IPV4
:
2751 case BGP_ATTR_NHLEN_VPNV4
:
2752 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2753 || IPV4_CLASS_DE(ntohl(
2754 attr
->mp_nexthop_global_in
.s_addr
))
2755 || bgp_nexthop_self(bgp
,
2756 attr
->mp_nexthop_global_in
));
2759 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2760 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2761 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2762 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2763 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2764 || IN6_IS_ADDR_MULTICAST(
2765 &attr
->mp_nexthop_global
));
2777 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2778 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2779 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2780 uint32_t num_labels
, int soft_reconfig
,
2781 struct bgp_route_evpn
*evpn
)
2784 int aspath_loop_count
= 0;
2785 struct bgp_node
*rn
;
2787 struct attr new_attr
;
2788 struct attr
*attr_new
;
2789 struct bgp_info
*ri
;
2790 struct bgp_info
*new;
2791 struct bgp_info_extra
*extra
;
2793 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2795 int do_loop_check
= 1;
2796 int has_valid_label
= 0;
2798 int vnc_implicit_withdraw
= 0;
2802 memset(&new_attr
, 0, sizeof(struct attr
));
2803 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2804 new_attr
.label
= MPLS_INVALID_LABEL
;
2807 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2808 /* TODO: Check to see if we can get rid of "is_valid_label" */
2809 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2810 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2812 has_valid_label
= bgp_is_valid_label(label
);
2814 /* When peer's soft reconfiguration enabled. Record input packet in
2817 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2818 && peer
!= bgp
->peer_self
)
2819 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2821 /* Check previously received route. */
2822 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2823 if (ri
->peer
== peer
&& ri
->type
== type
2824 && ri
->sub_type
== sub_type
2825 && ri
->addpath_rx_id
== addpath_id
)
2828 /* AS path local-as loop check. */
2829 if (peer
->change_local_as
) {
2830 if (peer
->allowas_in
[afi
][safi
])
2831 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2832 else if (!CHECK_FLAG(peer
->flags
,
2833 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2834 aspath_loop_count
= 1;
2836 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2837 > aspath_loop_count
) {
2838 reason
= "as-path contains our own AS;";
2843 /* If the peer is configured for "allowas-in origin" and the last ASN in
2845 * as-path is our ASN then we do not need to call aspath_loop_check
2847 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2848 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2851 /* AS path loop check. */
2852 if (do_loop_check
) {
2853 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2854 > peer
->allowas_in
[afi
][safi
]
2855 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2856 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2857 > peer
->allowas_in
[afi
][safi
])) {
2858 reason
= "as-path contains our own AS;";
2863 /* Route reflector originator ID check. */
2864 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2865 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2866 reason
= "originator is us;";
2870 /* Route reflector cluster ID check. */
2871 if (bgp_cluster_filter(peer
, attr
)) {
2872 reason
= "reflected from the same cluster;";
2876 /* Apply incoming filter. */
2877 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2882 bgp_attr_dup(&new_attr
, attr
);
2884 /* Apply incoming route-map.
2885 * NB: new_attr may now contain newly allocated values from route-map
2887 * commands, so we need bgp_attr_flush in the error paths, until we
2889 * the attr (which takes over the memory references) */
2890 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2892 reason
= "route-map;";
2893 bgp_attr_flush(&new_attr
);
2897 if (peer
->sort
== BGP_PEER_EBGP
) {
2899 /* If we receive the graceful-shutdown community from an eBGP
2900 * peer we must lower local-preference */
2901 if (new_attr
.community
2902 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2903 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2904 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2906 /* If graceful-shutdown is configured then add the GSHUT
2907 * community to all paths received from eBGP peers */
2908 } else if (bgp_flag_check(peer
->bgp
,
2909 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2910 bgp_attr_add_gshut_community(&new_attr
);
2914 /* next hop check. */
2915 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2916 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2917 reason
= "martian or self next-hop;";
2918 bgp_attr_flush(&new_attr
);
2922 attr_new
= bgp_attr_intern(&new_attr
);
2924 /* If the update is implicit withdraw. */
2926 ri
->uptime
= bgp_clock();
2927 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2929 /* Same attribute comes in. */
2930 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2931 && attrhash_cmp(ri
->attr
, attr_new
)
2932 && (!has_valid_label
2933 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2934 num_labels
* sizeof(mpls_label_t
))
2936 && (overlay_index_equal(
2937 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2938 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2939 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2940 BGP_CONFIG_DAMPENING
)
2941 && peer
->sort
== BGP_PEER_EBGP
2942 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2943 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2944 bgp_debug_rdpfxpath2str(
2945 afi
, safi
, prd
, p
, label
,
2946 num_labels
, addpath_id
? 1 : 0,
2947 addpath_id
, pfx_buf
,
2949 zlog_debug("%s rcvd %s", peer
->host
,
2953 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2954 != BGP_DAMP_SUPPRESSED
) {
2955 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2957 bgp_process(bgp
, rn
, afi
, safi
);
2959 } else /* Duplicate - odd */
2961 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2962 if (!peer
->rcvd_attr_printed
) {
2964 "%s rcvd UPDATE w/ attr: %s",
2966 peer
->rcvd_attr_str
);
2967 peer
->rcvd_attr_printed
= 1;
2970 bgp_debug_rdpfxpath2str(
2971 afi
, safi
, prd
, p
, label
,
2972 num_labels
, addpath_id
? 1 : 0,
2973 addpath_id
, pfx_buf
,
2976 "%s rcvd %s...duplicate ignored",
2977 peer
->host
, pfx_buf
);
2980 /* graceful restart STALE flag unset. */
2981 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2982 bgp_info_unset_flag(rn
, ri
,
2984 bgp_process(bgp
, rn
, afi
, safi
);
2988 bgp_unlock_node(rn
);
2989 bgp_attr_unintern(&attr_new
);
2994 /* Withdraw/Announce before we fully processed the withdraw */
2995 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2996 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2997 bgp_debug_rdpfxpath2str(
2998 afi
, safi
, prd
, p
, label
, num_labels
,
2999 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3002 "%s rcvd %s, flapped quicker than processing",
3003 peer
->host
, pfx_buf
);
3006 bgp_info_restore(rn
, ri
);
3009 /* Received Logging. */
3010 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3011 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3012 num_labels
, addpath_id
? 1 : 0,
3013 addpath_id
, pfx_buf
,
3015 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3018 /* graceful restart STALE flag unset. */
3019 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3020 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3022 /* The attribute is changed. */
3023 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3025 /* implicit withdraw, decrement aggregate and pcount here.
3026 * only if update is accepted, they'll increment below.
3028 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3030 /* Update bgp route dampening information. */
3031 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3032 && peer
->sort
== BGP_PEER_EBGP
) {
3033 /* This is implicit withdraw so we should update
3036 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3037 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3040 if (safi
== SAFI_MPLS_VPN
) {
3041 struct bgp_node
*prn
= NULL
;
3042 struct bgp_table
*table
= NULL
;
3044 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3045 (struct prefix
*)prd
);
3047 table
= (struct bgp_table
*)(prn
->info
);
3049 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3050 bgp
, prd
, table
, p
, ri
);
3052 bgp_unlock_node(prn
);
3054 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3055 && (safi
== SAFI_UNICAST
)) {
3056 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3058 * Implicit withdraw case.
3060 ++vnc_implicit_withdraw
;
3061 vnc_import_bgp_del_route(bgp
, p
, ri
);
3062 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3067 /* Special handling for EVPN update of an existing route. If the
3068 * extended community attribute has changed, we need to
3070 * the route using its existing extended community. It will be
3071 * subsequently processed for import with the new extended
3074 if (safi
== SAFI_EVPN
&& !same_attr
) {
3076 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3078 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3081 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3082 attr_new
->ecommunity
);
3084 if (bgp_debug_update(peer
, p
, NULL
, 1))
3086 "Change in EXT-COMM, existing %s new %s",
3088 ri
->attr
->ecommunity
),
3090 attr_new
->ecommunity
));
3091 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3097 /* Update to new attribute. */
3098 bgp_attr_unintern(&ri
->attr
);
3099 ri
->attr
= attr_new
;
3101 /* Update MPLS label */
3102 if (has_valid_label
) {
3103 extra
= bgp_info_extra_get(ri
);
3104 memcpy(&extra
->label
, label
,
3105 num_labels
* sizeof(mpls_label_t
));
3106 extra
->num_labels
= num_labels
;
3107 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3108 bgp_set_valid_label(&extra
->label
[0]);
3112 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3113 && (safi
== SAFI_UNICAST
)) {
3114 if (vnc_implicit_withdraw
) {
3116 * Add back the route with its new attributes
3118 * The route is still selected, until the route
3120 * queued by bgp_process actually runs. We have
3122 * update to the VNC side immediately to avoid
3124 * configuration changes (e.g., route-map
3126 * trigger re-importation of the entire RIB.
3128 vnc_import_bgp_add_route(bgp
, p
, ri
);
3129 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3133 /* Update Overlay Index */
3134 if (afi
== AFI_L2VPN
) {
3135 overlay_index_update(
3136 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3137 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3140 /* Update bgp route dampening information. */
3141 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3142 && peer
->sort
== BGP_PEER_EBGP
) {
3143 /* Now we do normal update dampening. */
3144 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3145 if (ret
== BGP_DAMP_SUPPRESSED
) {
3146 bgp_unlock_node(rn
);
3151 /* Nexthop reachability check - for unicast and
3152 * labeled-unicast.. */
3153 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3154 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3155 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3156 && !CHECK_FLAG(peer
->flags
,
3157 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3159 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3164 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
3166 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3167 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3169 if (BGP_DEBUG(nht
, NHT
)) {
3170 char buf1
[INET6_ADDRSTRLEN
];
3172 (const void *)&attr_new
3174 buf1
, INET6_ADDRSTRLEN
);
3175 zlog_debug("%s(%s): NH unresolved",
3176 __FUNCTION__
, buf1
);
3178 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3181 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3184 if (safi
== SAFI_MPLS_VPN
) {
3185 struct bgp_node
*prn
= NULL
;
3186 struct bgp_table
*table
= NULL
;
3188 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3189 (struct prefix
*)prd
);
3191 table
= (struct bgp_table
*)(prn
->info
);
3193 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3194 bgp
, prd
, table
, p
, ri
);
3196 bgp_unlock_node(prn
);
3200 /* If this is an EVPN route and some attribute has changed,
3202 * route for import. If the extended community has changed, we
3204 * have done the un-import earlier and the import would result
3206 * route getting injected into appropriate L2 VNIs. If it is
3208 * some other attribute change, the import will result in
3210 * the attributes for the route in the VNI(s).
3212 if (safi
== SAFI_EVPN
&& !same_attr
)
3213 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3215 /* Process change. */
3216 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3218 bgp_process(bgp
, rn
, afi
, safi
);
3219 bgp_unlock_node(rn
);
3221 if (SAFI_UNICAST
== safi
3222 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3223 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3225 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3227 if ((SAFI_MPLS_VPN
== safi
)
3228 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3230 vpn_leak_to_vrf_update(bgp
, ri
);
3234 if (SAFI_MPLS_VPN
== safi
) {
3235 mpls_label_t label_decoded
= decode_label(label
);
3237 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3238 type
, sub_type
, &label_decoded
);
3240 if (SAFI_ENCAP
== safi
) {
3241 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3242 type
, sub_type
, NULL
);
3247 } // End of implicit withdraw
3249 /* Received Logging. */
3250 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3251 if (!peer
->rcvd_attr_printed
) {
3252 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3253 peer
->rcvd_attr_str
);
3254 peer
->rcvd_attr_printed
= 1;
3257 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3258 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3260 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3263 /* Make new BGP info. */
3264 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3266 /* Update MPLS label */
3267 if (has_valid_label
) {
3268 extra
= bgp_info_extra_get(new);
3269 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3270 extra
->num_labels
= num_labels
;
3271 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3272 bgp_set_valid_label(&extra
->label
[0]);
3275 /* Update Overlay Index */
3276 if (afi
== AFI_L2VPN
) {
3277 overlay_index_update(new->attr
,
3278 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3279 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3281 /* Nexthop reachability check. */
3282 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3283 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3284 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3285 && !CHECK_FLAG(peer
->flags
,
3286 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3287 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3292 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
)
3293 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3294 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3296 if (BGP_DEBUG(nht
, NHT
)) {
3297 char buf1
[INET6_ADDRSTRLEN
];
3299 (const void *)&attr_new
->nexthop
,
3300 buf1
, INET6_ADDRSTRLEN
);
3301 zlog_debug("%s(%s): NH unresolved",
3302 __FUNCTION__
, buf1
);
3304 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3307 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3310 new->addpath_rx_id
= addpath_id
;
3312 /* Increment prefix */
3313 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3315 /* Register new BGP information. */
3316 bgp_info_add(rn
, new);
3318 /* route_node_get lock */
3319 bgp_unlock_node(rn
);
3322 if (safi
== SAFI_MPLS_VPN
) {
3323 struct bgp_node
*prn
= NULL
;
3324 struct bgp_table
*table
= NULL
;
3326 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3328 table
= (struct bgp_table
*)(prn
->info
);
3330 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3331 bgp
, prd
, table
, p
, new);
3333 bgp_unlock_node(prn
);
3337 /* If maximum prefix count is configured and current prefix
3339 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3342 /* If this is an EVPN route, process for import. */
3343 if (safi
== SAFI_EVPN
)
3344 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3346 /* Process change. */
3347 bgp_process(bgp
, rn
, afi
, safi
);
3349 if (SAFI_UNICAST
== safi
3350 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3351 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3352 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3354 if ((SAFI_MPLS_VPN
== safi
)
3355 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3357 vpn_leak_to_vrf_update(bgp
, new);
3360 if (SAFI_MPLS_VPN
== safi
) {
3361 mpls_label_t label_decoded
= decode_label(label
);
3363 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3364 sub_type
, &label_decoded
);
3366 if (SAFI_ENCAP
== safi
) {
3367 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3374 /* This BGP update is filtered. Log the reason then update BGP
3377 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3378 if (!peer
->rcvd_attr_printed
) {
3379 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3380 peer
->rcvd_attr_str
);
3381 peer
->rcvd_attr_printed
= 1;
3384 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3385 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3387 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3388 peer
->host
, pfx_buf
, reason
);
3392 /* If this is an EVPN route, un-import it as it is now filtered.
3394 if (safi
== SAFI_EVPN
)
3395 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3397 if (SAFI_UNICAST
== safi
3398 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3399 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3401 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3403 if ((SAFI_MPLS_VPN
== safi
)
3404 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3406 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3409 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3412 bgp_unlock_node(rn
);
3416 * Filtered update is treated as an implicit withdrawal (see
3418 * a few lines above)
3420 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3421 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3429 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3430 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3431 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3432 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3435 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3436 struct bgp_node
*rn
;
3437 struct bgp_info
*ri
;
3440 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3441 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3449 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3451 /* If peer is soft reconfiguration enabled. Record input packet for
3452 * further calculation.
3454 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3455 * routes that are filtered. This tanks out Quagga RS pretty badly due
3457 * the iteration over all RS clients.
3458 * Since we need to remove the entry from adj_in anyway, do that first
3460 * if there was no entry, we don't need to do anything more.
3462 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3463 && peer
!= bgp
->peer_self
)
3464 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3465 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3466 bgp_debug_rdpfxpath2str(
3467 afi
, safi
, prd
, p
, label
, num_labels
,
3468 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3471 "%s withdrawing route %s not in adj-in",
3472 peer
->host
, pfx_buf
);
3474 bgp_unlock_node(rn
);
3478 /* Lookup withdrawn route. */
3479 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3480 if (ri
->peer
== peer
&& ri
->type
== type
3481 && ri
->sub_type
== sub_type
3482 && ri
->addpath_rx_id
== addpath_id
)
3486 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3487 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3488 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3490 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3494 /* Withdraw specified route from routing table. */
3495 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3496 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3497 if (SAFI_UNICAST
== safi
3498 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3499 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3500 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3502 if ((SAFI_MPLS_VPN
== safi
)
3503 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3505 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3507 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3508 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3509 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3511 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3514 /* Unlock bgp_node_get() lock. */
3515 bgp_unlock_node(rn
);
3520 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3523 struct update_subgroup
*subgrp
;
3524 subgrp
= peer_subgroup(peer
, afi
, safi
);
3525 subgroup_default_originate(subgrp
, withdraw
);
3530 * bgp_stop_announce_route_timer
3532 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3534 if (!paf
->t_announce_route
)
3537 THREAD_TIMER_OFF(paf
->t_announce_route
);
3541 * bgp_announce_route_timer_expired
3543 * Callback that is invoked when the route announcement timer for a
3546 static int bgp_announce_route_timer_expired(struct thread
*t
)
3548 struct peer_af
*paf
;
3551 paf
= THREAD_ARG(t
);
3554 if (peer
->status
!= Established
)
3557 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3560 peer_af_announce_route(paf
, 1);
3565 * bgp_announce_route
3567 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3569 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3571 struct peer_af
*paf
;
3572 struct update_subgroup
*subgrp
;
3574 paf
= peer_af_find(peer
, afi
, safi
);
3577 subgrp
= PAF_SUBGRP(paf
);
3580 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3581 * or a refresh has already been triggered.
3583 if (!subgrp
|| paf
->t_announce_route
)
3587 * Start a timer to stagger/delay the announce. This serves
3588 * two purposes - announcement can potentially be combined for
3589 * multiple peers and the announcement doesn't happen in the
3592 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3593 (subgrp
->peer_count
== 1)
3594 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3595 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3596 &paf
->t_announce_route
);
3600 * Announce routes from all AF tables to a peer.
3602 * This should ONLY be called when there is a need to refresh the
3603 * routes to the peer based on a policy change for this peer alone
3604 * or a route refresh request received from the peer.
3605 * The operation will result in splitting the peer from its existing
3606 * subgroups and putting it in new subgroups.
3608 void bgp_announce_route_all(struct peer
*peer
)
3613 FOREACH_AFI_SAFI (afi
, safi
)
3614 bgp_announce_route(peer
, afi
, safi
);
3617 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3618 struct bgp_table
*table
,
3619 struct prefix_rd
*prd
)
3622 struct bgp_node
*rn
;
3623 struct bgp_adj_in
*ain
;
3626 table
= peer
->bgp
->rib
[afi
][safi
];
3628 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3629 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3630 if (ain
->peer
!= peer
)
3633 struct bgp_info
*ri
= rn
->info
;
3634 uint32_t num_labels
= 0;
3635 mpls_label_t
*label_pnt
= NULL
;
3637 if (ri
&& ri
->extra
)
3638 num_labels
= ri
->extra
->num_labels
;
3640 label_pnt
= &ri
->extra
->label
[0];
3642 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3643 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3644 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3645 num_labels
, 1, NULL
);
3648 bgp_unlock_node(rn
);
3654 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3656 struct bgp_node
*rn
;
3657 struct bgp_table
*table
;
3659 if (peer
->status
!= Established
)
3662 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3663 && (safi
!= SAFI_EVPN
))
3664 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3666 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3667 rn
= bgp_route_next(rn
))
3668 if ((table
= rn
->info
) != NULL
) {
3669 struct prefix_rd prd
;
3670 prd
.family
= AF_UNSPEC
;
3672 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3674 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3680 struct bgp_clear_node_queue
{
3681 struct bgp_node
*rn
;
3684 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3686 struct bgp_clear_node_queue
*cnq
= data
;
3687 struct bgp_node
*rn
= cnq
->rn
;
3688 struct peer
*peer
= wq
->spec
.data
;
3689 struct bgp_info
*ri
;
3691 afi_t afi
= bgp_node_table(rn
)->afi
;
3692 safi_t safi
= bgp_node_table(rn
)->safi
;
3697 /* It is possible that we have multiple paths for a prefix from a peer
3698 * if that peer is using AddPath.
3700 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3701 if (ri
->peer
!= peer
)
3704 /* graceful restart STALE flag set. */
3705 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3706 && peer
->nsf
[afi
][safi
]
3707 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3708 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3709 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3711 /* If this is an EVPN route, process for
3713 if (safi
== SAFI_EVPN
)
3714 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3716 /* Handle withdraw for VRF route-leaking and L3VPN */
3717 if (SAFI_UNICAST
== safi
3718 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3719 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
))
3720 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3722 if (SAFI_MPLS_VPN
== safi
&&
3723 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
3724 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3726 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3732 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3734 struct bgp_clear_node_queue
*cnq
= data
;
3735 struct bgp_node
*rn
= cnq
->rn
;
3736 struct bgp_table
*table
= bgp_node_table(rn
);
3738 bgp_unlock_node(rn
);
3739 bgp_table_unlock(table
);
3740 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3743 static void bgp_clear_node_complete(struct work_queue
*wq
)
3745 struct peer
*peer
= wq
->spec
.data
;
3747 /* Tickle FSM to start moving again */
3748 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3750 peer_unlock(peer
); /* bgp_clear_route */
3753 static void bgp_clear_node_queue_init(struct peer
*peer
)
3755 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3757 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3758 #undef CLEAR_QUEUE_NAME_LEN
3760 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3762 zlog_err("%s: Failed to allocate work queue", __func__
);
3765 peer
->clear_node_queue
->spec
.hold
= 10;
3766 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3767 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3768 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3769 peer
->clear_node_queue
->spec
.max_retries
= 0;
3771 /* we only 'lock' this peer reference when the queue is actually active
3773 peer
->clear_node_queue
->spec
.data
= peer
;
3776 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3777 struct bgp_table
*table
)
3779 struct bgp_node
*rn
;
3780 int force
= bm
->process_main_queue
? 0 : 1;
3783 table
= peer
->bgp
->rib
[afi
][safi
];
3785 /* If still no table => afi/safi isn't configured at all or smth. */
3789 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3790 struct bgp_info
*ri
, *next
;
3791 struct bgp_adj_in
*ain
;
3792 struct bgp_adj_in
*ain_next
;
3794 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3795 * queued for every clearing peer, regardless of whether it is
3796 * relevant to the peer at hand.
3798 * Overview: There are 3 different indices which need to be
3799 * scrubbed, potentially, when a peer is removed:
3801 * 1 peer's routes visible via the RIB (ie accepted routes)
3802 * 2 peer's routes visible by the (optional) peer's adj-in index
3803 * 3 other routes visible by the peer's adj-out index
3805 * 3 there is no hurry in scrubbing, once the struct peer is
3806 * removed from bgp->peer, we could just GC such deleted peer's
3807 * adj-outs at our leisure.
3809 * 1 and 2 must be 'scrubbed' in some way, at least made
3810 * invisible via RIB index before peer session is allowed to be
3811 * brought back up. So one needs to know when such a 'search' is
3816 * - there'd be a single global queue or a single RIB walker
3817 * - rather than tracking which route_nodes still need to be
3818 * examined on a peer basis, we'd track which peers still
3821 * Given that our per-peer prefix-counts now should be reliable,
3822 * this may actually be achievable. It doesn't seem to be a huge
3823 * problem at this time,
3825 * It is possible that we have multiple paths for a prefix from
3827 * if that peer is using AddPath.
3831 ain_next
= ain
->next
;
3833 if (ain
->peer
== peer
) {
3834 bgp_adj_in_remove(rn
, ain
);
3835 bgp_unlock_node(rn
);
3841 for (ri
= rn
->info
; ri
; ri
= next
) {
3843 if (ri
->peer
!= peer
)
3847 bgp_info_reap(rn
, ri
);
3849 struct bgp_clear_node_queue
*cnq
;
3851 /* both unlocked in bgp_clear_node_queue_del */
3852 bgp_table_lock(bgp_node_table(rn
));
3855 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3856 sizeof(struct bgp_clear_node_queue
));
3858 work_queue_add(peer
->clear_node_queue
, cnq
);
3866 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3868 struct bgp_node
*rn
;
3869 struct bgp_table
*table
;
3871 if (peer
->clear_node_queue
== NULL
)
3872 bgp_clear_node_queue_init(peer
);
3874 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3875 * Idle until it receives a Clearing_Completed event. This protects
3876 * against peers which flap faster than we can we clear, which could
3879 * a) race with routes from the new session being installed before
3880 * clear_route_node visits the node (to delete the route of that
3882 * b) resource exhaustion, clear_route_node likely leads to an entry
3883 * on the process_main queue. Fast-flapping could cause that queue
3887 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3888 * the unlock will happen upon work-queue completion; other wise, the
3889 * unlock happens at the end of this function.
3891 if (!peer
->clear_node_queue
->thread
)
3894 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3895 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3897 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3898 rn
= bgp_route_next(rn
))
3899 if ((table
= rn
->info
) != NULL
)
3900 bgp_clear_route_table(peer
, afi
, safi
, table
);
3902 /* unlock if no nodes got added to the clear-node-queue. */
3903 if (!peer
->clear_node_queue
->thread
)
3907 void bgp_clear_route_all(struct peer
*peer
)
3912 FOREACH_AFI_SAFI (afi
, safi
)
3913 bgp_clear_route(peer
, afi
, safi
);
3916 rfapiProcessPeerDown(peer
);
3920 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3922 struct bgp_table
*table
;
3923 struct bgp_node
*rn
;
3924 struct bgp_adj_in
*ain
;
3925 struct bgp_adj_in
*ain_next
;
3927 table
= peer
->bgp
->rib
[afi
][safi
];
3929 /* It is possible that we have multiple paths for a prefix from a peer
3930 * if that peer is using AddPath.
3932 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3936 ain_next
= ain
->next
;
3938 if (ain
->peer
== peer
) {
3939 bgp_adj_in_remove(rn
, ain
);
3940 bgp_unlock_node(rn
);
3948 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3950 struct bgp_node
*rn
;
3951 struct bgp_info
*ri
;
3952 struct bgp_table
*table
;
3954 if (safi
== SAFI_MPLS_VPN
) {
3955 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3956 rn
= bgp_route_next(rn
)) {
3957 struct bgp_node
*rm
;
3958 struct bgp_info
*ri
;
3960 /* look for neighbor in tables */
3961 if ((table
= rn
->info
) == NULL
)
3964 for (rm
= bgp_table_top(table
); rm
;
3965 rm
= bgp_route_next(rm
))
3966 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3967 if (ri
->peer
!= peer
)
3969 if (!CHECK_FLAG(ri
->flags
,
3973 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
3978 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3979 rn
= bgp_route_next(rn
))
3980 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3981 if (ri
->peer
!= peer
)
3983 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3985 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3991 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
3994 struct bgp_node
*rn
;
3995 struct bgp_info
*ri
;
3996 struct bgp_info
*next
;
3998 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3999 for (ri
= rn
->info
; ri
; ri
= next
) {
4001 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4002 && ri
->type
== ZEBRA_ROUTE_BGP
4003 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4004 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4005 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4007 if (bgp_fibupd_safi(safi
))
4008 bgp_zebra_withdraw(&rn
->p
, ri
,
4010 bgp_info_reap(rn
, ri
);
4015 /* Delete all kernel routes. */
4016 void bgp_cleanup_routes(struct bgp
*bgp
)
4019 struct bgp_node
*rn
;
4021 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4022 if (afi
== AFI_L2VPN
)
4024 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4027 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4029 if (afi
!= AFI_L2VPN
) {
4031 safi
= SAFI_MPLS_VPN
;
4032 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4033 rn
= bgp_route_next(rn
)) {
4035 bgp_cleanup_table(bgp
,
4036 (struct bgp_table
*)(rn
->info
),
4038 bgp_table_finish((struct bgp_table
**)&(
4041 bgp_unlock_node(rn
);
4045 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4046 rn
= bgp_route_next(rn
)) {
4048 bgp_cleanup_table(bgp
,
4049 (struct bgp_table
*)(rn
->info
),
4051 bgp_table_finish((struct bgp_table
**)&(
4054 bgp_unlock_node(rn
);
4059 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4060 rn
= bgp_route_next(rn
)) {
4062 bgp_cleanup_table(bgp
,
4063 (struct bgp_table
*)(rn
->info
),
4065 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4067 bgp_unlock_node(rn
);
4072 void bgp_reset(void)
4075 bgp_zclient_reset();
4076 access_list_reset();
4077 prefix_list_reset();
4080 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4082 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4083 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4084 PEER_CAP_ADDPATH_AF_TX_RCV
));
4087 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4089 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4090 struct bgp_nlri
*packet
)
4099 int addpath_encoded
;
4100 uint32_t addpath_id
;
4103 lim
= pnt
+ packet
->length
;
4105 safi
= packet
->safi
;
4107 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4109 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4110 syntactic validity. If the field is syntactically incorrect,
4111 then the Error Subcode is set to Invalid Network Field. */
4112 for (; pnt
< lim
; pnt
+= psize
) {
4113 /* Clear prefix structure. */
4114 memset(&p
, 0, sizeof(struct prefix
));
4116 if (addpath_encoded
) {
4118 /* When packet overflow occurs return immediately. */
4119 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4122 addpath_id
= ntohl(*((uint32_t *)pnt
));
4123 pnt
+= BGP_ADDPATH_ID_LEN
;
4126 /* Fetch prefix length. */
4127 p
.prefixlen
= *pnt
++;
4128 /* afi/safi validity already verified by caller,
4129 * bgp_update_receive */
4130 p
.family
= afi2family(afi
);
4132 /* Prefix length check. */
4133 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4135 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4136 peer
->host
, p
.prefixlen
, packet
->afi
);
4140 /* Packet size overflow check. */
4141 psize
= PSIZE(p
.prefixlen
);
4143 /* When packet overflow occur return immediately. */
4144 if (pnt
+ psize
> lim
) {
4146 "%s [Error] Update packet error (prefix length %d overflows packet)",
4147 peer
->host
, p
.prefixlen
);
4151 /* Defensive coding, double-check the psize fits in a struct
4153 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4155 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4156 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4160 /* Fetch prefix from NLRI packet. */
4161 memcpy(&p
.u
.prefix
, pnt
, psize
);
4163 /* Check address. */
4164 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4165 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4166 /* From RFC4271 Section 6.3:
4168 * If a prefix in the NLRI field is semantically
4170 * (e.g., an unexpected multicast IP address),
4172 * be logged locally, and the prefix SHOULD be
4176 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4177 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4182 /* Check address. */
4183 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4184 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4188 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4190 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4195 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4199 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4201 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4208 /* Normal process. */
4210 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4211 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4212 NULL
, NULL
, 0, 0, NULL
);
4214 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4215 safi
, ZEBRA_ROUTE_BGP
,
4216 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4219 /* Address family configuration mismatch or maximum-prefix count
4225 /* Packet length consistency check. */
4228 "%s [Error] Update packet error (prefix length mismatch with total length)",
4236 static struct bgp_static
*bgp_static_new(void)
4238 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4241 static void bgp_static_free(struct bgp_static
*bgp_static
)
4243 if (bgp_static
->rmap
.name
)
4244 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4245 if (bgp_static
->eth_s_id
)
4246 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4247 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4250 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4251 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4253 struct bgp_node
*rn
;
4254 struct bgp_info
*ri
;
4255 struct bgp_info
*new;
4256 struct bgp_info info
;
4258 struct attr
*attr_new
;
4261 int vnc_implicit_withdraw
= 0;
4268 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4270 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4272 attr
.nexthop
= bgp_static
->igpnexthop
;
4273 attr
.med
= bgp_static
->igpmetric
;
4274 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4276 if (bgp_static
->atomic
)
4277 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4279 /* Store label index, if required. */
4280 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4281 attr
.label_index
= bgp_static
->label_index
;
4282 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4285 /* Apply route-map. */
4286 if (bgp_static
->rmap
.name
) {
4287 struct attr attr_tmp
= attr
;
4288 info
.peer
= bgp
->peer_self
;
4289 info
.attr
= &attr_tmp
;
4291 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4293 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4295 bgp
->peer_self
->rmap_type
= 0;
4297 if (ret
== RMAP_DENYMATCH
) {
4298 /* Free uninterned attribute. */
4299 bgp_attr_flush(&attr_tmp
);
4301 /* Unintern original. */
4302 aspath_unintern(&attr
.aspath
);
4303 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4307 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4308 bgp_attr_add_gshut_community(&attr_tmp
);
4310 attr_new
= bgp_attr_intern(&attr_tmp
);
4313 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4314 bgp_attr_add_gshut_community(&attr
);
4316 attr_new
= bgp_attr_intern(&attr
);
4319 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4320 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4321 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4325 if (attrhash_cmp(ri
->attr
, attr_new
)
4326 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4327 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4328 bgp_unlock_node(rn
);
4329 bgp_attr_unintern(&attr_new
);
4330 aspath_unintern(&attr
.aspath
);
4333 /* The attribute is changed. */
4334 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4336 /* Rewrite BGP route information. */
4337 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4338 bgp_info_restore(rn
, ri
);
4340 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4342 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4343 && (safi
== SAFI_UNICAST
)) {
4344 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4346 * Implicit withdraw case.
4347 * We have to do this before ri is
4350 ++vnc_implicit_withdraw
;
4351 vnc_import_bgp_del_route(bgp
, p
, ri
);
4352 vnc_import_bgp_exterior_del_route(
4357 bgp_attr_unintern(&ri
->attr
);
4358 ri
->attr
= attr_new
;
4359 ri
->uptime
= bgp_clock();
4361 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4362 && (safi
== SAFI_UNICAST
)) {
4363 if (vnc_implicit_withdraw
) {
4364 vnc_import_bgp_add_route(bgp
, p
, ri
);
4365 vnc_import_bgp_exterior_add_route(
4371 /* Nexthop reachability check. */
4372 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4373 && (safi
== SAFI_UNICAST
4374 || safi
== SAFI_LABELED_UNICAST
)) {
4375 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4377 bgp_info_set_flag(rn
, ri
,
4380 if (BGP_DEBUG(nht
, NHT
)) {
4381 char buf1
[INET6_ADDRSTRLEN
];
4382 inet_ntop(p
->family
,
4386 "%s(%s): Route not in table, not advertising",
4387 __FUNCTION__
, buf1
);
4389 bgp_info_unset_flag(rn
, ri
,
4393 /* Delete the NHT structure if any, if we're
4395 * enabling/disabling import check. We
4396 * deregister the route
4397 * from NHT to avoid overloading NHT and the
4398 * process interaction
4400 bgp_unlink_nexthop(ri
);
4401 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4403 /* Process change. */
4404 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4405 bgp_process(bgp
, rn
, afi
, safi
);
4407 if (SAFI_UNICAST
== safi
4408 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4410 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4411 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4415 bgp_unlock_node(rn
);
4416 aspath_unintern(&attr
.aspath
);
4421 /* Make new BGP info. */
4422 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4424 /* Nexthop reachability check. */
4425 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4426 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4427 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4428 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4430 if (BGP_DEBUG(nht
, NHT
)) {
4431 char buf1
[INET6_ADDRSTRLEN
];
4432 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4435 "%s(%s): Route not in table, not advertising",
4436 __FUNCTION__
, buf1
);
4438 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4441 /* Delete the NHT structure if any, if we're toggling between
4442 * enabling/disabling import check. We deregister the route
4443 * from NHT to avoid overloading NHT and the process interaction
4445 bgp_unlink_nexthop(new);
4447 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4450 /* Aggregate address increment. */
4451 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4453 /* Register new BGP information. */
4454 bgp_info_add(rn
, new);
4456 /* route_node_get lock */
4457 bgp_unlock_node(rn
);
4459 /* Process change. */
4460 bgp_process(bgp
, rn
, afi
, safi
);
4462 if (SAFI_UNICAST
== safi
4463 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4464 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4465 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4468 /* Unintern original. */
4469 aspath_unintern(&attr
.aspath
);
4472 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4475 struct bgp_node
*rn
;
4476 struct bgp_info
*ri
;
4478 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4480 /* Check selected route and self inserted route. */
4481 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4482 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4483 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4486 /* Withdraw static BGP route from routing table. */
4488 if (SAFI_UNICAST
== safi
4489 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4490 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4491 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4493 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4494 bgp_unlink_nexthop(ri
);
4495 bgp_info_delete(rn
, ri
);
4496 bgp_process(bgp
, rn
, afi
, safi
);
4499 /* Unlock bgp_node_lookup. */
4500 bgp_unlock_node(rn
);
4504 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4506 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4507 afi_t afi
, safi_t safi
,
4508 struct prefix_rd
*prd
)
4510 struct bgp_node
*rn
;
4511 struct bgp_info
*ri
;
4513 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4515 /* Check selected route and self inserted route. */
4516 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4517 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4518 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4521 /* Withdraw static BGP route from routing table. */
4524 rfapiProcessWithdraw(
4525 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4526 1); /* Kill, since it is an administrative change */
4528 if (SAFI_MPLS_VPN
== safi
4529 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4530 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4532 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4533 bgp_info_delete(rn
, ri
);
4534 bgp_process(bgp
, rn
, afi
, safi
);
4537 /* Unlock bgp_node_lookup. */
4538 bgp_unlock_node(rn
);
4541 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4542 struct bgp_static
*bgp_static
, afi_t afi
,
4545 struct bgp_node
*rn
;
4546 struct bgp_info
*new;
4547 struct attr
*attr_new
;
4548 struct attr attr
= {0};
4549 struct bgp_info
*ri
;
4551 mpls_label_t label
= 0;
4553 uint32_t num_labels
= 0;
4558 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4560 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4563 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4565 attr
.nexthop
= bgp_static
->igpnexthop
;
4566 attr
.med
= bgp_static
->igpmetric
;
4567 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4569 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4570 || (safi
== SAFI_ENCAP
)) {
4571 if (afi
== AFI_IP
) {
4572 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4573 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4576 if (afi
== AFI_L2VPN
) {
4577 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4579 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4580 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4581 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4582 sizeof(struct in6_addr
));
4583 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4584 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4585 struct bgp_encap_type_vxlan bet
;
4586 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4587 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4588 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4590 if (bgp_static
->router_mac
) {
4591 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4594 /* Apply route-map. */
4595 if (bgp_static
->rmap
.name
) {
4596 struct attr attr_tmp
= attr
;
4597 struct bgp_info info
;
4600 info
.peer
= bgp
->peer_self
;
4601 info
.attr
= &attr_tmp
;
4603 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4605 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4607 bgp
->peer_self
->rmap_type
= 0;
4609 if (ret
== RMAP_DENYMATCH
) {
4610 /* Free uninterned attribute. */
4611 bgp_attr_flush(&attr_tmp
);
4613 /* Unintern original. */
4614 aspath_unintern(&attr
.aspath
);
4615 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4620 attr_new
= bgp_attr_intern(&attr_tmp
);
4622 attr_new
= bgp_attr_intern(&attr
);
4625 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4626 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4627 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4632 memset(&add
, 0, sizeof(union gw_addr
));
4633 if (attrhash_cmp(ri
->attr
, attr_new
)
4634 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4635 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4636 bgp_unlock_node(rn
);
4637 bgp_attr_unintern(&attr_new
);
4638 aspath_unintern(&attr
.aspath
);
4641 /* The attribute is changed. */
4642 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4644 /* Rewrite BGP route information. */
4645 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4646 bgp_info_restore(rn
, ri
);
4648 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4649 bgp_attr_unintern(&ri
->attr
);
4650 ri
->attr
= attr_new
;
4651 ri
->uptime
= bgp_clock();
4654 label
= decode_label(&ri
->extra
->label
[0]);
4657 /* Process change. */
4658 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4659 bgp_process(bgp
, rn
, afi
, safi
);
4661 if (SAFI_MPLS_VPN
== safi
4662 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4663 vpn_leak_to_vrf_update(bgp
, ri
);
4666 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4667 ri
->attr
, afi
, safi
, ri
->type
,
4668 ri
->sub_type
, &label
);
4670 bgp_unlock_node(rn
);
4671 aspath_unintern(&attr
.aspath
);
4677 /* Make new BGP info. */
4678 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4680 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4681 new->extra
= bgp_info_extra_new();
4683 new->extra
->label
[0] = bgp_static
->label
;
4684 new->extra
->num_labels
= num_labels
;
4687 label
= decode_label(&bgp_static
->label
);
4690 /* Aggregate address increment. */
4691 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4693 /* Register new BGP information. */
4694 bgp_info_add(rn
, new);
4695 /* route_node_get lock */
4696 bgp_unlock_node(rn
);
4698 /* Process change. */
4699 bgp_process(bgp
, rn
, afi
, safi
);
4701 if (SAFI_MPLS_VPN
== safi
4702 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4703 vpn_leak_to_vrf_update(bgp
, new);
4706 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4707 safi
, new->type
, new->sub_type
, &label
);
4710 /* Unintern original. */
4711 aspath_unintern(&attr
.aspath
);
4714 /* Configure static BGP network. When user don't run zebra, static
4715 route should be installed as valid. */
4716 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4717 const char *ip_str
, afi_t afi
, safi_t safi
,
4718 const char *rmap
, int backdoor
, uint32_t label_index
)
4720 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4723 struct bgp_static
*bgp_static
;
4724 struct bgp_node
*rn
;
4725 uint8_t need_update
= 0;
4727 /* Convert IP prefix string to struct prefix. */
4728 ret
= str2prefix(ip_str
, &p
);
4730 vty_out(vty
, "%% Malformed prefix\n");
4731 return CMD_WARNING_CONFIG_FAILED
;
4733 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4734 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4735 return CMD_WARNING_CONFIG_FAILED
;
4742 /* Set BGP static route configuration. */
4743 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4746 vty_out(vty
, "%% Can't find static route specified\n");
4747 return CMD_WARNING_CONFIG_FAILED
;
4750 bgp_static
= rn
->info
;
4752 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4753 && (label_index
!= bgp_static
->label_index
)) {
4755 "%% label-index doesn't match static route\n");
4756 return CMD_WARNING_CONFIG_FAILED
;
4759 if ((rmap
&& bgp_static
->rmap
.name
)
4760 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4762 "%% route-map name doesn't match static route\n");
4763 return CMD_WARNING_CONFIG_FAILED
;
4766 /* Update BGP RIB. */
4767 if (!bgp_static
->backdoor
)
4768 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4770 /* Clear configuration. */
4771 bgp_static_free(bgp_static
);
4773 bgp_unlock_node(rn
);
4774 bgp_unlock_node(rn
);
4777 /* Set BGP static route configuration. */
4778 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4781 /* Configuration change. */
4782 bgp_static
= rn
->info
;
4784 /* Label index cannot be changed. */
4785 if (bgp_static
->label_index
!= label_index
) {
4786 vty_out(vty
, "%% cannot change label-index\n");
4787 return CMD_WARNING_CONFIG_FAILED
;
4790 /* Check previous routes are installed into BGP. */
4791 if (bgp_static
->valid
4792 && bgp_static
->backdoor
!= backdoor
)
4795 bgp_static
->backdoor
= backdoor
;
4798 if (bgp_static
->rmap
.name
)
4799 XFREE(MTYPE_ROUTE_MAP_NAME
,
4800 bgp_static
->rmap
.name
);
4801 bgp_static
->rmap
.name
=
4802 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4803 bgp_static
->rmap
.map
=
4804 route_map_lookup_by_name(rmap
);
4806 if (bgp_static
->rmap
.name
)
4807 XFREE(MTYPE_ROUTE_MAP_NAME
,
4808 bgp_static
->rmap
.name
);
4809 bgp_static
->rmap
.name
= NULL
;
4810 bgp_static
->rmap
.map
= NULL
;
4811 bgp_static
->valid
= 0;
4813 bgp_unlock_node(rn
);
4815 /* New configuration. */
4816 bgp_static
= bgp_static_new();
4817 bgp_static
->backdoor
= backdoor
;
4818 bgp_static
->valid
= 0;
4819 bgp_static
->igpmetric
= 0;
4820 bgp_static
->igpnexthop
.s_addr
= 0;
4821 bgp_static
->label_index
= label_index
;
4824 if (bgp_static
->rmap
.name
)
4825 XFREE(MTYPE_ROUTE_MAP_NAME
,
4826 bgp_static
->rmap
.name
);
4827 bgp_static
->rmap
.name
=
4828 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4829 bgp_static
->rmap
.map
=
4830 route_map_lookup_by_name(rmap
);
4832 rn
->info
= bgp_static
;
4835 bgp_static
->valid
= 1;
4837 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4839 if (!bgp_static
->backdoor
)
4840 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4846 void bgp_static_add(struct bgp
*bgp
)
4850 struct bgp_node
*rn
;
4851 struct bgp_node
*rm
;
4852 struct bgp_table
*table
;
4853 struct bgp_static
*bgp_static
;
4855 FOREACH_AFI_SAFI (afi
, safi
)
4856 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4857 rn
= bgp_route_next(rn
)) {
4858 if (rn
->info
== NULL
)
4861 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4862 || (safi
== SAFI_EVPN
)) {
4865 for (rm
= bgp_table_top(table
); rm
;
4866 rm
= bgp_route_next(rm
)) {
4867 bgp_static
= rm
->info
;
4868 bgp_static_update_safi(bgp
, &rm
->p
,
4873 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4879 /* Called from bgp_delete(). Delete all static routes from the BGP
4881 void bgp_static_delete(struct bgp
*bgp
)
4885 struct bgp_node
*rn
;
4886 struct bgp_node
*rm
;
4887 struct bgp_table
*table
;
4888 struct bgp_static
*bgp_static
;
4890 FOREACH_AFI_SAFI (afi
, safi
)
4891 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4892 rn
= bgp_route_next(rn
)) {
4893 if (rn
->info
== NULL
)
4896 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4897 || (safi
== SAFI_EVPN
)) {
4900 for (rm
= bgp_table_top(table
); rm
;
4901 rm
= bgp_route_next(rm
)) {
4902 bgp_static
= rm
->info
;
4903 bgp_static_withdraw_safi(
4904 bgp
, &rm
->p
, AFI_IP
, safi
,
4905 (struct prefix_rd
*)&rn
->p
);
4906 bgp_static_free(bgp_static
);
4908 bgp_unlock_node(rn
);
4911 bgp_static
= rn
->info
;
4912 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4913 bgp_static_free(bgp_static
);
4915 bgp_unlock_node(rn
);
4920 void bgp_static_redo_import_check(struct bgp
*bgp
)
4924 struct bgp_node
*rn
;
4925 struct bgp_node
*rm
;
4926 struct bgp_table
*table
;
4927 struct bgp_static
*bgp_static
;
4929 /* Use this flag to force reprocessing of the route */
4930 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4931 FOREACH_AFI_SAFI (afi
, safi
) {
4932 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4933 rn
= bgp_route_next(rn
)) {
4934 if (rn
->info
== NULL
)
4937 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4938 || (safi
== SAFI_EVPN
)) {
4941 for (rm
= bgp_table_top(table
); rm
;
4942 rm
= bgp_route_next(rm
)) {
4943 bgp_static
= rm
->info
;
4944 bgp_static_update_safi(bgp
, &rm
->p
,
4949 bgp_static
= rn
->info
;
4950 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4955 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4958 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4961 struct bgp_table
*table
;
4962 struct bgp_node
*rn
;
4963 struct bgp_info
*ri
;
4965 table
= bgp
->rib
[afi
][safi
];
4966 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4967 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4968 if (ri
->peer
== bgp
->peer_self
4969 && ((ri
->type
== ZEBRA_ROUTE_BGP
4970 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4971 || (ri
->type
!= ZEBRA_ROUTE_BGP
4973 == BGP_ROUTE_REDISTRIBUTE
))) {
4974 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4976 bgp_unlink_nexthop(ri
);
4977 bgp_info_delete(rn
, ri
);
4978 bgp_process(bgp
, rn
, afi
, safi
);
4985 * Purge all networks and redistributed routes from routing table.
4986 * Invoked upon the instance going down.
4988 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4993 FOREACH_AFI_SAFI (afi
, safi
)
4994 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4999 * Currently this is used to set static routes for VPN and ENCAP.
5000 * I think it can probably be factored with bgp_static_set.
5002 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5003 const char *ip_str
, const char *rd_str
,
5004 const char *label_str
, const char *rmap_str
,
5005 int evpn_type
, const char *esi
, const char *gwip
,
5006 const char *ethtag
, const char *routermac
)
5008 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5011 struct prefix_rd prd
;
5012 struct bgp_node
*prn
;
5013 struct bgp_node
*rn
;
5014 struct bgp_table
*table
;
5015 struct bgp_static
*bgp_static
;
5016 mpls_label_t label
= MPLS_INVALID_LABEL
;
5017 struct prefix gw_ip
;
5019 /* validate ip prefix */
5020 ret
= str2prefix(ip_str
, &p
);
5022 vty_out(vty
, "%% Malformed prefix\n");
5023 return CMD_WARNING_CONFIG_FAILED
;
5026 if ((afi
== AFI_L2VPN
)
5027 && (bgp_build_evpn_prefix(evpn_type
,
5028 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5029 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5030 return CMD_WARNING_CONFIG_FAILED
;
5033 ret
= str2prefix_rd(rd_str
, &prd
);
5035 vty_out(vty
, "%% Malformed rd\n");
5036 return CMD_WARNING_CONFIG_FAILED
;
5040 unsigned long label_val
;
5041 label_val
= strtoul(label_str
, NULL
, 10);
5042 encode_label(label_val
, &label
);
5045 if (safi
== SAFI_EVPN
) {
5046 if (esi
&& str2esi(esi
, NULL
) == 0) {
5047 vty_out(vty
, "%% Malformed ESI\n");
5048 return CMD_WARNING_CONFIG_FAILED
;
5050 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5051 vty_out(vty
, "%% Malformed Router MAC\n");
5052 return CMD_WARNING_CONFIG_FAILED
;
5055 memset(&gw_ip
, 0, sizeof(struct prefix
));
5056 ret
= str2prefix(gwip
, &gw_ip
);
5058 vty_out(vty
, "%% Malformed GatewayIp\n");
5059 return CMD_WARNING_CONFIG_FAILED
;
5061 if ((gw_ip
.family
== AF_INET
5062 && IS_EVPN_PREFIX_IPADDR_V6(
5063 (struct prefix_evpn
*)&p
))
5064 || (gw_ip
.family
== AF_INET6
5065 && IS_EVPN_PREFIX_IPADDR_V4(
5066 (struct prefix_evpn
*)&p
))) {
5068 "%% GatewayIp family differs with IP prefix\n");
5069 return CMD_WARNING_CONFIG_FAILED
;
5073 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5074 if (prn
->info
== NULL
)
5075 prn
->info
= bgp_table_init(afi
, safi
);
5077 bgp_unlock_node(prn
);
5080 rn
= bgp_node_get(table
, &p
);
5083 vty_out(vty
, "%% Same network configuration exists\n");
5084 bgp_unlock_node(rn
);
5086 /* New configuration. */
5087 bgp_static
= bgp_static_new();
5088 bgp_static
->backdoor
= 0;
5089 bgp_static
->valid
= 0;
5090 bgp_static
->igpmetric
= 0;
5091 bgp_static
->igpnexthop
.s_addr
= 0;
5092 bgp_static
->label
= label
;
5093 bgp_static
->prd
= prd
;
5096 if (bgp_static
->rmap
.name
)
5097 XFREE(MTYPE_ROUTE_MAP_NAME
,
5098 bgp_static
->rmap
.name
);
5099 bgp_static
->rmap
.name
=
5100 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5101 bgp_static
->rmap
.map
=
5102 route_map_lookup_by_name(rmap_str
);
5105 if (safi
== SAFI_EVPN
) {
5107 bgp_static
->eth_s_id
=
5109 sizeof(struct eth_segment_id
));
5110 str2esi(esi
, bgp_static
->eth_s_id
);
5113 bgp_static
->router_mac
=
5114 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5115 prefix_str2mac(routermac
,
5116 bgp_static
->router_mac
);
5119 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5121 rn
->info
= bgp_static
;
5123 bgp_static
->valid
= 1;
5124 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5130 /* Configure static BGP network. */
5131 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5132 const char *ip_str
, const char *rd_str
,
5133 const char *label_str
, int evpn_type
, const char *esi
,
5134 const char *gwip
, const char *ethtag
)
5136 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5139 struct prefix_rd prd
;
5140 struct bgp_node
*prn
;
5141 struct bgp_node
*rn
;
5142 struct bgp_table
*table
;
5143 struct bgp_static
*bgp_static
;
5144 mpls_label_t label
= MPLS_INVALID_LABEL
;
5146 /* Convert IP prefix string to struct prefix. */
5147 ret
= str2prefix(ip_str
, &p
);
5149 vty_out(vty
, "%% Malformed prefix\n");
5150 return CMD_WARNING_CONFIG_FAILED
;
5153 if ((afi
== AFI_L2VPN
)
5154 && (bgp_build_evpn_prefix(evpn_type
,
5155 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5156 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5157 return CMD_WARNING_CONFIG_FAILED
;
5159 ret
= str2prefix_rd(rd_str
, &prd
);
5161 vty_out(vty
, "%% Malformed rd\n");
5162 return CMD_WARNING_CONFIG_FAILED
;
5166 unsigned long label_val
;
5167 label_val
= strtoul(label_str
, NULL
, 10);
5168 encode_label(label_val
, &label
);
5171 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5172 if (prn
->info
== NULL
)
5173 prn
->info
= bgp_table_init(afi
, safi
);
5175 bgp_unlock_node(prn
);
5178 rn
= bgp_node_lookup(table
, &p
);
5181 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5183 bgp_static
= rn
->info
;
5184 bgp_static_free(bgp_static
);
5186 bgp_unlock_node(rn
);
5187 bgp_unlock_node(rn
);
5189 vty_out(vty
, "%% Can't find the route\n");
5194 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5195 const char *rmap_name
)
5197 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5198 struct bgp_rmap
*rmap
;
5200 rmap
= &bgp
->table_map
[afi
][safi
];
5203 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5204 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5205 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5208 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5213 if (bgp_fibupd_safi(safi
))
5214 bgp_zebra_announce_table(bgp
, afi
, safi
);
5219 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5220 const char *rmap_name
)
5222 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5223 struct bgp_rmap
*rmap
;
5225 rmap
= &bgp
->table_map
[afi
][safi
];
5227 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5231 if (bgp_fibupd_safi(safi
))
5232 bgp_zebra_announce_table(bgp
, afi
, safi
);
5237 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5240 if (bgp
->table_map
[afi
][safi
].name
) {
5241 vty_out(vty
, " table-map %s\n",
5242 bgp
->table_map
[afi
][safi
].name
);
5246 DEFUN (bgp_table_map
,
5249 "BGP table to RIB route download filter\n"
5250 "Name of the route map\n")
5253 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5254 argv
[idx_word
]->arg
);
5256 DEFUN (no_bgp_table_map
,
5257 no_bgp_table_map_cmd
,
5258 "no table-map WORD",
5260 "BGP table to RIB route download filter\n"
5261 "Name of the route map\n")
5264 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5265 argv
[idx_word
]->arg
);
5271 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5272 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5273 backdoor$backdoor}]",
5275 "Specify a network to announce via BGP\n"
5280 "Route-map to modify the attributes\n"
5281 "Name of the route map\n"
5282 "Label index to associate with the prefix\n"
5283 "Label index value\n"
5284 "Specify a BGP backdoor route\n")
5286 char addr_prefix_str
[BUFSIZ
];
5291 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5294 vty_out(vty
, "%% Inconsistent address and mask\n");
5295 return CMD_WARNING_CONFIG_FAILED
;
5299 return bgp_static_set(
5300 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5301 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5302 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5305 DEFPY(ipv6_bgp_network
,
5306 ipv6_bgp_network_cmd
,
5307 "[no] network X:X::X:X/M$prefix \
5308 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5310 "Specify a network to announce via BGP\n"
5312 "Route-map to modify the attributes\n"
5313 "Name of the route map\n"
5314 "Label index to associate with the prefix\n"
5315 "Label index value\n")
5317 return bgp_static_set(
5318 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5319 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5322 /* Aggreagete address:
5324 advertise-map Set condition to advertise attribute
5325 as-set Generate AS set path information
5326 attribute-map Set attributes of aggregate
5327 route-map Set parameters of aggregate
5328 summary-only Filter more specific routes from updates
5329 suppress-map Conditionally filter more specific routes from updates
5332 struct bgp_aggregate
{
5333 /* Summary-only flag. */
5334 uint8_t summary_only
;
5336 /* AS set generation. */
5339 /* Route-map for aggregated route. */
5340 struct route_map
*map
;
5342 /* Suppress-count. */
5343 unsigned long count
;
5345 /* SAFI configuration. */
5349 static struct bgp_aggregate
*bgp_aggregate_new(void)
5351 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5354 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5356 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5359 /* Update an aggregate as routes are added/removed from the BGP table */
5360 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5361 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5362 struct bgp_info
*del
,
5363 struct bgp_aggregate
*aggregate
)
5365 struct bgp_table
*table
;
5366 struct bgp_node
*top
;
5367 struct bgp_node
*rn
;
5369 struct aspath
*aspath
= NULL
;
5370 struct aspath
*asmerge
= NULL
;
5371 struct community
*community
= NULL
;
5372 struct community
*commerge
= NULL
;
5373 #if defined(AGGREGATE_NEXTHOP_CHECK)
5374 struct in_addr nexthop
;
5377 struct bgp_info
*ri
;
5378 struct bgp_info
*new;
5380 unsigned long match
= 0;
5381 uint8_t atomic_aggregate
= 0;
5383 /* Record adding route's nexthop and med. */
5385 #if defined(AGGREGATE_NEXTHOP_CHECK)
5386 nexthop
= rinew
->attr
->nexthop
;
5387 med
= rinew
->attr
->med
;
5391 /* ORIGIN attribute: If at least one route among routes that are
5392 aggregated has ORIGIN with the value INCOMPLETE, then the
5393 aggregated route must have the ORIGIN attribute with the value
5394 INCOMPLETE. Otherwise, if at least one route among routes that
5395 are aggregated has ORIGIN with the value EGP, then the aggregated
5396 route must have the origin attribute with the value EGP. In all
5397 other case the value of the ORIGIN attribute of the aggregated
5398 route is INTERNAL. */
5399 origin
= BGP_ORIGIN_IGP
;
5401 table
= bgp
->rib
[afi
][safi
];
5403 top
= bgp_node_get(table
, p
);
5404 for (rn
= bgp_node_get(table
, p
); rn
;
5405 rn
= bgp_route_next_until(rn
, top
))
5406 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5409 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5410 if (BGP_INFO_HOLDDOWN(ri
))
5413 if (del
&& ri
== del
)
5416 if (!rinew
&& first
) {
5417 #if defined(AGGREGATE_NEXTHOP_CHECK)
5418 nexthop
= ri
->attr
->nexthop
;
5419 med
= ri
->attr
->med
;
5424 #ifdef AGGREGATE_NEXTHOP_CHECK
5425 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5427 || ri
->attr
->med
!= med
) {
5429 aspath_free(aspath
);
5431 community_free(community
);
5432 bgp_unlock_node(rn
);
5433 bgp_unlock_node(top
);
5436 #endif /* AGGREGATE_NEXTHOP_CHECK */
5439 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5440 atomic_aggregate
= 1;
5442 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5443 if (aggregate
->summary_only
) {
5444 (bgp_info_extra_get(ri
))
5448 BGP_INFO_ATTR_CHANGED
);
5454 if (origin
< ri
->attr
->origin
)
5455 origin
= ri
->attr
->origin
;
5457 if (aggregate
->as_set
) {
5459 asmerge
= aspath_aggregate(
5462 aspath_free(aspath
);
5465 aspath
= aspath_dup(
5468 if (ri
->attr
->community
) {
5470 commerge
= community_merge(
5472 ri
->attr
->community
);
5473 community
= community_uniq_sort(
5478 community
= community_dup(
5479 ri
->attr
->community
);
5485 bgp_process(bgp
, rn
, afi
, safi
);
5487 bgp_unlock_node(top
);
5492 if (aggregate
->summary_only
)
5493 (bgp_info_extra_get(rinew
))->suppress
++;
5495 if (origin
< rinew
->attr
->origin
)
5496 origin
= rinew
->attr
->origin
;
5498 if (aggregate
->as_set
) {
5500 asmerge
= aspath_aggregate(aspath
,
5501 rinew
->attr
->aspath
);
5502 aspath_free(aspath
);
5505 aspath
= aspath_dup(rinew
->attr
->aspath
);
5507 if (rinew
->attr
->community
) {
5509 commerge
= community_merge(
5511 rinew
->attr
->community
);
5513 community_uniq_sort(commerge
);
5514 community_free(commerge
);
5516 community
= community_dup(
5517 rinew
->attr
->community
);
5522 if (aggregate
->count
> 0) {
5523 rn
= bgp_node_get(table
, p
);
5525 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5526 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5527 community
, aggregate
->as_set
,
5530 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5532 bgp_info_add(rn
, new);
5533 bgp_unlock_node(rn
);
5534 bgp_process(bgp
, rn
, afi
, safi
);
5537 aspath_free(aspath
);
5539 community_free(community
);
5543 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5544 struct bgp_aggregate
*);
5546 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5547 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5549 struct bgp_node
*child
;
5550 struct bgp_node
*rn
;
5551 struct bgp_aggregate
*aggregate
;
5552 struct bgp_table
*table
;
5554 /* MPLS-VPN aggregation is not yet supported. */
5555 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5556 || (safi
== SAFI_EVPN
)
5557 || (safi
== SAFI_FLOWSPEC
))
5560 table
= bgp
->aggregate
[afi
][safi
];
5562 /* No aggregates configured. */
5563 if (bgp_table_top_nolock(table
) == NULL
)
5566 if (p
->prefixlen
== 0)
5569 if (BGP_INFO_HOLDDOWN(ri
))
5572 child
= bgp_node_get(table
, p
);
5574 /* Aggregate address configuration check. */
5575 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5576 if ((aggregate
= rn
->info
) != NULL
5577 && rn
->p
.prefixlen
< p
->prefixlen
) {
5578 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5579 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5582 bgp_unlock_node(child
);
5585 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5586 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5588 struct bgp_node
*child
;
5589 struct bgp_node
*rn
;
5590 struct bgp_aggregate
*aggregate
;
5591 struct bgp_table
*table
;
5593 /* MPLS-VPN aggregation is not yet supported. */
5594 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5595 || (safi
== SAFI_EVPN
)
5596 || (safi
== SAFI_FLOWSPEC
))
5599 table
= bgp
->aggregate
[afi
][safi
];
5601 /* No aggregates configured. */
5602 if (bgp_table_top_nolock(table
) == NULL
)
5605 if (p
->prefixlen
== 0)
5608 child
= bgp_node_get(table
, p
);
5610 /* Aggregate address configuration check. */
5611 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5612 if ((aggregate
= rn
->info
) != NULL
5613 && rn
->p
.prefixlen
< p
->prefixlen
) {
5614 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5615 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5618 bgp_unlock_node(child
);
5621 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5622 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5623 safi_t safi
, struct bgp_aggregate
*aggregate
)
5625 struct bgp_table
*table
;
5626 struct bgp_node
*top
;
5627 struct bgp_node
*rn
;
5628 struct bgp_info
*new;
5629 struct bgp_info
*ri
;
5630 unsigned long match
;
5631 uint8_t origin
= BGP_ORIGIN_IGP
;
5632 struct aspath
*aspath
= NULL
;
5633 struct aspath
*asmerge
= NULL
;
5634 struct community
*community
= NULL
;
5635 struct community
*commerge
= NULL
;
5636 uint8_t atomic_aggregate
= 0;
5638 table
= bgp
->rib
[afi
][safi
];
5641 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5643 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5646 /* If routes exists below this node, generate aggregate routes. */
5647 top
= bgp_node_get(table
, p
);
5648 for (rn
= bgp_node_get(table
, p
); rn
;
5649 rn
= bgp_route_next_until(rn
, top
)) {
5650 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5655 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5656 if (BGP_INFO_HOLDDOWN(ri
))
5660 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5661 atomic_aggregate
= 1;
5663 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5666 /* summary-only aggregate route suppress
5667 * aggregated route announcement. */
5668 if (aggregate
->summary_only
) {
5669 (bgp_info_extra_get(ri
))->suppress
++;
5670 bgp_info_set_flag(rn
, ri
,
5671 BGP_INFO_ATTR_CHANGED
);
5675 /* If at least one route among routes that are
5676 * aggregated has ORIGIN with the value INCOMPLETE,
5677 * then the aggregated route MUST have the ORIGIN
5678 * attribute with the value INCOMPLETE. Otherwise, if
5679 * at least one route among routes that are aggregated
5680 * has ORIGIN with the value EGP, then the aggregated
5681 * route MUST have the ORIGIN attribute with the value
5684 if (origin
< ri
->attr
->origin
)
5685 origin
= ri
->attr
->origin
;
5687 /* as-set aggregate route generate origin, as path,
5688 * community aggregation. */
5689 if (aggregate
->as_set
) {
5691 asmerge
= aspath_aggregate(
5692 aspath
, ri
->attr
->aspath
);
5693 aspath_free(aspath
);
5696 aspath
= aspath_dup(ri
->attr
->aspath
);
5698 if (ri
->attr
->community
) {
5700 commerge
= community_merge(
5702 ri
->attr
->community
);
5703 community
= community_uniq_sort(
5705 community_free(commerge
);
5707 community
= community_dup(
5708 ri
->attr
->community
);
5714 /* If this node is suppressed, process the change. */
5716 bgp_process(bgp
, rn
, afi
, safi
);
5718 bgp_unlock_node(top
);
5720 /* Add aggregate route to BGP table. */
5721 if (aggregate
->count
) {
5722 rn
= bgp_node_get(table
, p
);
5724 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5725 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5726 community
, aggregate
->as_set
,
5729 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5731 bgp_info_add(rn
, new);
5732 bgp_unlock_node(rn
);
5734 /* Process change. */
5735 bgp_process(bgp
, rn
, afi
, safi
);
5738 aspath_free(aspath
);
5740 community_free(community
);
5744 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5745 safi_t safi
, struct bgp_aggregate
*aggregate
)
5747 struct bgp_table
*table
;
5748 struct bgp_node
*top
;
5749 struct bgp_node
*rn
;
5750 struct bgp_info
*ri
;
5751 unsigned long match
;
5753 table
= bgp
->rib
[afi
][safi
];
5755 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5757 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5760 /* If routes exists below this node, generate aggregate routes. */
5761 top
= bgp_node_get(table
, p
);
5762 for (rn
= bgp_node_get(table
, p
); rn
;
5763 rn
= bgp_route_next_until(rn
, top
)) {
5764 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5768 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5769 if (BGP_INFO_HOLDDOWN(ri
))
5772 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5775 if (aggregate
->summary_only
&& ri
->extra
) {
5776 ri
->extra
->suppress
--;
5778 if (ri
->extra
->suppress
== 0) {
5780 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5787 /* If this node was suppressed, process the change. */
5789 bgp_process(bgp
, rn
, afi
, safi
);
5791 bgp_unlock_node(top
);
5793 /* Delete aggregate route from BGP table. */
5794 rn
= bgp_node_get(table
, p
);
5796 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5797 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5798 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5801 /* Withdraw static BGP route from routing table. */
5803 bgp_info_delete(rn
, ri
);
5804 bgp_process(bgp
, rn
, afi
, safi
);
5807 /* Unlock bgp_node_lookup. */
5808 bgp_unlock_node(rn
);
5811 /* Aggregate route attribute. */
5812 #define AGGREGATE_SUMMARY_ONLY 1
5813 #define AGGREGATE_AS_SET 1
5815 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5816 afi_t afi
, safi_t safi
)
5818 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5821 struct bgp_node
*rn
;
5822 struct bgp_aggregate
*aggregate
;
5824 if (safi
== SAFI_FLOWSPEC
)
5825 return CMD_WARNING_CONFIG_FAILED
;
5827 /* Convert string to prefix structure. */
5828 ret
= str2prefix(prefix_str
, &p
);
5830 vty_out(vty
, "Malformed prefix\n");
5831 return CMD_WARNING_CONFIG_FAILED
;
5835 /* Old configuration check. */
5836 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5839 "%% There is no aggregate-address configuration.\n");
5840 return CMD_WARNING_CONFIG_FAILED
;
5843 aggregate
= rn
->info
;
5844 if (aggregate
->safi
== SAFI_UNICAST
)
5845 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5846 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5847 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5849 if (aggregate
->safi
== SAFI_MULTICAST
)
5850 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5852 /* Unlock aggregate address configuration. */
5854 bgp_aggregate_free(aggregate
);
5855 bgp_unlock_node(rn
);
5856 bgp_unlock_node(rn
);
5861 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5862 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5864 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5867 struct bgp_node
*rn
;
5868 struct bgp_aggregate
*aggregate
;
5870 if (safi
== SAFI_FLOWSPEC
)
5871 return CMD_WARNING_CONFIG_FAILED
;
5873 /* Convert string to prefix structure. */
5874 ret
= str2prefix(prefix_str
, &p
);
5876 vty_out(vty
, "Malformed prefix\n");
5877 return CMD_WARNING_CONFIG_FAILED
;
5881 /* Old configuration check. */
5882 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5885 vty_out(vty
, "There is already same aggregate network.\n");
5886 /* try to remove the old entry */
5887 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5889 vty_out(vty
, "Error deleting aggregate.\n");
5890 bgp_unlock_node(rn
);
5891 return CMD_WARNING_CONFIG_FAILED
;
5895 /* Make aggregate address structure. */
5896 aggregate
= bgp_aggregate_new();
5897 aggregate
->summary_only
= summary_only
;
5898 aggregate
->as_set
= as_set
;
5899 aggregate
->safi
= safi
;
5900 rn
->info
= aggregate
;
5902 /* Aggregate address insert into BGP routing table. */
5903 if (safi
== SAFI_UNICAST
)
5904 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5905 if (safi
== SAFI_LABELED_UNICAST
)
5906 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5908 if (safi
== SAFI_MULTICAST
)
5909 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5914 DEFUN (aggregate_address
,
5915 aggregate_address_cmd
,
5916 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5917 "Configure BGP aggregate entries\n"
5918 "Aggregate prefix\n"
5919 "Generate AS set path information\n"
5920 "Filter more specific routes from updates\n"
5921 "Filter more specific routes from updates\n"
5922 "Generate AS set path information\n")
5925 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5926 char *prefix
= argv
[idx
]->arg
;
5928 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5930 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5931 ? AGGREGATE_SUMMARY_ONLY
5934 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5935 summary_only
, as_set
);
5938 DEFUN (aggregate_address_mask
,
5939 aggregate_address_mask_cmd
,
5940 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5941 "Configure BGP aggregate entries\n"
5942 "Aggregate address\n"
5944 "Generate AS set path information\n"
5945 "Filter more specific routes from updates\n"
5946 "Filter more specific routes from updates\n"
5947 "Generate AS set path information\n")
5950 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5951 char *prefix
= argv
[idx
]->arg
;
5952 char *mask
= argv
[idx
+ 1]->arg
;
5954 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5956 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5957 ? AGGREGATE_SUMMARY_ONLY
5960 char prefix_str
[BUFSIZ
];
5961 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5964 vty_out(vty
, "%% Inconsistent address and mask\n");
5965 return CMD_WARNING_CONFIG_FAILED
;
5968 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5969 summary_only
, as_set
);
5972 DEFUN (no_aggregate_address
,
5973 no_aggregate_address_cmd
,
5974 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5976 "Configure BGP aggregate entries\n"
5977 "Aggregate prefix\n"
5978 "Generate AS set path information\n"
5979 "Filter more specific routes from updates\n"
5980 "Filter more specific routes from updates\n"
5981 "Generate AS set path information\n")
5984 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5985 char *prefix
= argv
[idx
]->arg
;
5986 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5989 DEFUN (no_aggregate_address_mask
,
5990 no_aggregate_address_mask_cmd
,
5991 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5993 "Configure BGP aggregate entries\n"
5994 "Aggregate address\n"
5996 "Generate AS set path information\n"
5997 "Filter more specific routes from updates\n"
5998 "Filter more specific routes from updates\n"
5999 "Generate AS set path information\n")
6002 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6003 char *prefix
= argv
[idx
]->arg
;
6004 char *mask
= argv
[idx
+ 1]->arg
;
6006 char prefix_str
[BUFSIZ
];
6007 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6010 vty_out(vty
, "%% Inconsistent address and mask\n");
6011 return CMD_WARNING_CONFIG_FAILED
;
6014 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6017 DEFUN (ipv6_aggregate_address
,
6018 ipv6_aggregate_address_cmd
,
6019 "aggregate-address X:X::X:X/M [summary-only]",
6020 "Configure BGP aggregate entries\n"
6021 "Aggregate prefix\n"
6022 "Filter more specific routes from updates\n")
6025 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6026 char *prefix
= argv
[idx
]->arg
;
6027 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6028 ? AGGREGATE_SUMMARY_ONLY
6030 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6034 DEFUN (no_ipv6_aggregate_address
,
6035 no_ipv6_aggregate_address_cmd
,
6036 "no aggregate-address X:X::X:X/M [summary-only]",
6038 "Configure BGP aggregate entries\n"
6039 "Aggregate prefix\n"
6040 "Filter more specific routes from updates\n")
6043 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6044 char *prefix
= argv
[idx
]->arg
;
6045 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6048 /* Redistribute route treatment. */
6049 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6050 const union g_addr
*nexthop
, ifindex_t ifindex
,
6051 enum nexthop_types_t nhtype
, uint32_t metric
,
6052 uint8_t type
, unsigned short instance
,
6055 struct bgp_info
*new;
6056 struct bgp_info
*bi
;
6057 struct bgp_info info
;
6058 struct bgp_node
*bn
;
6060 struct attr
*new_attr
;
6063 struct bgp_redist
*red
;
6065 /* Make default attribute. */
6066 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6069 case NEXTHOP_TYPE_IFINDEX
:
6071 case NEXTHOP_TYPE_IPV4
:
6072 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6073 attr
.nexthop
= nexthop
->ipv4
;
6075 case NEXTHOP_TYPE_IPV6
:
6076 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6077 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6078 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6080 case NEXTHOP_TYPE_BLACKHOLE
:
6081 switch (p
->family
) {
6083 attr
.nexthop
.s_addr
= INADDR_ANY
;
6086 memset(&attr
.mp_nexthop_global
, 0,
6087 sizeof(attr
.mp_nexthop_global
));
6088 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6093 attr
.nh_ifindex
= ifindex
;
6096 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6099 afi
= family2afi(p
->family
);
6101 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6103 struct attr attr_new
;
6105 /* Copy attribute for modification. */
6106 bgp_attr_dup(&attr_new
, &attr
);
6108 if (red
->redist_metric_flag
)
6109 attr_new
.med
= red
->redist_metric
;
6111 /* Apply route-map. */
6112 if (red
->rmap
.name
) {
6113 info
.peer
= bgp
->peer_self
;
6114 info
.attr
= &attr_new
;
6116 SET_FLAG(bgp
->peer_self
->rmap_type
,
6117 PEER_RMAP_TYPE_REDISTRIBUTE
);
6119 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6122 bgp
->peer_self
->rmap_type
= 0;
6124 if (ret
== RMAP_DENYMATCH
) {
6125 /* Free uninterned attribute. */
6126 bgp_attr_flush(&attr_new
);
6128 /* Unintern original. */
6129 aspath_unintern(&attr
.aspath
);
6130 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6135 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6136 bgp_attr_add_gshut_community(&attr_new
);
6138 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6139 SAFI_UNICAST
, p
, NULL
);
6141 new_attr
= bgp_attr_intern(&attr_new
);
6143 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6144 if (bi
->peer
== bgp
->peer_self
6145 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6149 /* Ensure the (source route) type is updated. */
6151 if (attrhash_cmp(bi
->attr
, new_attr
)
6152 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6153 bgp_attr_unintern(&new_attr
);
6154 aspath_unintern(&attr
.aspath
);
6155 bgp_unlock_node(bn
);
6158 /* The attribute is changed. */
6159 bgp_info_set_flag(bn
, bi
,
6160 BGP_INFO_ATTR_CHANGED
);
6162 /* Rewrite BGP route information. */
6163 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6164 bgp_info_restore(bn
, bi
);
6166 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6168 bgp_attr_unintern(&bi
->attr
);
6169 bi
->attr
= new_attr
;
6170 bi
->uptime
= bgp_clock();
6172 /* Process change. */
6173 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6175 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6176 bgp_unlock_node(bn
);
6177 aspath_unintern(&attr
.aspath
);
6179 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6181 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6183 vpn_leak_from_vrf_update(
6184 bgp_get_default(), bgp
, bi
);
6190 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6191 bgp
->peer_self
, new_attr
, bn
);
6192 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6194 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6195 bgp_info_add(bn
, new);
6196 bgp_unlock_node(bn
);
6197 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6199 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6200 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6202 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6206 /* Unintern original. */
6207 aspath_unintern(&attr
.aspath
);
6210 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6211 unsigned short instance
)
6214 struct bgp_node
*rn
;
6215 struct bgp_info
*ri
;
6216 struct bgp_redist
*red
;
6218 afi
= family2afi(p
->family
);
6220 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6222 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6223 SAFI_UNICAST
, p
, NULL
);
6225 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6226 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6230 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6231 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6233 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6236 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6237 bgp_info_delete(rn
, ri
);
6238 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6240 bgp_unlock_node(rn
);
6244 /* Withdraw specified route type's route. */
6245 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6246 unsigned short instance
)
6248 struct bgp_node
*rn
;
6249 struct bgp_info
*ri
;
6250 struct bgp_table
*table
;
6252 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6254 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6255 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6256 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6257 && ri
->instance
== instance
)
6261 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6262 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6264 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6267 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6269 bgp_info_delete(rn
, ri
);
6270 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6275 /* Static function to display route. */
6276 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6280 uint32_t destination
;
6283 if (p
->family
== AF_INET
) {
6285 len
= vty_out(vty
, "%s",
6286 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6288 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6290 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6291 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6292 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6293 || p
->u
.prefix4
.s_addr
== 0) {
6294 /* When mask is natural,
6295 mask is not displayed. */
6297 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6299 json_object_string_add(json
, "prefix",
6300 inet_ntop(p
->family
,
6303 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6305 } else if (p
->family
== AF_ETHERNET
) {
6306 prefix2str(p
, buf
, PREFIX_STRLEN
);
6307 len
= vty_out(vty
, "%s", buf
);
6308 } else if (p
->family
== AF_EVPN
) {
6309 #if defined(HAVE_CUMULUS)
6313 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6316 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6318 prefix2str(p
, buf
, PREFIX_STRLEN
);
6319 len
= vty_out(vty
, "%s", buf
);
6321 } else if (p
->family
== AF_FLOWSPEC
) {
6322 route_vty_out_flowspec(vty
, p
, NULL
,
6324 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6325 NLRI_STRING_FORMAT_MIN
, json
);
6330 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6337 vty_out(vty
, "\n%*s", 20, " ");
6339 vty_out(vty
, "%*s", len
, " ");
6343 enum bgp_display_type
{
6347 /* Print the short form route status for a bgp_info */
6348 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6349 json_object
*json_path
)
6353 /* Route status display. */
6354 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6355 json_object_boolean_true_add(json_path
, "removed");
6357 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6358 json_object_boolean_true_add(json_path
, "stale");
6360 if (binfo
->extra
&& binfo
->extra
->suppress
)
6361 json_object_boolean_true_add(json_path
, "suppressed");
6363 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6364 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6365 json_object_boolean_true_add(json_path
, "valid");
6368 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6369 json_object_boolean_true_add(json_path
, "history");
6371 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6372 json_object_boolean_true_add(json_path
, "damped");
6374 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6375 json_object_boolean_true_add(json_path
, "bestpath");
6377 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6378 json_object_boolean_true_add(json_path
, "multipath");
6380 /* Internal route. */
6381 if ((binfo
->peer
->as
)
6382 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6383 json_object_string_add(json_path
, "pathFrom",
6386 json_object_string_add(json_path
, "pathFrom",
6392 /* Route status display. */
6393 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6395 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6397 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6399 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6400 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6406 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6408 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6410 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6412 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6417 /* Internal route. */
6418 if (binfo
->peer
&& (binfo
->peer
->as
)
6419 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6425 /* called from terminal list command */
6426 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6427 int display
, safi_t safi
, json_object
*json_paths
)
6430 json_object
*json_path
= NULL
;
6431 json_object
*json_nexthops
= NULL
;
6432 json_object
*json_nexthop_global
= NULL
;
6433 json_object
*json_nexthop_ll
= NULL
;
6436 json_path
= json_object_new_object();
6438 /* short status lead text */
6439 route_vty_short_status_out(vty
, binfo
, json_path
);
6442 /* print prefix and mask */
6444 route_vty_out_route(p
, vty
, json_path
);
6446 vty_out(vty
, "%*s", 17, " ");
6448 route_vty_out_route(p
, vty
, json_path
);
6451 /* Print attribute */
6455 json_object_array_add(json_paths
, json_path
);
6463 * For ENCAP and EVPN routes, nexthop address family is not
6464 * neccessarily the same as the prefix address family.
6465 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6466 * EVPN routes are also exchanged with a MP nexthop. Currently,
6468 * is only IPv4, the value will be present in either
6470 * attr->mp_nexthop_global_in
6472 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6475 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6479 sprintf(nexthop
, "%s",
6480 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6484 sprintf(nexthop
, "%s",
6485 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6489 sprintf(nexthop
, "?");
6494 json_nexthop_global
= json_object_new_object();
6496 json_object_string_add(json_nexthop_global
, "afi",
6497 (af
== AF_INET
) ? "ip" : "ipv6");
6498 json_object_string_add(json_nexthop_global
,
6499 (af
== AF_INET
) ? "ip" : "ipv6",
6501 json_object_boolean_true_add(json_nexthop_global
,
6504 vty_out(vty
, "%s", nexthop
);
6505 } else if (safi
== SAFI_EVPN
) {
6507 json_nexthop_global
= json_object_new_object();
6509 json_object_string_add(json_nexthop_global
, "ip",
6510 inet_ntoa(attr
->nexthop
));
6511 json_object_string_add(json_nexthop_global
, "afi",
6513 json_object_boolean_true_add(json_nexthop_global
,
6516 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6517 } else if (safi
== SAFI_FLOWSPEC
) {
6520 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6522 json_nexthop_global
= json_object_new_object();
6524 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6525 json_object_string_add(
6526 json_nexthop_global
, "ip",
6527 inet_ntoa(attr
->mp_nexthop_global_in
));
6529 json_object_string_add(
6530 json_nexthop_global
, "ip",
6531 inet_ntoa(attr
->nexthop
));
6533 json_object_string_add(json_nexthop_global
, "afi",
6535 json_object_boolean_true_add(json_nexthop_global
,
6538 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6539 vty_out(vty
, "%-16s",
6540 inet_ntoa(attr
->mp_nexthop_global_in
));
6542 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6547 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6552 json_nexthop_global
= json_object_new_object();
6553 json_object_string_add(
6554 json_nexthop_global
, "ip",
6555 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6557 json_object_string_add(json_nexthop_global
, "afi",
6559 json_object_string_add(json_nexthop_global
, "scope",
6562 /* We display both LL & GL if both have been
6564 if ((attr
->mp_nexthop_len
== 32)
6565 || (binfo
->peer
->conf_if
)) {
6566 json_nexthop_ll
= json_object_new_object();
6567 json_object_string_add(
6568 json_nexthop_ll
, "ip",
6570 &attr
->mp_nexthop_local
, buf
,
6572 json_object_string_add(json_nexthop_ll
, "afi",
6574 json_object_string_add(json_nexthop_ll
, "scope",
6577 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6578 &attr
->mp_nexthop_local
)
6580 && !attr
->mp_nexthop_prefer_global
)
6581 json_object_boolean_true_add(
6582 json_nexthop_ll
, "used");
6584 json_object_boolean_true_add(
6585 json_nexthop_global
, "used");
6587 json_object_boolean_true_add(
6588 json_nexthop_global
, "used");
6590 /* Display LL if LL/Global both in table unless
6591 * prefer-global is set */
6592 if (((attr
->mp_nexthop_len
== 32)
6593 && !attr
->mp_nexthop_prefer_global
)
6594 || (binfo
->peer
->conf_if
)) {
6595 if (binfo
->peer
->conf_if
) {
6596 len
= vty_out(vty
, "%s",
6597 binfo
->peer
->conf_if
);
6598 len
= 16 - len
; /* len of IPv6
6604 vty_out(vty
, "\n%*s", 36, " ");
6606 vty_out(vty
, "%*s", len
, " ");
6612 &attr
->mp_nexthop_local
,
6617 vty_out(vty
, "\n%*s", 36, " ");
6619 vty_out(vty
, "%*s", len
, " ");
6625 &attr
->mp_nexthop_global
, buf
,
6630 vty_out(vty
, "\n%*s", 36, " ");
6632 vty_out(vty
, "%*s", len
, " ");
6638 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6640 json_object_int_add(json_path
, "med", attr
->med
);
6642 vty_out(vty
, "%10u", attr
->med
);
6643 else if (!json_paths
)
6647 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6649 json_object_int_add(json_path
, "localpref",
6652 vty_out(vty
, "%7u", attr
->local_pref
);
6653 else if (!json_paths
)
6657 json_object_int_add(json_path
, "weight", attr
->weight
);
6659 vty_out(vty
, "%7u ", attr
->weight
);
6663 json_object_string_add(
6664 json_path
, "peerId",
6665 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6671 json_object_string_add(json_path
, "aspath",
6674 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6679 json_object_string_add(json_path
, "origin",
6680 bgp_origin_long_str
[attr
->origin
]);
6682 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6685 if (json_nexthop_global
|| json_nexthop_ll
) {
6686 json_nexthops
= json_object_new_array();
6688 if (json_nexthop_global
)
6689 json_object_array_add(json_nexthops
,
6690 json_nexthop_global
);
6692 if (json_nexthop_ll
)
6693 json_object_array_add(json_nexthops
,
6696 json_object_object_add(json_path
, "nexthops",
6700 json_object_array_add(json_paths
, json_path
);
6704 /* prints an additional line, indented, with VNC info, if
6706 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6707 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6712 /* called from terminal list command */
6713 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6714 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6716 json_object
*json_status
= NULL
;
6717 json_object
*json_net
= NULL
;
6719 /* Route status display. */
6721 json_status
= json_object_new_object();
6722 json_net
= json_object_new_object();
6729 /* print prefix and mask */
6731 json_object_string_add(
6732 json_net
, "addrPrefix",
6733 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6735 route_vty_out_route(p
, vty
, NULL
);
6737 /* Print attribute */
6740 if (p
->family
== AF_INET
6741 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6742 || safi
== SAFI_EVPN
6743 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6744 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6745 || safi
== SAFI_EVPN
)
6746 json_object_string_add(
6747 json_net
, "nextHop",
6749 attr
->mp_nexthop_global_in
));
6751 json_object_string_add(
6752 json_net
, "nextHop",
6753 inet_ntoa(attr
->nexthop
));
6754 } else if (p
->family
== AF_INET6
6755 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6758 json_object_string_add(
6759 json_net
, "netHopGloabal",
6761 &attr
->mp_nexthop_global
, buf
,
6766 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6767 json_object_int_add(json_net
, "metric",
6770 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6771 json_object_int_add(json_net
, "localPref",
6774 json_object_int_add(json_net
, "weight", attr
->weight
);
6778 json_object_string_add(json_net
, "asPath",
6782 json_object_string_add(json_net
, "bgpOriginCode",
6783 bgp_origin_str
[attr
->origin
]);
6785 if (p
->family
== AF_INET
6786 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6787 || safi
== SAFI_EVPN
6788 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6789 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6790 || safi
== SAFI_EVPN
)
6791 vty_out(vty
, "%-16s",
6793 attr
->mp_nexthop_global_in
));
6795 vty_out(vty
, "%-16s",
6796 inet_ntoa(attr
->nexthop
));
6797 } else if (p
->family
== AF_INET6
6798 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6805 &attr
->mp_nexthop_global
, buf
,
6809 vty_out(vty
, "\n%*s", 36, " ");
6811 vty_out(vty
, "%*s", len
, " ");
6814 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6815 vty_out(vty
, "%10u", attr
->med
);
6819 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6820 vty_out(vty
, "%7u", attr
->local_pref
);
6824 vty_out(vty
, "%7u ", attr
->weight
);
6828 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6831 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6835 json_object_boolean_true_add(json_status
, "*");
6836 json_object_boolean_true_add(json_status
, ">");
6837 json_object_object_add(json_net
, "appliedStatusSymbols",
6839 char buf_cut
[BUFSIZ
];
6840 json_object_object_add(
6842 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6848 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6849 struct bgp_info
*binfo
, int display
, safi_t safi
,
6852 json_object
*json_out
= NULL
;
6854 mpls_label_t label
= MPLS_INVALID_LABEL
;
6860 json_out
= json_object_new_object();
6862 /* short status lead text */
6863 route_vty_short_status_out(vty
, binfo
, json_out
);
6865 /* print prefix and mask */
6868 route_vty_out_route(p
, vty
, NULL
);
6870 vty_out(vty
, "%*s", 17, " ");
6873 /* Print attribute */
6876 if (((p
->family
== AF_INET
)
6877 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6878 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6879 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6880 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6881 || safi
== SAFI_EVPN
) {
6883 json_object_string_add(
6884 json_out
, "mpNexthopGlobalIn",
6886 attr
->mp_nexthop_global_in
));
6888 vty_out(vty
, "%-16s",
6890 attr
->mp_nexthop_global_in
));
6893 json_object_string_add(
6894 json_out
, "nexthop",
6895 inet_ntoa(attr
->nexthop
));
6897 vty_out(vty
, "%-16s",
6898 inet_ntoa(attr
->nexthop
));
6900 } else if (((p
->family
== AF_INET6
)
6901 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6902 || (safi
== SAFI_EVPN
6903 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6904 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6908 if (attr
->mp_nexthop_len
6909 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6911 json_object_string_add(
6912 json_out
, "mpNexthopGlobalIn",
6915 &attr
->mp_nexthop_global
,
6921 &attr
->mp_nexthop_global
,
6923 } else if (attr
->mp_nexthop_len
6924 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6927 &attr
->mp_nexthop_global
,
6930 &attr
->mp_nexthop_local
,
6932 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6933 json_object_string_add(
6935 "mpNexthopGlobalLocal", buf_c
);
6937 vty_out(vty
, "%s(%s)",
6940 &attr
->mp_nexthop_global
,
6944 &attr
->mp_nexthop_local
,
6950 label
= decode_label(&binfo
->extra
->label
[0]);
6952 if (bgp_is_valid_label(&label
)) {
6954 json_object_int_add(json_out
, "notag", label
);
6955 json_object_array_add(json
, json_out
);
6957 vty_out(vty
, "notag/%d", label
);
6963 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6964 struct bgp_info
*binfo
, int display
,
6965 json_object
*json_paths
)
6969 json_object
*json_path
= NULL
;
6972 json_path
= json_object_new_object();
6977 /* short status lead text */
6978 route_vty_short_status_out(vty
, binfo
, json_path
);
6980 /* print prefix and mask */
6982 route_vty_out_route(p
, vty
, NULL
);
6984 vty_out(vty
, "%*s", 17, " ");
6986 /* Print attribute */
6990 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6994 vty_out(vty
, "%-16s",
6995 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6999 vty_out(vty
, "%s(%s)",
7000 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7002 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7010 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
7011 char *str
= esi2str(id
);
7012 vty_out(vty
, "%s", str
);
7013 XFREE(MTYPE_TMP
, str
);
7014 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7015 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7016 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7018 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7021 if (attr
->ecommunity
) {
7023 struct ecommunity_val
*routermac
= ecommunity_lookup(
7024 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7025 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7027 mac
= ecom_mac2str((char *)routermac
->val
);
7029 vty_out(vty
, "/%s", (char *)mac
);
7030 XFREE(MTYPE_TMP
, mac
);
7036 /* dampening route */
7037 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7038 struct bgp_info
*binfo
, int display
, safi_t safi
,
7039 uint8_t use_json
, json_object
*json
)
7043 char timebuf
[BGP_UPTIME_LEN
];
7045 /* short status lead text */
7046 route_vty_short_status_out(vty
, binfo
, json
);
7048 /* print prefix and mask */
7051 route_vty_out_route(p
, vty
, NULL
);
7053 vty_out(vty
, "%*s", 17, " ");
7056 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7060 vty_out(vty
, "\n%*s", 34, " ");
7063 json_object_int_add(json
, "peerHost", len
);
7065 vty_out(vty
, "%*s", len
, " ");
7069 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7072 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7076 /* Print attribute */
7082 json_object_string_add(json
, "asPath",
7085 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7090 json_object_string_add(json
, "origin",
7091 bgp_origin_str
[attr
->origin
]);
7093 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7100 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7101 struct bgp_info
*binfo
, int display
, safi_t safi
,
7102 uint8_t use_json
, json_object
*json
)
7105 struct bgp_damp_info
*bdi
;
7106 char timebuf
[BGP_UPTIME_LEN
];
7112 bdi
= binfo
->extra
->damp_info
;
7114 /* short status lead text */
7115 route_vty_short_status_out(vty
, binfo
, json
);
7117 /* print prefix and mask */
7120 route_vty_out_route(p
, vty
, NULL
);
7122 vty_out(vty
, "%*s", 17, " ");
7125 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7129 vty_out(vty
, "\n%*s", 33, " ");
7132 json_object_int_add(json
, "peerHost", len
);
7134 vty_out(vty
, "%*s", len
, " ");
7137 len
= vty_out(vty
, "%d", bdi
->flap
);
7144 json_object_int_add(json
, "bdiFlap", len
);
7146 vty_out(vty
, "%*s", len
, " ");
7150 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7153 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7154 BGP_UPTIME_LEN
, 0, NULL
));
7156 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7157 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7159 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7160 BGP_UPTIME_LEN
, use_json
, json
);
7163 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7168 vty_out(vty
, "%*s ", 8, " ");
7171 /* Print attribute */
7177 json_object_string_add(json
, "asPath",
7180 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7185 json_object_string_add(json
, "origin",
7186 bgp_origin_str
[attr
->origin
]);
7188 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7194 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7195 int *first
, const char *header
,
7196 json_object
*json_adv_to
)
7198 char buf1
[INET6_ADDRSTRLEN
];
7199 json_object
*json_peer
= NULL
;
7202 /* 'advertised-to' is a dictionary of peers we have advertised
7204 * prefix too. The key is the peer's IP or swpX, the value is
7206 * hostname if we know it and "" if not.
7208 json_peer
= json_object_new_object();
7211 json_object_string_add(json_peer
, "hostname",
7215 json_object_object_add(json_adv_to
, peer
->conf_if
,
7218 json_object_object_add(
7220 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7224 vty_out(vty
, "%s", header
);
7229 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7231 vty_out(vty
, " %s(%s)", peer
->hostname
,
7234 vty_out(vty
, " %s(%s)", peer
->hostname
,
7235 sockunion2str(&peer
->su
, buf1
,
7239 vty_out(vty
, " %s", peer
->conf_if
);
7242 sockunion2str(&peer
->su
, buf1
,
7248 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7249 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7250 json_object
*json_paths
)
7252 char buf
[INET6_ADDRSTRLEN
];
7254 #if defined(HAVE_CUMULUS)
7255 char buf2
[EVPN_ROUTE_STRLEN
];
7258 int sockunion_vty_out(struct vty
*, union sockunion
*);
7260 json_object
*json_bestpath
= NULL
;
7261 json_object
*json_cluster_list
= NULL
;
7262 json_object
*json_cluster_list_list
= NULL
;
7263 json_object
*json_ext_community
= NULL
;
7264 json_object
*json_lcommunity
= NULL
;
7265 json_object
*json_last_update
= NULL
;
7266 json_object
*json_pmsi
= NULL
;
7267 json_object
*json_nexthop_global
= NULL
;
7268 json_object
*json_nexthop_ll
= NULL
;
7269 json_object
*json_nexthops
= NULL
;
7270 json_object
*json_path
= NULL
;
7271 json_object
*json_peer
= NULL
;
7272 json_object
*json_string
= NULL
;
7273 json_object
*json_adv_to
= NULL
;
7275 struct listnode
*node
, *nnode
;
7277 int addpath_capable
;
7279 unsigned int first_as
;
7282 json_path
= json_object_new_object();
7283 json_peer
= json_object_new_object();
7284 json_nexthop_global
= json_object_new_object();
7287 #if defined(HAVE_CUMULUS)
7288 if (!json_paths
&& safi
== SAFI_EVPN
) {
7291 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7292 vty_out(vty
, " Route %s", buf2
);
7294 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7295 bgp_evpn_label2str(binfo
->extra
->label
,
7296 binfo
->extra
->num_labels
, tag_buf
,
7298 vty_out(vty
, " VNI %s", tag_buf
);
7301 if (binfo
->extra
&& binfo
->extra
->parent
) {
7302 struct bgp_info
*parent_ri
;
7303 struct bgp_node
*rn
, *prn
;
7305 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7306 rn
= parent_ri
->net
;
7307 if (rn
&& rn
->prn
) {
7309 vty_out(vty
, " Imported from %s:%s\n",
7311 (struct prefix_rd
*)&prn
->p
,
7312 buf1
, sizeof(buf1
)),
7322 /* Line1 display AS-path, Aggregator */
7325 if (!attr
->aspath
->json
)
7326 aspath_str_update(attr
->aspath
, true);
7327 json_object_lock(attr
->aspath
->json
);
7328 json_object_object_add(json_path
, "aspath",
7329 attr
->aspath
->json
);
7331 if (attr
->aspath
->segments
)
7332 aspath_print_vty(vty
, " %s",
7335 vty_out(vty
, " Local");
7339 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7341 json_object_boolean_true_add(json_path
,
7344 vty_out(vty
, ", (removed)");
7347 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7349 json_object_boolean_true_add(json_path
,
7352 vty_out(vty
, ", (stale)");
7355 if (CHECK_FLAG(attr
->flag
,
7356 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7358 json_object_int_add(json_path
, "aggregatorAs",
7359 attr
->aggregator_as
);
7360 json_object_string_add(
7361 json_path
, "aggregatorId",
7362 inet_ntoa(attr
->aggregator_addr
));
7364 vty_out(vty
, ", (aggregated by %u %s)",
7365 attr
->aggregator_as
,
7366 inet_ntoa(attr
->aggregator_addr
));
7370 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7371 PEER_FLAG_REFLECTOR_CLIENT
)) {
7373 json_object_boolean_true_add(
7374 json_path
, "rxedFromRrClient");
7376 vty_out(vty
, ", (Received from a RR-client)");
7379 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7380 PEER_FLAG_RSERVER_CLIENT
)) {
7382 json_object_boolean_true_add(
7383 json_path
, "rxedFromRsClient");
7385 vty_out(vty
, ", (Received from a RS-client)");
7388 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7390 json_object_boolean_true_add(
7391 json_path
, "dampeningHistoryEntry");
7393 vty_out(vty
, ", (history entry)");
7394 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7396 json_object_boolean_true_add(
7397 json_path
, "dampeningSuppressed");
7399 vty_out(vty
, ", (suppressed due to dampening)");
7405 /* Line2 display Next-hop, Neighbor, Router-id */
7406 /* Display the nexthop */
7407 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7408 || p
->family
== AF_EVPN
)
7409 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7410 || safi
== SAFI_EVPN
7411 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7412 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7413 || safi
== SAFI_EVPN
) {
7415 json_object_string_add(
7416 json_nexthop_global
, "ip",
7418 attr
->mp_nexthop_global_in
));
7422 attr
->mp_nexthop_global_in
));
7425 json_object_string_add(
7426 json_nexthop_global
, "ip",
7427 inet_ntoa(attr
->nexthop
));
7430 inet_ntoa(attr
->nexthop
));
7434 json_object_string_add(json_nexthop_global
,
7438 json_object_string_add(
7439 json_nexthop_global
, "ip",
7441 &attr
->mp_nexthop_global
, buf
,
7443 json_object_string_add(json_nexthop_global
,
7445 json_object_string_add(json_nexthop_global
,
7450 &attr
->mp_nexthop_global
, buf
,
7455 /* Display the IGP cost or 'inaccessible' */
7456 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7458 json_object_boolean_false_add(
7459 json_nexthop_global
, "accessible");
7461 vty_out(vty
, " (inaccessible)");
7463 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7465 json_object_int_add(
7466 json_nexthop_global
, "metric",
7467 binfo
->extra
->igpmetric
);
7469 vty_out(vty
, " (metric %u)",
7470 binfo
->extra
->igpmetric
);
7473 /* IGP cost is 0, display this only for json */
7476 json_object_int_add(json_nexthop_global
,
7481 json_object_boolean_true_add(
7482 json_nexthop_global
, "accessible");
7485 /* Display peer "from" output */
7486 /* This path was originated locally */
7487 if (binfo
->peer
== bgp
->peer_self
) {
7489 if (safi
== SAFI_EVPN
7490 || (p
->family
== AF_INET
7491 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7493 json_object_string_add(
7494 json_peer
, "peerId", "0.0.0.0");
7496 vty_out(vty
, " from 0.0.0.0 ");
7499 json_object_string_add(json_peer
,
7502 vty_out(vty
, " from :: ");
7506 json_object_string_add(
7507 json_peer
, "routerId",
7508 inet_ntoa(bgp
->router_id
));
7510 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7513 /* We RXed this path from one of our peers */
7517 json_object_string_add(
7518 json_peer
, "peerId",
7519 sockunion2str(&binfo
->peer
->su
, buf
,
7521 json_object_string_add(
7522 json_peer
, "routerId",
7524 &binfo
->peer
->remote_id
, buf1
,
7527 if (binfo
->peer
->hostname
)
7528 json_object_string_add(
7529 json_peer
, "hostname",
7530 binfo
->peer
->hostname
);
7532 if (binfo
->peer
->domainname
)
7533 json_object_string_add(
7534 json_peer
, "domainname",
7535 binfo
->peer
->domainname
);
7537 if (binfo
->peer
->conf_if
)
7538 json_object_string_add(
7539 json_peer
, "interface",
7540 binfo
->peer
->conf_if
);
7542 if (binfo
->peer
->conf_if
) {
7543 if (binfo
->peer
->hostname
7546 BGP_FLAG_SHOW_HOSTNAME
))
7547 vty_out(vty
, " from %s(%s)",
7548 binfo
->peer
->hostname
,
7549 binfo
->peer
->conf_if
);
7551 vty_out(vty
, " from %s",
7552 binfo
->peer
->conf_if
);
7554 if (binfo
->peer
->hostname
7557 BGP_FLAG_SHOW_HOSTNAME
))
7558 vty_out(vty
, " from %s(%s)",
7559 binfo
->peer
->hostname
,
7562 vty_out(vty
, " from %s",
7571 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7572 vty_out(vty
, " (%s)",
7573 inet_ntoa(attr
->originator_id
));
7575 vty_out(vty
, " (%s)",
7578 &binfo
->peer
->remote_id
,
7579 buf1
, sizeof(buf1
)));
7586 /* display the link-local nexthop */
7587 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7589 json_nexthop_ll
= json_object_new_object();
7590 json_object_string_add(
7591 json_nexthop_ll
, "ip",
7593 &attr
->mp_nexthop_local
, buf
,
7595 json_object_string_add(json_nexthop_ll
, "afi",
7597 json_object_string_add(json_nexthop_ll
, "scope",
7600 json_object_boolean_true_add(json_nexthop_ll
,
7603 if (!attr
->mp_nexthop_prefer_global
)
7604 json_object_boolean_true_add(
7605 json_nexthop_ll
, "used");
7607 json_object_boolean_true_add(
7608 json_nexthop_global
, "used");
7610 vty_out(vty
, " (%s) %s\n",
7612 &attr
->mp_nexthop_local
, buf
,
7614 attr
->mp_nexthop_prefer_global
7619 /* If we do not have a link-local nexthop then we must flag the
7623 json_object_boolean_true_add(
7624 json_nexthop_global
, "used");
7627 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7628 * Int/Ext/Local, Atomic, best */
7630 json_object_string_add(
7631 json_path
, "origin",
7632 bgp_origin_long_str
[attr
->origin
]);
7634 vty_out(vty
, " Origin %s",
7635 bgp_origin_long_str
[attr
->origin
]);
7637 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7639 json_object_int_add(json_path
, "med",
7642 vty_out(vty
, ", metric %u", attr
->med
);
7645 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7647 json_object_int_add(json_path
, "localpref",
7650 vty_out(vty
, ", localpref %u",
7654 json_object_int_add(json_path
, "localpref",
7655 bgp
->default_local_pref
);
7657 vty_out(vty
, ", localpref %u",
7658 bgp
->default_local_pref
);
7661 if (attr
->weight
!= 0) {
7663 json_object_int_add(json_path
, "weight",
7666 vty_out(vty
, ", weight %u", attr
->weight
);
7669 if (attr
->tag
!= 0) {
7671 json_object_int_add(json_path
, "tag",
7674 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7678 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7680 json_object_boolean_false_add(json_path
,
7683 vty_out(vty
, ", invalid");
7684 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7686 json_object_boolean_true_add(json_path
,
7689 vty_out(vty
, ", valid");
7692 if (binfo
->peer
!= bgp
->peer_self
) {
7693 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7694 if (CHECK_FLAG(bgp
->config
,
7695 BGP_CONFIG_CONFEDERATION
)) {
7697 json_object_string_add(
7702 ", confed-internal");
7705 json_object_string_add(
7709 vty_out(vty
, ", internal");
7712 if (bgp_confederation_peers_check(
7713 bgp
, binfo
->peer
->as
)) {
7715 json_object_string_add(
7720 ", confed-external");
7723 json_object_string_add(
7727 vty_out(vty
, ", external");
7730 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7732 json_object_boolean_true_add(json_path
,
7734 json_object_boolean_true_add(json_path
,
7737 vty_out(vty
, ", aggregated, local");
7739 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7741 json_object_boolean_true_add(json_path
,
7744 vty_out(vty
, ", sourced");
7747 json_object_boolean_true_add(json_path
,
7749 json_object_boolean_true_add(json_path
,
7752 vty_out(vty
, ", sourced, local");
7756 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7758 json_object_boolean_true_add(json_path
,
7761 vty_out(vty
, ", atomic-aggregate");
7764 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7765 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7766 && bgp_info_mpath_count(binfo
))) {
7768 json_object_boolean_true_add(json_path
,
7771 vty_out(vty
, ", multipath");
7774 // Mark the bestpath(s)
7775 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7776 first_as
= aspath_get_first_as(attr
->aspath
);
7781 json_object_new_object();
7782 json_object_int_add(json_bestpath
,
7783 "bestpathFromAs", first_as
);
7786 vty_out(vty
, ", bestpath-from-AS %u",
7790 ", bestpath-from-AS Local");
7794 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7798 json_object_new_object();
7799 json_object_boolean_true_add(json_bestpath
,
7802 vty_out(vty
, ", best");
7806 json_object_object_add(json_path
, "bestpath",
7812 /* Line 4 display Community */
7813 if (attr
->community
) {
7815 if (!attr
->community
->json
)
7816 community_str(attr
->community
, true);
7817 json_object_lock(attr
->community
->json
);
7818 json_object_object_add(json_path
, "community",
7819 attr
->community
->json
);
7821 vty_out(vty
, " Community: %s\n",
7822 attr
->community
->str
);
7826 /* Line 5 display Extended-community */
7827 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7829 json_ext_community
= json_object_new_object();
7830 json_object_string_add(json_ext_community
,
7832 attr
->ecommunity
->str
);
7833 json_object_object_add(json_path
,
7834 "extendedCommunity",
7835 json_ext_community
);
7837 vty_out(vty
, " Extended Community: %s\n",
7838 attr
->ecommunity
->str
);
7842 /* Line 6 display Large community */
7843 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7845 json_lcommunity
= json_object_new_object();
7846 json_object_string_add(json_lcommunity
,
7848 attr
->lcommunity
->str
);
7849 json_object_object_add(json_path
,
7853 vty_out(vty
, " Large Community: %s\n",
7854 attr
->lcommunity
->str
);
7858 /* Line 7 display Originator, Cluster-id */
7859 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7860 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7862 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7864 json_object_string_add(
7865 json_path
, "originatorId",
7866 inet_ntoa(attr
->originator_id
));
7868 vty_out(vty
, " Originator: %s",
7869 inet_ntoa(attr
->originator_id
));
7872 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7877 json_object_new_object();
7878 json_cluster_list_list
=
7879 json_object_new_array();
7882 i
< attr
->cluster
->length
/ 4;
7884 json_string
= json_object_new_string(
7888 json_object_array_add(
7889 json_cluster_list_list
,
7893 /* struct cluster_list does not have
7895 * aspath and community do. Add this
7898 json_object_string_add(json_cluster_list,
7899 "string", attr->cluster->str);
7901 json_object_object_add(
7902 json_cluster_list
, "list",
7903 json_cluster_list_list
);
7904 json_object_object_add(
7905 json_path
, "clusterList",
7908 vty_out(vty
, ", Cluster list: ");
7911 i
< attr
->cluster
->length
/ 4;
7925 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7926 bgp_damp_info_vty(vty
, binfo
, json_path
);
7929 #if defined(HAVE_CUMULUS)
7930 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
7931 && safi
!= SAFI_EVPN
)
7933 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
7936 mpls_label_t label
=
7937 label_pton(&binfo
->extra
->label
[0]);
7939 json_object_int_add(json_path
, "remoteLabel",
7942 vty_out(vty
, " Remote label: %d\n", label
);
7946 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7948 json_object_int_add(json_path
, "labelIndex",
7951 vty_out(vty
, " Label Index: %d\n",
7955 /* Line 8 display Addpath IDs */
7956 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7958 json_object_int_add(json_path
, "addpathRxId",
7959 binfo
->addpath_rx_id
);
7960 json_object_int_add(json_path
, "addpathTxId",
7961 binfo
->addpath_tx_id
);
7963 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7964 binfo
->addpath_rx_id
,
7965 binfo
->addpath_tx_id
);
7969 /* If we used addpath to TX a non-bestpath we need to display
7970 * "Advertised to" on a path-by-path basis */
7971 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7974 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7976 bgp_addpath_encode_tx(peer
, afi
, safi
);
7977 has_adj
= bgp_adj_out_lookup(
7978 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7980 if ((addpath_capable
&& has_adj
)
7981 || (!addpath_capable
&& has_adj
7982 && CHECK_FLAG(binfo
->flags
,
7983 BGP_INFO_SELECTED
))) {
7984 if (json_path
&& !json_adv_to
)
7986 json_object_new_object();
7988 route_vty_out_advertised_to(
7997 json_object_object_add(json_path
,
8008 /* Line 9 display Uptime */
8009 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8011 json_last_update
= json_object_new_object();
8012 json_object_int_add(json_last_update
, "epoch", tbuf
);
8013 json_object_string_add(json_last_update
, "string",
8015 json_object_object_add(json_path
, "lastUpdate",
8018 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8020 /* Line 10 display PMSI tunnel attribute, if present */
8021 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8022 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8023 attr
->pmsi_tnl_type
,
8024 PMSI_TNLTYPE_STR_DEFAULT
);
8027 json_pmsi
= json_object_new_object();
8028 json_object_string_add(json_pmsi
,
8030 json_object_object_add(json_path
, "pmsi",
8033 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8039 /* We've constructed the json object for this path, add it to the json
8043 if (json_nexthop_global
|| json_nexthop_ll
) {
8044 json_nexthops
= json_object_new_array();
8046 if (json_nexthop_global
)
8047 json_object_array_add(json_nexthops
,
8048 json_nexthop_global
);
8050 if (json_nexthop_ll
)
8051 json_object_array_add(json_nexthops
,
8054 json_object_object_add(json_path
, "nexthops",
8058 json_object_object_add(json_path
, "peer", json_peer
);
8059 json_object_array_add(json_paths
, json_path
);
8064 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8065 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8066 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8068 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8069 const char *prefix_list_str
, afi_t afi
,
8070 safi_t safi
, enum bgp_show_type type
);
8071 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8072 const char *filter
, afi_t afi
, safi_t safi
,
8073 enum bgp_show_type type
);
8074 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8075 const char *rmap_str
, afi_t afi
, safi_t safi
,
8076 enum bgp_show_type type
);
8077 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8078 const char *com
, int exact
, afi_t afi
,
8080 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8081 const char *prefix
, afi_t afi
, safi_t safi
,
8082 enum bgp_show_type type
);
8083 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8084 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8085 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8086 const char *comstr
, int exact
, afi_t afi
,
8090 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8091 struct bgp_table
*table
, enum bgp_show_type type
,
8092 void *output_arg
, uint8_t use_json
, char *rd
,
8093 int is_last
, unsigned long *output_cum
,
8094 unsigned long *total_cum
,
8095 unsigned long *json_header_depth
)
8097 struct bgp_info
*ri
;
8098 struct bgp_node
*rn
;
8101 unsigned long output_count
= 0;
8102 unsigned long total_count
= 0;
8106 json_object
*json_paths
= NULL
;
8109 if (output_cum
&& *output_cum
!= 0)
8112 if (use_json
&& !*json_header_depth
) {
8114 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8115 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8116 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8117 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8119 table
->version
, inet_ntoa(bgp
->router_id
));
8120 *json_header_depth
= 2;
8122 vty_out(vty
, " \"routeDistinguishers\" : {");
8123 ++*json_header_depth
;
8125 json_paths
= json_object_new_object();
8128 if (use_json
&& rd
) {
8129 vty_out(vty
, " \"%s\" : { ", rd
);
8132 /* Start processing of routes. */
8133 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8134 if (rn
->info
== NULL
)
8139 json_paths
= json_object_new_array();
8143 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8145 if (type
== bgp_show_type_flap_statistics
8146 || type
== bgp_show_type_flap_neighbor
8147 || type
== bgp_show_type_dampend_paths
8148 || type
== bgp_show_type_damp_neighbor
) {
8149 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8152 if (type
== bgp_show_type_regexp
) {
8153 regex_t
*regex
= output_arg
;
8155 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8159 if (type
== bgp_show_type_prefix_list
) {
8160 struct prefix_list
*plist
= output_arg
;
8162 if (prefix_list_apply(plist
, &rn
->p
)
8166 if (type
== bgp_show_type_filter_list
) {
8167 struct as_list
*as_list
= output_arg
;
8169 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8170 != AS_FILTER_PERMIT
)
8173 if (type
== bgp_show_type_route_map
) {
8174 struct route_map
*rmap
= output_arg
;
8175 struct bgp_info binfo
;
8176 struct attr dummy_attr
;
8179 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8181 binfo
.peer
= ri
->peer
;
8182 binfo
.attr
= &dummy_attr
;
8184 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8186 if (ret
== RMAP_DENYMATCH
)
8189 if (type
== bgp_show_type_neighbor
8190 || type
== bgp_show_type_flap_neighbor
8191 || type
== bgp_show_type_damp_neighbor
) {
8192 union sockunion
*su
= output_arg
;
8194 if (ri
->peer
== NULL
8195 || ri
->peer
->su_remote
== NULL
8196 || !sockunion_same(ri
->peer
->su_remote
, su
))
8199 if (type
== bgp_show_type_cidr_only
) {
8200 uint32_t destination
;
8202 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8203 if (IN_CLASSC(destination
)
8204 && rn
->p
.prefixlen
== 24)
8206 if (IN_CLASSB(destination
)
8207 && rn
->p
.prefixlen
== 16)
8209 if (IN_CLASSA(destination
)
8210 && rn
->p
.prefixlen
== 8)
8213 if (type
== bgp_show_type_prefix_longer
) {
8214 struct prefix
*p
= output_arg
;
8216 if (!prefix_match(p
, &rn
->p
))
8219 if (type
== bgp_show_type_community_all
) {
8220 if (!ri
->attr
->community
)
8223 if (type
== bgp_show_type_community
) {
8224 struct community
*com
= output_arg
;
8226 if (!ri
->attr
->community
8227 || !community_match(ri
->attr
->community
,
8231 if (type
== bgp_show_type_community_exact
) {
8232 struct community
*com
= output_arg
;
8234 if (!ri
->attr
->community
8235 || !community_cmp(ri
->attr
->community
, com
))
8238 if (type
== bgp_show_type_community_list
) {
8239 struct community_list
*list
= output_arg
;
8241 if (!community_list_match(ri
->attr
->community
,
8245 if (type
== bgp_show_type_community_list_exact
) {
8246 struct community_list
*list
= output_arg
;
8248 if (!community_list_exact_match(
8249 ri
->attr
->community
, list
))
8252 if (type
== bgp_show_type_lcommunity
) {
8253 struct lcommunity
*lcom
= output_arg
;
8255 if (!ri
->attr
->lcommunity
8256 || !lcommunity_match(ri
->attr
->lcommunity
,
8260 if (type
== bgp_show_type_lcommunity_list
) {
8261 struct community_list
*list
= output_arg
;
8263 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8267 if (type
== bgp_show_type_lcommunity_all
) {
8268 if (!ri
->attr
->lcommunity
)
8271 if (type
== bgp_show_type_dampend_paths
8272 || type
== bgp_show_type_damp_neighbor
) {
8273 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8274 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8278 if (!use_json
&& header
) {
8279 vty_out(vty
, "BGP table version is %" PRIu64
8280 ", local router ID is %s\n",
8282 inet_ntoa(bgp
->router_id
));
8283 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8284 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8285 if (type
== bgp_show_type_dampend_paths
8286 || type
== bgp_show_type_damp_neighbor
)
8287 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8288 else if (type
== bgp_show_type_flap_statistics
8289 || type
== bgp_show_type_flap_neighbor
)
8290 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8292 vty_out(vty
, BGP_SHOW_HEADER
);
8295 if (rd
!= NULL
&& !display
&& !output_count
) {
8298 "Route Distinguisher: %s\n",
8301 if (type
== bgp_show_type_dampend_paths
8302 || type
== bgp_show_type_damp_neighbor
)
8303 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8304 safi
, use_json
, json_paths
);
8305 else if (type
== bgp_show_type_flap_statistics
8306 || type
== bgp_show_type_flap_neighbor
)
8307 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8308 safi
, use_json
, json_paths
);
8310 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8321 sprintf(buf2
, "%s/%d",
8322 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8325 vty_out(vty
, "\"%s\": ", buf2
);
8327 vty_out(vty
, ",\"%s\": ", buf2
);
8330 json_object_to_json_string(json_paths
));
8331 json_object_free(json_paths
);
8338 output_count
+= *output_cum
;
8339 *output_cum
= output_count
;
8342 total_count
+= *total_cum
;
8343 *total_cum
= total_count
;
8347 json_object_free(json_paths
);
8349 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8353 for (i
= 0; i
< *json_header_depth
; ++i
)
8354 vty_out(vty
, " } ");
8358 /* No route is displayed */
8359 if (output_count
== 0) {
8360 if (type
== bgp_show_type_normal
)
8362 "No BGP prefixes displayed, %ld exist\n",
8366 "\nDisplayed %ld routes and %ld total paths\n",
8367 output_count
, total_count
);
8374 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8375 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8376 enum bgp_show_type type
, void *output_arg
,
8379 struct bgp_node
*rn
, *next
;
8380 unsigned long output_cum
= 0;
8381 unsigned long total_cum
= 0;
8382 unsigned long json_header_depth
= 0;
8385 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8387 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8388 next
= bgp_route_next(rn
);
8389 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8391 if (rn
->info
!= NULL
) {
8392 struct prefix_rd prd
;
8393 char rd
[RD_ADDRSTRLEN
];
8395 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8396 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8397 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8398 output_arg
, use_json
, rd
, next
== NULL
,
8399 &output_cum
, &total_cum
,
8400 &json_header_depth
);
8406 if (output_cum
== 0)
8407 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8411 "\nDisplayed %ld routes and %ld total paths\n",
8412 output_cum
, total_cum
);
8416 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8417 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8419 struct bgp_table
*table
;
8420 unsigned long json_header_depth
= 0;
8423 bgp
= bgp_get_default();
8428 vty_out(vty
, "No BGP process is configured\n");
8430 vty_out(vty
, "{}\n");
8434 table
= bgp
->rib
[afi
][safi
];
8435 /* use MPLS and ENCAP specific shows until they are merged */
8436 if (safi
== SAFI_MPLS_VPN
) {
8437 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8438 output_arg
, use_json
);
8441 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8442 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8443 output_arg
, use_json
,
8446 /* labeled-unicast routes live in the unicast table */
8447 else if (safi
== SAFI_LABELED_UNICAST
)
8448 safi
= SAFI_UNICAST
;
8450 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8451 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8454 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8455 safi_t safi
, uint8_t use_json
)
8457 struct listnode
*node
, *nnode
;
8462 vty_out(vty
, "{\n");
8464 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8467 vty_out(vty
, ",\n");
8471 vty_out(vty
, "\"%s\":",
8472 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8476 vty_out(vty
, "\nInstance %s:\n",
8477 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8481 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8486 vty_out(vty
, "}\n");
8489 /* Header of detailed BGP route information */
8490 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8491 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8492 afi_t afi
, safi_t safi
, json_object
*json
)
8494 struct bgp_info
*ri
;
8497 struct listnode
*node
, *nnode
;
8498 char buf1
[RD_ADDRSTRLEN
];
8499 char buf2
[INET6_ADDRSTRLEN
];
8500 #if defined(HAVE_CUMULUS)
8501 char buf3
[EVPN_ROUTE_STRLEN
];
8503 char prefix_str
[BUFSIZ
];
8508 int no_advertise
= 0;
8511 int has_valid_label
= 0;
8512 mpls_label_t label
= 0;
8513 json_object
*json_adv_to
= NULL
;
8516 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8518 if (has_valid_label
)
8519 label
= label_pton(&rn
->local_label
);
8522 if (has_valid_label
)
8523 json_object_int_add(json
, "localLabel", label
);
8525 json_object_string_add(
8527 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8529 #if defined(HAVE_CUMULUS)
8530 if (safi
== SAFI_EVPN
)
8531 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8532 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8535 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8536 buf3
, sizeof(buf3
)));
8538 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8539 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8540 ? prefix_rd2str(prd
, buf1
,
8543 safi
== SAFI_MPLS_VPN
? ":" : "",
8544 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8548 if (p
->family
== AF_ETHERNET
)
8549 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8551 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8553 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8554 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8555 || safi
== SAFI_EVPN
)
8556 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8558 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8560 buf2
, p
->prefixlen
);
8563 if (has_valid_label
)
8564 vty_out(vty
, "Local label: %d\n", label
);
8565 #if defined(HAVE_CUMULUS)
8566 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8568 if (bgp_labeled_safi(safi
))
8570 vty_out(vty
, "not allocated\n");
8573 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8575 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8577 if (ri
->extra
&& ri
->extra
->suppress
)
8579 if (ri
->attr
->community
!= NULL
) {
8580 if (community_include(ri
->attr
->community
,
8581 COMMUNITY_NO_ADVERTISE
))
8583 if (community_include(ri
->attr
->community
,
8584 COMMUNITY_NO_EXPORT
))
8586 if (community_include(ri
->attr
->community
,
8587 COMMUNITY_LOCAL_AS
))
8594 vty_out(vty
, "Paths: (%d available", count
);
8596 vty_out(vty
, ", best #%d", best
);
8597 if (safi
== SAFI_UNICAST
)
8598 vty_out(vty
, ", table %s",
8600 == BGP_INSTANCE_TYPE_DEFAULT
)
8601 ? "Default-IP-Routing-Table"
8604 vty_out(vty
, ", no best path");
8607 vty_out(vty
, ", not advertised to any peer");
8609 vty_out(vty
, ", not advertised to EBGP peer");
8611 vty_out(vty
, ", not advertised outside local AS");
8615 ", Advertisements suppressed by an aggregate.");
8616 vty_out(vty
, ")\n");
8619 /* If we are not using addpath then we can display Advertised to and
8621 * show what peers we advertised the bestpath to. If we are using
8623 * though then we must display Advertised to on a path-by-path basis. */
8624 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8625 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8626 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8627 if (json
&& !json_adv_to
)
8628 json_adv_to
= json_object_new_object();
8630 route_vty_out_advertised_to(
8632 " Advertised to non peer-group peers:\n ",
8639 json_object_object_add(json
, "advertisedTo",
8644 vty_out(vty
, " Not advertised to any peer");
8650 /* Display specified route of BGP table. */
8651 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8652 struct bgp_table
*rib
, const char *ip_str
,
8653 afi_t afi
, safi_t safi
,
8654 struct prefix_rd
*prd
, int prefix_check
,
8655 enum bgp_path_type pathtype
,
8661 struct prefix match
;
8662 struct bgp_node
*rn
;
8663 struct bgp_node
*rm
;
8664 struct bgp_info
*ri
;
8665 struct bgp_table
*table
;
8666 json_object
*json
= NULL
;
8667 json_object
*json_paths
= NULL
;
8669 /* Check IP address argument. */
8670 ret
= str2prefix(ip_str
, &match
);
8672 vty_out(vty
, "address is malformed\n");
8676 match
.family
= afi2family(afi
);
8679 json
= json_object_new_object();
8680 json_paths
= json_object_new_array();
8683 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8684 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8685 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8688 if ((table
= rn
->info
) == NULL
)
8693 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8697 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8698 bgp_unlock_node(rm
);
8702 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8704 route_vty_out_detail_header(
8706 (struct prefix_rd
*)&rn
->p
,
8707 AFI_IP
, safi
, json
);
8712 if (pathtype
== BGP_PATH_ALL
8713 || (pathtype
== BGP_PATH_BESTPATH
8714 && CHECK_FLAG(ri
->flags
,
8716 || (pathtype
== BGP_PATH_MULTIPATH
8717 && (CHECK_FLAG(ri
->flags
,
8719 || CHECK_FLAG(ri
->flags
,
8720 BGP_INFO_SELECTED
))))
8721 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8726 bgp_unlock_node(rm
);
8728 } else if (safi
== SAFI_FLOWSPEC
) {
8729 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8730 &match
, prefix_check
);
8732 route_vty_out_flowspec(vty
, &rn
->p
,
8733 rn
->info
, use_json
?
8734 NLRI_STRING_FORMAT_JSON
:
8735 NLRI_STRING_FORMAT_LARGE
,
8738 bgp_unlock_node(rn
);
8743 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8745 || rn
->p
.prefixlen
== match
.prefixlen
) {
8746 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8748 route_vty_out_detail_header(
8749 vty
, bgp
, rn
, NULL
, afi
,
8755 if (pathtype
== BGP_PATH_ALL
8756 || (pathtype
== BGP_PATH_BESTPATH
8760 || (pathtype
== BGP_PATH_MULTIPATH
8766 BGP_INFO_SELECTED
))))
8767 route_vty_out_detail(
8768 vty
, bgp
, &rn
->p
, ri
,
8769 afi
, safi
, json_paths
);
8773 bgp_unlock_node(rn
);
8779 json_object_object_add(json
, "paths", json_paths
);
8781 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8782 json
, JSON_C_TO_STRING_PRETTY
));
8783 json_object_free(json
);
8786 vty_out(vty
, "%% Network not in table\n");
8794 /* Display specified route of Main RIB */
8795 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8796 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8797 int prefix_check
, enum bgp_path_type pathtype
,
8801 bgp
= bgp_get_default();
8804 vty_out(vty
, "No BGP process is configured\n");
8806 vty_out(vty
, "{}\n");
8811 /* labeled-unicast routes live in the unicast table */
8812 if (safi
== SAFI_LABELED_UNICAST
)
8813 safi
= SAFI_UNICAST
;
8815 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8816 afi
, safi
, prd
, prefix_check
, pathtype
,
8820 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8821 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8824 struct lcommunity
*lcom
;
8830 b
= buffer_new(1024);
8831 for (i
= 0; i
< argc
; i
++) {
8833 buffer_putc(b
, ' ');
8835 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8837 buffer_putstr(b
, argv
[i
]->arg
);
8841 buffer_putc(b
, '\0');
8843 str
= buffer_getstr(b
);
8846 lcom
= lcommunity_str2com(str
);
8847 XFREE(MTYPE_TMP
, str
);
8849 vty_out(vty
, "%% Large-community malformed\n");
8853 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8857 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8858 const char *lcom
, afi_t afi
, safi_t safi
,
8861 struct community_list
*list
;
8863 list
= community_list_lookup(bgp_clist
, lcom
,
8864 LARGE_COMMUNITY_LIST_MASTER
);
8866 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8871 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8875 DEFUN (show_ip_bgp_large_community_list
,
8876 show_ip_bgp_large_community_list_cmd
,
8877 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8881 BGP_INSTANCE_HELP_STR
8883 BGP_SAFI_WITH_LABEL_HELP_STR
8884 "Display routes matching the large-community-list\n"
8885 "large-community-list number\n"
8886 "large-community-list name\n"
8890 afi_t afi
= AFI_IP6
;
8891 safi_t safi
= SAFI_UNICAST
;
8894 if (argv_find(argv
, argc
, "ip", &idx
))
8896 if (argv_find(argv
, argc
, "view", &idx
)
8897 || argv_find(argv
, argc
, "vrf", &idx
))
8898 vrf
= argv
[++idx
]->arg
;
8899 if (argv_find(argv
, argc
, "ipv4", &idx
)
8900 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8901 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8902 if (argv_find(argv
, argc
, "unicast", &idx
)
8903 || argv_find(argv
, argc
, "multicast", &idx
))
8904 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8907 int uj
= use_json(argc
, argv
);
8909 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8911 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8915 argv_find(argv
, argc
, "large-community-list", &idx
);
8916 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8919 DEFUN (show_ip_bgp_large_community
,
8920 show_ip_bgp_large_community_cmd
,
8921 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8925 BGP_INSTANCE_HELP_STR
8927 BGP_SAFI_WITH_LABEL_HELP_STR
8928 "Display routes matching the large-communities\n"
8929 "List of large-community numbers\n"
8933 afi_t afi
= AFI_IP6
;
8934 safi_t safi
= SAFI_UNICAST
;
8937 if (argv_find(argv
, argc
, "ip", &idx
))
8939 if (argv_find(argv
, argc
, "view", &idx
)
8940 || argv_find(argv
, argc
, "vrf", &idx
))
8941 vrf
= argv
[++idx
]->arg
;
8942 if (argv_find(argv
, argc
, "ipv4", &idx
)
8943 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8944 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8945 if (argv_find(argv
, argc
, "unicast", &idx
)
8946 || argv_find(argv
, argc
, "multicast", &idx
))
8947 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8950 int uj
= use_json(argc
, argv
);
8952 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8954 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8958 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8959 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8961 return bgp_show(vty
, bgp
, afi
, safi
,
8962 bgp_show_type_lcommunity_all
, NULL
, uj
);
8965 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8969 /* BGP route print out function without JSON */
8972 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8973 <dampening <parameters>\
8978 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
8979 |community-list <(1-500)|WORD> [exact-match]\
8980 |A.B.C.D/M longer-prefixes\
8981 |X:X::X:X/M longer-prefixes\
8986 BGP_INSTANCE_HELP_STR
8988 BGP_SAFI_WITH_LABEL_HELP_STR
8989 "Display detailed information about dampening\n"
8990 "Display detail of configured dampening parameters\n"
8991 "Display routes matching the route-map\n"
8992 "A route-map to match on\n"
8993 "Display routes conforming to the prefix-list\n"
8994 "Prefix-list name\n"
8995 "Display routes conforming to the filter-list\n"
8996 "Regular expression access list name\n"
8997 "BGP RIB advertisement statistics\n"
8998 "Display routes matching the communities\n"
9000 "Do not send outside local AS (well-known community)\n"
9001 "Do not advertise to any peer (well-known community)\n"
9002 "Do not export to next AS (well-known community)\n"
9003 "Graceful shutdown (well-known community)\n"
9004 "Exact match of the communities\n"
9005 "Display routes matching the community-list\n"
9006 "community-list number\n"
9007 "community-list name\n"
9008 "Exact match of the communities\n"
9010 "Display route and more specific routes\n"
9012 "Display route and more specific routes\n")
9014 afi_t afi
= AFI_IP6
;
9015 safi_t safi
= SAFI_UNICAST
;
9016 int exact_match
= 0;
9017 struct bgp
*bgp
= NULL
;
9019 int idx_community_type
= 0;
9021 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9026 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9027 if (argv_find(argv
, argc
, "parameters", &idx
))
9028 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9031 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9032 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9033 safi
, bgp_show_type_prefix_list
);
9035 if (argv_find(argv
, argc
, "filter-list", &idx
))
9036 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9037 safi
, bgp_show_type_filter_list
);
9039 if (argv_find(argv
, argc
, "statistics", &idx
))
9040 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9042 if (argv_find(argv
, argc
, "route-map", &idx
))
9043 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9044 safi
, bgp_show_type_route_map
);
9046 if (argv_find(argv
, argc
, "community", &idx
)) {
9047 /* show a specific community */
9048 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9049 || argv_find(argv
, argc
, "no-advertise",
9050 &idx_community_type
)
9051 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9052 || argv_find(argv
, argc
, "graceful-shutdown",
9053 &idx_community_type
)
9054 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9056 if (argv_find(argv
, argc
, "exact-match", &idx
))
9058 return bgp_show_community(vty
, bgp
,
9059 argv
[idx_community_type
]->arg
,
9060 exact_match
, afi
, safi
);
9064 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9065 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9066 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9068 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9069 exact_match
, afi
, safi
);
9072 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9073 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9074 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9076 bgp_show_type_prefix_longer
);
9081 /* BGP route print out function with JSON */
9082 DEFUN (show_ip_bgp_json
,
9083 show_ip_bgp_json_cmd
,
9084 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9087 |dampening <flap-statistics|dampened-paths>\
9093 BGP_INSTANCE_HELP_STR
9095 BGP_SAFI_WITH_LABEL_HELP_STR
9096 "Display only routes with non-natural netmasks\n"
9097 "Display detailed information about dampening\n"
9098 "Display flap statistics of routes\n"
9099 "Display paths suppressed due to dampening\n"
9100 "Display routes matching the communities\n"
9103 afi_t afi
= AFI_IP6
;
9104 safi_t safi
= SAFI_UNICAST
;
9105 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9106 struct bgp
*bgp
= NULL
;
9109 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9114 int uj
= use_json(argc
, argv
);
9118 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9119 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9122 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9123 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9124 return bgp_show(vty
, bgp
, afi
, safi
,
9125 bgp_show_type_dampend_paths
, NULL
, uj
);
9126 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9127 return bgp_show(vty
, bgp
, afi
, safi
,
9128 bgp_show_type_flap_statistics
, NULL
,
9132 if (argv_find(argv
, argc
, "community", &idx
)) {
9133 /* show all communities */
9134 return bgp_show(vty
, bgp
, afi
, safi
,
9135 bgp_show_type_community_all
, NULL
, uj
);
9137 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9140 DEFUN (show_ip_bgp_route
,
9141 show_ip_bgp_route_cmd
,
9142 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9143 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9147 BGP_INSTANCE_HELP_STR
9149 BGP_SAFI_WITH_LABEL_HELP_STR
9150 "Network in the BGP routing table to display\n"
9152 "Network in the BGP routing table to display\n"
9154 "Display only the bestpath\n"
9155 "Display only multipaths\n"
9158 int prefix_check
= 0;
9160 afi_t afi
= AFI_IP6
;
9161 safi_t safi
= SAFI_UNICAST
;
9162 char *prefix
= NULL
;
9163 struct bgp
*bgp
= NULL
;
9164 enum bgp_path_type path_type
;
9165 uint8_t uj
= use_json(argc
, argv
);
9169 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9176 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9180 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9181 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9182 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9184 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9185 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9188 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9189 && afi
!= AFI_IP6
) {
9191 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9194 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9197 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9201 prefix
= argv
[idx
]->arg
;
9203 /* [<bestpath|multipath>] */
9204 if (argv_find(argv
, argc
, "bestpath", &idx
))
9205 path_type
= BGP_PATH_BESTPATH
;
9206 else if (argv_find(argv
, argc
, "multipath", &idx
))
9207 path_type
= BGP_PATH_MULTIPATH
;
9209 path_type
= BGP_PATH_ALL
;
9211 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9215 DEFUN (show_ip_bgp_regexp
,
9216 show_ip_bgp_regexp_cmd
,
9217 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9221 BGP_INSTANCE_HELP_STR
9223 BGP_SAFI_WITH_LABEL_HELP_STR
9224 "Display routes matching the AS path regular expression\n"
9225 "A regular-expression to match the BGP AS paths\n")
9227 afi_t afi
= AFI_IP6
;
9228 safi_t safi
= SAFI_UNICAST
;
9229 struct bgp
*bgp
= NULL
;
9232 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9237 // get index of regex
9238 argv_find(argv
, argc
, "regexp", &idx
);
9241 char *regstr
= argv_concat(argv
, argc
, idx
);
9242 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9243 bgp_show_type_regexp
);
9244 XFREE(MTYPE_TMP
, regstr
);
9248 DEFUN (show_ip_bgp_instance_all
,
9249 show_ip_bgp_instance_all_cmd
,
9250 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9254 BGP_INSTANCE_ALL_HELP_STR
9256 BGP_SAFI_WITH_LABEL_HELP_STR
9260 safi_t safi
= SAFI_UNICAST
;
9261 struct bgp
*bgp
= NULL
;
9264 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9269 int uj
= use_json(argc
, argv
);
9273 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9277 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9278 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9283 regex
= bgp_regcomp(regstr
);
9285 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9289 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9290 bgp_regex_free(regex
);
9294 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9295 const char *prefix_list_str
, afi_t afi
,
9296 safi_t safi
, enum bgp_show_type type
)
9298 struct prefix_list
*plist
;
9300 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9301 if (plist
== NULL
) {
9302 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9307 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9310 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9311 const char *filter
, afi_t afi
, safi_t safi
,
9312 enum bgp_show_type type
)
9314 struct as_list
*as_list
;
9316 as_list
= as_list_lookup(filter
);
9317 if (as_list
== NULL
) {
9318 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9323 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9326 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9327 const char *rmap_str
, afi_t afi
, safi_t safi
,
9328 enum bgp_show_type type
)
9330 struct route_map
*rmap
;
9332 rmap
= route_map_lookup_by_name(rmap_str
);
9334 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9338 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9341 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9342 const char *comstr
, int exact
, afi_t afi
,
9345 struct community
*com
;
9348 com
= community_str2com(comstr
);
9350 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9354 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9355 (exact
? bgp_show_type_community_exact
9356 : bgp_show_type_community
),
9358 community_free(com
);
9363 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9364 const char *com
, int exact
, afi_t afi
,
9367 struct community_list
*list
;
9369 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9371 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9375 return bgp_show(vty
, bgp
, afi
, safi
,
9376 (exact
? bgp_show_type_community_list_exact
9377 : bgp_show_type_community_list
),
9381 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9382 const char *prefix
, afi_t afi
, safi_t safi
,
9383 enum bgp_show_type type
)
9390 ret
= str2prefix(prefix
, p
);
9392 vty_out(vty
, "%% Malformed Prefix\n");
9396 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9401 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9402 const char *ip_str
, uint8_t use_json
)
9408 /* Get peer sockunion. */
9409 ret
= str2sockunion(ip_str
, &su
);
9411 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9413 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9417 json_object
*json_no
= NULL
;
9418 json_no
= json_object_new_object();
9419 json_object_string_add(
9421 "malformedAddressOrName",
9423 vty_out(vty
, "%s\n",
9424 json_object_to_json_string_ext(
9426 JSON_C_TO_STRING_PRETTY
));
9427 json_object_free(json_no
);
9430 "%% Malformed address or name: %s\n",
9438 /* Peer structure lookup. */
9439 peer
= peer_lookup(bgp
, &su
);
9442 json_object
*json_no
= NULL
;
9443 json_no
= json_object_new_object();
9444 json_object_string_add(json_no
, "warning",
9445 "No such neighbor");
9446 vty_out(vty
, "%s\n",
9447 json_object_to_json_string_ext(
9448 json_no
, JSON_C_TO_STRING_PRETTY
));
9449 json_object_free(json_no
);
9451 vty_out(vty
, "No such neighbor\n");
9459 BGP_STATS_MAXBITLEN
= 0,
9463 BGP_STATS_UNAGGREGATEABLE
,
9464 BGP_STATS_MAX_AGGREGATEABLE
,
9465 BGP_STATS_AGGREGATES
,
9467 BGP_STATS_ASPATH_COUNT
,
9468 BGP_STATS_ASPATH_MAXHOPS
,
9469 BGP_STATS_ASPATH_TOTHOPS
,
9470 BGP_STATS_ASPATH_MAXSIZE
,
9471 BGP_STATS_ASPATH_TOTSIZE
,
9472 BGP_STATS_ASN_HIGHEST
,
9476 static const char *table_stats_strs
[] = {
9477 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9478 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9479 [BGP_STATS_RIB
] = "Total Advertisements",
9480 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9481 [BGP_STATS_MAX_AGGREGATEABLE
] =
9482 "Maximum aggregateable prefixes",
9483 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9484 [BGP_STATS_SPACE
] = "Address space advertised",
9485 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9486 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9487 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9488 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9489 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9490 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9491 [BGP_STATS_MAX
] = NULL
,
9494 struct bgp_table_stats
{
9495 struct bgp_table
*table
;
9496 unsigned long long counts
[BGP_STATS_MAX
];
9501 #define TALLY_SIGFIG 100000
9502 static unsigned long
9503 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9505 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9506 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9507 unsigned long ret
= newtot
/ count
;
9509 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9516 static int bgp_table_stats_walker(struct thread
*t
)
9518 struct bgp_node
*rn
;
9519 struct bgp_node
*top
;
9520 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9521 unsigned int space
= 0;
9523 if (!(top
= bgp_table_top(ts
->table
)))
9526 switch (top
->p
.family
) {
9528 space
= IPV4_MAX_BITLEN
;
9531 space
= IPV6_MAX_BITLEN
;
9535 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9537 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9538 struct bgp_info
*ri
;
9539 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9540 unsigned int rinum
= 0;
9548 ts
->counts
[BGP_STATS_PREFIXES
]++;
9549 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9552 ts
->counts
[BGP_STATS_AVGPLEN
]
9553 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9554 ts
->counts
[BGP_STATS_AVGPLEN
],
9558 /* check if the prefix is included by any other announcements */
9559 while (prn
&& !prn
->info
)
9560 prn
= bgp_node_parent_nolock(prn
);
9562 if (prn
== NULL
|| prn
== top
) {
9563 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9564 /* announced address space */
9567 pow(2.0, space
- rn
->p
.prefixlen
);
9568 } else if (prn
->info
)
9569 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9571 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9573 ts
->counts
[BGP_STATS_RIB
]++;
9576 && (CHECK_FLAG(ri
->attr
->flag
,
9578 BGP_ATTR_ATOMIC_AGGREGATE
))))
9579 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9582 if (ri
->attr
&& ri
->attr
->aspath
) {
9584 aspath_count_hops(ri
->attr
->aspath
);
9586 aspath_size(ri
->attr
->aspath
);
9587 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9589 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9591 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9592 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9595 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9596 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9599 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9600 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9602 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9603 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9604 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9606 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9607 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9608 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9611 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9612 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9620 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9623 struct bgp_table_stats ts
;
9626 if (!bgp
->rib
[afi
][safi
]) {
9627 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9632 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9634 /* labeled-unicast routes live in the unicast table */
9635 if (safi
== SAFI_LABELED_UNICAST
)
9636 safi
= SAFI_UNICAST
;
9638 memset(&ts
, 0, sizeof(ts
));
9639 ts
.table
= bgp
->rib
[afi
][safi
];
9640 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9642 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9643 if (!table_stats_strs
[i
])
9648 case BGP_STATS_ASPATH_AVGHOPS
:
9649 case BGP_STATS_ASPATH_AVGSIZE
:
9650 case BGP_STATS_AVGPLEN
:
9651 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9652 vty_out (vty
, "%12.2f",
9653 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9656 case BGP_STATS_ASPATH_TOTHOPS
:
9657 case BGP_STATS_ASPATH_TOTSIZE
:
9658 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9659 vty_out(vty
, "%12.2f",
9661 ? (float)ts
.counts
[i
]
9663 [BGP_STATS_ASPATH_COUNT
]
9666 case BGP_STATS_TOTPLEN
:
9667 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9668 vty_out(vty
, "%12.2f",
9670 ? (float)ts
.counts
[i
]
9672 [BGP_STATS_PREFIXES
]
9675 case BGP_STATS_SPACE
:
9676 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9677 vty_out(vty
, "%12g\n", ts
.total_space
);
9679 if (afi
== AFI_IP6
) {
9680 vty_out(vty
, "%30s: ", "/32 equivalent ");
9681 vty_out(vty
, "%12g\n",
9682 ts
.total_space
* pow(2.0, -128 + 32));
9683 vty_out(vty
, "%30s: ", "/48 equivalent ");
9684 vty_out(vty
, "%12g\n",
9685 ts
.total_space
* pow(2.0, -128 + 48));
9687 vty_out(vty
, "%30s: ", "% announced ");
9688 vty_out(vty
, "%12.2f\n",
9689 ts
.total_space
* 100. * pow(2.0, -32));
9690 vty_out(vty
, "%30s: ", "/8 equivalent ");
9691 vty_out(vty
, "%12.2f\n",
9692 ts
.total_space
* pow(2.0, -32 + 8));
9693 vty_out(vty
, "%30s: ", "/24 equivalent ");
9694 vty_out(vty
, "%12.2f\n",
9695 ts
.total_space
* pow(2.0, -32 + 24));
9699 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9700 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9717 PCOUNT_PFCNT
, /* the figure we display to users */
9721 static const char *pcount_strs
[] = {
9722 [PCOUNT_ADJ_IN
] = "Adj-in",
9723 [PCOUNT_DAMPED
] = "Damped",
9724 [PCOUNT_REMOVED
] = "Removed",
9725 [PCOUNT_HISTORY
] = "History",
9726 [PCOUNT_STALE
] = "Stale",
9727 [PCOUNT_VALID
] = "Valid",
9728 [PCOUNT_ALL
] = "All RIB",
9729 [PCOUNT_COUNTED
] = "PfxCt counted",
9730 [PCOUNT_PFCNT
] = "Useable",
9731 [PCOUNT_MAX
] = NULL
,
9734 struct peer_pcounts
{
9735 unsigned int count
[PCOUNT_MAX
];
9736 const struct peer
*peer
;
9737 const struct bgp_table
*table
;
9740 static int bgp_peer_count_walker(struct thread
*t
)
9742 struct bgp_node
*rn
;
9743 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9744 const struct peer
*peer
= pc
->peer
;
9746 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9747 struct bgp_adj_in
*ain
;
9748 struct bgp_info
*ri
;
9750 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9751 if (ain
->peer
== peer
)
9752 pc
->count
[PCOUNT_ADJ_IN
]++;
9754 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9755 char buf
[SU_ADDRSTRLEN
];
9757 if (ri
->peer
!= peer
)
9760 pc
->count
[PCOUNT_ALL
]++;
9762 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9763 pc
->count
[PCOUNT_DAMPED
]++;
9764 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9765 pc
->count
[PCOUNT_HISTORY
]++;
9766 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9767 pc
->count
[PCOUNT_REMOVED
]++;
9768 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9769 pc
->count
[PCOUNT_STALE
]++;
9770 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9771 pc
->count
[PCOUNT_VALID
]++;
9772 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9773 pc
->count
[PCOUNT_PFCNT
]++;
9775 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9776 pc
->count
[PCOUNT_COUNTED
]++;
9777 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9779 "%s [pcount] %s/%d is counted but flags 0x%x",
9781 inet_ntop(rn
->p
.family
,
9782 &rn
->p
.u
.prefix
, buf
,
9784 rn
->p
.prefixlen
, ri
->flags
);
9786 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9788 "%s [pcount] %s/%d not counted but flags 0x%x",
9790 inet_ntop(rn
->p
.family
,
9791 &rn
->p
.u
.prefix
, buf
,
9793 rn
->p
.prefixlen
, ri
->flags
);
9800 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9801 safi_t safi
, uint8_t use_json
)
9803 struct peer_pcounts pcounts
= {.peer
= peer
};
9805 json_object
*json
= NULL
;
9806 json_object
*json_loop
= NULL
;
9809 json
= json_object_new_object();
9810 json_loop
= json_object_new_object();
9813 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9814 || !peer
->bgp
->rib
[afi
][safi
]) {
9816 json_object_string_add(
9818 "No such neighbor or address family");
9819 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9820 json_object_free(json
);
9822 vty_out(vty
, "%% No such neighbor or address family\n");
9827 memset(&pcounts
, 0, sizeof(pcounts
));
9828 pcounts
.peer
= peer
;
9829 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9831 /* in-place call via thread subsystem so as to record execution time
9832 * stats for the thread-walk (i.e. ensure this can't be blamed on
9833 * on just vty_read()).
9835 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9838 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9839 json_object_string_add(json
, "multiProtocol",
9840 afi_safi_print(afi
, safi
));
9841 json_object_int_add(json
, "pfxCounter",
9842 peer
->pcount
[afi
][safi
]);
9844 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9845 json_object_int_add(json_loop
, pcount_strs
[i
],
9848 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9850 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9851 json_object_string_add(json
, "pfxctDriftFor",
9853 json_object_string_add(
9854 json
, "recommended",
9855 "Please report this bug, with the above command output");
9857 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9858 json
, JSON_C_TO_STRING_PRETTY
));
9859 json_object_free(json
);
9863 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9864 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9865 peer
->hostname
, peer
->host
,
9866 afi_safi_print(afi
, safi
));
9868 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9869 afi_safi_print(afi
, safi
));
9872 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9873 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9875 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9876 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9879 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9880 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9882 "Please report this bug, with the above command output\n");
9889 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9890 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9891 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9892 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9896 BGP_INSTANCE_HELP_STR
9899 "Detailed information on TCP and BGP neighbor connections\n"
9900 "Neighbor to display information about\n"
9901 "Neighbor to display information about\n"
9902 "Neighbor on BGP configured interface\n"
9903 "Display detailed prefix count information\n"
9906 afi_t afi
= AFI_IP6
;
9907 safi_t safi
= SAFI_UNICAST
;
9910 struct bgp
*bgp
= NULL
;
9912 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9917 int uj
= use_json(argc
, argv
);
9921 argv_find(argv
, argc
, "neighbors", &idx
);
9922 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9926 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9929 #ifdef KEEP_OLD_VPN_COMMANDS
9930 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9931 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9932 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9937 "Display information about all VPNv4 NLRIs\n"
9938 "Detailed information on TCP and BGP neighbor connections\n"
9939 "Neighbor to display information about\n"
9940 "Neighbor to display information about\n"
9941 "Neighbor on BGP configured interface\n"
9942 "Display detailed prefix count information\n"
9947 uint8_t uj
= use_json(argc
, argv
);
9949 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9953 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9956 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9957 show_ip_bgp_vpn_all_route_prefix_cmd
,
9958 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9963 "Display information about all VPNv4 NLRIs\n"
9964 "Network in the BGP routing table to display\n"
9965 "Network in the BGP routing table to display\n"
9969 char *network
= NULL
;
9970 struct bgp
*bgp
= bgp_get_default();
9972 vty_out(vty
, "Can't find default instance\n");
9976 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9977 network
= argv
[idx
]->arg
;
9978 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9979 network
= argv
[idx
]->arg
;
9981 vty_out(vty
, "Unable to figure out Network\n");
9985 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9986 BGP_PATH_ALL
, use_json(argc
, argv
));
9988 #endif /* KEEP_OLD_VPN_COMMANDS */
9990 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9991 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9992 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9998 "Display information about all EVPN NLRIs\n"
9999 "Network in the BGP routing table to display\n"
10000 "Network in the BGP routing table to display\n"
10004 char *network
= NULL
;
10006 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10007 network
= argv
[idx
]->arg
;
10008 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10009 network
= argv
[idx
]->arg
;
10011 vty_out(vty
, "Unable to figure out Network\n");
10012 return CMD_WARNING
;
10014 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10015 BGP_PATH_ALL
, use_json(argc
, argv
));
10018 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10019 safi_t safi
, int in
, const char *rmap_name
,
10020 uint8_t use_json
, json_object
*json
)
10022 struct bgp_table
*table
;
10023 struct bgp_adj_in
*ain
;
10024 struct bgp_adj_out
*adj
;
10025 unsigned long output_count
;
10026 unsigned long filtered_count
;
10027 struct bgp_node
*rn
;
10033 struct update_subgroup
*subgrp
;
10034 json_object
*json_scode
= NULL
;
10035 json_object
*json_ocode
= NULL
;
10036 json_object
*json_ar
= NULL
;
10037 struct peer_af
*paf
;
10040 json_scode
= json_object_new_object();
10041 json_ocode
= json_object_new_object();
10042 json_ar
= json_object_new_object();
10044 json_object_string_add(json_scode
, "suppressed", "s");
10045 json_object_string_add(json_scode
, "damped", "d");
10046 json_object_string_add(json_scode
, "history", "h");
10047 json_object_string_add(json_scode
, "valid", "*");
10048 json_object_string_add(json_scode
, "best", ">");
10049 json_object_string_add(json_scode
, "multipath", "=");
10050 json_object_string_add(json_scode
, "internal", "i");
10051 json_object_string_add(json_scode
, "ribFailure", "r");
10052 json_object_string_add(json_scode
, "stale", "S");
10053 json_object_string_add(json_scode
, "removed", "R");
10055 json_object_string_add(json_ocode
, "igp", "i");
10056 json_object_string_add(json_ocode
, "egp", "e");
10057 json_object_string_add(json_ocode
, "incomplete", "?");
10064 json_object_string_add(json
, "alert", "no BGP");
10065 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10066 json_object_free(json
);
10068 vty_out(vty
, "%% No bgp\n");
10072 table
= bgp
->rib
[afi
][safi
];
10074 output_count
= filtered_count
= 0;
10075 subgrp
= peer_subgroup(peer
, afi
, safi
);
10078 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10080 json_object_int_add(json
, "bgpTableVersion",
10082 json_object_string_add(json
, "bgpLocalRouterId",
10083 inet_ntoa(bgp
->router_id
));
10084 json_object_object_add(json
, "bgpStatusCodes",
10086 json_object_object_add(json
, "bgpOriginCodes",
10088 json_object_string_add(json
,
10089 "bgpOriginatingDefaultNetwork",
10092 vty_out(vty
, "BGP table version is %" PRIu64
10093 ", local router ID is %s\n",
10094 table
->version
, inet_ntoa(bgp
->router_id
));
10095 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10096 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10098 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10103 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10105 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10106 if (ain
->peer
!= peer
)
10110 json_object_int_add(
10111 json
, "bgpTableVersion",
10113 json_object_string_add(
10115 "bgpLocalRouterId",
10118 json_object_object_add(
10119 json
, "bgpStatusCodes",
10121 json_object_object_add(
10122 json
, "bgpOriginCodes",
10126 "BGP table version is 0, local router ID is %s\n",
10130 BGP_SHOW_SCODE_HEADER
);
10132 BGP_SHOW_OCODE_HEADER
);
10138 vty_out(vty
, BGP_SHOW_HEADER
);
10142 bgp_attr_dup(&attr
, ain
->attr
);
10143 if (bgp_input_modifier(peer
, &rn
->p
,
10147 route_vty_out_tmp(vty
, &rn
->p
,
10157 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10158 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10159 if (paf
->peer
!= peer
)
10164 json_object_int_add(
10168 json_object_string_add(
10170 "bgpLocalRouterId",
10173 json_object_object_add(
10177 json_object_object_add(
10183 "BGP table version is %" PRIu64
10184 ", local router ID is %s\n",
10189 BGP_SHOW_SCODE_HEADER
);
10191 BGP_SHOW_OCODE_HEADER
);
10204 bgp_attr_dup(&attr
, adj
->attr
);
10205 ret
= bgp_output_modifier(
10206 peer
, &rn
->p
, &attr
,
10207 afi
, safi
, rmap_name
);
10208 if (ret
!= RMAP_DENY
) {
10218 bgp_attr_undup(&attr
,
10225 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10227 if (output_count
!= 0) {
10229 json_object_int_add(json
, "totalPrefixCounter",
10232 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10236 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10237 json
, JSON_C_TO_STRING_PRETTY
));
10238 json_object_free(json
);
10242 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10243 safi_t safi
, int in
, const char *rmap_name
,
10246 json_object
*json
= NULL
;
10249 json
= json_object_new_object();
10251 /* labeled-unicast routes live in the unicast table */
10252 if (safi
== SAFI_LABELED_UNICAST
)
10253 safi
= SAFI_UNICAST
;
10255 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10257 json_object_string_add(
10259 "No such neighbor or address family");
10260 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10261 json_object_free(json
);
10263 vty_out(vty
, "%% No such neighbor or address family\n");
10265 return CMD_WARNING
;
10269 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10270 PEER_FLAG_SOFT_RECONFIG
)) {
10272 json_object_string_add(
10274 "Inbound soft reconfiguration not enabled");
10275 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10276 json_object_free(json
);
10279 "%% Inbound soft reconfiguration not enabled\n");
10281 return CMD_WARNING
;
10284 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10286 return CMD_SUCCESS
;
10289 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10290 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10291 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10292 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10296 BGP_INSTANCE_HELP_STR
10298 BGP_SAFI_WITH_LABEL_HELP_STR
10299 "Detailed information on TCP and BGP neighbor connections\n"
10300 "Neighbor to display information about\n"
10301 "Neighbor to display information about\n"
10302 "Neighbor on BGP configured interface\n"
10303 "Display the received routes from neighbor\n"
10304 "Display the routes advertised to a BGP neighbor\n"
10305 "Route-map to modify the attributes\n"
10306 "Name of the route map\n"
10309 afi_t afi
= AFI_IP6
;
10310 safi_t safi
= SAFI_UNICAST
;
10311 char *rmap_name
= NULL
;
10312 char *peerstr
= NULL
;
10314 struct bgp
*bgp
= NULL
;
10319 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10322 return CMD_WARNING
;
10324 int uj
= use_json(argc
, argv
);
10328 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10329 argv_find(argv
, argc
, "neighbors", &idx
);
10330 peerstr
= argv
[++idx
]->arg
;
10332 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10334 return CMD_WARNING
;
10336 if (argv_find(argv
, argc
, "received-routes", &idx
))
10338 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10340 if (argv_find(argv
, argc
, "route-map", &idx
))
10341 rmap_name
= argv
[++idx
]->arg
;
10343 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10346 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10347 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10348 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10354 "Address Family modifier\n"
10355 "Detailed information on TCP and BGP neighbor connections\n"
10356 "Neighbor to display information about\n"
10357 "Neighbor to display information about\n"
10358 "Neighbor on BGP configured interface\n"
10359 "Display information received from a BGP neighbor\n"
10360 "Display the prefixlist filter\n"
10363 afi_t afi
= AFI_IP6
;
10364 safi_t safi
= SAFI_UNICAST
;
10365 char *peerstr
= NULL
;
10368 union sockunion su
;
10374 /* show [ip] bgp */
10375 if (argv_find(argv
, argc
, "ip", &idx
))
10377 /* [<ipv4|ipv6> [unicast]] */
10378 if (argv_find(argv
, argc
, "ipv4", &idx
))
10380 if (argv_find(argv
, argc
, "ipv6", &idx
))
10382 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10383 argv_find(argv
, argc
, "neighbors", &idx
);
10384 peerstr
= argv
[++idx
]->arg
;
10386 uint8_t uj
= use_json(argc
, argv
);
10388 ret
= str2sockunion(peerstr
, &su
);
10390 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10393 vty_out(vty
, "{}\n");
10396 "%% Malformed address or name: %s\n",
10398 return CMD_WARNING
;
10401 peer
= peer_lookup(NULL
, &su
);
10404 vty_out(vty
, "{}\n");
10406 vty_out(vty
, "No peer\n");
10407 return CMD_WARNING
;
10411 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10412 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10415 vty_out(vty
, "Address Family: %s\n",
10416 afi_safi_print(afi
, safi
));
10417 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10420 vty_out(vty
, "{}\n");
10422 vty_out(vty
, "No functional output\n");
10425 return CMD_SUCCESS
;
10428 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10429 afi_t afi
, safi_t safi
,
10430 enum bgp_show_type type
, uint8_t use_json
)
10432 /* labeled-unicast routes live in the unicast table */
10433 if (safi
== SAFI_LABELED_UNICAST
)
10434 safi
= SAFI_UNICAST
;
10436 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10438 json_object
*json_no
= NULL
;
10439 json_no
= json_object_new_object();
10440 json_object_string_add(
10441 json_no
, "warning",
10442 "No such neighbor or address family");
10443 vty_out(vty
, "%s\n",
10444 json_object_to_json_string(json_no
));
10445 json_object_free(json_no
);
10447 vty_out(vty
, "%% No such neighbor or address family\n");
10448 return CMD_WARNING
;
10451 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10454 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10455 show_ip_bgp_flowspec_routes_detailed_cmd
,
10456 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10460 BGP_INSTANCE_HELP_STR
10463 "Detailed information on flowspec entries\n"
10466 afi_t afi
= AFI_IP
;
10467 safi_t safi
= SAFI_UNICAST
;
10468 struct bgp
*bgp
= NULL
;
10471 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10474 return CMD_WARNING
;
10476 return bgp_show(vty
, bgp
, afi
, safi
,
10477 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10480 DEFUN (show_ip_bgp_neighbor_routes
,
10481 show_ip_bgp_neighbor_routes_cmd
,
10482 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10483 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10487 BGP_INSTANCE_HELP_STR
10489 BGP_SAFI_WITH_LABEL_HELP_STR
10490 "Detailed information on TCP and BGP neighbor connections\n"
10491 "Neighbor to display information about\n"
10492 "Neighbor to display information about\n"
10493 "Neighbor on BGP configured interface\n"
10494 "Display flap statistics of the routes learned from neighbor\n"
10495 "Display the dampened routes received from neighbor\n"
10496 "Display routes learned from neighbor\n"
10499 char *peerstr
= NULL
;
10500 struct bgp
*bgp
= NULL
;
10501 afi_t afi
= AFI_IP6
;
10502 safi_t safi
= SAFI_UNICAST
;
10504 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10508 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10511 return CMD_WARNING
;
10513 int uj
= use_json(argc
, argv
);
10517 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10518 argv_find(argv
, argc
, "neighbors", &idx
);
10519 peerstr
= argv
[++idx
]->arg
;
10521 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10523 vty_out(vty
, "No such neighbor\n");
10524 return CMD_WARNING
;
10527 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10528 sh_type
= bgp_show_type_flap_neighbor
;
10529 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10530 sh_type
= bgp_show_type_damp_neighbor
;
10531 else if (argv_find(argv
, argc
, "routes", &idx
))
10532 sh_type
= bgp_show_type_neighbor
;
10534 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10537 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10539 struct bgp_distance
{
10540 /* Distance value for the IP source prefix. */
10543 /* Name of the access-list to be matched. */
10547 DEFUN (show_bgp_afi_vpn_rd_route
,
10548 show_bgp_afi_vpn_rd_route_cmd
,
10549 "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]",
10553 "Address Family modifier\n"
10554 "Display information for a route distinguisher\n"
10555 "Route Distinguisher\n"
10556 "Network in the BGP routing table to display\n"
10557 "Network in the BGP routing table to display\n"
10561 struct prefix_rd prd
;
10562 afi_t afi
= AFI_MAX
;
10565 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10566 vty_out(vty
, "%% Malformed Address Family\n");
10567 return CMD_WARNING
;
10570 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10572 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10573 return CMD_WARNING
;
10576 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10577 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10580 static struct bgp_distance
*bgp_distance_new(void)
10582 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10585 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10587 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10590 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10591 const char *ip_str
, const char *access_list_str
)
10598 struct bgp_node
*rn
;
10599 struct bgp_distance
*bdistance
;
10601 afi
= bgp_node_afi(vty
);
10602 safi
= bgp_node_safi(vty
);
10604 ret
= str2prefix(ip_str
, &p
);
10606 vty_out(vty
, "Malformed prefix\n");
10607 return CMD_WARNING_CONFIG_FAILED
;
10610 distance
= atoi(distance_str
);
10612 /* Get BGP distance node. */
10613 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10615 bdistance
= rn
->info
;
10616 bgp_unlock_node(rn
);
10618 bdistance
= bgp_distance_new();
10619 rn
->info
= bdistance
;
10622 /* Set distance value. */
10623 bdistance
->distance
= distance
;
10625 /* Reset access-list configuration. */
10626 if (bdistance
->access_list
) {
10627 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10628 bdistance
->access_list
= NULL
;
10630 if (access_list_str
)
10631 bdistance
->access_list
=
10632 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10634 return CMD_SUCCESS
;
10637 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10638 const char *ip_str
, const char *access_list_str
)
10645 struct bgp_node
*rn
;
10646 struct bgp_distance
*bdistance
;
10648 afi
= bgp_node_afi(vty
);
10649 safi
= bgp_node_safi(vty
);
10651 ret
= str2prefix(ip_str
, &p
);
10653 vty_out(vty
, "Malformed prefix\n");
10654 return CMD_WARNING_CONFIG_FAILED
;
10657 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10658 (struct prefix
*)&p
);
10660 vty_out(vty
, "Can't find specified prefix\n");
10661 return CMD_WARNING_CONFIG_FAILED
;
10664 bdistance
= rn
->info
;
10665 distance
= atoi(distance_str
);
10667 if (bdistance
->distance
!= distance
) {
10668 vty_out(vty
, "Distance does not match configured\n");
10669 return CMD_WARNING_CONFIG_FAILED
;
10672 if (bdistance
->access_list
)
10673 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10674 bgp_distance_free(bdistance
);
10677 bgp_unlock_node(rn
);
10678 bgp_unlock_node(rn
);
10680 return CMD_SUCCESS
;
10683 /* Apply BGP information to distance method. */
10684 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10685 safi_t safi
, struct bgp
*bgp
)
10687 struct bgp_node
*rn
;
10690 struct bgp_distance
*bdistance
;
10691 struct access_list
*alist
;
10692 struct bgp_static
*bgp_static
;
10697 peer
= rinfo
->peer
;
10699 /* Check source address. */
10700 sockunion2hostprefix(&peer
->su
, &q
);
10701 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10703 bdistance
= rn
->info
;
10704 bgp_unlock_node(rn
);
10706 if (bdistance
->access_list
) {
10707 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10709 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10710 return bdistance
->distance
;
10712 return bdistance
->distance
;
10715 /* Backdoor check. */
10716 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10718 bgp_static
= rn
->info
;
10719 bgp_unlock_node(rn
);
10721 if (bgp_static
->backdoor
) {
10722 if (bgp
->distance_local
[afi
][safi
])
10723 return bgp
->distance_local
[afi
][safi
];
10725 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10729 if (peer
->sort
== BGP_PEER_EBGP
) {
10730 if (bgp
->distance_ebgp
[afi
][safi
])
10731 return bgp
->distance_ebgp
[afi
][safi
];
10732 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10734 if (bgp
->distance_ibgp
[afi
][safi
])
10735 return bgp
->distance_ibgp
[afi
][safi
];
10736 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10740 DEFUN (bgp_distance
,
10742 "distance bgp (1-255) (1-255) (1-255)",
10743 "Define an administrative distance\n"
10745 "Distance for routes external to the AS\n"
10746 "Distance for routes internal to the AS\n"
10747 "Distance for local routes\n")
10749 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10750 int idx_number
= 2;
10751 int idx_number_2
= 3;
10752 int idx_number_3
= 4;
10756 afi
= bgp_node_afi(vty
);
10757 safi
= bgp_node_safi(vty
);
10759 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10760 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10761 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10762 return CMD_SUCCESS
;
10765 DEFUN (no_bgp_distance
,
10766 no_bgp_distance_cmd
,
10767 "no distance bgp [(1-255) (1-255) (1-255)]",
10769 "Define an administrative distance\n"
10771 "Distance for routes external to the AS\n"
10772 "Distance for routes internal to the AS\n"
10773 "Distance for local routes\n")
10775 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10779 afi
= bgp_node_afi(vty
);
10780 safi
= bgp_node_safi(vty
);
10782 bgp
->distance_ebgp
[afi
][safi
] = 0;
10783 bgp
->distance_ibgp
[afi
][safi
] = 0;
10784 bgp
->distance_local
[afi
][safi
] = 0;
10785 return CMD_SUCCESS
;
10789 DEFUN (bgp_distance_source
,
10790 bgp_distance_source_cmd
,
10791 "distance (1-255) A.B.C.D/M",
10792 "Define an administrative distance\n"
10793 "Administrative distance\n"
10794 "IP source prefix\n")
10796 int idx_number
= 1;
10797 int idx_ipv4_prefixlen
= 2;
10798 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10799 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10800 return CMD_SUCCESS
;
10803 DEFUN (no_bgp_distance_source
,
10804 no_bgp_distance_source_cmd
,
10805 "no distance (1-255) A.B.C.D/M",
10807 "Define an administrative distance\n"
10808 "Administrative distance\n"
10809 "IP source prefix\n")
10811 int idx_number
= 2;
10812 int idx_ipv4_prefixlen
= 3;
10813 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10814 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10815 return CMD_SUCCESS
;
10818 DEFUN (bgp_distance_source_access_list
,
10819 bgp_distance_source_access_list_cmd
,
10820 "distance (1-255) A.B.C.D/M WORD",
10821 "Define an administrative distance\n"
10822 "Administrative distance\n"
10823 "IP source prefix\n"
10824 "Access list name\n")
10826 int idx_number
= 1;
10827 int idx_ipv4_prefixlen
= 2;
10829 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10830 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10831 return CMD_SUCCESS
;
10834 DEFUN (no_bgp_distance_source_access_list
,
10835 no_bgp_distance_source_access_list_cmd
,
10836 "no distance (1-255) A.B.C.D/M WORD",
10838 "Define an administrative distance\n"
10839 "Administrative distance\n"
10840 "IP source prefix\n"
10841 "Access list name\n")
10843 int idx_number
= 2;
10844 int idx_ipv4_prefixlen
= 3;
10846 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10847 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10848 return CMD_SUCCESS
;
10851 DEFUN (ipv6_bgp_distance_source
,
10852 ipv6_bgp_distance_source_cmd
,
10853 "distance (1-255) X:X::X:X/M",
10854 "Define an administrative distance\n"
10855 "Administrative distance\n"
10856 "IP source prefix\n")
10858 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10859 return CMD_SUCCESS
;
10862 DEFUN (no_ipv6_bgp_distance_source
,
10863 no_ipv6_bgp_distance_source_cmd
,
10864 "no distance (1-255) X:X::X:X/M",
10866 "Define an administrative distance\n"
10867 "Administrative distance\n"
10868 "IP source prefix\n")
10870 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10871 return CMD_SUCCESS
;
10874 DEFUN (ipv6_bgp_distance_source_access_list
,
10875 ipv6_bgp_distance_source_access_list_cmd
,
10876 "distance (1-255) X:X::X:X/M WORD",
10877 "Define an administrative distance\n"
10878 "Administrative distance\n"
10879 "IP source prefix\n"
10880 "Access list name\n")
10882 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10883 return CMD_SUCCESS
;
10886 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10887 no_ipv6_bgp_distance_source_access_list_cmd
,
10888 "no distance (1-255) X:X::X:X/M WORD",
10890 "Define an administrative distance\n"
10891 "Administrative distance\n"
10892 "IP source prefix\n"
10893 "Access list name\n")
10895 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10896 return CMD_SUCCESS
;
10899 DEFUN (bgp_damp_set
,
10901 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10902 "BGP Specific commands\n"
10903 "Enable route-flap dampening\n"
10904 "Half-life time for the penalty\n"
10905 "Value to start reusing a route\n"
10906 "Value to start suppressing a route\n"
10907 "Maximum duration to suppress a stable route\n")
10909 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10910 int idx_half_life
= 2;
10912 int idx_suppress
= 4;
10913 int idx_max_suppress
= 5;
10914 int half
= DEFAULT_HALF_LIFE
* 60;
10915 int reuse
= DEFAULT_REUSE
;
10916 int suppress
= DEFAULT_SUPPRESS
;
10917 int max
= 4 * half
;
10920 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10921 reuse
= atoi(argv
[idx_reuse
]->arg
);
10922 suppress
= atoi(argv
[idx_suppress
]->arg
);
10923 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10924 } else if (argc
== 3) {
10925 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10929 if (suppress
< reuse
) {
10931 "Suppress value cannot be less than reuse value \n");
10935 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10936 reuse
, suppress
, max
);
10939 DEFUN (bgp_damp_unset
,
10940 bgp_damp_unset_cmd
,
10941 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10943 "BGP Specific commands\n"
10944 "Enable route-flap dampening\n"
10945 "Half-life time for the penalty\n"
10946 "Value to start reusing a route\n"
10947 "Value to start suppressing a route\n"
10948 "Maximum duration to suppress a stable route\n")
10950 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10951 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10954 /* Display specified route of BGP table. */
10955 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10956 const char *ip_str
, afi_t afi
, safi_t safi
,
10957 struct prefix_rd
*prd
, int prefix_check
)
10960 struct prefix match
;
10961 struct bgp_node
*rn
;
10962 struct bgp_node
*rm
;
10963 struct bgp_info
*ri
;
10964 struct bgp_info
*ri_temp
;
10966 struct bgp_table
*table
;
10968 /* BGP structure lookup. */
10970 bgp
= bgp_lookup_by_name(view_name
);
10972 vty_out(vty
, "%% Can't find BGP instance %s\n",
10974 return CMD_WARNING
;
10977 bgp
= bgp_get_default();
10979 vty_out(vty
, "%% No BGP process is configured\n");
10980 return CMD_WARNING
;
10984 /* Check IP address argument. */
10985 ret
= str2prefix(ip_str
, &match
);
10987 vty_out(vty
, "%% address is malformed\n");
10988 return CMD_WARNING
;
10991 match
.family
= afi2family(afi
);
10993 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10994 || (safi
== SAFI_EVPN
)) {
10995 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10996 rn
= bgp_route_next(rn
)) {
10997 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10999 if ((table
= rn
->info
) == NULL
)
11001 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11005 || rm
->p
.prefixlen
== match
.prefixlen
) {
11008 if (ri
->extra
&& ri
->extra
->damp_info
) {
11009 ri_temp
= ri
->next
;
11010 bgp_damp_info_free(
11011 ri
->extra
->damp_info
,
11019 bgp_unlock_node(rm
);
11022 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11025 || rn
->p
.prefixlen
== match
.prefixlen
) {
11028 if (ri
->extra
&& ri
->extra
->damp_info
) {
11029 ri_temp
= ri
->next
;
11030 bgp_damp_info_free(
11031 ri
->extra
->damp_info
,
11039 bgp_unlock_node(rn
);
11043 return CMD_SUCCESS
;
11046 DEFUN (clear_ip_bgp_dampening
,
11047 clear_ip_bgp_dampening_cmd
,
11048 "clear ip bgp dampening",
11052 "Clear route flap dampening information\n")
11054 bgp_damp_info_clean();
11055 return CMD_SUCCESS
;
11058 DEFUN (clear_ip_bgp_dampening_prefix
,
11059 clear_ip_bgp_dampening_prefix_cmd
,
11060 "clear ip bgp dampening A.B.C.D/M",
11064 "Clear route flap dampening information\n"
11067 int idx_ipv4_prefixlen
= 4;
11068 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11069 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11072 DEFUN (clear_ip_bgp_dampening_address
,
11073 clear_ip_bgp_dampening_address_cmd
,
11074 "clear ip bgp dampening A.B.C.D",
11078 "Clear route flap dampening information\n"
11079 "Network to clear damping information\n")
11082 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11083 SAFI_UNICAST
, NULL
, 0);
11086 DEFUN (clear_ip_bgp_dampening_address_mask
,
11087 clear_ip_bgp_dampening_address_mask_cmd
,
11088 "clear ip bgp dampening A.B.C.D A.B.C.D",
11092 "Clear route flap dampening information\n"
11093 "Network to clear damping information\n"
11097 int idx_ipv4_2
= 5;
11099 char prefix_str
[BUFSIZ
];
11101 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11104 vty_out(vty
, "%% Inconsistent address and mask\n");
11105 return CMD_WARNING
;
11108 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11112 /* also used for encap safi */
11113 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11114 afi_t afi
, safi_t safi
)
11116 struct bgp_node
*prn
;
11117 struct bgp_node
*rn
;
11118 struct bgp_table
*table
;
11120 struct prefix_rd
*prd
;
11121 struct bgp_static
*bgp_static
;
11122 mpls_label_t label
;
11123 char buf
[SU_ADDRSTRLEN
];
11124 char rdbuf
[RD_ADDRSTRLEN
];
11126 /* Network configuration. */
11127 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11128 prn
= bgp_route_next(prn
)) {
11129 if ((table
= prn
->info
) == NULL
)
11132 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11133 if ((bgp_static
= rn
->info
) == NULL
)
11137 prd
= (struct prefix_rd
*)&prn
->p
;
11139 /* "network" configuration display. */
11140 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11141 label
= decode_label(&bgp_static
->label
);
11143 vty_out(vty
, " network %s/%d rd %s",
11144 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11146 p
->prefixlen
, rdbuf
);
11147 if (safi
== SAFI_MPLS_VPN
)
11148 vty_out(vty
, " label %u", label
);
11150 if (bgp_static
->rmap
.name
)
11151 vty_out(vty
, " route-map %s",
11152 bgp_static
->rmap
.name
);
11154 if (bgp_static
->backdoor
)
11155 vty_out(vty
, " backdoor");
11157 vty_out(vty
, "\n");
11162 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11163 afi_t afi
, safi_t safi
)
11165 struct bgp_node
*prn
;
11166 struct bgp_node
*rn
;
11167 struct bgp_table
*table
;
11169 struct prefix_rd
*prd
;
11170 struct bgp_static
*bgp_static
;
11171 char buf
[PREFIX_STRLEN
];
11172 char buf2
[SU_ADDRSTRLEN
];
11173 char rdbuf
[RD_ADDRSTRLEN
];
11175 /* Network configuration. */
11176 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11177 prn
= bgp_route_next(prn
)) {
11178 if ((table
= prn
->info
) == NULL
)
11181 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11182 if ((bgp_static
= rn
->info
) == NULL
)
11185 char *macrouter
= NULL
;
11188 if (bgp_static
->router_mac
)
11189 macrouter
= prefix_mac2str(
11190 bgp_static
->router_mac
, NULL
, 0);
11191 if (bgp_static
->eth_s_id
)
11192 esi
= esi2str(bgp_static
->eth_s_id
);
11194 prd
= (struct prefix_rd
*)&prn
->p
;
11196 /* "network" configuration display. */
11197 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11198 if (p
->u
.prefix_evpn
.route_type
== 5) {
11199 char local_buf
[PREFIX_STRLEN
];
11200 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((
11201 struct prefix_evpn
*)p
)
11204 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
,
11205 local_buf
, PREFIX_STRLEN
);
11206 sprintf(buf
, "%s/%u", local_buf
,
11207 p
->u
.prefix_evpn
.ip_prefix_length
);
11209 prefix2str(p
, buf
, sizeof(buf
));
11212 if (bgp_static
->gatewayIp
.family
== AF_INET
11213 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11214 inet_ntop(bgp_static
->gatewayIp
.family
,
11215 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11218 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11219 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11220 decode_label(&bgp_static
->label
), esi
, buf2
,
11224 XFREE(MTYPE_TMP
, macrouter
);
11226 XFREE(MTYPE_TMP
, esi
);
11231 /* Configuration of static route announcement and aggregate
11233 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11236 struct bgp_node
*rn
;
11238 struct bgp_static
*bgp_static
;
11239 struct bgp_aggregate
*bgp_aggregate
;
11240 char buf
[SU_ADDRSTRLEN
];
11242 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11243 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11247 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11248 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11252 /* Network configuration. */
11253 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11254 rn
= bgp_route_next(rn
)) {
11255 if ((bgp_static
= rn
->info
) == NULL
)
11260 /* "network" configuration display. */
11261 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11262 uint32_t destination
;
11263 struct in_addr netmask
;
11265 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11266 masklen2ip(p
->prefixlen
, &netmask
);
11267 vty_out(vty
, " network %s",
11268 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11271 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11272 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11273 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11274 || p
->u
.prefix4
.s_addr
== 0) {
11275 /* Natural mask is not display. */
11277 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11279 vty_out(vty
, " network %s/%d",
11280 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11285 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11286 vty_out(vty
, " label-index %u",
11287 bgp_static
->label_index
);
11289 if (bgp_static
->rmap
.name
)
11290 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11292 if (bgp_static
->backdoor
)
11293 vty_out(vty
, " backdoor");
11295 vty_out(vty
, "\n");
11298 /* Aggregate-address configuration. */
11299 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11300 rn
= bgp_route_next(rn
)) {
11301 if ((bgp_aggregate
= rn
->info
) == NULL
)
11306 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11307 struct in_addr netmask
;
11309 masklen2ip(p
->prefixlen
, &netmask
);
11310 vty_out(vty
, " aggregate-address %s %s",
11311 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11313 inet_ntoa(netmask
));
11315 vty_out(vty
, " aggregate-address %s/%d",
11316 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11321 if (bgp_aggregate
->as_set
)
11322 vty_out(vty
, " as-set");
11324 if (bgp_aggregate
->summary_only
)
11325 vty_out(vty
, " summary-only");
11327 vty_out(vty
, "\n");
11331 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11334 struct bgp_node
*rn
;
11335 struct bgp_distance
*bdistance
;
11337 /* Distance configuration. */
11338 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11339 && bgp
->distance_local
[afi
][safi
]
11340 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11341 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11342 || bgp
->distance_local
[afi
][safi
]
11343 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11344 vty_out(vty
, " distance bgp %d %d %d\n",
11345 bgp
->distance_ebgp
[afi
][safi
],
11346 bgp
->distance_ibgp
[afi
][safi
],
11347 bgp
->distance_local
[afi
][safi
]);
11350 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11351 rn
= bgp_route_next(rn
))
11352 if ((bdistance
= rn
->info
) != NULL
) {
11353 char buf
[PREFIX_STRLEN
];
11355 vty_out(vty
, " distance %d %s %s\n",
11356 bdistance
->distance
,
11357 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11358 bdistance
->access_list
? bdistance
->access_list
11363 /* Allocate routing table structure and install commands. */
11364 void bgp_route_init(void)
11369 /* Init BGP distance table. */
11370 FOREACH_AFI_SAFI (afi
, safi
)
11371 bgp_distance_table
[afi
][safi
] = bgp_table_init(afi
, safi
);
11373 /* IPv4 BGP commands. */
11374 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11375 install_element(BGP_NODE
, &bgp_network_cmd
);
11376 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11378 install_element(BGP_NODE
, &aggregate_address_cmd
);
11379 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11380 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11381 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11383 /* IPv4 unicast configuration. */
11384 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11385 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11386 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11388 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11389 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11390 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11391 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11393 /* IPv4 multicast configuration. */
11394 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11395 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11396 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11397 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11398 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11399 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11400 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11402 /* IPv4 labeled-unicast configuration. */
11403 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11404 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11405 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11406 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11407 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11409 install_element(VIEW_NODE
,
11410 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11411 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11412 install_element(VIEW_NODE
,
11413 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11414 #ifdef KEEP_OLD_VPN_COMMANDS
11415 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11416 #endif /* KEEP_OLD_VPN_COMMANDS */
11417 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11418 install_element(VIEW_NODE
,
11419 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11421 /* BGP dampening clear commands */
11422 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11423 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11425 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11426 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11429 install_element(ENABLE_NODE
,
11430 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11431 #ifdef KEEP_OLD_VPN_COMMANDS
11432 install_element(ENABLE_NODE
,
11433 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11434 #endif /* KEEP_OLD_VPN_COMMANDS */
11436 /* New config IPv6 BGP commands. */
11437 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11438 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11439 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11441 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11442 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11444 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11446 install_element(BGP_NODE
, &bgp_distance_cmd
);
11447 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11448 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11449 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11450 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11451 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11452 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11453 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11454 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11455 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11456 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11457 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11458 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11459 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11460 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11461 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11462 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11463 install_element(BGP_IPV4M_NODE
,
11464 &no_bgp_distance_source_access_list_cmd
);
11465 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11466 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11467 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11468 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11469 install_element(BGP_IPV6_NODE
,
11470 &ipv6_bgp_distance_source_access_list_cmd
);
11471 install_element(BGP_IPV6_NODE
,
11472 &no_ipv6_bgp_distance_source_access_list_cmd
);
11473 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11474 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11475 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11476 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11477 install_element(BGP_IPV6M_NODE
,
11478 &ipv6_bgp_distance_source_access_list_cmd
);
11479 install_element(BGP_IPV6M_NODE
,
11480 &no_ipv6_bgp_distance_source_access_list_cmd
);
11482 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11483 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11484 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11485 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11487 /* IPv4 Multicast Mode */
11488 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11489 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11491 /* Large Communities */
11492 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11493 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11495 /* show bgp ipv4 flowspec detailed */
11496 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11500 void bgp_route_finish(void)
11505 FOREACH_AFI_SAFI (afi
, safi
) {
11506 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11507 bgp_distance_table
[afi
][safi
] = NULL
;