1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
79 #ifndef VTYSH_EXTRACT_PL
80 #include "bgpd/bgp_route_clippy.c"
83 /* Extern from bgp_dump.c */
84 extern const char *bgp_origin_str
[];
85 extern const char *bgp_origin_long_str
[];
88 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
89 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
90 static const struct message bgp_pmsi_tnltype_str
[] = {
91 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
92 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
93 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
94 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
95 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
96 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
97 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
98 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
102 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
103 safi_t safi
, struct prefix
*p
,
104 struct prefix_rd
*prd
)
107 struct bgp_node
*prn
= NULL
;
113 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
114 || (safi
== SAFI_EVPN
)) {
115 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
117 if (prn
->info
== NULL
)
118 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
120 bgp_unlock_node(prn
);
124 rn
= bgp_node_get(table
, p
);
126 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
127 || (safi
== SAFI_EVPN
))
133 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
134 safi_t safi
, struct prefix
*p
,
135 struct prefix_rd
*prd
)
138 struct bgp_node
*prn
= NULL
;
143 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
144 || (safi
== SAFI_EVPN
)) {
145 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
149 if (prn
->info
== NULL
) {
150 bgp_unlock_node(prn
);
157 rn
= bgp_node_lookup(table
, p
);
162 /* Allocate bgp_info_extra */
163 static struct bgp_info_extra
*bgp_info_extra_new(void)
165 struct bgp_info_extra
*new;
166 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
167 new->label
[0] = MPLS_INVALID_LABEL
;
172 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
174 if (extra
&& *extra
) {
175 if ((*extra
)->damp_info
)
176 bgp_damp_info_free((*extra
)->damp_info
, 0);
178 (*extra
)->damp_info
= NULL
;
180 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
186 /* Get bgp_info extra information for the given bgp_info, lazy allocated
189 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
192 ri
->extra
= bgp_info_extra_new();
196 /* Allocate new bgp info structure. */
197 struct bgp_info
*bgp_info_new(void)
199 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
202 /* Free bgp route information. */
203 static void bgp_info_free(struct bgp_info
*binfo
)
206 bgp_attr_unintern(&binfo
->attr
);
208 bgp_unlink_nexthop(binfo
);
209 bgp_info_extra_free(&binfo
->extra
);
210 bgp_info_mpath_free(&binfo
->mpath
);
212 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
214 XFREE(MTYPE_BGP_ROUTE
, binfo
);
217 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
223 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
225 assert(binfo
&& binfo
->lock
> 0);
228 if (binfo
->lock
== 0) {
230 zlog_debug ("%s: unlocked and freeing", __func__
);
231 zlog_backtrace (LOG_DEBUG
);
233 bgp_info_free(binfo
);
238 if (binfo
->lock
== 1)
240 zlog_debug ("%s: unlocked to 1", __func__
);
241 zlog_backtrace (LOG_DEBUG
);
248 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
250 struct bgp_info
*top
;
262 peer_lock(ri
->peer
); /* bgp_info peer reference */
265 /* Do the actual removal of info from RIB, for use by bgp_process
266 completion callback *only* */
267 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
270 ri
->next
->prev
= ri
->prev
;
272 ri
->prev
->next
= ri
->next
;
276 bgp_info_mpath_dequeue(ri
);
281 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
283 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
284 /* set of previous already took care of pcount */
285 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
288 /* undo the effects of a previous call to bgp_info_delete; typically
289 called when a route is deleted and then quickly re-added before the
290 deletion has been processed */
291 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
293 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
294 /* unset of previous already took care of pcount */
295 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
298 /* Adjust pcount as required */
299 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
301 struct bgp_table
*table
;
303 assert(rn
&& bgp_node_table(rn
));
304 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
306 table
= bgp_node_table(rn
);
308 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
311 if (!BGP_INFO_COUNTABLE(ri
)
312 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
314 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
316 /* slight hack, but more robust against errors. */
317 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
318 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
321 "%s: Asked to decrement 0 prefix count for peer %s",
322 __func__
, ri
->peer
->host
);
323 zlog_backtrace(LOG_WARNING
);
324 zlog_warn("%s: Please report to Quagga bugzilla",
327 } else if (BGP_INFO_COUNTABLE(ri
)
328 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
329 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
330 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
334 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
336 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
339 /* Set/unset bgp_info flags, adjusting any other state as needed.
340 * This is here primarily to keep prefix-count in check.
342 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
344 SET_FLAG(ri
->flags
, flag
);
346 /* early bath if we know it's not a flag that changes countability state
348 if (!CHECK_FLAG(flag
,
349 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
352 bgp_pcount_adjust(rn
, ri
);
355 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
358 UNSET_FLAG(ri
->flags
, flag
);
360 /* early bath if we know it's not a flag that changes countability state
362 if (!CHECK_FLAG(flag
,
363 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
366 bgp_pcount_adjust(rn
, ri
);
369 /* Get MED value. If MED value is missing and "bgp bestpath
370 missing-as-worst" is specified, treat it as the worst value. */
371 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
373 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
376 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
383 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
385 if (ri
->addpath_rx_id
)
386 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
389 sprintf(buf
, "path %s", ri
->peer
->host
);
392 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
394 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
395 struct bgp_info
*exist
, int *paths_eq
,
396 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
397 char *pfx_buf
, afi_t afi
, safi_t safi
)
399 struct attr
*newattr
, *existattr
;
400 bgp_peer_sort_t new_sort
;
401 bgp_peer_sort_t exist_sort
;
407 uint32_t exist_weight
;
408 uint32_t newm
, existm
;
409 struct in_addr new_id
;
410 struct in_addr exist_id
;
413 int internal_as_route
;
416 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
417 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
419 uint32_t exist_mm_seq
;
426 zlog_debug("%s: new is NULL", pfx_buf
);
431 bgp_info_path_with_addpath_rx_str(new, new_buf
);
435 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
441 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
442 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
443 pfx_buf
, new_buf
, new->flags
, exist_buf
,
448 existattr
= exist
->attr
;
450 /* For EVPN routes, we cannot just go by local vs remote, we have to
451 * look at the MAC mobility sequence number, if present.
453 if (safi
== SAFI_EVPN
) {
454 /* This is an error condition described in RFC 7432 Section
456 * states that in this scenario "the PE MUST alert the operator"
458 * does not state what other action to take. In order to provide
460 * consistency in this scenario we are going to prefer the path
464 if (newattr
->sticky
!= existattr
->sticky
) {
466 prefix2str(&new->net
->p
, pfx_buf
,
468 * PREFIX2STR_BUFFER
);
469 bgp_info_path_with_addpath_rx_str(new, new_buf
);
470 bgp_info_path_with_addpath_rx_str(exist
,
474 if (newattr
->sticky
&& !existattr
->sticky
) {
476 "%s: %s wins over %s due to sticky MAC flag",
477 pfx_buf
, new_buf
, exist_buf
);
481 if (!newattr
->sticky
&& existattr
->sticky
) {
483 "%s: %s loses to %s due to sticky MAC flag",
484 pfx_buf
, new_buf
, exist_buf
);
489 new_mm_seq
= mac_mobility_seqnum(newattr
);
490 exist_mm_seq
= mac_mobility_seqnum(existattr
);
492 if (new_mm_seq
> exist_mm_seq
) {
495 "%s: %s wins over %s due to MM seq %u > %u",
496 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
501 if (new_mm_seq
< exist_mm_seq
) {
504 "%s: %s loses to %s due to MM seq %u < %u",
505 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
511 /* 1. Weight check. */
512 new_weight
= newattr
->weight
;
513 exist_weight
= existattr
->weight
;
515 if (new_weight
> exist_weight
) {
517 zlog_debug("%s: %s wins over %s due to weight %d > %d",
518 pfx_buf
, new_buf
, exist_buf
, new_weight
,
523 if (new_weight
< exist_weight
) {
525 zlog_debug("%s: %s loses to %s due to weight %d < %d",
526 pfx_buf
, new_buf
, exist_buf
, new_weight
,
531 /* 2. Local preference check. */
532 new_pref
= exist_pref
= bgp
->default_local_pref
;
534 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
535 new_pref
= newattr
->local_pref
;
536 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
537 exist_pref
= existattr
->local_pref
;
539 if (new_pref
> exist_pref
) {
542 "%s: %s wins over %s due to localpref %d > %d",
543 pfx_buf
, new_buf
, exist_buf
, new_pref
,
548 if (new_pref
< exist_pref
) {
551 "%s: %s loses to %s due to localpref %d < %d",
552 pfx_buf
, new_buf
, exist_buf
, new_pref
,
557 /* 3. Local route check. We prefer:
559 * - BGP_ROUTE_AGGREGATE
560 * - BGP_ROUTE_REDISTRIBUTE
562 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
563 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
566 "%s: %s wins over %s due to preferred BGP_ROUTE type",
567 pfx_buf
, new_buf
, exist_buf
);
571 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
572 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
575 "%s: %s loses to %s due to preferred BGP_ROUTE type",
576 pfx_buf
, new_buf
, exist_buf
);
580 /* 4. AS path length check. */
581 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
582 int exist_hops
= aspath_count_hops(existattr
->aspath
);
583 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
585 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
588 aspath_hops
= aspath_count_hops(newattr
->aspath
);
589 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
591 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
594 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
595 pfx_buf
, new_buf
, exist_buf
,
597 (exist_hops
+ exist_confeds
));
601 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
604 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
605 pfx_buf
, new_buf
, exist_buf
,
607 (exist_hops
+ exist_confeds
));
611 int newhops
= aspath_count_hops(newattr
->aspath
);
613 if (newhops
< exist_hops
) {
616 "%s: %s wins over %s due to aspath hopcount %d < %d",
617 pfx_buf
, new_buf
, exist_buf
,
618 newhops
, exist_hops
);
622 if (newhops
> exist_hops
) {
625 "%s: %s loses to %s due to aspath hopcount %d > %d",
626 pfx_buf
, new_buf
, exist_buf
,
627 newhops
, exist_hops
);
633 /* 5. Origin check. */
634 if (newattr
->origin
< existattr
->origin
) {
636 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
637 pfx_buf
, new_buf
, exist_buf
,
638 bgp_origin_long_str
[newattr
->origin
],
639 bgp_origin_long_str
[existattr
->origin
]);
643 if (newattr
->origin
> existattr
->origin
) {
645 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
646 pfx_buf
, new_buf
, exist_buf
,
647 bgp_origin_long_str
[newattr
->origin
],
648 bgp_origin_long_str
[existattr
->origin
]);
653 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
654 && aspath_count_hops(existattr
->aspath
) == 0);
655 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
656 && aspath_count_confeds(existattr
->aspath
) > 0
657 && aspath_count_hops(newattr
->aspath
) == 0
658 && aspath_count_hops(existattr
->aspath
) == 0);
660 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
661 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
662 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
663 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
664 || internal_as_route
) {
665 new_med
= bgp_med_value(new->attr
, bgp
);
666 exist_med
= bgp_med_value(exist
->attr
, bgp
);
668 if (new_med
< exist_med
) {
671 "%s: %s wins over %s due to MED %d < %d",
672 pfx_buf
, new_buf
, exist_buf
, new_med
,
677 if (new_med
> exist_med
) {
680 "%s: %s loses to %s due to MED %d > %d",
681 pfx_buf
, new_buf
, exist_buf
, new_med
,
687 /* 7. Peer type check. */
688 new_sort
= new->peer
->sort
;
689 exist_sort
= exist
->peer
->sort
;
691 if (new_sort
== BGP_PEER_EBGP
692 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
695 "%s: %s wins over %s due to eBGP peer > iBGP peer",
696 pfx_buf
, new_buf
, exist_buf
);
700 if (exist_sort
== BGP_PEER_EBGP
701 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
704 "%s: %s loses to %s due to iBGP peer < eBGP peer",
705 pfx_buf
, new_buf
, exist_buf
);
709 /* 8. IGP metric check. */
713 newm
= new->extra
->igpmetric
;
715 existm
= exist
->extra
->igpmetric
;
720 "%s: %s wins over %s due to IGP metric %d < %d",
721 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
728 "%s: %s loses to %s due to IGP metric %d > %d",
729 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
733 /* 9. Same IGP metric. Compare the cluster list length as
734 representative of IGP hops metric. Rewrite the metric value
735 pair (newm, existm) with the cluster list length. Prefer the
736 path with smaller cluster list length. */
737 if (newm
== existm
) {
738 if (peer_sort(new->peer
) == BGP_PEER_IBGP
739 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
740 && (mpath_cfg
== NULL
742 mpath_cfg
->ibgp_flags
,
743 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
744 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
745 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
750 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
751 pfx_buf
, new_buf
, exist_buf
,
759 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
760 pfx_buf
, new_buf
, exist_buf
,
767 /* 10. confed-external vs. confed-internal */
768 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
769 if (new_sort
== BGP_PEER_CONFED
770 && exist_sort
== BGP_PEER_IBGP
) {
773 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
774 pfx_buf
, new_buf
, exist_buf
);
778 if (exist_sort
== BGP_PEER_CONFED
779 && new_sort
== BGP_PEER_IBGP
) {
782 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
783 pfx_buf
, new_buf
, exist_buf
);
788 /* 11. Maximum path check. */
789 if (newm
== existm
) {
790 /* If one path has a label but the other does not, do not treat
791 * them as equals for multipath
793 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
795 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
798 "%s: %s and %s cannot be multipath, one has a label while the other does not",
799 pfx_buf
, new_buf
, exist_buf
);
800 } else if (bgp_flag_check(bgp
,
801 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
804 * For the two paths, all comparison steps till IGP
806 * have succeeded - including AS_PATH hop count. Since
808 * bestpath as-path multipath-relax' knob is on, we
810 * an exact match of AS_PATH. Thus, mark the paths are
812 * That will trigger both these paths to get into the
820 "%s: %s and %s are equal via multipath-relax",
821 pfx_buf
, new_buf
, exist_buf
);
822 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
823 if (aspath_cmp(new->attr
->aspath
,
824 exist
->attr
->aspath
)) {
829 "%s: %s and %s are equal via matching aspaths",
830 pfx_buf
, new_buf
, exist_buf
);
832 } else if (new->peer
->as
== exist
->peer
->as
) {
837 "%s: %s and %s are equal via same remote-as",
838 pfx_buf
, new_buf
, exist_buf
);
842 * TODO: If unequal cost ibgp multipath is enabled we can
843 * mark the paths as equal here instead of returning
848 "%s: %s wins over %s after IGP metric comparison",
849 pfx_buf
, new_buf
, exist_buf
);
852 "%s: %s loses to %s after IGP metric comparison",
853 pfx_buf
, new_buf
, exist_buf
);
858 /* 12. If both paths are external, prefer the path that was received
859 first (the oldest one). This step minimizes route-flap, since a
860 newer path won't displace an older one, even if it was the
861 preferred route based on the additional decision criteria below. */
862 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
863 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
864 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
867 "%s: %s wins over %s due to oldest external",
868 pfx_buf
, new_buf
, exist_buf
);
872 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
875 "%s: %s loses to %s due to oldest external",
876 pfx_buf
, new_buf
, exist_buf
);
881 /* 13. Router-ID comparision. */
882 /* If one of the paths is "stale", the corresponding peer router-id will
883 * be 0 and would always win over the other path. If originator id is
884 * used for the comparision, it will decide which path is better.
886 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
887 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
889 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
890 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
891 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
893 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
895 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
898 "%s: %s wins over %s due to Router-ID comparison",
899 pfx_buf
, new_buf
, exist_buf
);
903 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
906 "%s: %s loses to %s due to Router-ID comparison",
907 pfx_buf
, new_buf
, exist_buf
);
911 /* 14. Cluster length comparision. */
912 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
913 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
915 if (new_cluster
< exist_cluster
) {
918 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
919 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
924 if (new_cluster
> exist_cluster
) {
927 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
928 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
933 /* 15. Neighbor address comparision. */
934 /* Do this only if neither path is "stale" as stale paths do not have
935 * valid peer information (as the connection may or may not be up).
937 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
940 "%s: %s wins over %s due to latter path being STALE",
941 pfx_buf
, new_buf
, exist_buf
);
945 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
948 "%s: %s loses to %s due to former path being STALE",
949 pfx_buf
, new_buf
, exist_buf
);
953 /* locally configured routes to advertise do not have su_remote */
954 if (new->peer
->su_remote
== NULL
)
956 if (exist
->peer
->su_remote
== NULL
)
959 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
964 "%s: %s loses to %s due to Neighor IP comparison",
965 pfx_buf
, new_buf
, exist_buf
);
972 "%s: %s wins over %s due to Neighor IP comparison",
973 pfx_buf
, new_buf
, exist_buf
);
978 zlog_debug("%s: %s wins over %s due to nothing left to compare",
979 pfx_buf
, new_buf
, exist_buf
);
984 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
985 * is preferred, or 0 if they are the same (usually will only occur if
986 * multipath is enabled
987 * This version is compatible with */
988 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
989 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
994 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1008 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1009 struct attr
*attr
, afi_t afi
,
1012 struct bgp_filter
*filter
;
1014 filter
= &peer
->filter
[afi
][safi
];
1016 #define FILTER_EXIST_WARN(F, f, filter) \
1017 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1018 zlog_warn("%s: Could not find configured input %s-list %s!", \
1019 peer->host, #f, F##_IN_NAME(filter));
1021 if (DISTRIBUTE_IN_NAME(filter
)) {
1022 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1024 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1028 if (PREFIX_LIST_IN_NAME(filter
)) {
1029 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1031 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1035 if (FILTER_LIST_IN_NAME(filter
)) {
1036 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1038 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1043 return FILTER_PERMIT
;
1044 #undef FILTER_EXIST_WARN
1047 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1048 struct attr
*attr
, afi_t afi
,
1051 struct bgp_filter
*filter
;
1053 filter
= &peer
->filter
[afi
][safi
];
1055 #define FILTER_EXIST_WARN(F, f, filter) \
1056 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1057 zlog_warn("%s: Could not find configured output %s-list %s!", \
1058 peer->host, #f, F##_OUT_NAME(filter));
1060 if (DISTRIBUTE_OUT_NAME(filter
)) {
1061 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1063 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1067 if (PREFIX_LIST_OUT_NAME(filter
)) {
1068 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1070 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1075 if (FILTER_LIST_OUT_NAME(filter
)) {
1076 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1078 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1083 return FILTER_PERMIT
;
1084 #undef FILTER_EXIST_WARN
1087 /* If community attribute includes no_export then return 1. */
1088 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1090 if (attr
->community
) {
1091 /* NO_ADVERTISE check. */
1092 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1095 /* NO_EXPORT check. */
1096 if (peer
->sort
== BGP_PEER_EBGP
1097 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1100 /* NO_EXPORT_SUBCONFED check. */
1101 if (peer
->sort
== BGP_PEER_EBGP
1102 || peer
->sort
== BGP_PEER_CONFED
)
1103 if (community_include(attr
->community
,
1104 COMMUNITY_NO_EXPORT_SUBCONFED
))
1110 /* Route reflection loop check. */
1111 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1113 struct in_addr cluster_id
;
1115 if (attr
->cluster
) {
1116 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1117 cluster_id
= peer
->bgp
->cluster_id
;
1119 cluster_id
= peer
->bgp
->router_id
;
1121 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1127 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1128 struct attr
*attr
, afi_t afi
, safi_t safi
,
1129 const char *rmap_name
)
1131 struct bgp_filter
*filter
;
1132 struct bgp_info info
;
1133 route_map_result_t ret
;
1134 struct route_map
*rmap
= NULL
;
1136 filter
= &peer
->filter
[afi
][safi
];
1138 /* Apply default weight value. */
1139 if (peer
->weight
[afi
][safi
])
1140 attr
->weight
= peer
->weight
[afi
][safi
];
1143 rmap
= route_map_lookup_by_name(rmap_name
);
1148 if (ROUTE_MAP_IN_NAME(filter
)) {
1149 rmap
= ROUTE_MAP_IN(filter
);
1156 /* Route map apply. */
1158 /* Duplicate current value to new strucutre for modification. */
1162 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1164 /* Apply BGP route map to the attribute. */
1165 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1167 peer
->rmap_type
= 0;
1169 if (ret
== RMAP_DENYMATCH
) {
1170 /* Free newly generated AS path and community by
1172 bgp_attr_flush(attr
);
1179 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1180 struct attr
*attr
, afi_t afi
, safi_t safi
,
1181 const char *rmap_name
)
1183 struct bgp_info info
;
1184 route_map_result_t ret
;
1185 struct route_map
*rmap
= NULL
;
1189 * So if we get to this point and have no rmap_name
1190 * we want to just show the output as it currently
1196 /* Apply default weight value. */
1197 if (peer
->weight
[afi
][safi
])
1198 attr
->weight
= peer
->weight
[afi
][safi
];
1200 rmap
= route_map_lookup_by_name(rmap_name
);
1203 * If we have a route map name and we do not find
1204 * the routemap that means we have an implicit
1210 /* Route map apply. */
1211 /* Duplicate current value to new strucutre for modification. */
1215 rmap_type
= peer
->rmap_type
;
1216 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1218 /* Apply BGP route map to the attribute. */
1219 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1221 peer
->rmap_type
= rmap_type
;
1223 if (ret
== RMAP_DENYMATCH
)
1225 * caller has multiple error paths with bgp_attr_flush()
1232 /* If this is an EBGP peer with remove-private-AS */
1233 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1234 struct peer
*peer
, struct attr
*attr
)
1236 if (peer
->sort
== BGP_PEER_EBGP
1237 && (peer_af_flag_check(peer
, afi
, safi
,
1238 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1239 || peer_af_flag_check(peer
, afi
, safi
,
1240 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1241 || peer_af_flag_check(peer
, afi
, safi
,
1242 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1243 || peer_af_flag_check(peer
, afi
, safi
,
1244 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1245 // Take action on the entire aspath
1246 if (peer_af_flag_check(peer
, afi
, safi
,
1247 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1248 || peer_af_flag_check(peer
, afi
, safi
,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1250 if (peer_af_flag_check(
1252 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1253 attr
->aspath
= aspath_replace_private_asns(
1254 attr
->aspath
, bgp
->as
);
1256 // The entire aspath consists of private ASNs so create
1258 else if (aspath_private_as_check(attr
->aspath
))
1259 attr
->aspath
= aspath_empty_get();
1261 // There are some public and some private ASNs, remove
1264 attr
->aspath
= aspath_remove_private_asns(
1268 // 'all' was not specified so the entire aspath must be private
1270 // for us to do anything
1271 else if (aspath_private_as_check(attr
->aspath
)) {
1272 if (peer_af_flag_check(
1274 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1275 attr
->aspath
= aspath_replace_private_asns(
1276 attr
->aspath
, bgp
->as
);
1278 attr
->aspath
= aspath_empty_get();
1283 /* If this is an EBGP peer with as-override */
1284 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1285 struct peer
*peer
, struct attr
*attr
)
1287 if (peer
->sort
== BGP_PEER_EBGP
1288 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1289 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1290 attr
->aspath
= aspath_replace_specific_asn(
1291 attr
->aspath
, peer
->as
, bgp
->as
);
1295 void bgp_attr_add_gshut_community(struct attr
*attr
)
1297 struct community
*old
;
1298 struct community
*new;
1299 struct community
*merge
;
1300 struct community
*gshut
;
1302 old
= attr
->community
;
1303 gshut
= community_str2com("graceful-shutdown");
1306 merge
= community_merge(community_dup(old
), gshut
);
1308 if (old
->refcnt
== 0)
1309 community_free(old
);
1311 new = community_uniq_sort(merge
);
1312 community_free(merge
);
1314 new = community_dup(gshut
);
1317 community_free(gshut
);
1318 attr
->community
= new;
1319 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1321 /* When we add the graceful-shutdown community we must also
1322 * lower the local-preference */
1323 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1324 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1328 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1330 if (family
== AF_INET
) {
1331 attr
->nexthop
.s_addr
= 0;
1332 attr
->mp_nexthop_global_in
.s_addr
= 0;
1334 if (family
== AF_INET6
)
1335 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1338 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1339 struct update_subgroup
*subgrp
, struct prefix
*p
,
1342 struct bgp_filter
*filter
;
1345 struct peer
*onlypeer
;
1347 struct attr
*riattr
;
1348 char buf
[PREFIX_STRLEN
];
1354 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1356 if (DISABLE_BGP_ANNOUNCE
)
1359 afi
= SUBGRP_AFI(subgrp
);
1360 safi
= SUBGRP_SAFI(subgrp
);
1361 peer
= SUBGRP_PEER(subgrp
);
1363 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1364 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1367 filter
= &peer
->filter
[afi
][safi
];
1368 bgp
= SUBGRP_INST(subgrp
);
1369 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1372 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1373 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1374 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1377 * direct and direct_ext type routes originate internally even
1378 * though they can have peer pointers that reference other
1381 prefix2str(p
, buf
, PREFIX_STRLEN
);
1382 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1388 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1389 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1390 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1391 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1393 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1398 /* With addpath we may be asked to TX all kinds of paths so make sure
1400 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1401 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1402 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1406 /* If this is not the bestpath then check to see if there is an enabled
1408 * feature that requires us to advertise it */
1409 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1410 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1415 /* Aggregate-address suppress check. */
1416 if (ri
->extra
&& ri
->extra
->suppress
)
1417 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1422 * If we are doing VRF 2 VRF leaking via the import
1423 * statement, we want to prevent the route going
1424 * off box as that the RT and RD created are localy
1425 * significant and globaly useless.
1427 if (safi
== SAFI_MPLS_VPN
&& ri
->extra
&& ri
->extra
->num_labels
1428 && ri
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1431 /* If it's labeled safi, make sure the route has a valid label. */
1432 if (safi
== SAFI_LABELED_UNICAST
) {
1433 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1434 if (!bgp_is_valid_label(&label
)) {
1435 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1436 zlog_debug("u%" PRIu64
":s%" PRIu64
1437 " %s/%d is filtered - no label (%p)",
1438 subgrp
->update_group
->id
, subgrp
->id
,
1439 inet_ntop(p
->family
, &p
->u
.prefix
,
1440 buf
, SU_ADDRSTRLEN
),
1441 p
->prefixlen
, &label
);
1446 /* Do not send back route to sender. */
1447 if (onlypeer
&& from
== onlypeer
) {
1451 /* Do not send the default route in the BGP table if the neighbor is
1452 * configured for default-originate */
1453 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1454 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1455 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1457 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1461 /* Transparency check. */
1462 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1463 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1468 /* If community is not disabled check the no-export and local. */
1469 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1470 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1472 "subgrpannouncecheck: community filter check fail");
1476 /* If the attribute has originator-id and it is same as remote
1478 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1479 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1480 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1482 "%s [Update:SEND] %s originator-id is same as "
1485 prefix2str(p
, buf
, sizeof(buf
)));
1489 /* ORF prefix-list filter check */
1490 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1491 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1492 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1493 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1494 if (peer
->orf_plist
[afi
][safi
]) {
1495 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1497 if (bgp_debug_update(NULL
, p
,
1498 subgrp
->update_group
, 0))
1500 "%s [Update:SEND] %s is filtered via ORF",
1508 /* Output filter check. */
1509 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1510 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1511 zlog_debug("%s [Update:SEND] %s is filtered",
1512 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1516 #ifdef BGP_SEND_ASPATH_CHECK
1517 /* AS path loop check. */
1518 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1519 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1521 "%s [Update:SEND] suppress announcement to peer AS %u "
1522 "that is part of AS path.",
1523 onlypeer
->host
, onlypeer
->as
);
1526 #endif /* BGP_SEND_ASPATH_CHECK */
1528 /* If we're a CONFED we need to loop check the CONFED ID too */
1529 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1530 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1531 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1533 "%s [Update:SEND] suppress announcement to peer AS %u"
1535 peer
->host
, bgp
->confed_id
);
1540 /* Route-Reflect check. */
1541 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1546 /* IBGP reflection check. */
1547 if (reflect
&& !samepeer_safe
) {
1548 /* A route from a Client peer. */
1549 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1550 PEER_FLAG_REFLECTOR_CLIENT
)) {
1551 /* Reflect to all the Non-Client peers and also to the
1552 Client peers other than the originator. Originator
1554 is already done. So there is noting to do. */
1555 /* no bgp client-to-client reflection check. */
1556 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1557 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1558 PEER_FLAG_REFLECTOR_CLIENT
))
1561 /* A route from a Non-client peer. Reflect to all other
1563 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1564 PEER_FLAG_REFLECTOR_CLIENT
))
1569 /* For modify attribute, copy it to temporary structure. */
1570 bgp_attr_dup(attr
, riattr
);
1572 /* If local-preference is not set. */
1573 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1574 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1575 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1576 attr
->local_pref
= bgp
->default_local_pref
;
1579 /* If originator-id is not set and the route is to be reflected,
1580 set the originator id */
1582 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1583 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1584 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1587 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1589 if (peer
->sort
== BGP_PEER_EBGP
1590 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1591 if (from
!= bgp
->peer_self
&& !transparent
1592 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1593 PEER_FLAG_MED_UNCHANGED
))
1595 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1598 /* Since the nexthop attribute can vary per peer, it is not explicitly
1600 * in announce check, only certain flags and length (or number of
1602 * -- for IPv6/MP_REACH) are set here in order to guide the update
1604 * code in setting the nexthop(s) on a per peer basis in
1606 * Typically, the source nexthop in the attribute is preserved but in
1608 * scenarios where we know it will always be overwritten, we reset the
1609 * nexthop to "0" in an attempt to achieve better Update packing. An
1610 * example of this is when a prefix from each of 2 IBGP peers needs to
1612 * announced to an EBGP peer (and they have the same attributes barring
1616 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1618 #define NEXTHOP_IS_V6 \
1619 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1620 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1621 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1622 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1624 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1626 * the peer (group) is configured to receive link-local nexthop
1628 * and it is available in the prefix OR we're not reflecting the route
1630 * the peer (group) to whom we're going to announce is on a shared
1632 * and this is either a self-originated route or the peer is EBGP.
1634 if (NEXTHOP_IS_V6
) {
1635 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1636 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1637 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1638 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1639 || (!reflect
&& peer
->shared_network
1640 && (from
== bgp
->peer_self
1641 || peer
->sort
== BGP_PEER_EBGP
))) {
1642 attr
->mp_nexthop_len
=
1643 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1646 /* Clear off link-local nexthop in source, whenever it is not
1648 * ensure more prefixes share the same attribute for
1651 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1652 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1653 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1656 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1657 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1659 /* Route map & unsuppress-map apply. */
1660 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1661 struct bgp_info info
;
1662 struct bgp_info_extra dummy_info_extra
;
1663 struct attr dummy_attr
;
1669 memcpy(&dummy_info_extra
, ri
->extra
,
1670 sizeof(struct bgp_info_extra
));
1671 info
.extra
= &dummy_info_extra
;
1674 /* don't confuse inbound and outbound setting */
1675 RESET_FLAG(attr
->rmap_change_flags
);
1678 * The route reflector is not allowed to modify the attributes
1679 * of the reflected IBGP routes unless explicitly allowed.
1681 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1682 && !bgp_flag_check(bgp
,
1683 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1684 bgp_attr_dup(&dummy_attr
, attr
);
1685 info
.attr
= &dummy_attr
;
1688 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1690 if (ri
->extra
&& ri
->extra
->suppress
)
1691 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1694 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1697 peer
->rmap_type
= 0;
1699 if (ret
== RMAP_DENYMATCH
) {
1700 bgp_attr_flush(attr
);
1705 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1706 if (peer
->sort
== BGP_PEER_IBGP
1707 || peer
->sort
== BGP_PEER_CONFED
) {
1708 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1709 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1711 bgp_attr_add_gshut_community(attr
);
1715 /* After route-map has been applied, we check to see if the nexthop to
1716 * be carried in the attribute (that is used for the announcement) can
1717 * be cleared off or not. We do this in all cases where we would be
1718 * setting the nexthop to "ourselves". For IPv6, we only need to
1720 * the global nexthop here; the link-local nexthop would have been
1722 * already, and if not, it is required by the update formation code.
1723 * Also see earlier comments in this function.
1726 * If route-map has performed some operation on the nexthop or the peer
1727 * configuration says to pass it unchanged, we cannot reset the nexthop
1728 * here, so only attempt to do it if these aren't true. Note that the
1729 * route-map handler itself might have cleared the nexthop, if for
1731 * it is configured as 'peer-address'.
1733 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1734 riattr
->rmap_change_flags
)
1736 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1737 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1738 /* We can reset the nexthop, if setting (or forcing) it to
1740 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1741 PEER_FLAG_NEXTHOP_SELF
)
1742 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1743 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1745 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1746 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1747 subgroup_announce_reset_nhop(
1748 (peer_cap_enhe(peer
, afi
, safi
)
1752 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1753 /* Can also reset the nexthop if announcing to EBGP, but
1755 * no peer in the subgroup is on a shared subnet.
1756 * Note: 3rd party nexthop currently implemented for
1759 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1761 subgroup_announce_reset_nhop(
1762 (peer_cap_enhe(peer
, afi
, safi
)
1766 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1768 * This flag is used for leaked vpn-vrf routes
1770 int family
= p
->family
;
1772 if (peer_cap_enhe(peer
, afi
, safi
))
1775 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1777 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1778 __func__
, family2str(family
));
1779 subgroup_announce_reset_nhop(family
, attr
);
1782 /* If IPv6/MP and nexthop does not have any override and happens
1784 * be a link-local address, reset it so that we don't pass along
1786 * source's link-local IPv6 address to recipients who may not be
1788 * the same interface.
1790 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1791 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1792 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1799 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1800 struct bgp_maxpaths_cfg
*mpath_cfg
,
1801 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1803 struct bgp_info
*new_select
;
1804 struct bgp_info
*old_select
;
1805 struct bgp_info
*ri
;
1806 struct bgp_info
*ri1
;
1807 struct bgp_info
*ri2
;
1808 struct bgp_info
*nextri
= NULL
;
1809 int paths_eq
, do_mpath
, debug
;
1810 struct list mp_list
;
1811 char pfx_buf
[PREFIX2STR_BUFFER
];
1812 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1814 bgp_mp_list_init(&mp_list
);
1816 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1818 debug
= bgp_debug_bestpath(&rn
->p
);
1821 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1823 /* bgp deterministic-med */
1825 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1827 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1828 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1829 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1831 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1832 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1834 if (BGP_INFO_HOLDDOWN(ri1
))
1836 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1837 if (ri1
->peer
->status
!= Established
)
1842 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1843 if (CHECK_FLAG(ri2
->flags
,
1844 BGP_INFO_DMED_CHECK
))
1846 if (BGP_INFO_HOLDDOWN(ri2
))
1849 && ri2
->peer
!= bgp
->peer_self
1852 PEER_STATUS_NSF_WAIT
))
1853 if (ri2
->peer
->status
1857 if (aspath_cmp_left(ri1
->attr
->aspath
,
1859 || aspath_cmp_left_confed(
1861 ri2
->attr
->aspath
)) {
1862 if (bgp_info_cmp(bgp
, ri2
,
1868 bgp_info_unset_flag(
1870 BGP_INFO_DMED_SELECTED
);
1876 BGP_INFO_DMED_CHECK
);
1880 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1881 bgp_info_set_flag(rn
, new_select
,
1882 BGP_INFO_DMED_SELECTED
);
1885 bgp_info_path_with_addpath_rx_str(new_select
,
1887 zlog_debug("%s: %s is the bestpath from AS %u",
1889 aspath_get_first_as(
1890 new_select
->attr
->aspath
));
1895 /* Check old selected route and new selected route. */
1898 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1900 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1903 if (BGP_INFO_HOLDDOWN(ri
)) {
1904 /* reap REMOVED routes, if needs be
1905 * selected route must stay for a while longer though
1907 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1908 && (ri
!= old_select
))
1909 bgp_info_reap(rn
, ri
);
1912 zlog_debug("%s: ri %p in holddown", __func__
,
1918 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1919 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1920 if (ri
->peer
->status
!= Established
) {
1924 "%s: ri %p non self peer %s not estab state",
1925 __func__
, ri
, ri
->peer
->host
);
1930 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1931 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1932 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1934 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1938 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1940 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1941 debug
, pfx_buf
, afi
, safi
)) {
1946 /* Now that we know which path is the bestpath see if any of the other
1948 * qualify as multipaths
1952 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1954 sprintf(path_buf
, "NONE");
1956 "%s: After path selection, newbest is %s oldbest was %s",
1958 old_select
? old_select
->peer
->host
: "NONE");
1961 if (do_mpath
&& new_select
) {
1962 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1966 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1968 if (ri
== new_select
) {
1971 "%s: %s is the bestpath, add to the multipath list",
1973 bgp_mp_list_add(&mp_list
, ri
);
1977 if (BGP_INFO_HOLDDOWN(ri
))
1980 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1981 && !CHECK_FLAG(ri
->peer
->sflags
,
1982 PEER_STATUS_NSF_WAIT
))
1983 if (ri
->peer
->status
!= Established
)
1986 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1989 "%s: %s has the same nexthop as the bestpath, skip it",
1994 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1995 debug
, pfx_buf
, afi
, safi
);
2000 "%s: %s is equivalent to the bestpath, add to the multipath list",
2002 bgp_mp_list_add(&mp_list
, ri
);
2007 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
2008 bgp_info_mpath_aggregate_update(new_select
, old_select
);
2009 bgp_mp_list_clear(&mp_list
);
2011 result
->old
= old_select
;
2012 result
->new = new_select
;
2018 * A new route/change in bestpath of an existing route. Evaluate the path
2019 * for advertisement to the subgroup.
2021 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2022 struct bgp_info
*selected
,
2023 struct bgp_node
*rn
,
2024 uint32_t addpath_tx_id
)
2027 struct peer
*onlypeer
;
2033 afi
= SUBGRP_AFI(subgrp
);
2034 safi
= SUBGRP_SAFI(subgrp
);
2035 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2038 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2039 char buf_prefix
[PREFIX_STRLEN
];
2040 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2041 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2045 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2046 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2047 PEER_STATUS_ORF_WAIT_REFRESH
))
2050 memset(&attr
, 0, sizeof(struct attr
));
2051 /* It's initialized in bgp_announce_check() */
2053 /* Announcement to the subgroup. If the route is filtered withdraw it.
2056 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2057 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2059 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2060 selected
->addpath_tx_id
);
2063 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2065 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2072 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2073 * This is called at the end of route processing.
2075 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2077 struct bgp_info
*ri
;
2079 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2080 if (BGP_INFO_HOLDDOWN(ri
))
2082 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2083 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2088 * Has the route changed from the RIB's perspective? This is invoked only
2089 * if the route selection returns the same best route as earlier - to
2090 * determine if we need to update zebra or not.
2092 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2094 struct bgp_info
*mpinfo
;
2096 /* If this is multipath, check all selected paths for any nexthop change
2098 * attribute change. Some attribute changes (e.g., community) aren't of
2099 * relevance to the RIB, but we'll update zebra to ensure we handle the
2100 * case of BGP nexthop change. This is the behavior when the best path
2102 * an attribute change anyway.
2104 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2105 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2108 /* If this is multipath, check all selected paths for any nexthop change
2110 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2111 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2112 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2113 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2117 /* Nothing has changed from the RIB's perspective. */
2121 struct bgp_process_queue
{
2123 STAILQ_HEAD(, bgp_node
) pqueue
;
2124 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2126 unsigned int queued
;
2130 * old_select = The old best path
2131 * new_select = the new best path
2133 * if (!old_select && new_select)
2134 * We are sending new information on.
2136 * if (old_select && new_select) {
2137 * if (new_select != old_select)
2138 * We have a new best path send a change
2140 * We've received a update with new attributes that needs
2144 * if (old_select && !new_select)
2145 * We have no eligible route that we can announce or the rn
2148 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2149 afi_t afi
, safi_t safi
)
2151 struct prefix
*p
= &rn
->p
;
2152 struct bgp_info
*new_select
;
2153 struct bgp_info
*old_select
;
2154 struct bgp_info_pair old_and_new
;
2155 char pfx_buf
[PREFIX2STR_BUFFER
];
2158 /* Is it end of initial update? (after startup) */
2160 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2161 sizeof(bgp
->update_delay_zebra_resume_time
));
2163 bgp
->main_zebra_update_hold
= 0;
2164 FOREACH_AFI_SAFI (afi
, safi
) {
2165 if (bgp_fibupd_safi(safi
))
2166 bgp_zebra_announce_table(bgp
, afi
, safi
);
2168 bgp
->main_peers_update_hold
= 0;
2170 bgp_start_routeadv(bgp
);
2174 debug
= bgp_debug_bestpath(&rn
->p
);
2176 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2177 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2178 afi2str(afi
), safi2str(safi
));
2181 /* Best path selection. */
2182 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2184 old_select
= old_and_new
.old
;
2185 new_select
= old_and_new
.new;
2187 /* Do we need to allocate or free labels?
2188 * Right now, since we only deal with per-prefix labels, it is not
2189 * necessary to do this upon changes to best path except if the label
2192 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2195 || bgp_label_index_differs(new_select
, old_select
)
2196 || new_select
->sub_type
!= old_select
->sub_type
) {
2197 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2198 && new_select
->attr
->flag
2200 BGP_ATTR_PREFIX_SID
)
2201 && new_select
->attr
->label_index
2202 != BGP_INVALID_LABEL_INDEX
) {
2205 BGP_NODE_REGISTERED_FOR_LABEL
))
2206 bgp_unregister_for_label(rn
);
2207 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2209 bgp_set_valid_label(&rn
->local_label
);
2211 bgp_register_for_label(rn
, new_select
);
2213 } else if (CHECK_FLAG(rn
->flags
,
2214 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2215 bgp_unregister_for_label(rn
);
2217 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2218 bgp_unregister_for_label(rn
);
2222 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2224 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2225 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2226 old_select
, new_select
);
2229 /* If best route remains the same and this is not due to user-initiated
2230 * clear, see exactly what needs to be done.
2233 if (old_select
&& old_select
== new_select
2234 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2235 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2236 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2237 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2239 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2240 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2242 if (bgp_fibupd_safi(safi
)
2243 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2245 if (new_select
->type
== ZEBRA_ROUTE_BGP
2246 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2247 || new_select
->sub_type
2248 == BGP_ROUTE_IMPORTED
))
2250 bgp_zebra_announce(rn
, p
, old_select
,
2254 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2255 bgp_zebra_clear_route_change_flags(rn
);
2257 /* If there is a change of interest to peers, reannounce the
2259 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2260 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2261 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2263 /* unicast routes must also be annouced to
2264 * labeled-unicast update-groups */
2265 if (safi
== SAFI_UNICAST
)
2266 group_announce_route(bgp
, afi
,
2267 SAFI_LABELED_UNICAST
, rn
,
2270 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2271 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2274 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2278 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2280 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2282 /* bestpath has changed; bump version */
2283 if (old_select
|| new_select
) {
2284 bgp_bump_version(rn
);
2286 if (!bgp
->t_rmap_def_originate_eval
) {
2290 update_group_refresh_default_originate_route_map
,
2291 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2292 &bgp
->t_rmap_def_originate_eval
);
2297 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2300 zlog_debug("%s: setting SELECTED flag", __func__
);
2301 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2302 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2303 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2307 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2308 if (old_select
!= new_select
) {
2310 vnc_import_bgp_exterior_del_route(bgp
, p
,
2312 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2315 vnc_import_bgp_exterior_add_route(bgp
, p
,
2317 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2323 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2325 /* unicast routes must also be annouced to labeled-unicast update-groups
2327 if (safi
== SAFI_UNICAST
)
2328 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2332 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2333 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2334 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2335 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2336 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2337 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2339 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2341 /* Withdraw the route from the kernel. */
2342 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2343 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2344 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2345 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2347 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2351 /* advertise/withdraw type-5 routes */
2352 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2353 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2354 (!new_select
->extra
|| !new_select
->extra
->parent
))
2355 bgp_evpn_advertise_type5_route(bgp
, &rn
->p
,
2358 else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2359 (!old_select
->extra
|| !old_select
->extra
->parent
))
2360 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2363 /* Clear any route change flags. */
2364 bgp_zebra_clear_route_change_flags(rn
);
2366 /* Reap old select bgp_info, if it has been removed */
2367 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2368 bgp_info_reap(rn
, old_select
);
2370 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2374 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2376 struct bgp_process_queue
*pqnode
= data
;
2377 struct bgp
*bgp
= pqnode
->bgp
;
2378 struct bgp_table
*table
;
2379 struct bgp_node
*rn
;
2382 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2383 bgp_process_main_one(bgp
, NULL
, 0, 0);
2384 /* should always have dedicated wq call */
2385 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2389 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2390 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2391 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2392 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2393 table
= bgp_node_table(rn
);
2394 /* note, new RNs may be added as part of processing */
2395 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2397 bgp_unlock_node(rn
);
2398 bgp_table_unlock(table
);
2404 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2406 struct bgp_process_queue
*pqnode
= data
;
2408 bgp_unlock(pqnode
->bgp
);
2410 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2413 void bgp_process_queue_init(void)
2415 if (!bm
->process_main_queue
) {
2416 bm
->process_main_queue
=
2417 work_queue_new(bm
->master
, "process_main_queue");
2419 if (!bm
->process_main_queue
) {
2420 zlog_err("%s: Failed to allocate work queue", __func__
);
2425 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2426 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2427 bm
->process_main_queue
->spec
.max_retries
= 0;
2428 bm
->process_main_queue
->spec
.hold
= 50;
2429 /* Use a higher yield value of 50ms for main queue processing */
2430 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2433 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2435 struct bgp_process_queue
*pqnode
;
2437 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2438 sizeof(struct bgp_process_queue
));
2440 /* unlocked in bgp_processq_del */
2441 pqnode
->bgp
= bgp_lock(bgp
);
2442 STAILQ_INIT(&pqnode
->pqueue
);
2447 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2449 #define ARBITRARY_PROCESS_QLEN 10000
2450 struct work_queue
*wq
= bm
->process_main_queue
;
2451 struct bgp_process_queue
*pqnode
;
2452 int pqnode_reuse
= 0;
2454 /* already scheduled for processing? */
2455 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2461 /* Add route nodes to an existing work queue item until reaching the
2462 limit only if is from the same BGP view and it's not an EOIU marker
2464 if (work_queue_item_count(wq
)) {
2465 struct work_queue_item
*item
= work_queue_last_item(wq
);
2466 pqnode
= item
->data
;
2468 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2469 || pqnode
->bgp
!= bgp
2470 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2471 pqnode
= bgp_processq_alloc(bgp
);
2475 pqnode
= bgp_processq_alloc(bgp
);
2476 /* all unlocked in bgp_process_wq */
2477 bgp_table_lock(bgp_node_table(rn
));
2479 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2482 /* can't be enqueued twice */
2483 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2484 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2488 work_queue_add(wq
, pqnode
);
2493 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2495 struct bgp_process_queue
*pqnode
;
2497 if (bm
->process_main_queue
== NULL
)
2500 pqnode
= bgp_processq_alloc(bgp
);
2502 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2503 work_queue_add(bm
->process_main_queue
, pqnode
);
2506 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2510 peer
= THREAD_ARG(thread
);
2511 peer
->t_pmax_restart
= NULL
;
2513 if (bgp_debug_neighbor_events(peer
))
2515 "%s Maximum-prefix restart timer expired, restore peering",
2518 peer_clear(peer
, NULL
);
2523 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2527 iana_safi_t pkt_safi
;
2529 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2532 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2533 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2534 PEER_STATUS_PREFIX_LIMIT
)
2539 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2541 afi_safi_print(afi
, safi
), peer
->host
,
2542 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2543 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2545 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2546 PEER_FLAG_MAX_PREFIX_WARNING
))
2549 /* Convert AFI, SAFI to values for packet. */
2550 pkt_afi
= afi_int2iana(afi
);
2551 pkt_safi
= safi_int2iana(safi
);
2555 ndata
[0] = (pkt_afi
>> 8);
2557 ndata
[2] = pkt_safi
;
2558 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2559 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2560 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2561 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2563 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2564 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2565 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2569 /* Dynamic peers will just close their connection. */
2570 if (peer_dynamic_neighbor(peer
))
2573 /* restart timer start */
2574 if (peer
->pmax_restart
[afi
][safi
]) {
2575 peer
->v_pmax_restart
=
2576 peer
->pmax_restart
[afi
][safi
] * 60;
2578 if (bgp_debug_neighbor_events(peer
))
2580 "%s Maximum-prefix restart timer started for %d secs",
2581 peer
->host
, peer
->v_pmax_restart
);
2583 BGP_TIMER_ON(peer
->t_pmax_restart
,
2584 bgp_maximum_prefix_restart_timer
,
2585 peer
->v_pmax_restart
);
2590 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2591 PEER_STATUS_PREFIX_LIMIT
);
2593 if (peer
->pcount
[afi
][safi
]
2594 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2595 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2596 PEER_STATUS_PREFIX_THRESHOLD
)
2601 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2602 afi_safi_print(afi
, safi
), peer
->host
,
2603 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2604 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2605 PEER_STATUS_PREFIX_THRESHOLD
);
2607 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2608 PEER_STATUS_PREFIX_THRESHOLD
);
2612 /* Unconditionally remove the route from the RIB, without taking
2613 * damping into consideration (eg, because the session went down)
2615 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2616 afi_t afi
, safi_t safi
)
2618 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2620 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2621 bgp_info_delete(rn
, ri
); /* keep historical info */
2623 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2626 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2627 struct peer
*peer
, afi_t afi
, safi_t safi
,
2628 struct prefix_rd
*prd
)
2630 int status
= BGP_DAMP_NONE
;
2632 /* apply dampening, if result is suppressed, we'll be retaining
2633 * the bgp_info in the RIB for historical reference.
2635 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2636 && peer
->sort
== BGP_PEER_EBGP
)
2637 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2638 == BGP_DAMP_SUPPRESSED
) {
2639 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2645 if (safi
== SAFI_MPLS_VPN
) {
2646 struct bgp_node
*prn
= NULL
;
2647 struct bgp_table
*table
= NULL
;
2649 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2650 (struct prefix
*)prd
);
2652 table
= (struct bgp_table
*)(prn
->info
);
2654 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2655 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2657 bgp_unlock_node(prn
);
2659 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2660 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2662 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2663 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2669 /* If this is an EVPN route, process for un-import. */
2670 if (safi
== SAFI_EVPN
)
2671 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2673 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2676 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2677 struct peer
*peer
, struct attr
*attr
,
2678 struct bgp_node
*rn
)
2680 struct bgp_info
*new;
2682 /* Make new BGP info. */
2683 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2685 new->instance
= instance
;
2686 new->sub_type
= sub_type
;
2689 new->uptime
= bgp_clock();
2691 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2695 static void overlay_index_update(struct attr
*attr
,
2696 struct eth_segment_id
*eth_s_id
,
2697 union gw_addr
*gw_ip
)
2702 if (eth_s_id
== NULL
) {
2703 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2704 sizeof(struct eth_segment_id
));
2706 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2707 sizeof(struct eth_segment_id
));
2709 if (gw_ip
== NULL
) {
2710 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2712 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2713 sizeof(union gw_addr
));
2717 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2718 struct eth_segment_id
*eth_s_id
,
2719 union gw_addr
*gw_ip
)
2721 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2722 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2725 if (afi
!= AFI_L2VPN
)
2728 memset(&temp
, 0, 16);
2729 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2730 info_gw_ip
= (union gw_addr
*)&temp
;
2731 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2734 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2735 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2738 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2740 info_gw_ip_remote
= gw_ip
;
2741 if (eth_s_id
== NULL
)
2742 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2744 info_eth_s_id_remote
= eth_s_id
;
2745 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2747 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2748 sizeof(struct eth_segment_id
));
2751 /* Check if received nexthop is valid or not. */
2752 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2757 /* Only validated for unicast and multicast currently. */
2758 /* Also valid for EVPN where the nexthop is an IP address. */
2759 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2762 /* If NEXT_HOP is present, validate it. */
2763 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2764 if (attr
->nexthop
.s_addr
== 0
2765 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2766 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2770 /* If MP_NEXTHOP is present, validate it. */
2771 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2772 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2773 * it is not an IPv6 link-local address.
2775 if (attr
->mp_nexthop_len
) {
2776 switch (attr
->mp_nexthop_len
) {
2777 case BGP_ATTR_NHLEN_IPV4
:
2778 case BGP_ATTR_NHLEN_VPNV4
:
2779 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2780 || IPV4_CLASS_DE(ntohl(
2781 attr
->mp_nexthop_global_in
.s_addr
))
2782 || bgp_nexthop_self(bgp
,
2783 attr
->mp_nexthop_global_in
));
2786 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2787 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2788 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2789 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2790 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2791 || IN6_IS_ADDR_MULTICAST(
2792 &attr
->mp_nexthop_global
));
2804 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2805 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2806 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2807 uint32_t num_labels
, int soft_reconfig
,
2808 struct bgp_route_evpn
*evpn
)
2811 int aspath_loop_count
= 0;
2812 struct bgp_node
*rn
;
2814 struct attr new_attr
;
2815 struct attr
*attr_new
;
2816 struct bgp_info
*ri
;
2817 struct bgp_info
*new;
2818 struct bgp_info_extra
*extra
;
2820 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2822 int do_loop_check
= 1;
2823 int has_valid_label
= 0;
2825 int vnc_implicit_withdraw
= 0;
2829 memset(&new_attr
, 0, sizeof(struct attr
));
2830 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2831 new_attr
.label
= MPLS_INVALID_LABEL
;
2834 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2835 /* TODO: Check to see if we can get rid of "is_valid_label" */
2836 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2837 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2839 has_valid_label
= bgp_is_valid_label(label
);
2841 /* When peer's soft reconfiguration enabled. Record input packet in
2844 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2845 && peer
!= bgp
->peer_self
)
2846 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2848 /* Check previously received route. */
2849 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2850 if (ri
->peer
== peer
&& ri
->type
== type
2851 && ri
->sub_type
== sub_type
2852 && ri
->addpath_rx_id
== addpath_id
)
2855 /* AS path local-as loop check. */
2856 if (peer
->change_local_as
) {
2857 if (peer
->allowas_in
[afi
][safi
])
2858 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2859 else if (!CHECK_FLAG(peer
->flags
,
2860 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2861 aspath_loop_count
= 1;
2863 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2864 > aspath_loop_count
) {
2865 reason
= "as-path contains our own AS;";
2870 /* If the peer is configured for "allowas-in origin" and the last ASN in
2872 * as-path is our ASN then we do not need to call aspath_loop_check
2874 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2875 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2878 /* AS path loop check. */
2879 if (do_loop_check
) {
2880 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2881 > peer
->allowas_in
[afi
][safi
]
2882 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2883 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2884 > peer
->allowas_in
[afi
][safi
])) {
2885 reason
= "as-path contains our own AS;";
2890 /* Route reflector originator ID check. */
2891 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2892 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2893 reason
= "originator is us;";
2897 /* Route reflector cluster ID check. */
2898 if (bgp_cluster_filter(peer
, attr
)) {
2899 reason
= "reflected from the same cluster;";
2903 /* Apply incoming filter. */
2904 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2909 bgp_attr_dup(&new_attr
, attr
);
2911 /* Apply incoming route-map.
2912 * NB: new_attr may now contain newly allocated values from route-map
2914 * commands, so we need bgp_attr_flush in the error paths, until we
2916 * the attr (which takes over the memory references) */
2917 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2919 reason
= "route-map;";
2920 bgp_attr_flush(&new_attr
);
2924 if (peer
->sort
== BGP_PEER_EBGP
) {
2926 /* If we receive the graceful-shutdown community from an eBGP
2927 * peer we must lower local-preference */
2928 if (new_attr
.community
2929 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2930 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2931 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2933 /* If graceful-shutdown is configured then add the GSHUT
2934 * community to all paths received from eBGP peers */
2935 } else if (bgp_flag_check(peer
->bgp
,
2936 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2937 bgp_attr_add_gshut_community(&new_attr
);
2941 /* next hop check. */
2942 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2943 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2944 reason
= "martian or self next-hop;";
2945 bgp_attr_flush(&new_attr
);
2949 attr_new
= bgp_attr_intern(&new_attr
);
2951 /* If the update is implicit withdraw. */
2953 ri
->uptime
= bgp_clock();
2954 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2956 /* Same attribute comes in. */
2957 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2958 && attrhash_cmp(ri
->attr
, attr_new
)
2959 && (!has_valid_label
2960 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2961 num_labels
* sizeof(mpls_label_t
))
2963 && (overlay_index_equal(
2964 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2965 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2966 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2967 BGP_CONFIG_DAMPENING
)
2968 && peer
->sort
== BGP_PEER_EBGP
2969 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2970 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2971 bgp_debug_rdpfxpath2str(
2972 afi
, safi
, prd
, p
, label
,
2973 num_labels
, addpath_id
? 1 : 0,
2974 addpath_id
, pfx_buf
,
2976 zlog_debug("%s rcvd %s", peer
->host
,
2980 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2981 != BGP_DAMP_SUPPRESSED
) {
2982 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2984 bgp_process(bgp
, rn
, afi
, safi
);
2986 } else /* Duplicate - odd */
2988 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2989 if (!peer
->rcvd_attr_printed
) {
2991 "%s rcvd UPDATE w/ attr: %s",
2993 peer
->rcvd_attr_str
);
2994 peer
->rcvd_attr_printed
= 1;
2997 bgp_debug_rdpfxpath2str(
2998 afi
, safi
, prd
, p
, label
,
2999 num_labels
, addpath_id
? 1 : 0,
3000 addpath_id
, pfx_buf
,
3003 "%s rcvd %s...duplicate ignored",
3004 peer
->host
, pfx_buf
);
3007 /* graceful restart STALE flag unset. */
3008 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
3009 bgp_info_unset_flag(rn
, ri
,
3011 bgp_process(bgp
, rn
, afi
, safi
);
3015 bgp_unlock_node(rn
);
3016 bgp_attr_unintern(&attr_new
);
3021 /* Withdraw/Announce before we fully processed the withdraw */
3022 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3023 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3024 bgp_debug_rdpfxpath2str(
3025 afi
, safi
, prd
, p
, label
, num_labels
,
3026 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3029 "%s rcvd %s, flapped quicker than processing",
3030 peer
->host
, pfx_buf
);
3033 bgp_info_restore(rn
, ri
);
3036 /* Received Logging. */
3037 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3038 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3039 num_labels
, addpath_id
? 1 : 0,
3040 addpath_id
, pfx_buf
,
3042 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3045 /* graceful restart STALE flag unset. */
3046 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3047 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3049 /* The attribute is changed. */
3050 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3052 /* implicit withdraw, decrement aggregate and pcount here.
3053 * only if update is accepted, they'll increment below.
3055 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3057 /* Update bgp route dampening information. */
3058 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3059 && peer
->sort
== BGP_PEER_EBGP
) {
3060 /* This is implicit withdraw so we should update
3063 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3064 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3067 if (safi
== SAFI_MPLS_VPN
) {
3068 struct bgp_node
*prn
= NULL
;
3069 struct bgp_table
*table
= NULL
;
3071 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3072 (struct prefix
*)prd
);
3074 table
= (struct bgp_table
*)(prn
->info
);
3076 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3077 bgp
, prd
, table
, p
, ri
);
3079 bgp_unlock_node(prn
);
3081 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3082 && (safi
== SAFI_UNICAST
)) {
3083 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3085 * Implicit withdraw case.
3087 ++vnc_implicit_withdraw
;
3088 vnc_import_bgp_del_route(bgp
, p
, ri
);
3089 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3094 /* Special handling for EVPN update of an existing route. If the
3095 * extended community attribute has changed, we need to
3097 * the route using its existing extended community. It will be
3098 * subsequently processed for import with the new extended
3101 if (safi
== SAFI_EVPN
&& !same_attr
) {
3103 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3105 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3108 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3109 attr_new
->ecommunity
);
3111 if (bgp_debug_update(peer
, p
, NULL
, 1))
3113 "Change in EXT-COMM, existing %s new %s",
3115 ri
->attr
->ecommunity
),
3117 attr_new
->ecommunity
));
3118 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3124 /* Update to new attribute. */
3125 bgp_attr_unintern(&ri
->attr
);
3126 ri
->attr
= attr_new
;
3128 /* Update MPLS label */
3129 if (has_valid_label
) {
3130 extra
= bgp_info_extra_get(ri
);
3131 memcpy(&extra
->label
, label
,
3132 num_labels
* sizeof(mpls_label_t
));
3133 extra
->num_labels
= num_labels
;
3134 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3135 bgp_set_valid_label(&extra
->label
[0]);
3139 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3140 && (safi
== SAFI_UNICAST
)) {
3141 if (vnc_implicit_withdraw
) {
3143 * Add back the route with its new attributes
3145 * The route is still selected, until the route
3147 * queued by bgp_process actually runs. We have
3149 * update to the VNC side immediately to avoid
3151 * configuration changes (e.g., route-map
3153 * trigger re-importation of the entire RIB.
3155 vnc_import_bgp_add_route(bgp
, p
, ri
);
3156 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3160 /* Update Overlay Index */
3161 if (afi
== AFI_L2VPN
) {
3162 overlay_index_update(
3163 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3164 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3167 /* Update bgp route dampening information. */
3168 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3169 && peer
->sort
== BGP_PEER_EBGP
) {
3170 /* Now we do normal update dampening. */
3171 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3172 if (ret
== BGP_DAMP_SUPPRESSED
) {
3173 bgp_unlock_node(rn
);
3178 /* Nexthop reachability check - for unicast and
3179 * labeled-unicast.. */
3180 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3181 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3182 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3183 && !CHECK_FLAG(peer
->flags
,
3184 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3186 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3191 struct bgp
*bgp_nexthop
= bgp
;
3193 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3194 bgp_nexthop
= ri
->extra
->bgp_orig
;
3196 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3197 ri
, NULL
, connected
)
3198 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3199 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3201 if (BGP_DEBUG(nht
, NHT
)) {
3202 char buf1
[INET6_ADDRSTRLEN
];
3204 (const void *)&attr_new
3206 buf1
, INET6_ADDRSTRLEN
);
3207 zlog_debug("%s(%s): NH unresolved",
3208 __FUNCTION__
, buf1
);
3210 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3213 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3216 if (safi
== SAFI_MPLS_VPN
) {
3217 struct bgp_node
*prn
= NULL
;
3218 struct bgp_table
*table
= NULL
;
3220 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3221 (struct prefix
*)prd
);
3223 table
= (struct bgp_table
*)(prn
->info
);
3225 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3226 bgp
, prd
, table
, p
, ri
);
3228 bgp_unlock_node(prn
);
3232 /* If this is an EVPN route and some attribute has changed,
3234 * route for import. If the extended community has changed, we
3236 * have done the un-import earlier and the import would result
3238 * route getting injected into appropriate L2 VNIs. If it is
3240 * some other attribute change, the import will result in
3242 * the attributes for the route in the VNI(s).
3244 if (safi
== SAFI_EVPN
&& !same_attr
)
3245 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3247 /* Process change. */
3248 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3250 bgp_process(bgp
, rn
, afi
, safi
);
3251 bgp_unlock_node(rn
);
3253 if (SAFI_UNICAST
== safi
3254 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3255 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3257 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3259 if ((SAFI_MPLS_VPN
== safi
)
3260 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3262 vpn_leak_to_vrf_update(bgp
, ri
);
3266 if (SAFI_MPLS_VPN
== safi
) {
3267 mpls_label_t label_decoded
= decode_label(label
);
3269 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3270 type
, sub_type
, &label_decoded
);
3272 if (SAFI_ENCAP
== safi
) {
3273 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3274 type
, sub_type
, NULL
);
3279 } // End of implicit withdraw
3281 /* Received Logging. */
3282 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3283 if (!peer
->rcvd_attr_printed
) {
3284 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3285 peer
->rcvd_attr_str
);
3286 peer
->rcvd_attr_printed
= 1;
3289 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3290 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3292 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3295 /* Make new BGP info. */
3296 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3298 /* Update MPLS label */
3299 if (has_valid_label
) {
3300 extra
= bgp_info_extra_get(new);
3301 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3302 extra
->num_labels
= num_labels
;
3303 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3304 bgp_set_valid_label(&extra
->label
[0]);
3307 /* Update Overlay Index */
3308 if (afi
== AFI_L2VPN
) {
3309 overlay_index_update(new->attr
,
3310 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3311 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3313 /* Nexthop reachability check. */
3314 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3315 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3316 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3317 && !CHECK_FLAG(peer
->flags
,
3318 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3319 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3324 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3325 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3326 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3328 if (BGP_DEBUG(nht
, NHT
)) {
3329 char buf1
[INET6_ADDRSTRLEN
];
3331 (const void *)&attr_new
->nexthop
,
3332 buf1
, INET6_ADDRSTRLEN
);
3333 zlog_debug("%s(%s): NH unresolved",
3334 __FUNCTION__
, buf1
);
3336 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3339 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3342 new->addpath_rx_id
= addpath_id
;
3344 /* Increment prefix */
3345 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3347 /* Register new BGP information. */
3348 bgp_info_add(rn
, new);
3350 /* route_node_get lock */
3351 bgp_unlock_node(rn
);
3354 if (safi
== SAFI_MPLS_VPN
) {
3355 struct bgp_node
*prn
= NULL
;
3356 struct bgp_table
*table
= NULL
;
3358 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3360 table
= (struct bgp_table
*)(prn
->info
);
3362 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3363 bgp
, prd
, table
, p
, new);
3365 bgp_unlock_node(prn
);
3369 /* If maximum prefix count is configured and current prefix
3371 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3374 /* If this is an EVPN route, process for import. */
3375 if (safi
== SAFI_EVPN
)
3376 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3378 /* Process change. */
3379 bgp_process(bgp
, rn
, afi
, safi
);
3381 if (SAFI_UNICAST
== safi
3382 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3383 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3384 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3386 if ((SAFI_MPLS_VPN
== safi
)
3387 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3389 vpn_leak_to_vrf_update(bgp
, new);
3392 if (SAFI_MPLS_VPN
== safi
) {
3393 mpls_label_t label_decoded
= decode_label(label
);
3395 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3396 sub_type
, &label_decoded
);
3398 if (SAFI_ENCAP
== safi
) {
3399 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3406 /* This BGP update is filtered. Log the reason then update BGP
3409 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3410 if (!peer
->rcvd_attr_printed
) {
3411 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3412 peer
->rcvd_attr_str
);
3413 peer
->rcvd_attr_printed
= 1;
3416 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3417 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3419 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3420 peer
->host
, pfx_buf
, reason
);
3424 /* If this is an EVPN route, un-import it as it is now filtered.
3426 if (safi
== SAFI_EVPN
)
3427 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3429 if (SAFI_UNICAST
== safi
3430 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3431 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3433 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3435 if ((SAFI_MPLS_VPN
== safi
)
3436 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3438 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3441 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3444 bgp_unlock_node(rn
);
3448 * Filtered update is treated as an implicit withdrawal (see
3450 * a few lines above)
3452 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3453 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3461 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3462 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3463 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3464 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3467 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3468 struct bgp_node
*rn
;
3469 struct bgp_info
*ri
;
3472 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3473 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3481 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3483 /* If peer is soft reconfiguration enabled. Record input packet for
3484 * further calculation.
3486 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3487 * routes that are filtered. This tanks out Quagga RS pretty badly due
3489 * the iteration over all RS clients.
3490 * Since we need to remove the entry from adj_in anyway, do that first
3492 * if there was no entry, we don't need to do anything more.
3494 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3495 && peer
!= bgp
->peer_self
)
3496 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3497 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3498 bgp_debug_rdpfxpath2str(
3499 afi
, safi
, prd
, p
, label
, num_labels
,
3500 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3503 "%s withdrawing route %s not in adj-in",
3504 peer
->host
, pfx_buf
);
3506 bgp_unlock_node(rn
);
3510 /* Lookup withdrawn route. */
3511 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3512 if (ri
->peer
== peer
&& ri
->type
== type
3513 && ri
->sub_type
== sub_type
3514 && ri
->addpath_rx_id
== addpath_id
)
3518 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3519 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3520 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3522 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3526 /* Withdraw specified route from routing table. */
3527 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3528 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3529 if (SAFI_UNICAST
== safi
3530 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3531 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3532 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3534 if ((SAFI_MPLS_VPN
== safi
)
3535 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3537 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3539 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3540 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3541 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3543 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3546 /* Unlock bgp_node_get() lock. */
3547 bgp_unlock_node(rn
);
3552 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3555 struct update_subgroup
*subgrp
;
3556 subgrp
= peer_subgroup(peer
, afi
, safi
);
3557 subgroup_default_originate(subgrp
, withdraw
);
3562 * bgp_stop_announce_route_timer
3564 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3566 if (!paf
->t_announce_route
)
3569 THREAD_TIMER_OFF(paf
->t_announce_route
);
3573 * bgp_announce_route_timer_expired
3575 * Callback that is invoked when the route announcement timer for a
3578 static int bgp_announce_route_timer_expired(struct thread
*t
)
3580 struct peer_af
*paf
;
3583 paf
= THREAD_ARG(t
);
3586 if (peer
->status
!= Established
)
3589 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3592 peer_af_announce_route(paf
, 1);
3597 * bgp_announce_route
3599 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3601 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3603 struct peer_af
*paf
;
3604 struct update_subgroup
*subgrp
;
3606 paf
= peer_af_find(peer
, afi
, safi
);
3609 subgrp
= PAF_SUBGRP(paf
);
3612 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3613 * or a refresh has already been triggered.
3615 if (!subgrp
|| paf
->t_announce_route
)
3619 * Start a timer to stagger/delay the announce. This serves
3620 * two purposes - announcement can potentially be combined for
3621 * multiple peers and the announcement doesn't happen in the
3624 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3625 (subgrp
->peer_count
== 1)
3626 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3627 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3628 &paf
->t_announce_route
);
3632 * Announce routes from all AF tables to a peer.
3634 * This should ONLY be called when there is a need to refresh the
3635 * routes to the peer based on a policy change for this peer alone
3636 * or a route refresh request received from the peer.
3637 * The operation will result in splitting the peer from its existing
3638 * subgroups and putting it in new subgroups.
3640 void bgp_announce_route_all(struct peer
*peer
)
3645 FOREACH_AFI_SAFI (afi
, safi
)
3646 bgp_announce_route(peer
, afi
, safi
);
3649 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3650 struct bgp_table
*table
,
3651 struct prefix_rd
*prd
)
3654 struct bgp_node
*rn
;
3655 struct bgp_adj_in
*ain
;
3658 table
= peer
->bgp
->rib
[afi
][safi
];
3660 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3661 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3662 if (ain
->peer
!= peer
)
3665 struct bgp_info
*ri
= rn
->info
;
3666 uint32_t num_labels
= 0;
3667 mpls_label_t
*label_pnt
= NULL
;
3669 if (ri
&& ri
->extra
)
3670 num_labels
= ri
->extra
->num_labels
;
3672 label_pnt
= &ri
->extra
->label
[0];
3674 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3675 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3676 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3677 num_labels
, 1, NULL
);
3680 bgp_unlock_node(rn
);
3686 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3688 struct bgp_node
*rn
;
3689 struct bgp_table
*table
;
3691 if (peer
->status
!= Established
)
3694 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3695 && (safi
!= SAFI_EVPN
))
3696 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3698 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3699 rn
= bgp_route_next(rn
))
3700 if ((table
= rn
->info
) != NULL
) {
3701 struct prefix_rd prd
;
3702 prd
.family
= AF_UNSPEC
;
3704 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3706 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3712 struct bgp_clear_node_queue
{
3713 struct bgp_node
*rn
;
3716 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3718 struct bgp_clear_node_queue
*cnq
= data
;
3719 struct bgp_node
*rn
= cnq
->rn
;
3720 struct peer
*peer
= wq
->spec
.data
;
3721 struct bgp_info
*ri
;
3723 afi_t afi
= bgp_node_table(rn
)->afi
;
3724 safi_t safi
= bgp_node_table(rn
)->safi
;
3729 /* It is possible that we have multiple paths for a prefix from a peer
3730 * if that peer is using AddPath.
3732 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3733 if (ri
->peer
!= peer
)
3736 /* graceful restart STALE flag set. */
3737 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3738 && peer
->nsf
[afi
][safi
]
3739 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3740 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3741 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3743 /* If this is an EVPN route, process for
3745 if (safi
== SAFI_EVPN
)
3746 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3748 /* Handle withdraw for VRF route-leaking and L3VPN */
3749 if (SAFI_UNICAST
== safi
3750 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3751 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3752 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3755 if (SAFI_MPLS_VPN
== safi
&&
3756 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3757 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3760 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3766 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3768 struct bgp_clear_node_queue
*cnq
= data
;
3769 struct bgp_node
*rn
= cnq
->rn
;
3770 struct bgp_table
*table
= bgp_node_table(rn
);
3772 bgp_unlock_node(rn
);
3773 bgp_table_unlock(table
);
3774 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3777 static void bgp_clear_node_complete(struct work_queue
*wq
)
3779 struct peer
*peer
= wq
->spec
.data
;
3781 /* Tickle FSM to start moving again */
3782 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3784 peer_unlock(peer
); /* bgp_clear_route */
3787 static void bgp_clear_node_queue_init(struct peer
*peer
)
3789 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3791 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3792 #undef CLEAR_QUEUE_NAME_LEN
3794 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3796 zlog_err("%s: Failed to allocate work queue", __func__
);
3799 peer
->clear_node_queue
->spec
.hold
= 10;
3800 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3801 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3802 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3803 peer
->clear_node_queue
->spec
.max_retries
= 0;
3805 /* we only 'lock' this peer reference when the queue is actually active
3807 peer
->clear_node_queue
->spec
.data
= peer
;
3810 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3811 struct bgp_table
*table
)
3813 struct bgp_node
*rn
;
3814 int force
= bm
->process_main_queue
? 0 : 1;
3817 table
= peer
->bgp
->rib
[afi
][safi
];
3819 /* If still no table => afi/safi isn't configured at all or smth. */
3823 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3824 struct bgp_info
*ri
, *next
;
3825 struct bgp_adj_in
*ain
;
3826 struct bgp_adj_in
*ain_next
;
3828 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3829 * queued for every clearing peer, regardless of whether it is
3830 * relevant to the peer at hand.
3832 * Overview: There are 3 different indices which need to be
3833 * scrubbed, potentially, when a peer is removed:
3835 * 1 peer's routes visible via the RIB (ie accepted routes)
3836 * 2 peer's routes visible by the (optional) peer's adj-in index
3837 * 3 other routes visible by the peer's adj-out index
3839 * 3 there is no hurry in scrubbing, once the struct peer is
3840 * removed from bgp->peer, we could just GC such deleted peer's
3841 * adj-outs at our leisure.
3843 * 1 and 2 must be 'scrubbed' in some way, at least made
3844 * invisible via RIB index before peer session is allowed to be
3845 * brought back up. So one needs to know when such a 'search' is
3850 * - there'd be a single global queue or a single RIB walker
3851 * - rather than tracking which route_nodes still need to be
3852 * examined on a peer basis, we'd track which peers still
3855 * Given that our per-peer prefix-counts now should be reliable,
3856 * this may actually be achievable. It doesn't seem to be a huge
3857 * problem at this time,
3859 * It is possible that we have multiple paths for a prefix from
3861 * if that peer is using AddPath.
3865 ain_next
= ain
->next
;
3867 if (ain
->peer
== peer
) {
3868 bgp_adj_in_remove(rn
, ain
);
3869 bgp_unlock_node(rn
);
3875 for (ri
= rn
->info
; ri
; ri
= next
) {
3877 if (ri
->peer
!= peer
)
3881 bgp_info_reap(rn
, ri
);
3883 struct bgp_clear_node_queue
*cnq
;
3885 /* both unlocked in bgp_clear_node_queue_del */
3886 bgp_table_lock(bgp_node_table(rn
));
3889 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3890 sizeof(struct bgp_clear_node_queue
));
3892 work_queue_add(peer
->clear_node_queue
, cnq
);
3900 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3902 struct bgp_node
*rn
;
3903 struct bgp_table
*table
;
3905 if (peer
->clear_node_queue
== NULL
)
3906 bgp_clear_node_queue_init(peer
);
3908 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3909 * Idle until it receives a Clearing_Completed event. This protects
3910 * against peers which flap faster than we can we clear, which could
3913 * a) race with routes from the new session being installed before
3914 * clear_route_node visits the node (to delete the route of that
3916 * b) resource exhaustion, clear_route_node likely leads to an entry
3917 * on the process_main queue. Fast-flapping could cause that queue
3921 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3922 * the unlock will happen upon work-queue completion; other wise, the
3923 * unlock happens at the end of this function.
3925 if (!peer
->clear_node_queue
->thread
)
3928 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3929 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3931 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3932 rn
= bgp_route_next(rn
))
3933 if ((table
= rn
->info
) != NULL
)
3934 bgp_clear_route_table(peer
, afi
, safi
, table
);
3936 /* unlock if no nodes got added to the clear-node-queue. */
3937 if (!peer
->clear_node_queue
->thread
)
3941 void bgp_clear_route_all(struct peer
*peer
)
3946 FOREACH_AFI_SAFI (afi
, safi
)
3947 bgp_clear_route(peer
, afi
, safi
);
3950 rfapiProcessPeerDown(peer
);
3954 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3956 struct bgp_table
*table
;
3957 struct bgp_node
*rn
;
3958 struct bgp_adj_in
*ain
;
3959 struct bgp_adj_in
*ain_next
;
3961 table
= peer
->bgp
->rib
[afi
][safi
];
3963 /* It is possible that we have multiple paths for a prefix from a peer
3964 * if that peer is using AddPath.
3966 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3970 ain_next
= ain
->next
;
3972 if (ain
->peer
== peer
) {
3973 bgp_adj_in_remove(rn
, ain
);
3974 bgp_unlock_node(rn
);
3982 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3984 struct bgp_node
*rn
;
3985 struct bgp_info
*ri
;
3986 struct bgp_table
*table
;
3988 if (safi
== SAFI_MPLS_VPN
) {
3989 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3990 rn
= bgp_route_next(rn
)) {
3991 struct bgp_node
*rm
;
3992 struct bgp_info
*ri
;
3994 /* look for neighbor in tables */
3995 if ((table
= rn
->info
) == NULL
)
3998 for (rm
= bgp_table_top(table
); rm
;
3999 rm
= bgp_route_next(rm
))
4000 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
4001 if (ri
->peer
!= peer
)
4003 if (!CHECK_FLAG(ri
->flags
,
4007 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4012 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4013 rn
= bgp_route_next(rn
))
4014 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4015 if (ri
->peer
!= peer
)
4017 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4019 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4025 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4028 struct bgp_node
*rn
;
4029 struct bgp_info
*ri
;
4030 struct bgp_info
*next
;
4032 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4033 for (ri
= rn
->info
; ri
; ri
= next
) {
4035 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4036 && ri
->type
== ZEBRA_ROUTE_BGP
4037 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4038 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4039 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4041 if (bgp_fibupd_safi(safi
))
4042 bgp_zebra_withdraw(&rn
->p
, ri
,
4044 bgp_info_reap(rn
, ri
);
4049 /* Delete all kernel routes. */
4050 void bgp_cleanup_routes(struct bgp
*bgp
)
4053 struct bgp_node
*rn
;
4055 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4056 if (afi
== AFI_L2VPN
)
4058 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4061 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4063 if (afi
!= AFI_L2VPN
) {
4065 safi
= SAFI_MPLS_VPN
;
4066 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4067 rn
= bgp_route_next(rn
)) {
4069 bgp_cleanup_table(bgp
,
4070 (struct bgp_table
*)(rn
->info
),
4072 bgp_table_finish((struct bgp_table
**)&(
4075 bgp_unlock_node(rn
);
4079 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4080 rn
= bgp_route_next(rn
)) {
4082 bgp_cleanup_table(bgp
,
4083 (struct bgp_table
*)(rn
->info
),
4085 bgp_table_finish((struct bgp_table
**)&(
4088 bgp_unlock_node(rn
);
4093 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4094 rn
= bgp_route_next(rn
)) {
4096 bgp_cleanup_table(bgp
,
4097 (struct bgp_table
*)(rn
->info
),
4099 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4101 bgp_unlock_node(rn
);
4106 void bgp_reset(void)
4109 bgp_zclient_reset();
4110 access_list_reset();
4111 prefix_list_reset();
4114 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4116 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4117 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4118 PEER_CAP_ADDPATH_AF_TX_RCV
));
4121 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4123 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4124 struct bgp_nlri
*packet
)
4133 int addpath_encoded
;
4134 uint32_t addpath_id
;
4137 lim
= pnt
+ packet
->length
;
4139 safi
= packet
->safi
;
4141 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4143 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4144 syntactic validity. If the field is syntactically incorrect,
4145 then the Error Subcode is set to Invalid Network Field. */
4146 for (; pnt
< lim
; pnt
+= psize
) {
4147 /* Clear prefix structure. */
4148 memset(&p
, 0, sizeof(struct prefix
));
4150 if (addpath_encoded
) {
4152 /* When packet overflow occurs return immediately. */
4153 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4156 addpath_id
= ntohl(*((uint32_t *)pnt
));
4157 pnt
+= BGP_ADDPATH_ID_LEN
;
4160 /* Fetch prefix length. */
4161 p
.prefixlen
= *pnt
++;
4162 /* afi/safi validity already verified by caller,
4163 * bgp_update_receive */
4164 p
.family
= afi2family(afi
);
4166 /* Prefix length check. */
4167 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4169 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4170 peer
->host
, p
.prefixlen
, packet
->afi
);
4174 /* Packet size overflow check. */
4175 psize
= PSIZE(p
.prefixlen
);
4177 /* When packet overflow occur return immediately. */
4178 if (pnt
+ psize
> lim
) {
4180 "%s [Error] Update packet error (prefix length %d overflows packet)",
4181 peer
->host
, p
.prefixlen
);
4185 /* Defensive coding, double-check the psize fits in a struct
4187 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4189 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4190 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4194 /* Fetch prefix from NLRI packet. */
4195 memcpy(&p
.u
.prefix
, pnt
, psize
);
4197 /* Check address. */
4198 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4199 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4200 /* From RFC4271 Section 6.3:
4202 * If a prefix in the NLRI field is semantically
4204 * (e.g., an unexpected multicast IP address),
4206 * be logged locally, and the prefix SHOULD be
4210 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4211 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4216 /* Check address. */
4217 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4218 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4222 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4224 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4229 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4233 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4235 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4242 /* Normal process. */
4244 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4245 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4246 NULL
, NULL
, 0, 0, NULL
);
4248 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4249 safi
, ZEBRA_ROUTE_BGP
,
4250 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4253 /* Address family configuration mismatch or maximum-prefix count
4259 /* Packet length consistency check. */
4262 "%s [Error] Update packet error (prefix length mismatch with total length)",
4270 static struct bgp_static
*bgp_static_new(void)
4272 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4275 static void bgp_static_free(struct bgp_static
*bgp_static
)
4277 if (bgp_static
->rmap
.name
)
4278 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4279 if (bgp_static
->eth_s_id
)
4280 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4281 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4284 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4285 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4287 struct bgp_node
*rn
;
4288 struct bgp_info
*ri
;
4289 struct bgp_info
*new;
4290 struct bgp_info info
;
4292 struct attr
*attr_new
;
4295 int vnc_implicit_withdraw
= 0;
4302 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4304 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4306 attr
.nexthop
= bgp_static
->igpnexthop
;
4307 attr
.med
= bgp_static
->igpmetric
;
4308 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4310 if (bgp_static
->atomic
)
4311 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4313 /* Store label index, if required. */
4314 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4315 attr
.label_index
= bgp_static
->label_index
;
4316 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4319 /* Apply route-map. */
4320 if (bgp_static
->rmap
.name
) {
4321 struct attr attr_tmp
= attr
;
4322 info
.peer
= bgp
->peer_self
;
4323 info
.attr
= &attr_tmp
;
4325 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4327 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4329 bgp
->peer_self
->rmap_type
= 0;
4331 if (ret
== RMAP_DENYMATCH
) {
4332 /* Free uninterned attribute. */
4333 bgp_attr_flush(&attr_tmp
);
4335 /* Unintern original. */
4336 aspath_unintern(&attr
.aspath
);
4337 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4341 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4342 bgp_attr_add_gshut_community(&attr_tmp
);
4344 attr_new
= bgp_attr_intern(&attr_tmp
);
4347 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4348 bgp_attr_add_gshut_community(&attr
);
4350 attr_new
= bgp_attr_intern(&attr
);
4353 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4354 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4355 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4359 if (attrhash_cmp(ri
->attr
, attr_new
)
4360 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4361 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4362 bgp_unlock_node(rn
);
4363 bgp_attr_unintern(&attr_new
);
4364 aspath_unintern(&attr
.aspath
);
4367 /* The attribute is changed. */
4368 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4370 /* Rewrite BGP route information. */
4371 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4372 bgp_info_restore(rn
, ri
);
4374 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4376 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4377 && (safi
== SAFI_UNICAST
)) {
4378 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4380 * Implicit withdraw case.
4381 * We have to do this before ri is
4384 ++vnc_implicit_withdraw
;
4385 vnc_import_bgp_del_route(bgp
, p
, ri
);
4386 vnc_import_bgp_exterior_del_route(
4391 bgp_attr_unintern(&ri
->attr
);
4392 ri
->attr
= attr_new
;
4393 ri
->uptime
= bgp_clock();
4395 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4396 && (safi
== SAFI_UNICAST
)) {
4397 if (vnc_implicit_withdraw
) {
4398 vnc_import_bgp_add_route(bgp
, p
, ri
);
4399 vnc_import_bgp_exterior_add_route(
4405 /* Nexthop reachability check. */
4406 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4407 && (safi
== SAFI_UNICAST
4408 || safi
== SAFI_LABELED_UNICAST
)) {
4410 struct bgp
*bgp_nexthop
= bgp
;
4412 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4413 bgp_nexthop
= ri
->extra
->bgp_orig
;
4415 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4417 bgp_info_set_flag(rn
, ri
,
4420 if (BGP_DEBUG(nht
, NHT
)) {
4421 char buf1
[INET6_ADDRSTRLEN
];
4422 inet_ntop(p
->family
,
4426 "%s(%s): Route not in table, not advertising",
4427 __FUNCTION__
, buf1
);
4429 bgp_info_unset_flag(rn
, ri
,
4433 /* Delete the NHT structure if any, if we're
4435 * enabling/disabling import check. We
4436 * deregister the route
4437 * from NHT to avoid overloading NHT and the
4438 * process interaction
4440 bgp_unlink_nexthop(ri
);
4441 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4443 /* Process change. */
4444 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4445 bgp_process(bgp
, rn
, afi
, safi
);
4447 if (SAFI_UNICAST
== safi
4448 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4450 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4451 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4455 bgp_unlock_node(rn
);
4456 aspath_unintern(&attr
.aspath
);
4461 /* Make new BGP info. */
4462 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4464 /* Nexthop reachability check. */
4465 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4466 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4467 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4468 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4470 if (BGP_DEBUG(nht
, NHT
)) {
4471 char buf1
[INET6_ADDRSTRLEN
];
4472 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4475 "%s(%s): Route not in table, not advertising",
4476 __FUNCTION__
, buf1
);
4478 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4481 /* Delete the NHT structure if any, if we're toggling between
4482 * enabling/disabling import check. We deregister the route
4483 * from NHT to avoid overloading NHT and the process interaction
4485 bgp_unlink_nexthop(new);
4487 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4490 /* Aggregate address increment. */
4491 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4493 /* Register new BGP information. */
4494 bgp_info_add(rn
, new);
4496 /* route_node_get lock */
4497 bgp_unlock_node(rn
);
4499 /* Process change. */
4500 bgp_process(bgp
, rn
, afi
, safi
);
4502 if (SAFI_UNICAST
== safi
4503 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4504 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4505 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4508 /* Unintern original. */
4509 aspath_unintern(&attr
.aspath
);
4512 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4515 struct bgp_node
*rn
;
4516 struct bgp_info
*ri
;
4518 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4520 /* Check selected route and self inserted route. */
4521 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4522 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4523 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4526 /* Withdraw static BGP route from routing table. */
4528 if (SAFI_UNICAST
== safi
4529 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4530 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4531 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4533 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4534 bgp_unlink_nexthop(ri
);
4535 bgp_info_delete(rn
, ri
);
4536 bgp_process(bgp
, rn
, afi
, safi
);
4539 /* Unlock bgp_node_lookup. */
4540 bgp_unlock_node(rn
);
4544 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4546 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4547 afi_t afi
, safi_t safi
,
4548 struct prefix_rd
*prd
)
4550 struct bgp_node
*rn
;
4551 struct bgp_info
*ri
;
4553 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4555 /* Check selected route and self inserted route. */
4556 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4557 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4558 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4561 /* Withdraw static BGP route from routing table. */
4564 rfapiProcessWithdraw(
4565 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4566 1); /* Kill, since it is an administrative change */
4568 if (SAFI_MPLS_VPN
== safi
4569 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4570 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4572 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4573 bgp_info_delete(rn
, ri
);
4574 bgp_process(bgp
, rn
, afi
, safi
);
4577 /* Unlock bgp_node_lookup. */
4578 bgp_unlock_node(rn
);
4581 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4582 struct bgp_static
*bgp_static
, afi_t afi
,
4585 struct bgp_node
*rn
;
4586 struct bgp_info
*new;
4587 struct attr
*attr_new
;
4588 struct attr attr
= {0};
4589 struct bgp_info
*ri
;
4591 mpls_label_t label
= 0;
4593 uint32_t num_labels
= 0;
4598 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4600 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4603 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4605 attr
.nexthop
= bgp_static
->igpnexthop
;
4606 attr
.med
= bgp_static
->igpmetric
;
4607 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4609 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4610 || (safi
== SAFI_ENCAP
)) {
4611 if (afi
== AFI_IP
) {
4612 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4613 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4616 if (afi
== AFI_L2VPN
) {
4617 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4619 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4620 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4621 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4622 sizeof(struct in6_addr
));
4623 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4624 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4625 struct bgp_encap_type_vxlan bet
;
4626 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4627 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4628 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4630 if (bgp_static
->router_mac
) {
4631 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4634 /* Apply route-map. */
4635 if (bgp_static
->rmap
.name
) {
4636 struct attr attr_tmp
= attr
;
4637 struct bgp_info info
;
4640 info
.peer
= bgp
->peer_self
;
4641 info
.attr
= &attr_tmp
;
4643 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4645 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4647 bgp
->peer_self
->rmap_type
= 0;
4649 if (ret
== RMAP_DENYMATCH
) {
4650 /* Free uninterned attribute. */
4651 bgp_attr_flush(&attr_tmp
);
4653 /* Unintern original. */
4654 aspath_unintern(&attr
.aspath
);
4655 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4660 attr_new
= bgp_attr_intern(&attr_tmp
);
4662 attr_new
= bgp_attr_intern(&attr
);
4665 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4666 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4667 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4672 memset(&add
, 0, sizeof(union gw_addr
));
4673 if (attrhash_cmp(ri
->attr
, attr_new
)
4674 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4675 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4676 bgp_unlock_node(rn
);
4677 bgp_attr_unintern(&attr_new
);
4678 aspath_unintern(&attr
.aspath
);
4681 /* The attribute is changed. */
4682 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4684 /* Rewrite BGP route information. */
4685 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4686 bgp_info_restore(rn
, ri
);
4688 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4689 bgp_attr_unintern(&ri
->attr
);
4690 ri
->attr
= attr_new
;
4691 ri
->uptime
= bgp_clock();
4694 label
= decode_label(&ri
->extra
->label
[0]);
4697 /* Process change. */
4698 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
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
, ri
);
4706 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4707 ri
->attr
, afi
, safi
, ri
->type
,
4708 ri
->sub_type
, &label
);
4710 bgp_unlock_node(rn
);
4711 aspath_unintern(&attr
.aspath
);
4717 /* Make new BGP info. */
4718 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4720 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4721 new->extra
= bgp_info_extra_new();
4723 new->extra
->label
[0] = bgp_static
->label
;
4724 new->extra
->num_labels
= num_labels
;
4727 label
= decode_label(&bgp_static
->label
);
4730 /* Aggregate address increment. */
4731 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4733 /* Register new BGP information. */
4734 bgp_info_add(rn
, new);
4735 /* route_node_get lock */
4736 bgp_unlock_node(rn
);
4738 /* Process change. */
4739 bgp_process(bgp
, rn
, afi
, safi
);
4741 if (SAFI_MPLS_VPN
== safi
4742 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4743 vpn_leak_to_vrf_update(bgp
, new);
4746 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4747 safi
, new->type
, new->sub_type
, &label
);
4750 /* Unintern original. */
4751 aspath_unintern(&attr
.aspath
);
4754 /* Configure static BGP network. When user don't run zebra, static
4755 route should be installed as valid. */
4756 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4757 const char *ip_str
, afi_t afi
, safi_t safi
,
4758 const char *rmap
, int backdoor
, uint32_t label_index
)
4760 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4763 struct bgp_static
*bgp_static
;
4764 struct bgp_node
*rn
;
4765 uint8_t need_update
= 0;
4767 /* Convert IP prefix string to struct prefix. */
4768 ret
= str2prefix(ip_str
, &p
);
4770 vty_out(vty
, "%% Malformed prefix\n");
4771 return CMD_WARNING_CONFIG_FAILED
;
4773 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4774 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4775 return CMD_WARNING_CONFIG_FAILED
;
4782 /* Set BGP static route configuration. */
4783 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4786 vty_out(vty
, "%% Can't find static route specified\n");
4787 return CMD_WARNING_CONFIG_FAILED
;
4790 bgp_static
= rn
->info
;
4792 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4793 && (label_index
!= bgp_static
->label_index
)) {
4795 "%% label-index doesn't match static route\n");
4796 return CMD_WARNING_CONFIG_FAILED
;
4799 if ((rmap
&& bgp_static
->rmap
.name
)
4800 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4802 "%% route-map name doesn't match static route\n");
4803 return CMD_WARNING_CONFIG_FAILED
;
4806 /* Update BGP RIB. */
4807 if (!bgp_static
->backdoor
)
4808 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4810 /* Clear configuration. */
4811 bgp_static_free(bgp_static
);
4813 bgp_unlock_node(rn
);
4814 bgp_unlock_node(rn
);
4817 /* Set BGP static route configuration. */
4818 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4821 /* Configuration change. */
4822 bgp_static
= rn
->info
;
4824 /* Label index cannot be changed. */
4825 if (bgp_static
->label_index
!= label_index
) {
4826 vty_out(vty
, "%% cannot change label-index\n");
4827 return CMD_WARNING_CONFIG_FAILED
;
4830 /* Check previous routes are installed into BGP. */
4831 if (bgp_static
->valid
4832 && bgp_static
->backdoor
!= backdoor
)
4835 bgp_static
->backdoor
= backdoor
;
4838 if (bgp_static
->rmap
.name
)
4839 XFREE(MTYPE_ROUTE_MAP_NAME
,
4840 bgp_static
->rmap
.name
);
4841 bgp_static
->rmap
.name
=
4842 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4843 bgp_static
->rmap
.map
=
4844 route_map_lookup_by_name(rmap
);
4846 if (bgp_static
->rmap
.name
)
4847 XFREE(MTYPE_ROUTE_MAP_NAME
,
4848 bgp_static
->rmap
.name
);
4849 bgp_static
->rmap
.name
= NULL
;
4850 bgp_static
->rmap
.map
= NULL
;
4851 bgp_static
->valid
= 0;
4853 bgp_unlock_node(rn
);
4855 /* New configuration. */
4856 bgp_static
= bgp_static_new();
4857 bgp_static
->backdoor
= backdoor
;
4858 bgp_static
->valid
= 0;
4859 bgp_static
->igpmetric
= 0;
4860 bgp_static
->igpnexthop
.s_addr
= 0;
4861 bgp_static
->label_index
= label_index
;
4864 if (bgp_static
->rmap
.name
)
4865 XFREE(MTYPE_ROUTE_MAP_NAME
,
4866 bgp_static
->rmap
.name
);
4867 bgp_static
->rmap
.name
=
4868 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4869 bgp_static
->rmap
.map
=
4870 route_map_lookup_by_name(rmap
);
4872 rn
->info
= bgp_static
;
4875 bgp_static
->valid
= 1;
4877 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4879 if (!bgp_static
->backdoor
)
4880 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4886 void bgp_static_add(struct bgp
*bgp
)
4890 struct bgp_node
*rn
;
4891 struct bgp_node
*rm
;
4892 struct bgp_table
*table
;
4893 struct bgp_static
*bgp_static
;
4895 FOREACH_AFI_SAFI (afi
, safi
)
4896 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4897 rn
= bgp_route_next(rn
)) {
4898 if (rn
->info
== NULL
)
4901 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4902 || (safi
== SAFI_EVPN
)) {
4905 for (rm
= bgp_table_top(table
); rm
;
4906 rm
= bgp_route_next(rm
)) {
4907 bgp_static
= rm
->info
;
4908 bgp_static_update_safi(bgp
, &rm
->p
,
4913 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4919 /* Called from bgp_delete(). Delete all static routes from the BGP
4921 void bgp_static_delete(struct bgp
*bgp
)
4925 struct bgp_node
*rn
;
4926 struct bgp_node
*rm
;
4927 struct bgp_table
*table
;
4928 struct bgp_static
*bgp_static
;
4930 FOREACH_AFI_SAFI (afi
, safi
)
4931 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4932 rn
= bgp_route_next(rn
)) {
4933 if (rn
->info
== NULL
)
4936 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4937 || (safi
== SAFI_EVPN
)) {
4940 for (rm
= bgp_table_top(table
); rm
;
4941 rm
= bgp_route_next(rm
)) {
4942 bgp_static
= rm
->info
;
4943 bgp_static_withdraw_safi(
4944 bgp
, &rm
->p
, AFI_IP
, safi
,
4945 (struct prefix_rd
*)&rn
->p
);
4946 bgp_static_free(bgp_static
);
4948 bgp_unlock_node(rn
);
4951 bgp_static
= rn
->info
;
4952 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4953 bgp_static_free(bgp_static
);
4955 bgp_unlock_node(rn
);
4960 void bgp_static_redo_import_check(struct bgp
*bgp
)
4964 struct bgp_node
*rn
;
4965 struct bgp_node
*rm
;
4966 struct bgp_table
*table
;
4967 struct bgp_static
*bgp_static
;
4969 /* Use this flag to force reprocessing of the route */
4970 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4971 FOREACH_AFI_SAFI (afi
, safi
) {
4972 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4973 rn
= bgp_route_next(rn
)) {
4974 if (rn
->info
== NULL
)
4977 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4978 || (safi
== SAFI_EVPN
)) {
4981 for (rm
= bgp_table_top(table
); rm
;
4982 rm
= bgp_route_next(rm
)) {
4983 bgp_static
= rm
->info
;
4984 bgp_static_update_safi(bgp
, &rm
->p
,
4989 bgp_static
= rn
->info
;
4990 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4995 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4998 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5001 struct bgp_table
*table
;
5002 struct bgp_node
*rn
;
5003 struct bgp_info
*ri
;
5005 table
= bgp
->rib
[afi
][safi
];
5006 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5007 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5008 if (ri
->peer
== bgp
->peer_self
5009 && ((ri
->type
== ZEBRA_ROUTE_BGP
5010 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5011 || (ri
->type
!= ZEBRA_ROUTE_BGP
5013 == BGP_ROUTE_REDISTRIBUTE
))) {
5014 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5016 bgp_unlink_nexthop(ri
);
5017 bgp_info_delete(rn
, ri
);
5018 bgp_process(bgp
, rn
, afi
, safi
);
5025 * Purge all networks and redistributed routes from routing table.
5026 * Invoked upon the instance going down.
5028 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5033 FOREACH_AFI_SAFI (afi
, safi
)
5034 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5039 * Currently this is used to set static routes for VPN and ENCAP.
5040 * I think it can probably be factored with bgp_static_set.
5042 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5043 const char *ip_str
, const char *rd_str
,
5044 const char *label_str
, const char *rmap_str
,
5045 int evpn_type
, const char *esi
, const char *gwip
,
5046 const char *ethtag
, const char *routermac
)
5048 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5051 struct prefix_rd prd
;
5052 struct bgp_node
*prn
;
5053 struct bgp_node
*rn
;
5054 struct bgp_table
*table
;
5055 struct bgp_static
*bgp_static
;
5056 mpls_label_t label
= MPLS_INVALID_LABEL
;
5057 struct prefix gw_ip
;
5059 /* validate ip prefix */
5060 ret
= str2prefix(ip_str
, &p
);
5062 vty_out(vty
, "%% Malformed prefix\n");
5063 return CMD_WARNING_CONFIG_FAILED
;
5066 if ((afi
== AFI_L2VPN
)
5067 && (bgp_build_evpn_prefix(evpn_type
,
5068 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5069 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5070 return CMD_WARNING_CONFIG_FAILED
;
5073 ret
= str2prefix_rd(rd_str
, &prd
);
5075 vty_out(vty
, "%% Malformed rd\n");
5076 return CMD_WARNING_CONFIG_FAILED
;
5080 unsigned long label_val
;
5081 label_val
= strtoul(label_str
, NULL
, 10);
5082 encode_label(label_val
, &label
);
5085 if (safi
== SAFI_EVPN
) {
5086 if (esi
&& str2esi(esi
, NULL
) == 0) {
5087 vty_out(vty
, "%% Malformed ESI\n");
5088 return CMD_WARNING_CONFIG_FAILED
;
5090 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5091 vty_out(vty
, "%% Malformed Router MAC\n");
5092 return CMD_WARNING_CONFIG_FAILED
;
5095 memset(&gw_ip
, 0, sizeof(struct prefix
));
5096 ret
= str2prefix(gwip
, &gw_ip
);
5098 vty_out(vty
, "%% Malformed GatewayIp\n");
5099 return CMD_WARNING_CONFIG_FAILED
;
5101 if ((gw_ip
.family
== AF_INET
5102 && is_evpn_prefix_ipaddr_v6(
5103 (struct prefix_evpn
*)&p
))
5104 || (gw_ip
.family
== AF_INET6
5105 && is_evpn_prefix_ipaddr_v4(
5106 (struct prefix_evpn
*)&p
))) {
5108 "%% GatewayIp family differs with IP prefix\n");
5109 return CMD_WARNING_CONFIG_FAILED
;
5113 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5114 if (prn
->info
== NULL
)
5115 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5117 bgp_unlock_node(prn
);
5120 rn
= bgp_node_get(table
, &p
);
5123 vty_out(vty
, "%% Same network configuration exists\n");
5124 bgp_unlock_node(rn
);
5126 /* New configuration. */
5127 bgp_static
= bgp_static_new();
5128 bgp_static
->backdoor
= 0;
5129 bgp_static
->valid
= 0;
5130 bgp_static
->igpmetric
= 0;
5131 bgp_static
->igpnexthop
.s_addr
= 0;
5132 bgp_static
->label
= label
;
5133 bgp_static
->prd
= prd
;
5136 if (bgp_static
->rmap
.name
)
5137 XFREE(MTYPE_ROUTE_MAP_NAME
,
5138 bgp_static
->rmap
.name
);
5139 bgp_static
->rmap
.name
=
5140 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5141 bgp_static
->rmap
.map
=
5142 route_map_lookup_by_name(rmap_str
);
5145 if (safi
== SAFI_EVPN
) {
5147 bgp_static
->eth_s_id
=
5149 sizeof(struct eth_segment_id
));
5150 str2esi(esi
, bgp_static
->eth_s_id
);
5153 bgp_static
->router_mac
=
5154 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5155 prefix_str2mac(routermac
,
5156 bgp_static
->router_mac
);
5159 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5161 rn
->info
= bgp_static
;
5163 bgp_static
->valid
= 1;
5164 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5170 /* Configure static BGP network. */
5171 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5172 const char *ip_str
, const char *rd_str
,
5173 const char *label_str
, int evpn_type
, const char *esi
,
5174 const char *gwip
, const char *ethtag
)
5176 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5179 struct prefix_rd prd
;
5180 struct bgp_node
*prn
;
5181 struct bgp_node
*rn
;
5182 struct bgp_table
*table
;
5183 struct bgp_static
*bgp_static
;
5184 mpls_label_t label
= MPLS_INVALID_LABEL
;
5186 /* Convert IP prefix string to struct prefix. */
5187 ret
= str2prefix(ip_str
, &p
);
5189 vty_out(vty
, "%% Malformed prefix\n");
5190 return CMD_WARNING_CONFIG_FAILED
;
5193 if ((afi
== AFI_L2VPN
)
5194 && (bgp_build_evpn_prefix(evpn_type
,
5195 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5196 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5197 return CMD_WARNING_CONFIG_FAILED
;
5199 ret
= str2prefix_rd(rd_str
, &prd
);
5201 vty_out(vty
, "%% Malformed rd\n");
5202 return CMD_WARNING_CONFIG_FAILED
;
5206 unsigned long label_val
;
5207 label_val
= strtoul(label_str
, NULL
, 10);
5208 encode_label(label_val
, &label
);
5211 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5212 if (prn
->info
== NULL
)
5213 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5215 bgp_unlock_node(prn
);
5218 rn
= bgp_node_lookup(table
, &p
);
5221 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5223 bgp_static
= rn
->info
;
5224 bgp_static_free(bgp_static
);
5226 bgp_unlock_node(rn
);
5227 bgp_unlock_node(rn
);
5229 vty_out(vty
, "%% Can't find the route\n");
5234 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5235 const char *rmap_name
)
5237 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5238 struct bgp_rmap
*rmap
;
5240 rmap
= &bgp
->table_map
[afi
][safi
];
5243 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5244 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5245 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5248 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5253 if (bgp_fibupd_safi(safi
))
5254 bgp_zebra_announce_table(bgp
, afi
, safi
);
5259 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5260 const char *rmap_name
)
5262 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5263 struct bgp_rmap
*rmap
;
5265 rmap
= &bgp
->table_map
[afi
][safi
];
5267 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5271 if (bgp_fibupd_safi(safi
))
5272 bgp_zebra_announce_table(bgp
, afi
, safi
);
5277 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5280 if (bgp
->table_map
[afi
][safi
].name
) {
5281 vty_out(vty
, " table-map %s\n",
5282 bgp
->table_map
[afi
][safi
].name
);
5286 DEFUN (bgp_table_map
,
5289 "BGP table to RIB route download filter\n"
5290 "Name of the route map\n")
5293 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5294 argv
[idx_word
]->arg
);
5296 DEFUN (no_bgp_table_map
,
5297 no_bgp_table_map_cmd
,
5298 "no table-map WORD",
5300 "BGP table to RIB route download filter\n"
5301 "Name of the route map\n")
5304 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5305 argv
[idx_word
]->arg
);
5311 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5312 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5313 backdoor$backdoor}]",
5315 "Specify a network to announce via BGP\n"
5320 "Route-map to modify the attributes\n"
5321 "Name of the route map\n"
5322 "Label index to associate with the prefix\n"
5323 "Label index value\n"
5324 "Specify a BGP backdoor route\n")
5326 char addr_prefix_str
[BUFSIZ
];
5331 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5334 vty_out(vty
, "%% Inconsistent address and mask\n");
5335 return CMD_WARNING_CONFIG_FAILED
;
5339 return bgp_static_set(
5340 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5341 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5342 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5345 DEFPY(ipv6_bgp_network
,
5346 ipv6_bgp_network_cmd
,
5347 "[no] network X:X::X:X/M$prefix \
5348 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5350 "Specify a network to announce via BGP\n"
5352 "Route-map to modify the attributes\n"
5353 "Name of the route map\n"
5354 "Label index to associate with the prefix\n"
5355 "Label index value\n")
5357 return bgp_static_set(
5358 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5359 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5362 /* Aggreagete address:
5364 advertise-map Set condition to advertise attribute
5365 as-set Generate AS set path information
5366 attribute-map Set attributes of aggregate
5367 route-map Set parameters of aggregate
5368 summary-only Filter more specific routes from updates
5369 suppress-map Conditionally filter more specific routes from updates
5372 struct bgp_aggregate
{
5373 /* Summary-only flag. */
5374 uint8_t summary_only
;
5376 /* AS set generation. */
5379 /* Route-map for aggregated route. */
5380 struct route_map
*map
;
5382 /* Suppress-count. */
5383 unsigned long count
;
5385 /* SAFI configuration. */
5389 static struct bgp_aggregate
*bgp_aggregate_new(void)
5391 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5394 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5396 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5399 /* Update an aggregate as routes are added/removed from the BGP table */
5400 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5401 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5402 struct bgp_info
*del
,
5403 struct bgp_aggregate
*aggregate
)
5405 struct bgp_table
*table
;
5406 struct bgp_node
*top
;
5407 struct bgp_node
*rn
;
5409 struct aspath
*aspath
= NULL
;
5410 struct aspath
*asmerge
= NULL
;
5411 struct community
*community
= NULL
;
5412 struct community
*commerge
= NULL
;
5413 #if defined(AGGREGATE_NEXTHOP_CHECK)
5414 struct in_addr nexthop
;
5417 struct bgp_info
*ri
;
5418 struct bgp_info
*new;
5420 unsigned long match
= 0;
5421 uint8_t atomic_aggregate
= 0;
5423 /* Record adding route's nexthop and med. */
5425 #if defined(AGGREGATE_NEXTHOP_CHECK)
5426 nexthop
= rinew
->attr
->nexthop
;
5427 med
= rinew
->attr
->med
;
5431 /* ORIGIN attribute: If at least one route among routes that are
5432 aggregated has ORIGIN with the value INCOMPLETE, then the
5433 aggregated route must have the ORIGIN attribute with the value
5434 INCOMPLETE. Otherwise, if at least one route among routes that
5435 are aggregated has ORIGIN with the value EGP, then the aggregated
5436 route must have the origin attribute with the value EGP. In all
5437 other case the value of the ORIGIN attribute of the aggregated
5438 route is INTERNAL. */
5439 origin
= BGP_ORIGIN_IGP
;
5441 table
= bgp
->rib
[afi
][safi
];
5443 top
= bgp_node_get(table
, p
);
5444 for (rn
= bgp_node_get(table
, p
); rn
;
5445 rn
= bgp_route_next_until(rn
, top
))
5446 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5449 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5450 if (BGP_INFO_HOLDDOWN(ri
))
5453 if (del
&& ri
== del
)
5456 if (!rinew
&& first
) {
5457 #if defined(AGGREGATE_NEXTHOP_CHECK)
5458 nexthop
= ri
->attr
->nexthop
;
5459 med
= ri
->attr
->med
;
5464 #ifdef AGGREGATE_NEXTHOP_CHECK
5465 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5467 || ri
->attr
->med
!= med
) {
5469 aspath_free(aspath
);
5471 community_free(community
);
5472 bgp_unlock_node(rn
);
5473 bgp_unlock_node(top
);
5476 #endif /* AGGREGATE_NEXTHOP_CHECK */
5479 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5480 atomic_aggregate
= 1;
5482 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5483 if (aggregate
->summary_only
) {
5484 (bgp_info_extra_get(ri
))
5488 BGP_INFO_ATTR_CHANGED
);
5494 if (origin
< ri
->attr
->origin
)
5495 origin
= ri
->attr
->origin
;
5497 if (aggregate
->as_set
) {
5499 asmerge
= aspath_aggregate(
5502 aspath_free(aspath
);
5505 aspath
= aspath_dup(
5508 if (ri
->attr
->community
) {
5510 commerge
= community_merge(
5512 ri
->attr
->community
);
5513 community
= community_uniq_sort(
5518 community
= community_dup(
5519 ri
->attr
->community
);
5525 bgp_process(bgp
, rn
, afi
, safi
);
5527 bgp_unlock_node(top
);
5532 if (aggregate
->summary_only
)
5533 (bgp_info_extra_get(rinew
))->suppress
++;
5535 if (origin
< rinew
->attr
->origin
)
5536 origin
= rinew
->attr
->origin
;
5538 if (aggregate
->as_set
) {
5540 asmerge
= aspath_aggregate(aspath
,
5541 rinew
->attr
->aspath
);
5542 aspath_free(aspath
);
5545 aspath
= aspath_dup(rinew
->attr
->aspath
);
5547 if (rinew
->attr
->community
) {
5549 commerge
= community_merge(
5551 rinew
->attr
->community
);
5553 community_uniq_sort(commerge
);
5554 community_free(commerge
);
5556 community
= community_dup(
5557 rinew
->attr
->community
);
5562 if (aggregate
->count
> 0) {
5563 rn
= bgp_node_get(table
, p
);
5565 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5566 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5567 community
, aggregate
->as_set
,
5570 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5572 bgp_info_add(rn
, new);
5573 bgp_unlock_node(rn
);
5574 bgp_process(bgp
, rn
, afi
, safi
);
5577 aspath_free(aspath
);
5579 community_free(community
);
5583 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5584 struct bgp_aggregate
*);
5586 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5587 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5589 struct bgp_node
*child
;
5590 struct bgp_node
*rn
;
5591 struct bgp_aggregate
*aggregate
;
5592 struct bgp_table
*table
;
5594 /* MPLS-VPN aggregation is not yet supported. */
5595 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5596 || (safi
== SAFI_EVPN
)
5597 || (safi
== SAFI_FLOWSPEC
))
5600 table
= bgp
->aggregate
[afi
][safi
];
5602 /* No aggregates configured. */
5603 if (bgp_table_top_nolock(table
) == NULL
)
5606 if (p
->prefixlen
== 0)
5609 if (BGP_INFO_HOLDDOWN(ri
))
5612 child
= bgp_node_get(table
, p
);
5614 /* Aggregate address configuration check. */
5615 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5616 if ((aggregate
= rn
->info
) != NULL
5617 && rn
->p
.prefixlen
< p
->prefixlen
) {
5618 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5619 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5622 bgp_unlock_node(child
);
5625 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5626 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5628 struct bgp_node
*child
;
5629 struct bgp_node
*rn
;
5630 struct bgp_aggregate
*aggregate
;
5631 struct bgp_table
*table
;
5633 /* MPLS-VPN aggregation is not yet supported. */
5634 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5635 || (safi
== SAFI_EVPN
)
5636 || (safi
== SAFI_FLOWSPEC
))
5639 table
= bgp
->aggregate
[afi
][safi
];
5641 /* No aggregates configured. */
5642 if (bgp_table_top_nolock(table
) == NULL
)
5645 if (p
->prefixlen
== 0)
5648 child
= bgp_node_get(table
, p
);
5650 /* Aggregate address configuration check. */
5651 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5652 if ((aggregate
= rn
->info
) != NULL
5653 && rn
->p
.prefixlen
< p
->prefixlen
) {
5654 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5655 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5658 bgp_unlock_node(child
);
5661 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5662 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5663 safi_t safi
, struct bgp_aggregate
*aggregate
)
5665 struct bgp_table
*table
;
5666 struct bgp_node
*top
;
5667 struct bgp_node
*rn
;
5668 struct bgp_info
*new;
5669 struct bgp_info
*ri
;
5670 unsigned long match
;
5671 uint8_t origin
= BGP_ORIGIN_IGP
;
5672 struct aspath
*aspath
= NULL
;
5673 struct aspath
*asmerge
= NULL
;
5674 struct community
*community
= NULL
;
5675 struct community
*commerge
= NULL
;
5676 uint8_t atomic_aggregate
= 0;
5678 table
= bgp
->rib
[afi
][safi
];
5681 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5683 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5686 /* If routes exists below this node, generate aggregate routes. */
5687 top
= bgp_node_get(table
, p
);
5688 for (rn
= bgp_node_get(table
, p
); rn
;
5689 rn
= bgp_route_next_until(rn
, top
)) {
5690 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5695 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5696 if (BGP_INFO_HOLDDOWN(ri
))
5700 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5701 atomic_aggregate
= 1;
5703 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5706 /* summary-only aggregate route suppress
5707 * aggregated route announcement. */
5708 if (aggregate
->summary_only
) {
5709 (bgp_info_extra_get(ri
))->suppress
++;
5710 bgp_info_set_flag(rn
, ri
,
5711 BGP_INFO_ATTR_CHANGED
);
5715 /* If at least one route among routes that are
5716 * aggregated has ORIGIN with the value INCOMPLETE,
5717 * then the aggregated route MUST have the ORIGIN
5718 * attribute with the value INCOMPLETE. Otherwise, if
5719 * at least one route among routes that are aggregated
5720 * has ORIGIN with the value EGP, then the aggregated
5721 * route MUST have the ORIGIN attribute with the value
5724 if (origin
< ri
->attr
->origin
)
5725 origin
= ri
->attr
->origin
;
5727 /* as-set aggregate route generate origin, as path,
5728 * community aggregation. */
5729 if (aggregate
->as_set
) {
5731 asmerge
= aspath_aggregate(
5732 aspath
, ri
->attr
->aspath
);
5733 aspath_free(aspath
);
5736 aspath
= aspath_dup(ri
->attr
->aspath
);
5738 if (ri
->attr
->community
) {
5740 commerge
= community_merge(
5742 ri
->attr
->community
);
5743 community
= community_uniq_sort(
5745 community_free(commerge
);
5747 community
= community_dup(
5748 ri
->attr
->community
);
5754 /* If this node is suppressed, process the change. */
5756 bgp_process(bgp
, rn
, afi
, safi
);
5758 bgp_unlock_node(top
);
5760 /* Add aggregate route to BGP table. */
5761 if (aggregate
->count
) {
5762 rn
= bgp_node_get(table
, p
);
5764 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5765 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5766 community
, aggregate
->as_set
,
5769 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5771 bgp_info_add(rn
, new);
5772 bgp_unlock_node(rn
);
5774 /* Process change. */
5775 bgp_process(bgp
, rn
, afi
, safi
);
5778 aspath_free(aspath
);
5780 community_free(community
);
5784 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5785 safi_t safi
, struct bgp_aggregate
*aggregate
)
5787 struct bgp_table
*table
;
5788 struct bgp_node
*top
;
5789 struct bgp_node
*rn
;
5790 struct bgp_info
*ri
;
5791 unsigned long match
;
5793 table
= bgp
->rib
[afi
][safi
];
5795 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5797 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5800 /* If routes exists below this node, generate aggregate routes. */
5801 top
= bgp_node_get(table
, p
);
5802 for (rn
= bgp_node_get(table
, p
); rn
;
5803 rn
= bgp_route_next_until(rn
, top
)) {
5804 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5808 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5809 if (BGP_INFO_HOLDDOWN(ri
))
5812 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5815 if (aggregate
->summary_only
&& ri
->extra
) {
5816 ri
->extra
->suppress
--;
5818 if (ri
->extra
->suppress
== 0) {
5820 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5827 /* If this node was suppressed, process the change. */
5829 bgp_process(bgp
, rn
, afi
, safi
);
5831 bgp_unlock_node(top
);
5833 /* Delete aggregate route from BGP table. */
5834 rn
= bgp_node_get(table
, p
);
5836 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5837 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5838 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5841 /* Withdraw static BGP route from routing table. */
5843 bgp_info_delete(rn
, ri
);
5844 bgp_process(bgp
, rn
, afi
, safi
);
5847 /* Unlock bgp_node_lookup. */
5848 bgp_unlock_node(rn
);
5851 /* Aggregate route attribute. */
5852 #define AGGREGATE_SUMMARY_ONLY 1
5853 #define AGGREGATE_AS_SET 1
5855 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5856 afi_t afi
, safi_t safi
)
5858 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5861 struct bgp_node
*rn
;
5862 struct bgp_aggregate
*aggregate
;
5864 if (safi
== SAFI_FLOWSPEC
)
5865 return CMD_WARNING_CONFIG_FAILED
;
5867 /* Convert string to prefix structure. */
5868 ret
= str2prefix(prefix_str
, &p
);
5870 vty_out(vty
, "Malformed prefix\n");
5871 return CMD_WARNING_CONFIG_FAILED
;
5875 /* Old configuration check. */
5876 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5879 "%% There is no aggregate-address configuration.\n");
5880 return CMD_WARNING_CONFIG_FAILED
;
5883 aggregate
= rn
->info
;
5884 if (aggregate
->safi
== SAFI_UNICAST
)
5885 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5886 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5887 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5889 if (aggregate
->safi
== SAFI_MULTICAST
)
5890 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5892 /* Unlock aggregate address configuration. */
5894 bgp_aggregate_free(aggregate
);
5895 bgp_unlock_node(rn
);
5896 bgp_unlock_node(rn
);
5901 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5902 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5904 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5907 struct bgp_node
*rn
;
5908 struct bgp_aggregate
*aggregate
;
5910 if (safi
== SAFI_FLOWSPEC
)
5911 return CMD_WARNING_CONFIG_FAILED
;
5913 /* Convert string to prefix structure. */
5914 ret
= str2prefix(prefix_str
, &p
);
5916 vty_out(vty
, "Malformed prefix\n");
5917 return CMD_WARNING_CONFIG_FAILED
;
5921 /* Old configuration check. */
5922 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5925 vty_out(vty
, "There is already same aggregate network.\n");
5926 /* try to remove the old entry */
5927 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5929 vty_out(vty
, "Error deleting aggregate.\n");
5930 bgp_unlock_node(rn
);
5931 return CMD_WARNING_CONFIG_FAILED
;
5935 /* Make aggregate address structure. */
5936 aggregate
= bgp_aggregate_new();
5937 aggregate
->summary_only
= summary_only
;
5938 aggregate
->as_set
= as_set
;
5939 aggregate
->safi
= safi
;
5940 rn
->info
= aggregate
;
5942 /* Aggregate address insert into BGP routing table. */
5943 if (safi
== SAFI_UNICAST
)
5944 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5945 if (safi
== SAFI_LABELED_UNICAST
)
5946 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5948 if (safi
== SAFI_MULTICAST
)
5949 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5954 DEFUN (aggregate_address
,
5955 aggregate_address_cmd
,
5956 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5957 "Configure BGP aggregate entries\n"
5958 "Aggregate prefix\n"
5959 "Generate AS set path information\n"
5960 "Filter more specific routes from updates\n"
5961 "Filter more specific routes from updates\n"
5962 "Generate AS set path information\n")
5965 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5966 char *prefix
= argv
[idx
]->arg
;
5968 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5970 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5971 ? AGGREGATE_SUMMARY_ONLY
5974 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5975 summary_only
, as_set
);
5978 DEFUN (aggregate_address_mask
,
5979 aggregate_address_mask_cmd
,
5980 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5981 "Configure BGP aggregate entries\n"
5982 "Aggregate address\n"
5984 "Generate AS set path information\n"
5985 "Filter more specific routes from updates\n"
5986 "Filter more specific routes from updates\n"
5987 "Generate AS set path information\n")
5990 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5991 char *prefix
= argv
[idx
]->arg
;
5992 char *mask
= argv
[idx
+ 1]->arg
;
5994 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5996 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5997 ? AGGREGATE_SUMMARY_ONLY
6000 char prefix_str
[BUFSIZ
];
6001 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6004 vty_out(vty
, "%% Inconsistent address and mask\n");
6005 return CMD_WARNING_CONFIG_FAILED
;
6008 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6009 summary_only
, as_set
);
6012 DEFUN (no_aggregate_address
,
6013 no_aggregate_address_cmd
,
6014 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6016 "Configure BGP aggregate entries\n"
6017 "Aggregate prefix\n"
6018 "Generate AS set path information\n"
6019 "Filter more specific routes from updates\n"
6020 "Filter more specific routes from updates\n"
6021 "Generate AS set path information\n")
6024 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6025 char *prefix
= argv
[idx
]->arg
;
6026 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6029 DEFUN (no_aggregate_address_mask
,
6030 no_aggregate_address_mask_cmd
,
6031 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6033 "Configure BGP aggregate entries\n"
6034 "Aggregate address\n"
6036 "Generate AS set path information\n"
6037 "Filter more specific routes from updates\n"
6038 "Filter more specific routes from updates\n"
6039 "Generate AS set path information\n")
6042 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6043 char *prefix
= argv
[idx
]->arg
;
6044 char *mask
= argv
[idx
+ 1]->arg
;
6046 char prefix_str
[BUFSIZ
];
6047 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6050 vty_out(vty
, "%% Inconsistent address and mask\n");
6051 return CMD_WARNING_CONFIG_FAILED
;
6054 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6057 DEFUN (ipv6_aggregate_address
,
6058 ipv6_aggregate_address_cmd
,
6059 "aggregate-address X:X::X:X/M [summary-only]",
6060 "Configure BGP aggregate entries\n"
6061 "Aggregate prefix\n"
6062 "Filter more specific routes from updates\n")
6065 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6066 char *prefix
= argv
[idx
]->arg
;
6067 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6068 ? AGGREGATE_SUMMARY_ONLY
6070 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6074 DEFUN (no_ipv6_aggregate_address
,
6075 no_ipv6_aggregate_address_cmd
,
6076 "no aggregate-address X:X::X:X/M [summary-only]",
6078 "Configure BGP aggregate entries\n"
6079 "Aggregate prefix\n"
6080 "Filter more specific routes from updates\n")
6083 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6084 char *prefix
= argv
[idx
]->arg
;
6085 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6088 /* Redistribute route treatment. */
6089 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6090 const union g_addr
*nexthop
, ifindex_t ifindex
,
6091 enum nexthop_types_t nhtype
, uint32_t metric
,
6092 uint8_t type
, unsigned short instance
,
6095 struct bgp_info
*new;
6096 struct bgp_info
*bi
;
6097 struct bgp_info info
;
6098 struct bgp_node
*bn
;
6100 struct attr
*new_attr
;
6103 struct bgp_redist
*red
;
6105 /* Make default attribute. */
6106 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6109 case NEXTHOP_TYPE_IFINDEX
:
6111 case NEXTHOP_TYPE_IPV4
:
6112 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6113 attr
.nexthop
= nexthop
->ipv4
;
6115 case NEXTHOP_TYPE_IPV6
:
6116 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6117 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6118 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6120 case NEXTHOP_TYPE_BLACKHOLE
:
6121 switch (p
->family
) {
6123 attr
.nexthop
.s_addr
= INADDR_ANY
;
6126 memset(&attr
.mp_nexthop_global
, 0,
6127 sizeof(attr
.mp_nexthop_global
));
6128 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6133 attr
.nh_ifindex
= ifindex
;
6136 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6139 afi
= family2afi(p
->family
);
6141 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6143 struct attr attr_new
;
6145 /* Copy attribute for modification. */
6146 bgp_attr_dup(&attr_new
, &attr
);
6148 if (red
->redist_metric_flag
)
6149 attr_new
.med
= red
->redist_metric
;
6151 /* Apply route-map. */
6152 if (red
->rmap
.name
) {
6153 info
.peer
= bgp
->peer_self
;
6154 info
.attr
= &attr_new
;
6156 SET_FLAG(bgp
->peer_self
->rmap_type
,
6157 PEER_RMAP_TYPE_REDISTRIBUTE
);
6159 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6162 bgp
->peer_self
->rmap_type
= 0;
6164 if (ret
== RMAP_DENYMATCH
) {
6165 /* Free uninterned attribute. */
6166 bgp_attr_flush(&attr_new
);
6168 /* Unintern original. */
6169 aspath_unintern(&attr
.aspath
);
6170 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6175 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6176 bgp_attr_add_gshut_community(&attr_new
);
6178 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6179 SAFI_UNICAST
, p
, NULL
);
6181 new_attr
= bgp_attr_intern(&attr_new
);
6183 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6184 if (bi
->peer
== bgp
->peer_self
6185 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6189 /* Ensure the (source route) type is updated. */
6191 if (attrhash_cmp(bi
->attr
, new_attr
)
6192 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6193 bgp_attr_unintern(&new_attr
);
6194 aspath_unintern(&attr
.aspath
);
6195 bgp_unlock_node(bn
);
6198 /* The attribute is changed. */
6199 bgp_info_set_flag(bn
, bi
,
6200 BGP_INFO_ATTR_CHANGED
);
6202 /* Rewrite BGP route information. */
6203 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6204 bgp_info_restore(bn
, bi
);
6206 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6208 bgp_attr_unintern(&bi
->attr
);
6209 bi
->attr
= new_attr
;
6210 bi
->uptime
= bgp_clock();
6212 /* Process change. */
6213 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6215 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6216 bgp_unlock_node(bn
);
6217 aspath_unintern(&attr
.aspath
);
6219 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6221 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6223 vpn_leak_from_vrf_update(
6224 bgp_get_default(), bgp
, bi
);
6230 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6231 bgp
->peer_self
, new_attr
, bn
);
6232 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6234 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6235 bgp_info_add(bn
, new);
6236 bgp_unlock_node(bn
);
6237 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6239 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6240 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6242 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6246 /* Unintern original. */
6247 aspath_unintern(&attr
.aspath
);
6250 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6251 unsigned short instance
)
6254 struct bgp_node
*rn
;
6255 struct bgp_info
*ri
;
6256 struct bgp_redist
*red
;
6258 afi
= family2afi(p
->family
);
6260 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6262 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6263 SAFI_UNICAST
, p
, NULL
);
6265 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6266 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6270 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6271 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6273 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6276 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6277 bgp_info_delete(rn
, ri
);
6278 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6280 bgp_unlock_node(rn
);
6284 /* Withdraw specified route type's route. */
6285 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6286 unsigned short instance
)
6288 struct bgp_node
*rn
;
6289 struct bgp_info
*ri
;
6290 struct bgp_table
*table
;
6292 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6294 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6295 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6296 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6297 && ri
->instance
== instance
)
6301 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6302 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6304 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6307 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6309 bgp_info_delete(rn
, ri
);
6310 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6315 /* Static function to display route. */
6316 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6320 uint32_t destination
;
6323 if (p
->family
== AF_INET
) {
6325 len
= vty_out(vty
, "%s",
6326 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6328 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6330 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6331 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6332 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6333 || p
->u
.prefix4
.s_addr
== 0) {
6334 /* When mask is natural,
6335 mask is not displayed. */
6337 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6339 json_object_string_add(json
, "prefix",
6340 inet_ntop(p
->family
,
6343 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6345 } else if (p
->family
== AF_ETHERNET
) {
6346 prefix2str(p
, buf
, PREFIX_STRLEN
);
6347 len
= vty_out(vty
, "%s", buf
);
6348 } else if (p
->family
== AF_EVPN
) {
6349 #if defined(HAVE_CUMULUS)
6353 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6356 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6358 prefix2str(p
, buf
, PREFIX_STRLEN
);
6359 len
= vty_out(vty
, "%s", buf
);
6361 } else if (p
->family
== AF_FLOWSPEC
) {
6362 route_vty_out_flowspec(vty
, p
, NULL
,
6364 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6365 NLRI_STRING_FORMAT_MIN
, json
);
6370 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6377 vty_out(vty
, "\n%*s", 20, " ");
6379 vty_out(vty
, "%*s", len
, " ");
6383 enum bgp_display_type
{
6387 /* Print the short form route status for a bgp_info */
6388 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6389 json_object
*json_path
)
6393 /* Route status display. */
6394 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6395 json_object_boolean_true_add(json_path
, "removed");
6397 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6398 json_object_boolean_true_add(json_path
, "stale");
6400 if (binfo
->extra
&& binfo
->extra
->suppress
)
6401 json_object_boolean_true_add(json_path
, "suppressed");
6403 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6404 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6405 json_object_boolean_true_add(json_path
, "valid");
6408 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6409 json_object_boolean_true_add(json_path
, "history");
6411 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6412 json_object_boolean_true_add(json_path
, "damped");
6414 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6415 json_object_boolean_true_add(json_path
, "bestpath");
6417 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6418 json_object_boolean_true_add(json_path
, "multipath");
6420 /* Internal route. */
6421 if ((binfo
->peer
->as
)
6422 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6423 json_object_string_add(json_path
, "pathFrom",
6426 json_object_string_add(json_path
, "pathFrom",
6432 /* Route status display. */
6433 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6435 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6437 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6439 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6440 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6446 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6448 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6450 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6452 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6457 /* Internal route. */
6458 if (binfo
->peer
&& (binfo
->peer
->as
)
6459 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6465 /* called from terminal list command */
6466 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6467 int display
, safi_t safi
, json_object
*json_paths
)
6470 json_object
*json_path
= NULL
;
6471 json_object
*json_nexthops
= NULL
;
6472 json_object
*json_nexthop_global
= NULL
;
6473 json_object
*json_nexthop_ll
= NULL
;
6476 json_path
= json_object_new_object();
6478 /* short status lead text */
6479 route_vty_short_status_out(vty
, binfo
, json_path
);
6482 /* print prefix and mask */
6484 route_vty_out_route(p
, vty
, json_path
);
6486 vty_out(vty
, "%*s", 17, " ");
6488 route_vty_out_route(p
, vty
, json_path
);
6491 /* Print attribute */
6495 json_object_array_add(json_paths
, json_path
);
6503 * For ENCAP and EVPN routes, nexthop address family is not
6504 * neccessarily the same as the prefix address family.
6505 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6506 * EVPN routes are also exchanged with a MP nexthop. Currently,
6508 * is only IPv4, the value will be present in either
6510 * attr->mp_nexthop_global_in
6512 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6515 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6519 sprintf(nexthop
, "%s",
6520 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6524 sprintf(nexthop
, "%s",
6525 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6529 sprintf(nexthop
, "?");
6534 json_nexthop_global
= json_object_new_object();
6536 json_object_string_add(json_nexthop_global
, "afi",
6537 (af
== AF_INET
) ? "ip" : "ipv6");
6538 json_object_string_add(json_nexthop_global
,
6539 (af
== AF_INET
) ? "ip" : "ipv6",
6541 json_object_boolean_true_add(json_nexthop_global
,
6544 vty_out(vty
, "%s", nexthop
);
6545 } else if (safi
== SAFI_EVPN
) {
6547 json_nexthop_global
= json_object_new_object();
6549 json_object_string_add(json_nexthop_global
, "ip",
6550 inet_ntoa(attr
->nexthop
));
6551 json_object_string_add(json_nexthop_global
, "afi",
6553 json_object_boolean_true_add(json_nexthop_global
,
6556 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6557 } else if (safi
== SAFI_FLOWSPEC
) {
6558 if (attr
->nexthop
.s_addr
!= 0) {
6560 json_nexthop_global
= json_object_new_object();
6561 json_object_string_add(
6562 json_nexthop_global
, "ip",
6563 inet_ntoa(attr
->nexthop
));
6564 json_object_string_add(json_nexthop_global
,
6566 json_object_boolean_true_add(json_nexthop_global
,
6569 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6572 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6574 json_nexthop_global
= json_object_new_object();
6576 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6577 json_object_string_add(
6578 json_nexthop_global
, "ip",
6579 inet_ntoa(attr
->mp_nexthop_global_in
));
6581 json_object_string_add(
6582 json_nexthop_global
, "ip",
6583 inet_ntoa(attr
->nexthop
));
6585 json_object_string_add(json_nexthop_global
, "afi",
6587 json_object_boolean_true_add(json_nexthop_global
,
6590 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6591 vty_out(vty
, "%-16s",
6592 inet_ntoa(attr
->mp_nexthop_global_in
));
6594 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6599 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6604 json_nexthop_global
= json_object_new_object();
6605 json_object_string_add(
6606 json_nexthop_global
, "ip",
6607 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6609 json_object_string_add(json_nexthop_global
, "afi",
6611 json_object_string_add(json_nexthop_global
, "scope",
6614 /* We display both LL & GL if both have been
6616 if ((attr
->mp_nexthop_len
== 32)
6617 || (binfo
->peer
->conf_if
)) {
6618 json_nexthop_ll
= json_object_new_object();
6619 json_object_string_add(
6620 json_nexthop_ll
, "ip",
6622 &attr
->mp_nexthop_local
, buf
,
6624 json_object_string_add(json_nexthop_ll
, "afi",
6626 json_object_string_add(json_nexthop_ll
, "scope",
6629 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6630 &attr
->mp_nexthop_local
)
6632 && !attr
->mp_nexthop_prefer_global
)
6633 json_object_boolean_true_add(
6634 json_nexthop_ll
, "used");
6636 json_object_boolean_true_add(
6637 json_nexthop_global
, "used");
6639 json_object_boolean_true_add(
6640 json_nexthop_global
, "used");
6642 /* Display LL if LL/Global both in table unless
6643 * prefer-global is set */
6644 if (((attr
->mp_nexthop_len
== 32)
6645 && !attr
->mp_nexthop_prefer_global
)
6646 || (binfo
->peer
->conf_if
)) {
6647 if (binfo
->peer
->conf_if
) {
6648 len
= vty_out(vty
, "%s",
6649 binfo
->peer
->conf_if
);
6650 len
= 16 - len
; /* len of IPv6
6656 vty_out(vty
, "\n%*s", 36, " ");
6658 vty_out(vty
, "%*s", len
, " ");
6664 &attr
->mp_nexthop_local
,
6669 vty_out(vty
, "\n%*s", 36, " ");
6671 vty_out(vty
, "%*s", len
, " ");
6677 &attr
->mp_nexthop_global
, buf
,
6682 vty_out(vty
, "\n%*s", 36, " ");
6684 vty_out(vty
, "%*s", len
, " ");
6690 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6692 json_object_int_add(json_path
, "med", attr
->med
);
6694 vty_out(vty
, "%10u", attr
->med
);
6695 else if (!json_paths
)
6699 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6701 json_object_int_add(json_path
, "localpref",
6704 vty_out(vty
, "%7u", attr
->local_pref
);
6705 else if (!json_paths
)
6709 json_object_int_add(json_path
, "weight", attr
->weight
);
6711 vty_out(vty
, "%7u ", attr
->weight
);
6715 json_object_string_add(
6716 json_path
, "peerId",
6717 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6723 json_object_string_add(json_path
, "aspath",
6726 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6731 json_object_string_add(json_path
, "origin",
6732 bgp_origin_long_str
[attr
->origin
]);
6734 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6737 if (json_nexthop_global
|| json_nexthop_ll
) {
6738 json_nexthops
= json_object_new_array();
6740 if (json_nexthop_global
)
6741 json_object_array_add(json_nexthops
,
6742 json_nexthop_global
);
6744 if (json_nexthop_ll
)
6745 json_object_array_add(json_nexthops
,
6748 json_object_object_add(json_path
, "nexthops",
6752 json_object_array_add(json_paths
, json_path
);
6756 /* prints an additional line, indented, with VNC info, if
6758 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6759 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6764 /* called from terminal list command */
6765 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6766 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6768 json_object
*json_status
= NULL
;
6769 json_object
*json_net
= NULL
;
6771 /* Route status display. */
6773 json_status
= json_object_new_object();
6774 json_net
= json_object_new_object();
6781 /* print prefix and mask */
6783 json_object_string_add(
6784 json_net
, "addrPrefix",
6785 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6787 route_vty_out_route(p
, vty
, NULL
);
6789 /* Print attribute */
6792 if (p
->family
== AF_INET
6793 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6794 || safi
== SAFI_EVPN
6795 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6796 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6797 || safi
== SAFI_EVPN
)
6798 json_object_string_add(
6799 json_net
, "nextHop",
6801 attr
->mp_nexthop_global_in
));
6803 json_object_string_add(
6804 json_net
, "nextHop",
6805 inet_ntoa(attr
->nexthop
));
6806 } else if (p
->family
== AF_INET6
6807 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6810 json_object_string_add(
6811 json_net
, "netHopGloabal",
6813 &attr
->mp_nexthop_global
, buf
,
6818 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6819 json_object_int_add(json_net
, "metric",
6822 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6823 json_object_int_add(json_net
, "localPref",
6826 json_object_int_add(json_net
, "weight", attr
->weight
);
6830 json_object_string_add(json_net
, "asPath",
6834 json_object_string_add(json_net
, "bgpOriginCode",
6835 bgp_origin_str
[attr
->origin
]);
6837 if (p
->family
== AF_INET
6838 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6839 || safi
== SAFI_EVPN
6840 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6841 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6842 || safi
== SAFI_EVPN
)
6843 vty_out(vty
, "%-16s",
6845 attr
->mp_nexthop_global_in
));
6847 vty_out(vty
, "%-16s",
6848 inet_ntoa(attr
->nexthop
));
6849 } else if (p
->family
== AF_INET6
6850 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6857 &attr
->mp_nexthop_global
, buf
,
6861 vty_out(vty
, "\n%*s", 36, " ");
6863 vty_out(vty
, "%*s", len
, " ");
6866 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6867 vty_out(vty
, "%10u", attr
->med
);
6871 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6872 vty_out(vty
, "%7u", attr
->local_pref
);
6876 vty_out(vty
, "%7u ", attr
->weight
);
6880 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6883 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6887 json_object_boolean_true_add(json_status
, "*");
6888 json_object_boolean_true_add(json_status
, ">");
6889 json_object_object_add(json_net
, "appliedStatusSymbols",
6891 char buf_cut
[BUFSIZ
];
6892 json_object_object_add(
6894 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6900 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6901 struct bgp_info
*binfo
, int display
, safi_t safi
,
6904 json_object
*json_out
= NULL
;
6906 mpls_label_t label
= MPLS_INVALID_LABEL
;
6912 json_out
= json_object_new_object();
6914 /* short status lead text */
6915 route_vty_short_status_out(vty
, binfo
, json_out
);
6917 /* print prefix and mask */
6920 route_vty_out_route(p
, vty
, NULL
);
6922 vty_out(vty
, "%*s", 17, " ");
6925 /* Print attribute */
6928 if (((p
->family
== AF_INET
)
6929 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6930 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6931 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6932 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6933 || safi
== SAFI_EVPN
) {
6935 json_object_string_add(
6936 json_out
, "mpNexthopGlobalIn",
6938 attr
->mp_nexthop_global_in
));
6940 vty_out(vty
, "%-16s",
6942 attr
->mp_nexthop_global_in
));
6945 json_object_string_add(
6946 json_out
, "nexthop",
6947 inet_ntoa(attr
->nexthop
));
6949 vty_out(vty
, "%-16s",
6950 inet_ntoa(attr
->nexthop
));
6952 } else if (((p
->family
== AF_INET6
)
6953 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6954 || (safi
== SAFI_EVPN
6955 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6956 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6960 if (attr
->mp_nexthop_len
6961 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6963 json_object_string_add(
6964 json_out
, "mpNexthopGlobalIn",
6967 &attr
->mp_nexthop_global
,
6973 &attr
->mp_nexthop_global
,
6975 } else if (attr
->mp_nexthop_len
6976 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6979 &attr
->mp_nexthop_global
,
6982 &attr
->mp_nexthop_local
,
6984 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6985 json_object_string_add(
6987 "mpNexthopGlobalLocal", buf_c
);
6989 vty_out(vty
, "%s(%s)",
6992 &attr
->mp_nexthop_global
,
6996 &attr
->mp_nexthop_local
,
7002 label
= decode_label(&binfo
->extra
->label
[0]);
7004 if (bgp_is_valid_label(&label
)) {
7006 json_object_int_add(json_out
, "notag", label
);
7007 json_object_array_add(json
, json_out
);
7009 vty_out(vty
, "notag/%d", label
);
7015 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7016 struct bgp_info
*binfo
, int display
,
7017 json_object
*json_paths
)
7021 json_object
*json_path
= NULL
;
7024 json_path
= json_object_new_object();
7029 /* short status lead text */
7030 route_vty_short_status_out(vty
, binfo
, json_path
);
7032 /* print prefix and mask */
7034 route_vty_out_route(p
, vty
, NULL
);
7036 vty_out(vty
, "%*s", 17, " ");
7038 /* Print attribute */
7042 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7046 vty_out(vty
, "%-16s",
7047 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7051 vty_out(vty
, "%s(%s)",
7052 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7054 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7061 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7063 vty_out(vty
, "%s", str
);
7064 XFREE(MTYPE_TMP
, str
);
7066 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7068 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7069 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7072 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7075 if (attr
->ecommunity
) {
7077 struct ecommunity_val
*routermac
= ecommunity_lookup(
7078 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7079 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7081 mac
= ecom_mac2str((char *)routermac
->val
);
7083 vty_out(vty
, "/%s", (char *)mac
);
7084 XFREE(MTYPE_TMP
, mac
);
7092 /* dampening route */
7093 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7094 struct bgp_info
*binfo
, int display
, safi_t safi
,
7095 uint8_t use_json
, json_object
*json
)
7099 char timebuf
[BGP_UPTIME_LEN
];
7101 /* short status lead text */
7102 route_vty_short_status_out(vty
, binfo
, json
);
7104 /* print prefix and mask */
7107 route_vty_out_route(p
, vty
, NULL
);
7109 vty_out(vty
, "%*s", 17, " ");
7112 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7116 vty_out(vty
, "\n%*s", 34, " ");
7119 json_object_int_add(json
, "peerHost", len
);
7121 vty_out(vty
, "%*s", len
, " ");
7125 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7128 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7132 /* Print attribute */
7138 json_object_string_add(json
, "asPath",
7141 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7146 json_object_string_add(json
, "origin",
7147 bgp_origin_str
[attr
->origin
]);
7149 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7156 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7157 struct bgp_info
*binfo
, int display
, safi_t safi
,
7158 uint8_t use_json
, json_object
*json
)
7161 struct bgp_damp_info
*bdi
;
7162 char timebuf
[BGP_UPTIME_LEN
];
7168 bdi
= binfo
->extra
->damp_info
;
7170 /* short status lead text */
7171 route_vty_short_status_out(vty
, binfo
, json
);
7173 /* print prefix and mask */
7176 route_vty_out_route(p
, vty
, NULL
);
7178 vty_out(vty
, "%*s", 17, " ");
7181 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7185 vty_out(vty
, "\n%*s", 33, " ");
7188 json_object_int_add(json
, "peerHost", len
);
7190 vty_out(vty
, "%*s", len
, " ");
7193 len
= vty_out(vty
, "%d", bdi
->flap
);
7200 json_object_int_add(json
, "bdiFlap", len
);
7202 vty_out(vty
, "%*s", len
, " ");
7206 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7209 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7210 BGP_UPTIME_LEN
, 0, NULL
));
7212 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7213 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7215 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7216 BGP_UPTIME_LEN
, use_json
, json
);
7219 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7224 vty_out(vty
, "%*s ", 8, " ");
7227 /* Print attribute */
7233 json_object_string_add(json
, "asPath",
7236 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7241 json_object_string_add(json
, "origin",
7242 bgp_origin_str
[attr
->origin
]);
7244 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7250 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7251 int *first
, const char *header
,
7252 json_object
*json_adv_to
)
7254 char buf1
[INET6_ADDRSTRLEN
];
7255 json_object
*json_peer
= NULL
;
7258 /* 'advertised-to' is a dictionary of peers we have advertised
7260 * prefix too. The key is the peer's IP or swpX, the value is
7262 * hostname if we know it and "" if not.
7264 json_peer
= json_object_new_object();
7267 json_object_string_add(json_peer
, "hostname",
7271 json_object_object_add(json_adv_to
, peer
->conf_if
,
7274 json_object_object_add(
7276 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7280 vty_out(vty
, "%s", header
);
7285 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7287 vty_out(vty
, " %s(%s)", peer
->hostname
,
7290 vty_out(vty
, " %s(%s)", peer
->hostname
,
7291 sockunion2str(&peer
->su
, buf1
,
7295 vty_out(vty
, " %s", peer
->conf_if
);
7298 sockunion2str(&peer
->su
, buf1
,
7304 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7305 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7306 json_object
*json_paths
)
7308 char buf
[INET6_ADDRSTRLEN
];
7310 #if defined(HAVE_CUMULUS)
7311 char buf2
[EVPN_ROUTE_STRLEN
];
7314 int sockunion_vty_out(struct vty
*, union sockunion
*);
7316 json_object
*json_bestpath
= NULL
;
7317 json_object
*json_cluster_list
= NULL
;
7318 json_object
*json_cluster_list_list
= NULL
;
7319 json_object
*json_ext_community
= NULL
;
7320 json_object
*json_lcommunity
= NULL
;
7321 json_object
*json_last_update
= NULL
;
7322 json_object
*json_pmsi
= NULL
;
7323 json_object
*json_nexthop_global
= NULL
;
7324 json_object
*json_nexthop_ll
= NULL
;
7325 json_object
*json_nexthops
= NULL
;
7326 json_object
*json_path
= NULL
;
7327 json_object
*json_peer
= NULL
;
7328 json_object
*json_string
= NULL
;
7329 json_object
*json_adv_to
= NULL
;
7331 struct listnode
*node
, *nnode
;
7333 int addpath_capable
;
7335 unsigned int first_as
;
7338 json_path
= json_object_new_object();
7339 json_peer
= json_object_new_object();
7340 json_nexthop_global
= json_object_new_object();
7343 #if defined(HAVE_CUMULUS)
7344 if (!json_paths
&& safi
== SAFI_EVPN
) {
7347 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7348 vty_out(vty
, " Route %s", buf2
);
7350 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7351 bgp_evpn_label2str(binfo
->extra
->label
,
7352 binfo
->extra
->num_labels
, tag_buf
,
7354 vty_out(vty
, " VNI %s", tag_buf
);
7357 if (binfo
->extra
&& binfo
->extra
->parent
) {
7358 struct bgp_info
*parent_ri
;
7359 struct bgp_node
*rn
, *prn
;
7361 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7362 rn
= parent_ri
->net
;
7363 if (rn
&& rn
->prn
) {
7365 vty_out(vty
, " Imported from %s:%s\n",
7367 (struct prefix_rd
*)&prn
->p
,
7368 buf1
, sizeof(buf1
)),
7378 /* Line1 display AS-path, Aggregator */
7381 if (!attr
->aspath
->json
)
7382 aspath_str_update(attr
->aspath
, true);
7383 json_object_lock(attr
->aspath
->json
);
7384 json_object_object_add(json_path
, "aspath",
7385 attr
->aspath
->json
);
7387 if (attr
->aspath
->segments
)
7388 aspath_print_vty(vty
, " %s",
7391 vty_out(vty
, " Local");
7395 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7397 json_object_boolean_true_add(json_path
,
7400 vty_out(vty
, ", (removed)");
7403 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7405 json_object_boolean_true_add(json_path
,
7408 vty_out(vty
, ", (stale)");
7411 if (CHECK_FLAG(attr
->flag
,
7412 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7414 json_object_int_add(json_path
, "aggregatorAs",
7415 attr
->aggregator_as
);
7416 json_object_string_add(
7417 json_path
, "aggregatorId",
7418 inet_ntoa(attr
->aggregator_addr
));
7420 vty_out(vty
, ", (aggregated by %u %s)",
7421 attr
->aggregator_as
,
7422 inet_ntoa(attr
->aggregator_addr
));
7426 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7427 PEER_FLAG_REFLECTOR_CLIENT
)) {
7429 json_object_boolean_true_add(
7430 json_path
, "rxedFromRrClient");
7432 vty_out(vty
, ", (Received from a RR-client)");
7435 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7436 PEER_FLAG_RSERVER_CLIENT
)) {
7438 json_object_boolean_true_add(
7439 json_path
, "rxedFromRsClient");
7441 vty_out(vty
, ", (Received from a RS-client)");
7444 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7446 json_object_boolean_true_add(
7447 json_path
, "dampeningHistoryEntry");
7449 vty_out(vty
, ", (history entry)");
7450 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7452 json_object_boolean_true_add(
7453 json_path
, "dampeningSuppressed");
7455 vty_out(vty
, ", (suppressed due to dampening)");
7461 /* Line2 display Next-hop, Neighbor, Router-id */
7462 /* Display the nexthop */
7463 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7464 || p
->family
== AF_EVPN
)
7465 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7466 || safi
== SAFI_EVPN
7467 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7468 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7469 || safi
== SAFI_EVPN
) {
7471 json_object_string_add(
7472 json_nexthop_global
, "ip",
7474 attr
->mp_nexthop_global_in
));
7478 attr
->mp_nexthop_global_in
));
7481 json_object_string_add(
7482 json_nexthop_global
, "ip",
7483 inet_ntoa(attr
->nexthop
));
7486 inet_ntoa(attr
->nexthop
));
7490 json_object_string_add(json_nexthop_global
,
7494 json_object_string_add(
7495 json_nexthop_global
, "ip",
7497 &attr
->mp_nexthop_global
, buf
,
7499 json_object_string_add(json_nexthop_global
,
7501 json_object_string_add(json_nexthop_global
,
7506 &attr
->mp_nexthop_global
, buf
,
7511 /* Display the IGP cost or 'inaccessible' */
7512 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7514 json_object_boolean_false_add(
7515 json_nexthop_global
, "accessible");
7517 vty_out(vty
, " (inaccessible)");
7519 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7521 json_object_int_add(
7522 json_nexthop_global
, "metric",
7523 binfo
->extra
->igpmetric
);
7525 vty_out(vty
, " (metric %u)",
7526 binfo
->extra
->igpmetric
);
7529 /* IGP cost is 0, display this only for json */
7532 json_object_int_add(json_nexthop_global
,
7537 json_object_boolean_true_add(
7538 json_nexthop_global
, "accessible");
7541 /* Display peer "from" output */
7542 /* This path was originated locally */
7543 if (binfo
->peer
== bgp
->peer_self
) {
7545 if (safi
== SAFI_EVPN
7546 || (p
->family
== AF_INET
7547 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7549 json_object_string_add(
7550 json_peer
, "peerId", "0.0.0.0");
7552 vty_out(vty
, " from 0.0.0.0 ");
7555 json_object_string_add(json_peer
,
7558 vty_out(vty
, " from :: ");
7562 json_object_string_add(
7563 json_peer
, "routerId",
7564 inet_ntoa(bgp
->router_id
));
7566 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7569 /* We RXed this path from one of our peers */
7573 json_object_string_add(
7574 json_peer
, "peerId",
7575 sockunion2str(&binfo
->peer
->su
, buf
,
7577 json_object_string_add(
7578 json_peer
, "routerId",
7580 &binfo
->peer
->remote_id
, buf1
,
7583 if (binfo
->peer
->hostname
)
7584 json_object_string_add(
7585 json_peer
, "hostname",
7586 binfo
->peer
->hostname
);
7588 if (binfo
->peer
->domainname
)
7589 json_object_string_add(
7590 json_peer
, "domainname",
7591 binfo
->peer
->domainname
);
7593 if (binfo
->peer
->conf_if
)
7594 json_object_string_add(
7595 json_peer
, "interface",
7596 binfo
->peer
->conf_if
);
7598 if (binfo
->peer
->conf_if
) {
7599 if (binfo
->peer
->hostname
7602 BGP_FLAG_SHOW_HOSTNAME
))
7603 vty_out(vty
, " from %s(%s)",
7604 binfo
->peer
->hostname
,
7605 binfo
->peer
->conf_if
);
7607 vty_out(vty
, " from %s",
7608 binfo
->peer
->conf_if
);
7610 if (binfo
->peer
->hostname
7613 BGP_FLAG_SHOW_HOSTNAME
))
7614 vty_out(vty
, " from %s(%s)",
7615 binfo
->peer
->hostname
,
7618 vty_out(vty
, " from %s",
7627 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7628 vty_out(vty
, " (%s)",
7629 inet_ntoa(attr
->originator_id
));
7631 vty_out(vty
, " (%s)",
7634 &binfo
->peer
->remote_id
,
7635 buf1
, sizeof(buf1
)));
7642 /* display the link-local nexthop */
7643 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7645 json_nexthop_ll
= json_object_new_object();
7646 json_object_string_add(
7647 json_nexthop_ll
, "ip",
7649 &attr
->mp_nexthop_local
, buf
,
7651 json_object_string_add(json_nexthop_ll
, "afi",
7653 json_object_string_add(json_nexthop_ll
, "scope",
7656 json_object_boolean_true_add(json_nexthop_ll
,
7659 if (!attr
->mp_nexthop_prefer_global
)
7660 json_object_boolean_true_add(
7661 json_nexthop_ll
, "used");
7663 json_object_boolean_true_add(
7664 json_nexthop_global
, "used");
7666 vty_out(vty
, " (%s) %s\n",
7668 &attr
->mp_nexthop_local
, buf
,
7670 attr
->mp_nexthop_prefer_global
7675 /* If we do not have a link-local nexthop then we must flag the
7679 json_object_boolean_true_add(
7680 json_nexthop_global
, "used");
7683 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7684 * Int/Ext/Local, Atomic, best */
7686 json_object_string_add(
7687 json_path
, "origin",
7688 bgp_origin_long_str
[attr
->origin
]);
7690 vty_out(vty
, " Origin %s",
7691 bgp_origin_long_str
[attr
->origin
]);
7693 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7695 json_object_int_add(json_path
, "med",
7698 vty_out(vty
, ", metric %u", attr
->med
);
7701 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7703 json_object_int_add(json_path
, "localpref",
7706 vty_out(vty
, ", localpref %u",
7710 json_object_int_add(json_path
, "localpref",
7711 bgp
->default_local_pref
);
7713 vty_out(vty
, ", localpref %u",
7714 bgp
->default_local_pref
);
7717 if (attr
->weight
!= 0) {
7719 json_object_int_add(json_path
, "weight",
7722 vty_out(vty
, ", weight %u", attr
->weight
);
7725 if (attr
->tag
!= 0) {
7727 json_object_int_add(json_path
, "tag",
7730 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7734 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7736 json_object_boolean_false_add(json_path
,
7739 vty_out(vty
, ", invalid");
7740 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7742 json_object_boolean_true_add(json_path
,
7745 vty_out(vty
, ", valid");
7748 if (binfo
->peer
!= bgp
->peer_self
) {
7749 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7750 if (CHECK_FLAG(bgp
->config
,
7751 BGP_CONFIG_CONFEDERATION
)) {
7753 json_object_string_add(
7758 ", confed-internal");
7761 json_object_string_add(
7765 vty_out(vty
, ", internal");
7768 if (bgp_confederation_peers_check(
7769 bgp
, binfo
->peer
->as
)) {
7771 json_object_string_add(
7776 ", confed-external");
7779 json_object_string_add(
7783 vty_out(vty
, ", external");
7786 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7788 json_object_boolean_true_add(json_path
,
7790 json_object_boolean_true_add(json_path
,
7793 vty_out(vty
, ", aggregated, local");
7795 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7797 json_object_boolean_true_add(json_path
,
7800 vty_out(vty
, ", sourced");
7803 json_object_boolean_true_add(json_path
,
7805 json_object_boolean_true_add(json_path
,
7808 vty_out(vty
, ", sourced, local");
7812 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7814 json_object_boolean_true_add(json_path
,
7817 vty_out(vty
, ", atomic-aggregate");
7820 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7821 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7822 && bgp_info_mpath_count(binfo
))) {
7824 json_object_boolean_true_add(json_path
,
7827 vty_out(vty
, ", multipath");
7830 // Mark the bestpath(s)
7831 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7832 first_as
= aspath_get_first_as(attr
->aspath
);
7837 json_object_new_object();
7838 json_object_int_add(json_bestpath
,
7839 "bestpathFromAs", first_as
);
7842 vty_out(vty
, ", bestpath-from-AS %u",
7846 ", bestpath-from-AS Local");
7850 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7854 json_object_new_object();
7855 json_object_boolean_true_add(json_bestpath
,
7858 vty_out(vty
, ", best");
7862 json_object_object_add(json_path
, "bestpath",
7868 /* Line 4 display Community */
7869 if (attr
->community
) {
7871 if (!attr
->community
->json
)
7872 community_str(attr
->community
, true);
7873 json_object_lock(attr
->community
->json
);
7874 json_object_object_add(json_path
, "community",
7875 attr
->community
->json
);
7877 vty_out(vty
, " Community: %s\n",
7878 attr
->community
->str
);
7882 /* Line 5 display Extended-community */
7883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7885 json_ext_community
= json_object_new_object();
7886 json_object_string_add(json_ext_community
,
7888 attr
->ecommunity
->str
);
7889 json_object_object_add(json_path
,
7890 "extendedCommunity",
7891 json_ext_community
);
7893 vty_out(vty
, " Extended Community: %s\n",
7894 attr
->ecommunity
->str
);
7898 /* Line 6 display Large community */
7899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7901 json_lcommunity
= json_object_new_object();
7902 json_object_string_add(json_lcommunity
,
7904 attr
->lcommunity
->str
);
7905 json_object_object_add(json_path
,
7909 vty_out(vty
, " Large Community: %s\n",
7910 attr
->lcommunity
->str
);
7914 /* Line 7 display Originator, Cluster-id */
7915 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7916 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7918 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7920 json_object_string_add(
7921 json_path
, "originatorId",
7922 inet_ntoa(attr
->originator_id
));
7924 vty_out(vty
, " Originator: %s",
7925 inet_ntoa(attr
->originator_id
));
7928 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7933 json_object_new_object();
7934 json_cluster_list_list
=
7935 json_object_new_array();
7938 i
< attr
->cluster
->length
/ 4;
7940 json_string
= json_object_new_string(
7944 json_object_array_add(
7945 json_cluster_list_list
,
7949 /* struct cluster_list does not have
7951 * aspath and community do. Add this
7954 json_object_string_add(json_cluster_list,
7955 "string", attr->cluster->str);
7957 json_object_object_add(
7958 json_cluster_list
, "list",
7959 json_cluster_list_list
);
7960 json_object_object_add(
7961 json_path
, "clusterList",
7964 vty_out(vty
, ", Cluster list: ");
7967 i
< attr
->cluster
->length
/ 4;
7981 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7982 bgp_damp_info_vty(vty
, binfo
, json_path
);
7985 #if defined(HAVE_CUMULUS)
7986 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
7987 && safi
!= SAFI_EVPN
)
7989 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
7992 mpls_label_t label
=
7993 label_pton(&binfo
->extra
->label
[0]);
7995 json_object_int_add(json_path
, "remoteLabel",
7998 vty_out(vty
, " Remote label: %d\n", label
);
8002 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8004 json_object_int_add(json_path
, "labelIndex",
8007 vty_out(vty
, " Label Index: %d\n",
8011 /* Line 8 display Addpath IDs */
8012 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8014 json_object_int_add(json_path
, "addpathRxId",
8015 binfo
->addpath_rx_id
);
8016 json_object_int_add(json_path
, "addpathTxId",
8017 binfo
->addpath_tx_id
);
8019 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8020 binfo
->addpath_rx_id
,
8021 binfo
->addpath_tx_id
);
8025 /* If we used addpath to TX a non-bestpath we need to display
8026 * "Advertised to" on a path-by-path basis */
8027 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8030 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8032 bgp_addpath_encode_tx(peer
, afi
, safi
);
8033 has_adj
= bgp_adj_out_lookup(
8034 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8036 if ((addpath_capable
&& has_adj
)
8037 || (!addpath_capable
&& has_adj
8038 && CHECK_FLAG(binfo
->flags
,
8039 BGP_INFO_SELECTED
))) {
8040 if (json_path
&& !json_adv_to
)
8042 json_object_new_object();
8044 route_vty_out_advertised_to(
8053 json_object_object_add(json_path
,
8064 /* Line 9 display Uptime */
8065 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8067 json_last_update
= json_object_new_object();
8068 json_object_int_add(json_last_update
, "epoch", tbuf
);
8069 json_object_string_add(json_last_update
, "string",
8071 json_object_object_add(json_path
, "lastUpdate",
8074 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8076 /* Line 10 display PMSI tunnel attribute, if present */
8077 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8078 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8079 attr
->pmsi_tnl_type
,
8080 PMSI_TNLTYPE_STR_DEFAULT
);
8083 json_pmsi
= json_object_new_object();
8084 json_object_string_add(json_pmsi
,
8086 json_object_object_add(json_path
, "pmsi",
8089 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8095 /* We've constructed the json object for this path, add it to the json
8099 if (json_nexthop_global
|| json_nexthop_ll
) {
8100 json_nexthops
= json_object_new_array();
8102 if (json_nexthop_global
)
8103 json_object_array_add(json_nexthops
,
8104 json_nexthop_global
);
8106 if (json_nexthop_ll
)
8107 json_object_array_add(json_nexthops
,
8110 json_object_object_add(json_path
, "nexthops",
8114 json_object_object_add(json_path
, "peer", json_peer
);
8115 json_object_array_add(json_paths
, json_path
);
8120 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8121 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8122 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8124 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8125 const char *prefix_list_str
, afi_t afi
,
8126 safi_t safi
, enum bgp_show_type type
);
8127 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8128 const char *filter
, afi_t afi
, safi_t safi
,
8129 enum bgp_show_type type
);
8130 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8131 const char *rmap_str
, afi_t afi
, safi_t safi
,
8132 enum bgp_show_type type
);
8133 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8134 const char *com
, int exact
, afi_t afi
,
8136 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8137 const char *prefix
, afi_t afi
, safi_t safi
,
8138 enum bgp_show_type type
);
8139 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8140 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8141 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8142 const char *comstr
, int exact
, afi_t afi
,
8146 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8147 struct bgp_table
*table
, enum bgp_show_type type
,
8148 void *output_arg
, uint8_t use_json
, char *rd
,
8149 int is_last
, unsigned long *output_cum
,
8150 unsigned long *total_cum
,
8151 unsigned long *json_header_depth
)
8153 struct bgp_info
*ri
;
8154 struct bgp_node
*rn
;
8157 unsigned long output_count
= 0;
8158 unsigned long total_count
= 0;
8162 json_object
*json_paths
= NULL
;
8165 if (output_cum
&& *output_cum
!= 0)
8168 if (use_json
&& !*json_header_depth
) {
8170 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8171 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8172 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8173 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8175 table
->version
, inet_ntoa(bgp
->router_id
));
8176 *json_header_depth
= 2;
8178 vty_out(vty
, " \"routeDistinguishers\" : {");
8179 ++*json_header_depth
;
8181 json_paths
= json_object_new_object();
8184 if (use_json
&& rd
) {
8185 vty_out(vty
, " \"%s\" : { ", rd
);
8188 /* Start processing of routes. */
8189 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8190 if (rn
->info
== NULL
)
8195 json_paths
= json_object_new_array();
8199 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8201 if (type
== bgp_show_type_flap_statistics
8202 || type
== bgp_show_type_flap_neighbor
8203 || type
== bgp_show_type_dampend_paths
8204 || type
== bgp_show_type_damp_neighbor
) {
8205 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8208 if (type
== bgp_show_type_regexp
) {
8209 regex_t
*regex
= output_arg
;
8211 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8215 if (type
== bgp_show_type_prefix_list
) {
8216 struct prefix_list
*plist
= output_arg
;
8218 if (prefix_list_apply(plist
, &rn
->p
)
8222 if (type
== bgp_show_type_filter_list
) {
8223 struct as_list
*as_list
= output_arg
;
8225 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8226 != AS_FILTER_PERMIT
)
8229 if (type
== bgp_show_type_route_map
) {
8230 struct route_map
*rmap
= output_arg
;
8231 struct bgp_info binfo
;
8232 struct attr dummy_attr
;
8235 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8237 binfo
.peer
= ri
->peer
;
8238 binfo
.attr
= &dummy_attr
;
8240 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8242 if (ret
== RMAP_DENYMATCH
)
8245 if (type
== bgp_show_type_neighbor
8246 || type
== bgp_show_type_flap_neighbor
8247 || type
== bgp_show_type_damp_neighbor
) {
8248 union sockunion
*su
= output_arg
;
8250 if (ri
->peer
== NULL
8251 || ri
->peer
->su_remote
== NULL
8252 || !sockunion_same(ri
->peer
->su_remote
, su
))
8255 if (type
== bgp_show_type_cidr_only
) {
8256 uint32_t destination
;
8258 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8259 if (IN_CLASSC(destination
)
8260 && rn
->p
.prefixlen
== 24)
8262 if (IN_CLASSB(destination
)
8263 && rn
->p
.prefixlen
== 16)
8265 if (IN_CLASSA(destination
)
8266 && rn
->p
.prefixlen
== 8)
8269 if (type
== bgp_show_type_prefix_longer
) {
8270 struct prefix
*p
= output_arg
;
8272 if (!prefix_match(p
, &rn
->p
))
8275 if (type
== bgp_show_type_community_all
) {
8276 if (!ri
->attr
->community
)
8279 if (type
== bgp_show_type_community
) {
8280 struct community
*com
= output_arg
;
8282 if (!ri
->attr
->community
8283 || !community_match(ri
->attr
->community
,
8287 if (type
== bgp_show_type_community_exact
) {
8288 struct community
*com
= output_arg
;
8290 if (!ri
->attr
->community
8291 || !community_cmp(ri
->attr
->community
, com
))
8294 if (type
== bgp_show_type_community_list
) {
8295 struct community_list
*list
= output_arg
;
8297 if (!community_list_match(ri
->attr
->community
,
8301 if (type
== bgp_show_type_community_list_exact
) {
8302 struct community_list
*list
= output_arg
;
8304 if (!community_list_exact_match(
8305 ri
->attr
->community
, list
))
8308 if (type
== bgp_show_type_lcommunity
) {
8309 struct lcommunity
*lcom
= output_arg
;
8311 if (!ri
->attr
->lcommunity
8312 || !lcommunity_match(ri
->attr
->lcommunity
,
8316 if (type
== bgp_show_type_lcommunity_list
) {
8317 struct community_list
*list
= output_arg
;
8319 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8323 if (type
== bgp_show_type_lcommunity_all
) {
8324 if (!ri
->attr
->lcommunity
)
8327 if (type
== bgp_show_type_dampend_paths
8328 || type
== bgp_show_type_damp_neighbor
) {
8329 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8330 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8334 if (!use_json
&& header
) {
8335 vty_out(vty
, "BGP table version is %" PRIu64
8336 ", local router ID is %s\n",
8338 inet_ntoa(bgp
->router_id
));
8339 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8340 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8341 if (type
== bgp_show_type_dampend_paths
8342 || type
== bgp_show_type_damp_neighbor
)
8343 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8344 else if (type
== bgp_show_type_flap_statistics
8345 || type
== bgp_show_type_flap_neighbor
)
8346 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8348 vty_out(vty
, BGP_SHOW_HEADER
);
8351 if (rd
!= NULL
&& !display
&& !output_count
) {
8354 "Route Distinguisher: %s\n",
8357 if (type
== bgp_show_type_dampend_paths
8358 || type
== bgp_show_type_damp_neighbor
)
8359 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8360 safi
, use_json
, json_paths
);
8361 else if (type
== bgp_show_type_flap_statistics
8362 || type
== bgp_show_type_flap_neighbor
)
8363 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8364 safi
, use_json
, json_paths
);
8366 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8377 sprintf(buf2
, "%s/%d",
8378 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8381 vty_out(vty
, "\"%s\": ", buf2
);
8383 vty_out(vty
, ",\"%s\": ", buf2
);
8386 json_object_to_json_string(json_paths
));
8387 json_object_free(json_paths
);
8394 output_count
+= *output_cum
;
8395 *output_cum
= output_count
;
8398 total_count
+= *total_cum
;
8399 *total_cum
= total_count
;
8403 json_object_free(json_paths
);
8405 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8409 for (i
= 0; i
< *json_header_depth
; ++i
)
8410 vty_out(vty
, " } ");
8414 /* No route is displayed */
8415 if (output_count
== 0) {
8416 if (type
== bgp_show_type_normal
)
8418 "No BGP prefixes displayed, %ld exist\n",
8422 "\nDisplayed %ld routes and %ld total paths\n",
8423 output_count
, total_count
);
8430 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8431 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8432 enum bgp_show_type type
, void *output_arg
,
8435 struct bgp_node
*rn
, *next
;
8436 unsigned long output_cum
= 0;
8437 unsigned long total_cum
= 0;
8438 unsigned long json_header_depth
= 0;
8441 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8443 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8444 next
= bgp_route_next(rn
);
8445 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8447 if (rn
->info
!= NULL
) {
8448 struct prefix_rd prd
;
8449 char rd
[RD_ADDRSTRLEN
];
8451 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8452 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8453 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8454 output_arg
, use_json
, rd
, next
== NULL
,
8455 &output_cum
, &total_cum
,
8456 &json_header_depth
);
8462 if (output_cum
== 0)
8463 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8467 "\nDisplayed %ld routes and %ld total paths\n",
8468 output_cum
, total_cum
);
8472 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8473 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8475 struct bgp_table
*table
;
8476 unsigned long json_header_depth
= 0;
8479 bgp
= bgp_get_default();
8484 vty_out(vty
, "No BGP process is configured\n");
8486 vty_out(vty
, "{}\n");
8490 table
= bgp
->rib
[afi
][safi
];
8491 /* use MPLS and ENCAP specific shows until they are merged */
8492 if (safi
== SAFI_MPLS_VPN
) {
8493 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8494 output_arg
, use_json
);
8497 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8498 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8499 output_arg
, use_json
,
8502 /* labeled-unicast routes live in the unicast table */
8503 else if (safi
== SAFI_LABELED_UNICAST
)
8504 safi
= SAFI_UNICAST
;
8506 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8507 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8510 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8511 safi_t safi
, uint8_t use_json
)
8513 struct listnode
*node
, *nnode
;
8518 vty_out(vty
, "{\n");
8520 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8523 vty_out(vty
, ",\n");
8527 vty_out(vty
, "\"%s\":",
8528 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8532 vty_out(vty
, "\nInstance %s:\n",
8533 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8537 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8542 vty_out(vty
, "}\n");
8545 /* Header of detailed BGP route information */
8546 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8547 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8548 afi_t afi
, safi_t safi
, json_object
*json
)
8550 struct bgp_info
*ri
;
8553 struct listnode
*node
, *nnode
;
8554 char buf1
[RD_ADDRSTRLEN
];
8555 char buf2
[INET6_ADDRSTRLEN
];
8556 #if defined(HAVE_CUMULUS)
8557 char buf3
[EVPN_ROUTE_STRLEN
];
8559 char prefix_str
[BUFSIZ
];
8564 int no_advertise
= 0;
8567 int has_valid_label
= 0;
8568 mpls_label_t label
= 0;
8569 json_object
*json_adv_to
= NULL
;
8572 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8574 if (has_valid_label
)
8575 label
= label_pton(&rn
->local_label
);
8578 if (has_valid_label
)
8579 json_object_int_add(json
, "localLabel", label
);
8581 json_object_string_add(
8583 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8585 #if defined(HAVE_CUMULUS)
8586 if (safi
== SAFI_EVPN
)
8587 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8588 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8591 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8592 buf3
, sizeof(buf3
)));
8594 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8595 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8596 ? prefix_rd2str(prd
, buf1
,
8599 safi
== SAFI_MPLS_VPN
? ":" : "",
8600 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8604 if (p
->family
== AF_ETHERNET
)
8605 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8607 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8609 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8610 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8611 || safi
== SAFI_EVPN
)
8612 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8614 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8616 buf2
, p
->prefixlen
);
8619 if (has_valid_label
)
8620 vty_out(vty
, "Local label: %d\n", label
);
8621 #if defined(HAVE_CUMULUS)
8622 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8624 if (bgp_labeled_safi(safi
))
8626 vty_out(vty
, "not allocated\n");
8629 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8631 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8633 if (ri
->extra
&& ri
->extra
->suppress
)
8635 if (ri
->attr
->community
!= NULL
) {
8636 if (community_include(ri
->attr
->community
,
8637 COMMUNITY_NO_ADVERTISE
))
8639 if (community_include(ri
->attr
->community
,
8640 COMMUNITY_NO_EXPORT
))
8642 if (community_include(ri
->attr
->community
,
8643 COMMUNITY_LOCAL_AS
))
8650 vty_out(vty
, "Paths: (%d available", count
);
8652 vty_out(vty
, ", best #%d", best
);
8653 if (safi
== SAFI_UNICAST
)
8654 vty_out(vty
, ", table %s",
8656 == BGP_INSTANCE_TYPE_DEFAULT
)
8657 ? "Default-IP-Routing-Table"
8660 vty_out(vty
, ", no best path");
8663 vty_out(vty
, ", not advertised to any peer");
8665 vty_out(vty
, ", not advertised to EBGP peer");
8667 vty_out(vty
, ", not advertised outside local AS");
8671 ", Advertisements suppressed by an aggregate.");
8672 vty_out(vty
, ")\n");
8675 /* If we are not using addpath then we can display Advertised to and
8677 * show what peers we advertised the bestpath to. If we are using
8679 * though then we must display Advertised to on a path-by-path basis. */
8680 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8681 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8682 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8683 if (json
&& !json_adv_to
)
8684 json_adv_to
= json_object_new_object();
8686 route_vty_out_advertised_to(
8688 " Advertised to non peer-group peers:\n ",
8695 json_object_object_add(json
, "advertisedTo",
8700 vty_out(vty
, " Not advertised to any peer");
8706 /* Display specified route of BGP table. */
8707 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8708 struct bgp_table
*rib
, const char *ip_str
,
8709 afi_t afi
, safi_t safi
,
8710 struct prefix_rd
*prd
, int prefix_check
,
8711 enum bgp_path_type pathtype
,
8717 struct prefix match
;
8718 struct bgp_node
*rn
;
8719 struct bgp_node
*rm
;
8720 struct bgp_info
*ri
;
8721 struct bgp_table
*table
;
8722 json_object
*json
= NULL
;
8723 json_object
*json_paths
= NULL
;
8725 /* Check IP address argument. */
8726 ret
= str2prefix(ip_str
, &match
);
8728 vty_out(vty
, "address is malformed\n");
8732 match
.family
= afi2family(afi
);
8735 json
= json_object_new_object();
8736 json_paths
= json_object_new_array();
8739 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8740 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8741 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8744 if ((table
= rn
->info
) == NULL
)
8749 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8753 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8754 bgp_unlock_node(rm
);
8758 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8760 route_vty_out_detail_header(
8762 (struct prefix_rd
*)&rn
->p
,
8763 AFI_IP
, safi
, json
);
8768 if (pathtype
== BGP_PATH_ALL
8769 || (pathtype
== BGP_PATH_BESTPATH
8770 && CHECK_FLAG(ri
->flags
,
8772 || (pathtype
== BGP_PATH_MULTIPATH
8773 && (CHECK_FLAG(ri
->flags
,
8775 || CHECK_FLAG(ri
->flags
,
8776 BGP_INFO_SELECTED
))))
8777 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8782 bgp_unlock_node(rm
);
8784 } else if (safi
== SAFI_FLOWSPEC
) {
8785 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8786 &match
, prefix_check
);
8788 route_vty_out_flowspec(vty
, &rn
->p
,
8789 rn
->info
, use_json
?
8790 NLRI_STRING_FORMAT_JSON
:
8791 NLRI_STRING_FORMAT_LARGE
,
8794 bgp_unlock_node(rn
);
8799 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8801 || rn
->p
.prefixlen
== match
.prefixlen
) {
8802 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8804 route_vty_out_detail_header(
8805 vty
, bgp
, rn
, NULL
, afi
,
8811 if (pathtype
== BGP_PATH_ALL
8812 || (pathtype
== BGP_PATH_BESTPATH
8816 || (pathtype
== BGP_PATH_MULTIPATH
8822 BGP_INFO_SELECTED
))))
8823 route_vty_out_detail(
8824 vty
, bgp
, &rn
->p
, ri
,
8825 afi
, safi
, json_paths
);
8829 bgp_unlock_node(rn
);
8835 json_object_object_add(json
, "paths", json_paths
);
8837 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8838 json
, JSON_C_TO_STRING_PRETTY
));
8839 json_object_free(json
);
8842 vty_out(vty
, "%% Network not in table\n");
8850 /* Display specified route of Main RIB */
8851 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8852 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8853 int prefix_check
, enum bgp_path_type pathtype
,
8857 bgp
= bgp_get_default();
8860 vty_out(vty
, "No BGP process is configured\n");
8862 vty_out(vty
, "{}\n");
8867 /* labeled-unicast routes live in the unicast table */
8868 if (safi
== SAFI_LABELED_UNICAST
)
8869 safi
= SAFI_UNICAST
;
8871 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8872 afi
, safi
, prd
, prefix_check
, pathtype
,
8876 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8877 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8880 struct lcommunity
*lcom
;
8886 b
= buffer_new(1024);
8887 for (i
= 0; i
< argc
; i
++) {
8889 buffer_putc(b
, ' ');
8891 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8893 buffer_putstr(b
, argv
[i
]->arg
);
8897 buffer_putc(b
, '\0');
8899 str
= buffer_getstr(b
);
8902 lcom
= lcommunity_str2com(str
);
8903 XFREE(MTYPE_TMP
, str
);
8905 vty_out(vty
, "%% Large-community malformed\n");
8909 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8913 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8914 const char *lcom
, afi_t afi
, safi_t safi
,
8917 struct community_list
*list
;
8919 list
= community_list_lookup(bgp_clist
, lcom
,
8920 LARGE_COMMUNITY_LIST_MASTER
);
8922 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8927 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8931 DEFUN (show_ip_bgp_large_community_list
,
8932 show_ip_bgp_large_community_list_cmd
,
8933 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8937 BGP_INSTANCE_HELP_STR
8939 BGP_SAFI_WITH_LABEL_HELP_STR
8940 "Display routes matching the large-community-list\n"
8941 "large-community-list number\n"
8942 "large-community-list name\n"
8946 afi_t afi
= AFI_IP6
;
8947 safi_t safi
= SAFI_UNICAST
;
8950 if (argv_find(argv
, argc
, "ip", &idx
))
8952 if (argv_find(argv
, argc
, "view", &idx
)
8953 || argv_find(argv
, argc
, "vrf", &idx
))
8954 vrf
= argv
[++idx
]->arg
;
8955 if (argv_find(argv
, argc
, "ipv4", &idx
)
8956 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8957 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8958 if (argv_find(argv
, argc
, "unicast", &idx
)
8959 || argv_find(argv
, argc
, "multicast", &idx
))
8960 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8963 int uj
= use_json(argc
, argv
);
8965 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8967 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8971 argv_find(argv
, argc
, "large-community-list", &idx
);
8972 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8975 DEFUN (show_ip_bgp_large_community
,
8976 show_ip_bgp_large_community_cmd
,
8977 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8981 BGP_INSTANCE_HELP_STR
8983 BGP_SAFI_WITH_LABEL_HELP_STR
8984 "Display routes matching the large-communities\n"
8985 "List of large-community numbers\n"
8989 afi_t afi
= AFI_IP6
;
8990 safi_t safi
= SAFI_UNICAST
;
8993 if (argv_find(argv
, argc
, "ip", &idx
))
8995 if (argv_find(argv
, argc
, "view", &idx
)
8996 || argv_find(argv
, argc
, "vrf", &idx
))
8997 vrf
= argv
[++idx
]->arg
;
8998 if (argv_find(argv
, argc
, "ipv4", &idx
)
8999 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9000 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9001 if (argv_find(argv
, argc
, "unicast", &idx
)
9002 || argv_find(argv
, argc
, "multicast", &idx
))
9003 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9006 int uj
= use_json(argc
, argv
);
9008 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9010 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9014 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9015 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9017 return bgp_show(vty
, bgp
, afi
, safi
,
9018 bgp_show_type_lcommunity_all
, NULL
, uj
);
9021 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9025 /* BGP route print out function without JSON */
9028 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9029 <dampening <parameters>\
9034 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9035 |community-list <(1-500)|WORD> [exact-match]\
9036 |A.B.C.D/M longer-prefixes\
9037 |X:X::X:X/M longer-prefixes\
9042 BGP_INSTANCE_HELP_STR
9044 BGP_SAFI_WITH_LABEL_HELP_STR
9045 "Display detailed information about dampening\n"
9046 "Display detail of configured dampening parameters\n"
9047 "Display routes matching the route-map\n"
9048 "A route-map to match on\n"
9049 "Display routes conforming to the prefix-list\n"
9050 "Prefix-list name\n"
9051 "Display routes conforming to the filter-list\n"
9052 "Regular expression access list name\n"
9053 "BGP RIB advertisement statistics\n"
9054 "Display routes matching the communities\n"
9056 "Do not send outside local AS (well-known community)\n"
9057 "Do not advertise to any peer (well-known community)\n"
9058 "Do not export to next AS (well-known community)\n"
9059 "Graceful shutdown (well-known community)\n"
9060 "Exact match of the communities\n"
9061 "Display routes matching the community-list\n"
9062 "community-list number\n"
9063 "community-list name\n"
9064 "Exact match of the communities\n"
9066 "Display route and more specific routes\n"
9068 "Display route and more specific routes\n")
9070 afi_t afi
= AFI_IP6
;
9071 safi_t safi
= SAFI_UNICAST
;
9072 int exact_match
= 0;
9073 struct bgp
*bgp
= NULL
;
9075 int idx_community_type
= 0;
9077 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9082 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9083 if (argv_find(argv
, argc
, "parameters", &idx
))
9084 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9087 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9088 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9089 safi
, bgp_show_type_prefix_list
);
9091 if (argv_find(argv
, argc
, "filter-list", &idx
))
9092 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9093 safi
, bgp_show_type_filter_list
);
9095 if (argv_find(argv
, argc
, "statistics", &idx
))
9096 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9098 if (argv_find(argv
, argc
, "route-map", &idx
))
9099 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9100 safi
, bgp_show_type_route_map
);
9102 if (argv_find(argv
, argc
, "community", &idx
)) {
9103 /* show a specific community */
9104 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9105 || argv_find(argv
, argc
, "no-advertise",
9106 &idx_community_type
)
9107 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9108 || argv_find(argv
, argc
, "graceful-shutdown",
9109 &idx_community_type
)
9110 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9112 if (argv_find(argv
, argc
, "exact-match", &idx
))
9114 return bgp_show_community(vty
, bgp
,
9115 argv
[idx_community_type
]->arg
,
9116 exact_match
, afi
, safi
);
9120 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9121 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9122 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9124 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9125 exact_match
, afi
, safi
);
9128 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9129 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9130 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9132 bgp_show_type_prefix_longer
);
9137 /* BGP route print out function with JSON */
9138 DEFUN (show_ip_bgp_json
,
9139 show_ip_bgp_json_cmd
,
9140 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9143 |dampening <flap-statistics|dampened-paths>\
9149 BGP_INSTANCE_HELP_STR
9151 BGP_SAFI_WITH_LABEL_HELP_STR
9152 "Display only routes with non-natural netmasks\n"
9153 "Display detailed information about dampening\n"
9154 "Display flap statistics of routes\n"
9155 "Display paths suppressed due to dampening\n"
9156 "Display routes matching the communities\n"
9159 afi_t afi
= AFI_IP6
;
9160 safi_t safi
= SAFI_UNICAST
;
9161 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9162 struct bgp
*bgp
= NULL
;
9165 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9170 int uj
= use_json(argc
, argv
);
9174 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9175 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9178 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9179 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9180 return bgp_show(vty
, bgp
, afi
, safi
,
9181 bgp_show_type_dampend_paths
, NULL
, uj
);
9182 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9183 return bgp_show(vty
, bgp
, afi
, safi
,
9184 bgp_show_type_flap_statistics
, NULL
,
9188 if (argv_find(argv
, argc
, "community", &idx
)) {
9189 /* show all communities */
9190 return bgp_show(vty
, bgp
, afi
, safi
,
9191 bgp_show_type_community_all
, NULL
, uj
);
9193 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9196 DEFUN (show_ip_bgp_route
,
9197 show_ip_bgp_route_cmd
,
9198 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9199 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9203 BGP_INSTANCE_HELP_STR
9205 BGP_SAFI_WITH_LABEL_HELP_STR
9206 "Network in the BGP routing table to display\n"
9208 "Network in the BGP routing table to display\n"
9210 "Display only the bestpath\n"
9211 "Display only multipaths\n"
9214 int prefix_check
= 0;
9216 afi_t afi
= AFI_IP6
;
9217 safi_t safi
= SAFI_UNICAST
;
9218 char *prefix
= NULL
;
9219 struct bgp
*bgp
= NULL
;
9220 enum bgp_path_type path_type
;
9221 uint8_t uj
= use_json(argc
, argv
);
9225 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9232 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9236 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9237 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9238 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9240 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9241 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9244 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9245 && afi
!= AFI_IP6
) {
9247 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9250 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9253 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9257 prefix
= argv
[idx
]->arg
;
9259 /* [<bestpath|multipath>] */
9260 if (argv_find(argv
, argc
, "bestpath", &idx
))
9261 path_type
= BGP_PATH_BESTPATH
;
9262 else if (argv_find(argv
, argc
, "multipath", &idx
))
9263 path_type
= BGP_PATH_MULTIPATH
;
9265 path_type
= BGP_PATH_ALL
;
9267 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9271 DEFUN (show_ip_bgp_regexp
,
9272 show_ip_bgp_regexp_cmd
,
9273 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9277 BGP_INSTANCE_HELP_STR
9279 BGP_SAFI_WITH_LABEL_HELP_STR
9280 "Display routes matching the AS path regular expression\n"
9281 "A regular-expression to match the BGP AS paths\n")
9283 afi_t afi
= AFI_IP6
;
9284 safi_t safi
= SAFI_UNICAST
;
9285 struct bgp
*bgp
= NULL
;
9288 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9293 // get index of regex
9294 argv_find(argv
, argc
, "regexp", &idx
);
9297 char *regstr
= argv_concat(argv
, argc
, idx
);
9298 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9299 bgp_show_type_regexp
);
9300 XFREE(MTYPE_TMP
, regstr
);
9304 DEFUN (show_ip_bgp_instance_all
,
9305 show_ip_bgp_instance_all_cmd
,
9306 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9310 BGP_INSTANCE_ALL_HELP_STR
9312 BGP_SAFI_WITH_LABEL_HELP_STR
9316 safi_t safi
= SAFI_UNICAST
;
9317 struct bgp
*bgp
= NULL
;
9320 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9325 int uj
= use_json(argc
, argv
);
9329 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9333 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9334 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9339 regex
= bgp_regcomp(regstr
);
9341 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9345 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9346 bgp_regex_free(regex
);
9350 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9351 const char *prefix_list_str
, afi_t afi
,
9352 safi_t safi
, enum bgp_show_type type
)
9354 struct prefix_list
*plist
;
9356 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9357 if (plist
== NULL
) {
9358 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9363 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9366 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9367 const char *filter
, afi_t afi
, safi_t safi
,
9368 enum bgp_show_type type
)
9370 struct as_list
*as_list
;
9372 as_list
= as_list_lookup(filter
);
9373 if (as_list
== NULL
) {
9374 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9379 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9382 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9383 const char *rmap_str
, afi_t afi
, safi_t safi
,
9384 enum bgp_show_type type
)
9386 struct route_map
*rmap
;
9388 rmap
= route_map_lookup_by_name(rmap_str
);
9390 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9394 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9397 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9398 const char *comstr
, int exact
, afi_t afi
,
9401 struct community
*com
;
9404 com
= community_str2com(comstr
);
9406 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9410 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9411 (exact
? bgp_show_type_community_exact
9412 : bgp_show_type_community
),
9414 community_free(com
);
9419 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9420 const char *com
, int exact
, afi_t afi
,
9423 struct community_list
*list
;
9425 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9427 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9431 return bgp_show(vty
, bgp
, afi
, safi
,
9432 (exact
? bgp_show_type_community_list_exact
9433 : bgp_show_type_community_list
),
9437 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9438 const char *prefix
, afi_t afi
, safi_t safi
,
9439 enum bgp_show_type type
)
9446 ret
= str2prefix(prefix
, p
);
9448 vty_out(vty
, "%% Malformed Prefix\n");
9452 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9457 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9458 const char *ip_str
, uint8_t use_json
)
9464 /* Get peer sockunion. */
9465 ret
= str2sockunion(ip_str
, &su
);
9467 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9469 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9473 json_object
*json_no
= NULL
;
9474 json_no
= json_object_new_object();
9475 json_object_string_add(
9477 "malformedAddressOrName",
9479 vty_out(vty
, "%s\n",
9480 json_object_to_json_string_ext(
9482 JSON_C_TO_STRING_PRETTY
));
9483 json_object_free(json_no
);
9486 "%% Malformed address or name: %s\n",
9494 /* Peer structure lookup. */
9495 peer
= peer_lookup(bgp
, &su
);
9498 json_object
*json_no
= NULL
;
9499 json_no
= json_object_new_object();
9500 json_object_string_add(json_no
, "warning",
9501 "No such neighbor");
9502 vty_out(vty
, "%s\n",
9503 json_object_to_json_string_ext(
9504 json_no
, JSON_C_TO_STRING_PRETTY
));
9505 json_object_free(json_no
);
9507 vty_out(vty
, "No such neighbor\n");
9515 BGP_STATS_MAXBITLEN
= 0,
9519 BGP_STATS_UNAGGREGATEABLE
,
9520 BGP_STATS_MAX_AGGREGATEABLE
,
9521 BGP_STATS_AGGREGATES
,
9523 BGP_STATS_ASPATH_COUNT
,
9524 BGP_STATS_ASPATH_MAXHOPS
,
9525 BGP_STATS_ASPATH_TOTHOPS
,
9526 BGP_STATS_ASPATH_MAXSIZE
,
9527 BGP_STATS_ASPATH_TOTSIZE
,
9528 BGP_STATS_ASN_HIGHEST
,
9532 static const char *table_stats_strs
[] = {
9533 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9534 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9535 [BGP_STATS_RIB
] = "Total Advertisements",
9536 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9537 [BGP_STATS_MAX_AGGREGATEABLE
] =
9538 "Maximum aggregateable prefixes",
9539 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9540 [BGP_STATS_SPACE
] = "Address space advertised",
9541 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9542 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9543 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9544 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9545 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9546 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9547 [BGP_STATS_MAX
] = NULL
,
9550 struct bgp_table_stats
{
9551 struct bgp_table
*table
;
9552 unsigned long long counts
[BGP_STATS_MAX
];
9557 #define TALLY_SIGFIG 100000
9558 static unsigned long
9559 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9561 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9562 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9563 unsigned long ret
= newtot
/ count
;
9565 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9572 static int bgp_table_stats_walker(struct thread
*t
)
9574 struct bgp_node
*rn
;
9575 struct bgp_node
*top
;
9576 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9577 unsigned int space
= 0;
9579 if (!(top
= bgp_table_top(ts
->table
)))
9582 switch (top
->p
.family
) {
9584 space
= IPV4_MAX_BITLEN
;
9587 space
= IPV6_MAX_BITLEN
;
9591 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9593 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9594 struct bgp_info
*ri
;
9595 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9596 unsigned int rinum
= 0;
9604 ts
->counts
[BGP_STATS_PREFIXES
]++;
9605 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9608 ts
->counts
[BGP_STATS_AVGPLEN
]
9609 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9610 ts
->counts
[BGP_STATS_AVGPLEN
],
9614 /* check if the prefix is included by any other announcements */
9615 while (prn
&& !prn
->info
)
9616 prn
= bgp_node_parent_nolock(prn
);
9618 if (prn
== NULL
|| prn
== top
) {
9619 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9620 /* announced address space */
9623 pow(2.0, space
- rn
->p
.prefixlen
);
9624 } else if (prn
->info
)
9625 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9627 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9629 ts
->counts
[BGP_STATS_RIB
]++;
9632 && (CHECK_FLAG(ri
->attr
->flag
,
9634 BGP_ATTR_ATOMIC_AGGREGATE
))))
9635 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9638 if (ri
->attr
&& ri
->attr
->aspath
) {
9640 aspath_count_hops(ri
->attr
->aspath
);
9642 aspath_size(ri
->attr
->aspath
);
9643 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9645 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9647 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9648 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9651 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9652 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9655 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9656 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9658 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9659 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9660 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9662 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9663 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9664 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9667 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9668 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9676 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9679 struct bgp_table_stats ts
;
9682 if (!bgp
->rib
[afi
][safi
]) {
9683 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9688 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9690 /* labeled-unicast routes live in the unicast table */
9691 if (safi
== SAFI_LABELED_UNICAST
)
9692 safi
= SAFI_UNICAST
;
9694 memset(&ts
, 0, sizeof(ts
));
9695 ts
.table
= bgp
->rib
[afi
][safi
];
9696 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9698 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9699 if (!table_stats_strs
[i
])
9704 case BGP_STATS_ASPATH_AVGHOPS
:
9705 case BGP_STATS_ASPATH_AVGSIZE
:
9706 case BGP_STATS_AVGPLEN
:
9707 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9708 vty_out (vty
, "%12.2f",
9709 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9712 case BGP_STATS_ASPATH_TOTHOPS
:
9713 case BGP_STATS_ASPATH_TOTSIZE
:
9714 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9715 vty_out(vty
, "%12.2f",
9717 ? (float)ts
.counts
[i
]
9719 [BGP_STATS_ASPATH_COUNT
]
9722 case BGP_STATS_TOTPLEN
:
9723 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9724 vty_out(vty
, "%12.2f",
9726 ? (float)ts
.counts
[i
]
9728 [BGP_STATS_PREFIXES
]
9731 case BGP_STATS_SPACE
:
9732 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9733 vty_out(vty
, "%12g\n", ts
.total_space
);
9735 if (afi
== AFI_IP6
) {
9736 vty_out(vty
, "%30s: ", "/32 equivalent ");
9737 vty_out(vty
, "%12g\n",
9738 ts
.total_space
* pow(2.0, -128 + 32));
9739 vty_out(vty
, "%30s: ", "/48 equivalent ");
9740 vty_out(vty
, "%12g\n",
9741 ts
.total_space
* pow(2.0, -128 + 48));
9743 vty_out(vty
, "%30s: ", "% announced ");
9744 vty_out(vty
, "%12.2f\n",
9745 ts
.total_space
* 100. * pow(2.0, -32));
9746 vty_out(vty
, "%30s: ", "/8 equivalent ");
9747 vty_out(vty
, "%12.2f\n",
9748 ts
.total_space
* pow(2.0, -32 + 8));
9749 vty_out(vty
, "%30s: ", "/24 equivalent ");
9750 vty_out(vty
, "%12.2f\n",
9751 ts
.total_space
* pow(2.0, -32 + 24));
9755 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9756 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9773 PCOUNT_PFCNT
, /* the figure we display to users */
9777 static const char *pcount_strs
[] = {
9778 [PCOUNT_ADJ_IN
] = "Adj-in",
9779 [PCOUNT_DAMPED
] = "Damped",
9780 [PCOUNT_REMOVED
] = "Removed",
9781 [PCOUNT_HISTORY
] = "History",
9782 [PCOUNT_STALE
] = "Stale",
9783 [PCOUNT_VALID
] = "Valid",
9784 [PCOUNT_ALL
] = "All RIB",
9785 [PCOUNT_COUNTED
] = "PfxCt counted",
9786 [PCOUNT_PFCNT
] = "Useable",
9787 [PCOUNT_MAX
] = NULL
,
9790 struct peer_pcounts
{
9791 unsigned int count
[PCOUNT_MAX
];
9792 const struct peer
*peer
;
9793 const struct bgp_table
*table
;
9796 static int bgp_peer_count_walker(struct thread
*t
)
9798 struct bgp_node
*rn
;
9799 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9800 const struct peer
*peer
= pc
->peer
;
9802 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9803 struct bgp_adj_in
*ain
;
9804 struct bgp_info
*ri
;
9806 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9807 if (ain
->peer
== peer
)
9808 pc
->count
[PCOUNT_ADJ_IN
]++;
9810 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9811 char buf
[SU_ADDRSTRLEN
];
9813 if (ri
->peer
!= peer
)
9816 pc
->count
[PCOUNT_ALL
]++;
9818 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9819 pc
->count
[PCOUNT_DAMPED
]++;
9820 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9821 pc
->count
[PCOUNT_HISTORY
]++;
9822 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9823 pc
->count
[PCOUNT_REMOVED
]++;
9824 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9825 pc
->count
[PCOUNT_STALE
]++;
9826 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9827 pc
->count
[PCOUNT_VALID
]++;
9828 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9829 pc
->count
[PCOUNT_PFCNT
]++;
9831 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9832 pc
->count
[PCOUNT_COUNTED
]++;
9833 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9835 "%s [pcount] %s/%d is counted but flags 0x%x",
9837 inet_ntop(rn
->p
.family
,
9838 &rn
->p
.u
.prefix
, buf
,
9840 rn
->p
.prefixlen
, ri
->flags
);
9842 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9844 "%s [pcount] %s/%d not counted but flags 0x%x",
9846 inet_ntop(rn
->p
.family
,
9847 &rn
->p
.u
.prefix
, buf
,
9849 rn
->p
.prefixlen
, ri
->flags
);
9856 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9857 safi_t safi
, uint8_t use_json
)
9859 struct peer_pcounts pcounts
= {.peer
= peer
};
9861 json_object
*json
= NULL
;
9862 json_object
*json_loop
= NULL
;
9865 json
= json_object_new_object();
9866 json_loop
= json_object_new_object();
9869 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9870 || !peer
->bgp
->rib
[afi
][safi
]) {
9872 json_object_string_add(
9874 "No such neighbor or address family");
9875 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9876 json_object_free(json
);
9878 vty_out(vty
, "%% No such neighbor or address family\n");
9883 memset(&pcounts
, 0, sizeof(pcounts
));
9884 pcounts
.peer
= peer
;
9885 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9887 /* in-place call via thread subsystem so as to record execution time
9888 * stats for the thread-walk (i.e. ensure this can't be blamed on
9889 * on just vty_read()).
9891 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9894 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9895 json_object_string_add(json
, "multiProtocol",
9896 afi_safi_print(afi
, safi
));
9897 json_object_int_add(json
, "pfxCounter",
9898 peer
->pcount
[afi
][safi
]);
9900 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9901 json_object_int_add(json_loop
, pcount_strs
[i
],
9904 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9906 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9907 json_object_string_add(json
, "pfxctDriftFor",
9909 json_object_string_add(
9910 json
, "recommended",
9911 "Please report this bug, with the above command output");
9913 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9914 json
, JSON_C_TO_STRING_PRETTY
));
9915 json_object_free(json
);
9919 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9920 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9921 peer
->hostname
, peer
->host
,
9922 afi_safi_print(afi
, safi
));
9924 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9925 afi_safi_print(afi
, safi
));
9928 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9929 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9931 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9932 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9935 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9936 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9938 "Please report this bug, with the above command output\n");
9945 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9946 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9947 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9948 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9952 BGP_INSTANCE_HELP_STR
9955 "Detailed information on TCP and BGP neighbor connections\n"
9956 "Neighbor to display information about\n"
9957 "Neighbor to display information about\n"
9958 "Neighbor on BGP configured interface\n"
9959 "Display detailed prefix count information\n"
9962 afi_t afi
= AFI_IP6
;
9963 safi_t safi
= SAFI_UNICAST
;
9966 struct bgp
*bgp
= NULL
;
9968 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9973 int uj
= use_json(argc
, argv
);
9977 argv_find(argv
, argc
, "neighbors", &idx
);
9978 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9982 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9985 #ifdef KEEP_OLD_VPN_COMMANDS
9986 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9987 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9988 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9993 "Display information about all VPNv4 NLRIs\n"
9994 "Detailed information on TCP and BGP neighbor connections\n"
9995 "Neighbor to display information about\n"
9996 "Neighbor to display information about\n"
9997 "Neighbor on BGP configured interface\n"
9998 "Display detailed prefix count information\n"
10003 uint8_t uj
= use_json(argc
, argv
);
10005 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10007 return CMD_WARNING
;
10009 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10012 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10013 show_ip_bgp_vpn_all_route_prefix_cmd
,
10014 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10019 "Display information about all VPNv4 NLRIs\n"
10020 "Network in the BGP routing table to display\n"
10021 "Network in the BGP routing table to display\n"
10025 char *network
= NULL
;
10026 struct bgp
*bgp
= bgp_get_default();
10028 vty_out(vty
, "Can't find default instance\n");
10029 return CMD_WARNING
;
10032 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10033 network
= argv
[idx
]->arg
;
10034 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10035 network
= argv
[idx
]->arg
;
10037 vty_out(vty
, "Unable to figure out Network\n");
10038 return CMD_WARNING
;
10041 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10042 BGP_PATH_ALL
, use_json(argc
, argv
));
10044 #endif /* KEEP_OLD_VPN_COMMANDS */
10046 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10047 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10048 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10054 "Display information about all EVPN NLRIs\n"
10055 "Network in the BGP routing table to display\n"
10056 "Network in the BGP routing table to display\n"
10060 char *network
= NULL
;
10062 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10063 network
= argv
[idx
]->arg
;
10064 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10065 network
= argv
[idx
]->arg
;
10067 vty_out(vty
, "Unable to figure out Network\n");
10068 return CMD_WARNING
;
10070 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10071 BGP_PATH_ALL
, use_json(argc
, argv
));
10074 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10075 safi_t safi
, int in
, const char *rmap_name
,
10076 uint8_t use_json
, json_object
*json
)
10078 struct bgp_table
*table
;
10079 struct bgp_adj_in
*ain
;
10080 struct bgp_adj_out
*adj
;
10081 unsigned long output_count
;
10082 unsigned long filtered_count
;
10083 struct bgp_node
*rn
;
10089 struct update_subgroup
*subgrp
;
10090 json_object
*json_scode
= NULL
;
10091 json_object
*json_ocode
= NULL
;
10092 json_object
*json_ar
= NULL
;
10093 struct peer_af
*paf
;
10096 json_scode
= json_object_new_object();
10097 json_ocode
= json_object_new_object();
10098 json_ar
= json_object_new_object();
10100 json_object_string_add(json_scode
, "suppressed", "s");
10101 json_object_string_add(json_scode
, "damped", "d");
10102 json_object_string_add(json_scode
, "history", "h");
10103 json_object_string_add(json_scode
, "valid", "*");
10104 json_object_string_add(json_scode
, "best", ">");
10105 json_object_string_add(json_scode
, "multipath", "=");
10106 json_object_string_add(json_scode
, "internal", "i");
10107 json_object_string_add(json_scode
, "ribFailure", "r");
10108 json_object_string_add(json_scode
, "stale", "S");
10109 json_object_string_add(json_scode
, "removed", "R");
10111 json_object_string_add(json_ocode
, "igp", "i");
10112 json_object_string_add(json_ocode
, "egp", "e");
10113 json_object_string_add(json_ocode
, "incomplete", "?");
10120 json_object_string_add(json
, "alert", "no BGP");
10121 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10122 json_object_free(json
);
10124 vty_out(vty
, "%% No bgp\n");
10128 table
= bgp
->rib
[afi
][safi
];
10130 output_count
= filtered_count
= 0;
10131 subgrp
= peer_subgroup(peer
, afi
, safi
);
10134 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10136 json_object_int_add(json
, "bgpTableVersion",
10138 json_object_string_add(json
, "bgpLocalRouterId",
10139 inet_ntoa(bgp
->router_id
));
10140 json_object_object_add(json
, "bgpStatusCodes",
10142 json_object_object_add(json
, "bgpOriginCodes",
10144 json_object_string_add(json
,
10145 "bgpOriginatingDefaultNetwork",
10148 vty_out(vty
, "BGP table version is %" PRIu64
10149 ", local router ID is %s\n",
10150 table
->version
, inet_ntoa(bgp
->router_id
));
10151 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10152 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10154 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10159 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10161 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10162 if (ain
->peer
!= peer
)
10166 json_object_int_add(
10167 json
, "bgpTableVersion",
10169 json_object_string_add(
10171 "bgpLocalRouterId",
10174 json_object_object_add(
10175 json
, "bgpStatusCodes",
10177 json_object_object_add(
10178 json
, "bgpOriginCodes",
10182 "BGP table version is 0, local router ID is %s\n",
10186 BGP_SHOW_SCODE_HEADER
);
10188 BGP_SHOW_OCODE_HEADER
);
10194 vty_out(vty
, BGP_SHOW_HEADER
);
10198 bgp_attr_dup(&attr
, ain
->attr
);
10199 if (bgp_input_modifier(peer
, &rn
->p
,
10203 route_vty_out_tmp(vty
, &rn
->p
,
10213 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10214 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10215 if (paf
->peer
!= peer
)
10220 json_object_int_add(
10224 json_object_string_add(
10226 "bgpLocalRouterId",
10229 json_object_object_add(
10233 json_object_object_add(
10239 "BGP table version is %" PRIu64
10240 ", local router ID is %s\n",
10245 BGP_SHOW_SCODE_HEADER
);
10247 BGP_SHOW_OCODE_HEADER
);
10260 bgp_attr_dup(&attr
, adj
->attr
);
10261 ret
= bgp_output_modifier(
10262 peer
, &rn
->p
, &attr
,
10263 afi
, safi
, rmap_name
);
10264 if (ret
!= RMAP_DENY
) {
10274 bgp_attr_undup(&attr
,
10281 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10283 if (output_count
!= 0) {
10285 json_object_int_add(json
, "totalPrefixCounter",
10288 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10292 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10293 json
, JSON_C_TO_STRING_PRETTY
));
10294 json_object_free(json
);
10298 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10299 safi_t safi
, int in
, const char *rmap_name
,
10302 json_object
*json
= NULL
;
10305 json
= json_object_new_object();
10307 /* labeled-unicast routes live in the unicast table */
10308 if (safi
== SAFI_LABELED_UNICAST
)
10309 safi
= SAFI_UNICAST
;
10311 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10313 json_object_string_add(
10315 "No such neighbor or address family");
10316 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10317 json_object_free(json
);
10319 vty_out(vty
, "%% No such neighbor or address family\n");
10321 return CMD_WARNING
;
10325 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10326 PEER_FLAG_SOFT_RECONFIG
)) {
10328 json_object_string_add(
10330 "Inbound soft reconfiguration not enabled");
10331 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10332 json_object_free(json
);
10335 "%% Inbound soft reconfiguration not enabled\n");
10337 return CMD_WARNING
;
10340 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10342 return CMD_SUCCESS
;
10345 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10346 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10347 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10348 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10352 BGP_INSTANCE_HELP_STR
10354 BGP_SAFI_WITH_LABEL_HELP_STR
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 the received routes from neighbor\n"
10360 "Display the routes advertised to a BGP neighbor\n"
10361 "Route-map to modify the attributes\n"
10362 "Name of the route map\n"
10365 afi_t afi
= AFI_IP6
;
10366 safi_t safi
= SAFI_UNICAST
;
10367 char *rmap_name
= NULL
;
10368 char *peerstr
= NULL
;
10370 struct bgp
*bgp
= NULL
;
10375 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10378 return CMD_WARNING
;
10380 int uj
= use_json(argc
, argv
);
10384 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10385 argv_find(argv
, argc
, "neighbors", &idx
);
10386 peerstr
= argv
[++idx
]->arg
;
10388 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10390 return CMD_WARNING
;
10392 if (argv_find(argv
, argc
, "received-routes", &idx
))
10394 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10396 if (argv_find(argv
, argc
, "route-map", &idx
))
10397 rmap_name
= argv
[++idx
]->arg
;
10399 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10402 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10403 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10404 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10410 "Address Family modifier\n"
10411 "Detailed information on TCP and BGP neighbor connections\n"
10412 "Neighbor to display information about\n"
10413 "Neighbor to display information about\n"
10414 "Neighbor on BGP configured interface\n"
10415 "Display information received from a BGP neighbor\n"
10416 "Display the prefixlist filter\n"
10419 afi_t afi
= AFI_IP6
;
10420 safi_t safi
= SAFI_UNICAST
;
10421 char *peerstr
= NULL
;
10424 union sockunion su
;
10430 /* show [ip] bgp */
10431 if (argv_find(argv
, argc
, "ip", &idx
))
10433 /* [<ipv4|ipv6> [unicast]] */
10434 if (argv_find(argv
, argc
, "ipv4", &idx
))
10436 if (argv_find(argv
, argc
, "ipv6", &idx
))
10438 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10439 argv_find(argv
, argc
, "neighbors", &idx
);
10440 peerstr
= argv
[++idx
]->arg
;
10442 uint8_t uj
= use_json(argc
, argv
);
10444 ret
= str2sockunion(peerstr
, &su
);
10446 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10449 vty_out(vty
, "{}\n");
10452 "%% Malformed address or name: %s\n",
10454 return CMD_WARNING
;
10457 peer
= peer_lookup(NULL
, &su
);
10460 vty_out(vty
, "{}\n");
10462 vty_out(vty
, "No peer\n");
10463 return CMD_WARNING
;
10467 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10468 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10471 vty_out(vty
, "Address Family: %s\n",
10472 afi_safi_print(afi
, safi
));
10473 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10476 vty_out(vty
, "{}\n");
10478 vty_out(vty
, "No functional output\n");
10481 return CMD_SUCCESS
;
10484 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10485 afi_t afi
, safi_t safi
,
10486 enum bgp_show_type type
, uint8_t use_json
)
10488 /* labeled-unicast routes live in the unicast table */
10489 if (safi
== SAFI_LABELED_UNICAST
)
10490 safi
= SAFI_UNICAST
;
10492 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10494 json_object
*json_no
= NULL
;
10495 json_no
= json_object_new_object();
10496 json_object_string_add(
10497 json_no
, "warning",
10498 "No such neighbor or address family");
10499 vty_out(vty
, "%s\n",
10500 json_object_to_json_string(json_no
));
10501 json_object_free(json_no
);
10503 vty_out(vty
, "%% No such neighbor or address family\n");
10504 return CMD_WARNING
;
10507 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10510 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10511 show_ip_bgp_flowspec_routes_detailed_cmd
,
10512 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10516 BGP_INSTANCE_HELP_STR
10519 "Detailed information on flowspec entries\n"
10522 afi_t afi
= AFI_IP
;
10523 safi_t safi
= SAFI_UNICAST
;
10524 struct bgp
*bgp
= NULL
;
10527 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10530 return CMD_WARNING
;
10532 return bgp_show(vty
, bgp
, afi
, safi
,
10533 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10536 DEFUN (show_ip_bgp_neighbor_routes
,
10537 show_ip_bgp_neighbor_routes_cmd
,
10538 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10539 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10543 BGP_INSTANCE_HELP_STR
10545 BGP_SAFI_WITH_LABEL_HELP_STR
10546 "Detailed information on TCP and BGP neighbor connections\n"
10547 "Neighbor to display information about\n"
10548 "Neighbor to display information about\n"
10549 "Neighbor on BGP configured interface\n"
10550 "Display flap statistics of the routes learned from neighbor\n"
10551 "Display the dampened routes received from neighbor\n"
10552 "Display routes learned from neighbor\n"
10555 char *peerstr
= NULL
;
10556 struct bgp
*bgp
= NULL
;
10557 afi_t afi
= AFI_IP6
;
10558 safi_t safi
= SAFI_UNICAST
;
10560 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10564 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10567 return CMD_WARNING
;
10569 int uj
= use_json(argc
, argv
);
10573 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10574 argv_find(argv
, argc
, "neighbors", &idx
);
10575 peerstr
= argv
[++idx
]->arg
;
10577 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10579 vty_out(vty
, "No such neighbor\n");
10580 return CMD_WARNING
;
10583 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10584 sh_type
= bgp_show_type_flap_neighbor
;
10585 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10586 sh_type
= bgp_show_type_damp_neighbor
;
10587 else if (argv_find(argv
, argc
, "routes", &idx
))
10588 sh_type
= bgp_show_type_neighbor
;
10590 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10593 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10595 struct bgp_distance
{
10596 /* Distance value for the IP source prefix. */
10599 /* Name of the access-list to be matched. */
10603 DEFUN (show_bgp_afi_vpn_rd_route
,
10604 show_bgp_afi_vpn_rd_route_cmd
,
10605 "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]",
10609 "Address Family modifier\n"
10610 "Display information for a route distinguisher\n"
10611 "Route Distinguisher\n"
10612 "Network in the BGP routing table to display\n"
10613 "Network in the BGP routing table to display\n"
10617 struct prefix_rd prd
;
10618 afi_t afi
= AFI_MAX
;
10621 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10622 vty_out(vty
, "%% Malformed Address Family\n");
10623 return CMD_WARNING
;
10626 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10628 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10629 return CMD_WARNING
;
10632 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10633 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10636 static struct bgp_distance
*bgp_distance_new(void)
10638 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10641 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10643 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10646 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10647 const char *ip_str
, const char *access_list_str
)
10654 struct bgp_node
*rn
;
10655 struct bgp_distance
*bdistance
;
10657 afi
= bgp_node_afi(vty
);
10658 safi
= bgp_node_safi(vty
);
10660 ret
= str2prefix(ip_str
, &p
);
10662 vty_out(vty
, "Malformed prefix\n");
10663 return CMD_WARNING_CONFIG_FAILED
;
10666 distance
= atoi(distance_str
);
10668 /* Get BGP distance node. */
10669 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10671 bdistance
= rn
->info
;
10672 bgp_unlock_node(rn
);
10674 bdistance
= bgp_distance_new();
10675 rn
->info
= bdistance
;
10678 /* Set distance value. */
10679 bdistance
->distance
= distance
;
10681 /* Reset access-list configuration. */
10682 if (bdistance
->access_list
) {
10683 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10684 bdistance
->access_list
= NULL
;
10686 if (access_list_str
)
10687 bdistance
->access_list
=
10688 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10690 return CMD_SUCCESS
;
10693 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10694 const char *ip_str
, const char *access_list_str
)
10701 struct bgp_node
*rn
;
10702 struct bgp_distance
*bdistance
;
10704 afi
= bgp_node_afi(vty
);
10705 safi
= bgp_node_safi(vty
);
10707 ret
= str2prefix(ip_str
, &p
);
10709 vty_out(vty
, "Malformed prefix\n");
10710 return CMD_WARNING_CONFIG_FAILED
;
10713 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10714 (struct prefix
*)&p
);
10716 vty_out(vty
, "Can't find specified prefix\n");
10717 return CMD_WARNING_CONFIG_FAILED
;
10720 bdistance
= rn
->info
;
10721 distance
= atoi(distance_str
);
10723 if (bdistance
->distance
!= distance
) {
10724 vty_out(vty
, "Distance does not match configured\n");
10725 return CMD_WARNING_CONFIG_FAILED
;
10728 if (bdistance
->access_list
)
10729 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10730 bgp_distance_free(bdistance
);
10733 bgp_unlock_node(rn
);
10734 bgp_unlock_node(rn
);
10736 return CMD_SUCCESS
;
10739 /* Apply BGP information to distance method. */
10740 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10741 safi_t safi
, struct bgp
*bgp
)
10743 struct bgp_node
*rn
;
10746 struct bgp_distance
*bdistance
;
10747 struct access_list
*alist
;
10748 struct bgp_static
*bgp_static
;
10753 peer
= rinfo
->peer
;
10755 /* Check source address. */
10756 sockunion2hostprefix(&peer
->su
, &q
);
10757 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10759 bdistance
= rn
->info
;
10760 bgp_unlock_node(rn
);
10762 if (bdistance
->access_list
) {
10763 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10765 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10766 return bdistance
->distance
;
10768 return bdistance
->distance
;
10771 /* Backdoor check. */
10772 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10774 bgp_static
= rn
->info
;
10775 bgp_unlock_node(rn
);
10777 if (bgp_static
->backdoor
) {
10778 if (bgp
->distance_local
[afi
][safi
])
10779 return bgp
->distance_local
[afi
][safi
];
10781 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10785 if (peer
->sort
== BGP_PEER_EBGP
) {
10786 if (bgp
->distance_ebgp
[afi
][safi
])
10787 return bgp
->distance_ebgp
[afi
][safi
];
10788 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10790 if (bgp
->distance_ibgp
[afi
][safi
])
10791 return bgp
->distance_ibgp
[afi
][safi
];
10792 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10796 DEFUN (bgp_distance
,
10798 "distance bgp (1-255) (1-255) (1-255)",
10799 "Define an administrative distance\n"
10801 "Distance for routes external to the AS\n"
10802 "Distance for routes internal to the AS\n"
10803 "Distance for local routes\n")
10805 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10806 int idx_number
= 2;
10807 int idx_number_2
= 3;
10808 int idx_number_3
= 4;
10812 afi
= bgp_node_afi(vty
);
10813 safi
= bgp_node_safi(vty
);
10815 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10816 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10817 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10818 return CMD_SUCCESS
;
10821 DEFUN (no_bgp_distance
,
10822 no_bgp_distance_cmd
,
10823 "no distance bgp [(1-255) (1-255) (1-255)]",
10825 "Define an administrative distance\n"
10827 "Distance for routes external to the AS\n"
10828 "Distance for routes internal to the AS\n"
10829 "Distance for local routes\n")
10831 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10835 afi
= bgp_node_afi(vty
);
10836 safi
= bgp_node_safi(vty
);
10838 bgp
->distance_ebgp
[afi
][safi
] = 0;
10839 bgp
->distance_ibgp
[afi
][safi
] = 0;
10840 bgp
->distance_local
[afi
][safi
] = 0;
10841 return CMD_SUCCESS
;
10845 DEFUN (bgp_distance_source
,
10846 bgp_distance_source_cmd
,
10847 "distance (1-255) A.B.C.D/M",
10848 "Define an administrative distance\n"
10849 "Administrative distance\n"
10850 "IP source prefix\n")
10852 int idx_number
= 1;
10853 int idx_ipv4_prefixlen
= 2;
10854 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10855 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10856 return CMD_SUCCESS
;
10859 DEFUN (no_bgp_distance_source
,
10860 no_bgp_distance_source_cmd
,
10861 "no distance (1-255) A.B.C.D/M",
10863 "Define an administrative distance\n"
10864 "Administrative distance\n"
10865 "IP source prefix\n")
10867 int idx_number
= 2;
10868 int idx_ipv4_prefixlen
= 3;
10869 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10870 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10871 return CMD_SUCCESS
;
10874 DEFUN (bgp_distance_source_access_list
,
10875 bgp_distance_source_access_list_cmd
,
10876 "distance (1-255) A.B.C.D/M WORD",
10877 "Define an administrative distance\n"
10878 "Administrative distance\n"
10879 "IP source prefix\n"
10880 "Access list name\n")
10882 int idx_number
= 1;
10883 int idx_ipv4_prefixlen
= 2;
10885 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10886 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10887 return CMD_SUCCESS
;
10890 DEFUN (no_bgp_distance_source_access_list
,
10891 no_bgp_distance_source_access_list_cmd
,
10892 "no distance (1-255) A.B.C.D/M WORD",
10894 "Define an administrative distance\n"
10895 "Administrative distance\n"
10896 "IP source prefix\n"
10897 "Access list name\n")
10899 int idx_number
= 2;
10900 int idx_ipv4_prefixlen
= 3;
10902 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10903 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10904 return CMD_SUCCESS
;
10907 DEFUN (ipv6_bgp_distance_source
,
10908 ipv6_bgp_distance_source_cmd
,
10909 "distance (1-255) X:X::X:X/M",
10910 "Define an administrative distance\n"
10911 "Administrative distance\n"
10912 "IP source prefix\n")
10914 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10915 return CMD_SUCCESS
;
10918 DEFUN (no_ipv6_bgp_distance_source
,
10919 no_ipv6_bgp_distance_source_cmd
,
10920 "no distance (1-255) X:X::X:X/M",
10922 "Define an administrative distance\n"
10923 "Administrative distance\n"
10924 "IP source prefix\n")
10926 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10927 return CMD_SUCCESS
;
10930 DEFUN (ipv6_bgp_distance_source_access_list
,
10931 ipv6_bgp_distance_source_access_list_cmd
,
10932 "distance (1-255) X:X::X:X/M WORD",
10933 "Define an administrative distance\n"
10934 "Administrative distance\n"
10935 "IP source prefix\n"
10936 "Access list name\n")
10938 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10939 return CMD_SUCCESS
;
10942 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10943 no_ipv6_bgp_distance_source_access_list_cmd
,
10944 "no distance (1-255) X:X::X:X/M WORD",
10946 "Define an administrative distance\n"
10947 "Administrative distance\n"
10948 "IP source prefix\n"
10949 "Access list name\n")
10951 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10952 return CMD_SUCCESS
;
10955 DEFUN (bgp_damp_set
,
10957 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10958 "BGP Specific commands\n"
10959 "Enable route-flap dampening\n"
10960 "Half-life time for the penalty\n"
10961 "Value to start reusing a route\n"
10962 "Value to start suppressing a route\n"
10963 "Maximum duration to suppress a stable route\n")
10965 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10966 int idx_half_life
= 2;
10968 int idx_suppress
= 4;
10969 int idx_max_suppress
= 5;
10970 int half
= DEFAULT_HALF_LIFE
* 60;
10971 int reuse
= DEFAULT_REUSE
;
10972 int suppress
= DEFAULT_SUPPRESS
;
10973 int max
= 4 * half
;
10976 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10977 reuse
= atoi(argv
[idx_reuse
]->arg
);
10978 suppress
= atoi(argv
[idx_suppress
]->arg
);
10979 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10980 } else if (argc
== 3) {
10981 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10985 if (suppress
< reuse
) {
10987 "Suppress value cannot be less than reuse value \n");
10991 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10992 reuse
, suppress
, max
);
10995 DEFUN (bgp_damp_unset
,
10996 bgp_damp_unset_cmd
,
10997 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10999 "BGP Specific commands\n"
11000 "Enable route-flap dampening\n"
11001 "Half-life time for the penalty\n"
11002 "Value to start reusing a route\n"
11003 "Value to start suppressing a route\n"
11004 "Maximum duration to suppress a stable route\n")
11006 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11007 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11010 /* Display specified route of BGP table. */
11011 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11012 const char *ip_str
, afi_t afi
, safi_t safi
,
11013 struct prefix_rd
*prd
, int prefix_check
)
11016 struct prefix match
;
11017 struct bgp_node
*rn
;
11018 struct bgp_node
*rm
;
11019 struct bgp_info
*ri
;
11020 struct bgp_info
*ri_temp
;
11022 struct bgp_table
*table
;
11024 /* BGP structure lookup. */
11026 bgp
= bgp_lookup_by_name(view_name
);
11028 vty_out(vty
, "%% Can't find BGP instance %s\n",
11030 return CMD_WARNING
;
11033 bgp
= bgp_get_default();
11035 vty_out(vty
, "%% No BGP process is configured\n");
11036 return CMD_WARNING
;
11040 /* Check IP address argument. */
11041 ret
= str2prefix(ip_str
, &match
);
11043 vty_out(vty
, "%% address is malformed\n");
11044 return CMD_WARNING
;
11047 match
.family
= afi2family(afi
);
11049 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11050 || (safi
== SAFI_EVPN
)) {
11051 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11052 rn
= bgp_route_next(rn
)) {
11053 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11055 if ((table
= rn
->info
) == NULL
)
11057 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11061 || rm
->p
.prefixlen
== match
.prefixlen
) {
11064 if (ri
->extra
&& ri
->extra
->damp_info
) {
11065 ri_temp
= ri
->next
;
11066 bgp_damp_info_free(
11067 ri
->extra
->damp_info
,
11075 bgp_unlock_node(rm
);
11078 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11081 || rn
->p
.prefixlen
== match
.prefixlen
) {
11084 if (ri
->extra
&& ri
->extra
->damp_info
) {
11085 ri_temp
= ri
->next
;
11086 bgp_damp_info_free(
11087 ri
->extra
->damp_info
,
11095 bgp_unlock_node(rn
);
11099 return CMD_SUCCESS
;
11102 DEFUN (clear_ip_bgp_dampening
,
11103 clear_ip_bgp_dampening_cmd
,
11104 "clear ip bgp dampening",
11108 "Clear route flap dampening information\n")
11110 bgp_damp_info_clean();
11111 return CMD_SUCCESS
;
11114 DEFUN (clear_ip_bgp_dampening_prefix
,
11115 clear_ip_bgp_dampening_prefix_cmd
,
11116 "clear ip bgp dampening A.B.C.D/M",
11120 "Clear route flap dampening information\n"
11123 int idx_ipv4_prefixlen
= 4;
11124 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11125 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11128 DEFUN (clear_ip_bgp_dampening_address
,
11129 clear_ip_bgp_dampening_address_cmd
,
11130 "clear ip bgp dampening A.B.C.D",
11134 "Clear route flap dampening information\n"
11135 "Network to clear damping information\n")
11138 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11139 SAFI_UNICAST
, NULL
, 0);
11142 DEFUN (clear_ip_bgp_dampening_address_mask
,
11143 clear_ip_bgp_dampening_address_mask_cmd
,
11144 "clear ip bgp dampening A.B.C.D A.B.C.D",
11148 "Clear route flap dampening information\n"
11149 "Network to clear damping information\n"
11153 int idx_ipv4_2
= 5;
11155 char prefix_str
[BUFSIZ
];
11157 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11160 vty_out(vty
, "%% Inconsistent address and mask\n");
11161 return CMD_WARNING
;
11164 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11168 /* also used for encap safi */
11169 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11170 afi_t afi
, safi_t safi
)
11172 struct bgp_node
*prn
;
11173 struct bgp_node
*rn
;
11174 struct bgp_table
*table
;
11176 struct prefix_rd
*prd
;
11177 struct bgp_static
*bgp_static
;
11178 mpls_label_t label
;
11179 char buf
[SU_ADDRSTRLEN
];
11180 char rdbuf
[RD_ADDRSTRLEN
];
11182 /* Network configuration. */
11183 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11184 prn
= bgp_route_next(prn
)) {
11185 if ((table
= prn
->info
) == NULL
)
11188 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11189 if ((bgp_static
= rn
->info
) == NULL
)
11193 prd
= (struct prefix_rd
*)&prn
->p
;
11195 /* "network" configuration display. */
11196 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11197 label
= decode_label(&bgp_static
->label
);
11199 vty_out(vty
, " network %s/%d rd %s",
11200 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11202 p
->prefixlen
, rdbuf
);
11203 if (safi
== SAFI_MPLS_VPN
)
11204 vty_out(vty
, " label %u", label
);
11206 if (bgp_static
->rmap
.name
)
11207 vty_out(vty
, " route-map %s",
11208 bgp_static
->rmap
.name
);
11210 if (bgp_static
->backdoor
)
11211 vty_out(vty
, " backdoor");
11213 vty_out(vty
, "\n");
11218 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11219 afi_t afi
, safi_t safi
)
11221 struct bgp_node
*prn
;
11222 struct bgp_node
*rn
;
11223 struct bgp_table
*table
;
11225 struct prefix_rd
*prd
;
11226 struct bgp_static
*bgp_static
;
11227 char buf
[PREFIX_STRLEN
];
11228 char buf2
[SU_ADDRSTRLEN
];
11229 char rdbuf
[RD_ADDRSTRLEN
];
11231 /* Network configuration. */
11232 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11233 prn
= bgp_route_next(prn
)) {
11234 if ((table
= prn
->info
) == NULL
)
11237 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11238 if ((bgp_static
= rn
->info
) == NULL
)
11241 char *macrouter
= NULL
;
11244 if (bgp_static
->router_mac
)
11245 macrouter
= prefix_mac2str(
11246 bgp_static
->router_mac
, NULL
, 0);
11247 if (bgp_static
->eth_s_id
)
11248 esi
= esi2str(bgp_static
->eth_s_id
);
11250 prd
= (struct prefix_rd
*)&prn
->p
;
11252 /* "network" configuration display. */
11253 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11254 if (p
->u
.prefix_evpn
.route_type
== 5) {
11255 char local_buf
[PREFIX_STRLEN
];
11256 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11257 struct prefix_evpn
*)p
)
11261 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11262 local_buf
, PREFIX_STRLEN
);
11263 sprintf(buf
, "%s/%u", local_buf
,
11264 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11266 prefix2str(p
, buf
, sizeof(buf
));
11269 if (bgp_static
->gatewayIp
.family
== AF_INET
11270 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11271 inet_ntop(bgp_static
->gatewayIp
.family
,
11272 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11275 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11277 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11278 decode_label(&bgp_static
->label
), esi
, buf2
,
11282 XFREE(MTYPE_TMP
, macrouter
);
11284 XFREE(MTYPE_TMP
, esi
);
11289 /* Configuration of static route announcement and aggregate
11291 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11294 struct bgp_node
*rn
;
11296 struct bgp_static
*bgp_static
;
11297 struct bgp_aggregate
*bgp_aggregate
;
11298 char buf
[SU_ADDRSTRLEN
];
11300 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11301 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11305 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11306 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11310 /* Network configuration. */
11311 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11312 rn
= bgp_route_next(rn
)) {
11313 if ((bgp_static
= rn
->info
) == NULL
)
11318 /* "network" configuration display. */
11319 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11320 uint32_t destination
;
11321 struct in_addr netmask
;
11323 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11324 masklen2ip(p
->prefixlen
, &netmask
);
11325 vty_out(vty
, " network %s",
11326 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11329 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11330 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11331 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11332 || p
->u
.prefix4
.s_addr
== 0) {
11333 /* Natural mask is not display. */
11335 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11337 vty_out(vty
, " network %s/%d",
11338 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11343 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11344 vty_out(vty
, " label-index %u",
11345 bgp_static
->label_index
);
11347 if (bgp_static
->rmap
.name
)
11348 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11350 if (bgp_static
->backdoor
)
11351 vty_out(vty
, " backdoor");
11353 vty_out(vty
, "\n");
11356 /* Aggregate-address configuration. */
11357 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11358 rn
= bgp_route_next(rn
)) {
11359 if ((bgp_aggregate
= rn
->info
) == NULL
)
11364 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11365 struct in_addr netmask
;
11367 masklen2ip(p
->prefixlen
, &netmask
);
11368 vty_out(vty
, " aggregate-address %s %s",
11369 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11371 inet_ntoa(netmask
));
11373 vty_out(vty
, " aggregate-address %s/%d",
11374 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11379 if (bgp_aggregate
->as_set
)
11380 vty_out(vty
, " as-set");
11382 if (bgp_aggregate
->summary_only
)
11383 vty_out(vty
, " summary-only");
11385 vty_out(vty
, "\n");
11389 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11392 struct bgp_node
*rn
;
11393 struct bgp_distance
*bdistance
;
11395 /* Distance configuration. */
11396 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11397 && bgp
->distance_local
[afi
][safi
]
11398 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11399 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11400 || bgp
->distance_local
[afi
][safi
]
11401 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11402 vty_out(vty
, " distance bgp %d %d %d\n",
11403 bgp
->distance_ebgp
[afi
][safi
],
11404 bgp
->distance_ibgp
[afi
][safi
],
11405 bgp
->distance_local
[afi
][safi
]);
11408 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11409 rn
= bgp_route_next(rn
))
11410 if ((bdistance
= rn
->info
) != NULL
) {
11411 char buf
[PREFIX_STRLEN
];
11413 vty_out(vty
, " distance %d %s %s\n",
11414 bdistance
->distance
,
11415 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11416 bdistance
->access_list
? bdistance
->access_list
11421 /* Allocate routing table structure and install commands. */
11422 void bgp_route_init(void)
11427 /* Init BGP distance table. */
11428 FOREACH_AFI_SAFI (afi
, safi
)
11429 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11431 /* IPv4 BGP commands. */
11432 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11433 install_element(BGP_NODE
, &bgp_network_cmd
);
11434 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11436 install_element(BGP_NODE
, &aggregate_address_cmd
);
11437 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11438 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11439 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11441 /* IPv4 unicast configuration. */
11442 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11443 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11444 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11446 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11447 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11448 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11449 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11451 /* IPv4 multicast configuration. */
11452 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11453 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11454 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11455 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11456 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11457 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11458 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11460 /* IPv4 labeled-unicast configuration. */
11461 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11462 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11463 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11464 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11465 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11467 install_element(VIEW_NODE
,
11468 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11469 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11470 install_element(VIEW_NODE
,
11471 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11472 #ifdef KEEP_OLD_VPN_COMMANDS
11473 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11474 #endif /* KEEP_OLD_VPN_COMMANDS */
11475 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11476 install_element(VIEW_NODE
,
11477 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11479 /* BGP dampening clear commands */
11480 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11481 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11483 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11484 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11487 install_element(ENABLE_NODE
,
11488 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11489 #ifdef KEEP_OLD_VPN_COMMANDS
11490 install_element(ENABLE_NODE
,
11491 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11492 #endif /* KEEP_OLD_VPN_COMMANDS */
11494 /* New config IPv6 BGP commands. */
11495 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11496 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11497 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11499 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11500 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11502 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11504 install_element(BGP_NODE
, &bgp_distance_cmd
);
11505 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11506 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11507 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11508 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11509 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11510 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11511 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11512 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11513 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11514 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11515 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11516 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11517 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11518 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11519 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11520 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11521 install_element(BGP_IPV4M_NODE
,
11522 &no_bgp_distance_source_access_list_cmd
);
11523 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11524 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11525 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11526 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11527 install_element(BGP_IPV6_NODE
,
11528 &ipv6_bgp_distance_source_access_list_cmd
);
11529 install_element(BGP_IPV6_NODE
,
11530 &no_ipv6_bgp_distance_source_access_list_cmd
);
11531 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11532 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11533 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11534 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11535 install_element(BGP_IPV6M_NODE
,
11536 &ipv6_bgp_distance_source_access_list_cmd
);
11537 install_element(BGP_IPV6M_NODE
,
11538 &no_ipv6_bgp_distance_source_access_list_cmd
);
11540 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11541 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11542 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11543 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11545 /* IPv4 Multicast Mode */
11546 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11547 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11549 /* Large Communities */
11550 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11551 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11553 /* show bgp ipv4 flowspec detailed */
11554 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11558 void bgp_route_finish(void)
11563 FOREACH_AFI_SAFI (afi
, safi
) {
11564 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11565 bgp_distance_table
[afi
][safi
] = NULL
;