1 /* BGP routing information
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "sockunion.h"
37 #include "workqueue.h"
42 #include "bgpd/bgpd.h"
43 #include "bgpd/bgp_table.h"
44 #include "bgpd/bgp_route.h"
45 #include "bgpd/bgp_attr.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_aspath.h"
48 #include "bgpd/bgp_regex.h"
49 #include "bgpd/bgp_community.h"
50 #include "bgpd/bgp_ecommunity.h"
51 #include "bgpd/bgp_lcommunity.h"
52 #include "bgpd/bgp_clist.h"
53 #include "bgpd/bgp_packet.h"
54 #include "bgpd/bgp_filter.h"
55 #include "bgpd/bgp_fsm.h"
56 #include "bgpd/bgp_mplsvpn.h"
57 #include "bgpd/bgp_nexthop.h"
58 #include "bgpd/bgp_damp.h"
59 #include "bgpd/bgp_advertise.h"
60 #include "bgpd/bgp_zebra.h"
61 #include "bgpd/bgp_vty.h"
62 #include "bgpd/bgp_mpath.h"
63 #include "bgpd/bgp_nht.h"
64 #include "bgpd/bgp_updgrp.h"
65 #include "bgpd/bgp_label.h"
68 #include "bgpd/rfapi/rfapi_backend.h"
69 #include "bgpd/rfapi/vnc_import_bgp.h"
70 #include "bgpd/rfapi/vnc_export_bgp.h"
72 #include "bgpd/bgp_encap_types.h"
73 #include "bgpd/bgp_encap_tlv.h"
74 #include "bgpd/bgp_evpn.h"
75 #include "bgpd/bgp_evpn_vty.h"
76 #include "bgpd/bgp_flowspec.h"
77 #include "bgpd/bgp_flowspec_util.h"
79 #ifndef VTYSH_EXTRACT_PL
80 #include "bgpd/bgp_route_clippy.c"
83 /* Extern from bgp_dump.c */
84 extern const char *bgp_origin_str
[];
85 extern const char *bgp_origin_long_str
[];
88 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
89 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
90 static const struct message bgp_pmsi_tnltype_str
[] = {
91 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
92 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
93 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
94 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
95 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
96 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
97 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
98 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
102 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
103 safi_t safi
, struct prefix
*p
,
104 struct prefix_rd
*prd
)
107 struct bgp_node
*prn
= NULL
;
113 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
114 || (safi
== SAFI_EVPN
)) {
115 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
117 if (prn
->info
== NULL
)
118 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
120 bgp_unlock_node(prn
);
124 rn
= bgp_node_get(table
, p
);
126 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
127 || (safi
== SAFI_EVPN
))
133 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
134 safi_t safi
, struct prefix
*p
,
135 struct prefix_rd
*prd
)
138 struct bgp_node
*prn
= NULL
;
143 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
144 || (safi
== SAFI_EVPN
)) {
145 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
149 if (prn
->info
== NULL
) {
150 bgp_unlock_node(prn
);
157 rn
= bgp_node_lookup(table
, p
);
162 /* Allocate bgp_info_extra */
163 static struct bgp_info_extra
*bgp_info_extra_new(void)
165 struct bgp_info_extra
*new;
166 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
167 new->label
[0] = MPLS_INVALID_LABEL
;
172 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
174 if (extra
&& *extra
) {
175 if ((*extra
)->damp_info
)
176 bgp_damp_info_free((*extra
)->damp_info
, 0);
178 (*extra
)->damp_info
= NULL
;
180 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
186 /* Get bgp_info extra information for the given bgp_info, lazy allocated
189 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
192 ri
->extra
= bgp_info_extra_new();
196 /* Allocate new bgp info structure. */
197 struct bgp_info
*bgp_info_new(void)
199 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
202 /* Free bgp route information. */
203 static void bgp_info_free(struct bgp_info
*binfo
)
206 bgp_attr_unintern(&binfo
->attr
);
208 bgp_unlink_nexthop(binfo
);
209 bgp_info_extra_free(&binfo
->extra
);
210 bgp_info_mpath_free(&binfo
->mpath
);
212 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
214 XFREE(MTYPE_BGP_ROUTE
, binfo
);
217 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
223 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
225 assert(binfo
&& binfo
->lock
> 0);
228 if (binfo
->lock
== 0) {
230 zlog_debug ("%s: unlocked and freeing", __func__
);
231 zlog_backtrace (LOG_DEBUG
);
233 bgp_info_free(binfo
);
238 if (binfo
->lock
== 1)
240 zlog_debug ("%s: unlocked to 1", __func__
);
241 zlog_backtrace (LOG_DEBUG
);
248 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
250 struct bgp_info
*top
;
262 peer_lock(ri
->peer
); /* bgp_info peer reference */
265 /* Do the actual removal of info from RIB, for use by bgp_process
266 completion callback *only* */
267 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
270 ri
->next
->prev
= ri
->prev
;
272 ri
->prev
->next
= ri
->next
;
276 bgp_info_mpath_dequeue(ri
);
281 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
283 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
284 /* set of previous already took care of pcount */
285 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
288 /* undo the effects of a previous call to bgp_info_delete; typically
289 called when a route is deleted and then quickly re-added before the
290 deletion has been processed */
291 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
293 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
294 /* unset of previous already took care of pcount */
295 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
298 /* Adjust pcount as required */
299 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
301 struct bgp_table
*table
;
303 assert(rn
&& bgp_node_table(rn
));
304 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
306 table
= bgp_node_table(rn
);
308 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
311 if (!BGP_INFO_COUNTABLE(ri
)
312 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
314 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
316 /* slight hack, but more robust against errors. */
317 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
318 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
321 "%s: Asked to decrement 0 prefix count for peer %s",
322 __func__
, ri
->peer
->host
);
323 zlog_backtrace(LOG_WARNING
);
324 zlog_warn("%s: Please report to Quagga bugzilla",
327 } else if (BGP_INFO_COUNTABLE(ri
)
328 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
329 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
330 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
334 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
336 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
339 /* Set/unset bgp_info flags, adjusting any other state as needed.
340 * This is here primarily to keep prefix-count in check.
342 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, uint32_t flag
)
344 SET_FLAG(ri
->flags
, flag
);
346 /* early bath if we know it's not a flag that changes countability state
348 if (!CHECK_FLAG(flag
,
349 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
352 bgp_pcount_adjust(rn
, ri
);
355 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
358 UNSET_FLAG(ri
->flags
, flag
);
360 /* early bath if we know it's not a flag that changes countability state
362 if (!CHECK_FLAG(flag
,
363 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
366 bgp_pcount_adjust(rn
, ri
);
369 /* Get MED value. If MED value is missing and "bgp bestpath
370 missing-as-worst" is specified, treat it as the worst value. */
371 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
373 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
376 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
383 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
385 if (ri
->addpath_rx_id
)
386 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
389 sprintf(buf
, "path %s", ri
->peer
->host
);
392 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
394 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
395 struct bgp_info
*exist
, int *paths_eq
,
396 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
397 char *pfx_buf
, afi_t afi
, safi_t safi
)
399 struct attr
*newattr
, *existattr
;
400 bgp_peer_sort_t new_sort
;
401 bgp_peer_sort_t exist_sort
;
407 uint32_t exist_weight
;
408 uint32_t newm
, existm
;
409 struct in_addr new_id
;
410 struct in_addr exist_id
;
413 int internal_as_route
;
416 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
417 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
419 uint32_t exist_mm_seq
;
426 zlog_debug("%s: new is NULL", pfx_buf
);
431 bgp_info_path_with_addpath_rx_str(new, new_buf
);
435 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
441 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
442 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
443 pfx_buf
, new_buf
, new->flags
, exist_buf
,
448 existattr
= exist
->attr
;
450 /* For EVPN routes, we cannot just go by local vs remote, we have to
451 * look at the MAC mobility sequence number, if present.
453 if (safi
== SAFI_EVPN
) {
454 /* This is an error condition described in RFC 7432 Section
456 * states that in this scenario "the PE MUST alert the operator"
458 * does not state what other action to take. In order to provide
460 * consistency in this scenario we are going to prefer the path
464 if (newattr
->sticky
!= existattr
->sticky
) {
466 prefix2str(&new->net
->p
, pfx_buf
,
468 * PREFIX2STR_BUFFER
);
469 bgp_info_path_with_addpath_rx_str(new, new_buf
);
470 bgp_info_path_with_addpath_rx_str(exist
,
474 if (newattr
->sticky
&& !existattr
->sticky
) {
476 "%s: %s wins over %s due to sticky MAC flag",
477 pfx_buf
, new_buf
, exist_buf
);
481 if (!newattr
->sticky
&& existattr
->sticky
) {
483 "%s: %s loses to %s due to sticky MAC flag",
484 pfx_buf
, new_buf
, exist_buf
);
489 new_mm_seq
= mac_mobility_seqnum(newattr
);
490 exist_mm_seq
= mac_mobility_seqnum(existattr
);
492 if (new_mm_seq
> exist_mm_seq
) {
495 "%s: %s wins over %s due to MM seq %u > %u",
496 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
501 if (new_mm_seq
< exist_mm_seq
) {
504 "%s: %s loses to %s due to MM seq %u < %u",
505 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
511 /* 1. Weight check. */
512 new_weight
= newattr
->weight
;
513 exist_weight
= existattr
->weight
;
515 if (new_weight
> exist_weight
) {
517 zlog_debug("%s: %s wins over %s due to weight %d > %d",
518 pfx_buf
, new_buf
, exist_buf
, new_weight
,
523 if (new_weight
< exist_weight
) {
525 zlog_debug("%s: %s loses to %s due to weight %d < %d",
526 pfx_buf
, new_buf
, exist_buf
, new_weight
,
531 /* 2. Local preference check. */
532 new_pref
= exist_pref
= bgp
->default_local_pref
;
534 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
535 new_pref
= newattr
->local_pref
;
536 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
537 exist_pref
= existattr
->local_pref
;
539 if (new_pref
> exist_pref
) {
542 "%s: %s wins over %s due to localpref %d > %d",
543 pfx_buf
, new_buf
, exist_buf
, new_pref
,
548 if (new_pref
< exist_pref
) {
551 "%s: %s loses to %s due to localpref %d < %d",
552 pfx_buf
, new_buf
, exist_buf
, new_pref
,
557 /* 3. Local route check. We prefer:
559 * - BGP_ROUTE_AGGREGATE
560 * - BGP_ROUTE_REDISTRIBUTE
562 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
563 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
566 "%s: %s wins over %s due to preferred BGP_ROUTE type",
567 pfx_buf
, new_buf
, exist_buf
);
571 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
572 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
575 "%s: %s loses to %s due to preferred BGP_ROUTE type",
576 pfx_buf
, new_buf
, exist_buf
);
580 /* 4. AS path length check. */
581 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
582 int exist_hops
= aspath_count_hops(existattr
->aspath
);
583 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
585 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
588 aspath_hops
= aspath_count_hops(newattr
->aspath
);
589 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
591 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
594 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
595 pfx_buf
, new_buf
, exist_buf
,
597 (exist_hops
+ exist_confeds
));
601 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
604 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
605 pfx_buf
, new_buf
, exist_buf
,
607 (exist_hops
+ exist_confeds
));
611 int newhops
= aspath_count_hops(newattr
->aspath
);
613 if (newhops
< exist_hops
) {
616 "%s: %s wins over %s due to aspath hopcount %d < %d",
617 pfx_buf
, new_buf
, exist_buf
,
618 newhops
, exist_hops
);
622 if (newhops
> exist_hops
) {
625 "%s: %s loses to %s due to aspath hopcount %d > %d",
626 pfx_buf
, new_buf
, exist_buf
,
627 newhops
, exist_hops
);
633 /* 5. Origin check. */
634 if (newattr
->origin
< existattr
->origin
) {
636 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
637 pfx_buf
, new_buf
, exist_buf
,
638 bgp_origin_long_str
[newattr
->origin
],
639 bgp_origin_long_str
[existattr
->origin
]);
643 if (newattr
->origin
> existattr
->origin
) {
645 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
646 pfx_buf
, new_buf
, exist_buf
,
647 bgp_origin_long_str
[newattr
->origin
],
648 bgp_origin_long_str
[existattr
->origin
]);
653 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
654 && aspath_count_hops(existattr
->aspath
) == 0);
655 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
656 && aspath_count_confeds(existattr
->aspath
) > 0
657 && aspath_count_hops(newattr
->aspath
) == 0
658 && aspath_count_hops(existattr
->aspath
) == 0);
660 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
661 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
662 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
663 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
664 || internal_as_route
) {
665 new_med
= bgp_med_value(new->attr
, bgp
);
666 exist_med
= bgp_med_value(exist
->attr
, bgp
);
668 if (new_med
< exist_med
) {
671 "%s: %s wins over %s due to MED %d < %d",
672 pfx_buf
, new_buf
, exist_buf
, new_med
,
677 if (new_med
> exist_med
) {
680 "%s: %s loses to %s due to MED %d > %d",
681 pfx_buf
, new_buf
, exist_buf
, new_med
,
687 /* 7. Peer type check. */
688 new_sort
= new->peer
->sort
;
689 exist_sort
= exist
->peer
->sort
;
691 if (new_sort
== BGP_PEER_EBGP
692 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
695 "%s: %s wins over %s due to eBGP peer > iBGP peer",
696 pfx_buf
, new_buf
, exist_buf
);
700 if (exist_sort
== BGP_PEER_EBGP
701 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
704 "%s: %s loses to %s due to iBGP peer < eBGP peer",
705 pfx_buf
, new_buf
, exist_buf
);
709 /* 8. IGP metric check. */
713 newm
= new->extra
->igpmetric
;
715 existm
= exist
->extra
->igpmetric
;
720 "%s: %s wins over %s due to IGP metric %d < %d",
721 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
728 "%s: %s loses to %s due to IGP metric %d > %d",
729 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
733 /* 9. Same IGP metric. Compare the cluster list length as
734 representative of IGP hops metric. Rewrite the metric value
735 pair (newm, existm) with the cluster list length. Prefer the
736 path with smaller cluster list length. */
737 if (newm
== existm
) {
738 if (peer_sort(new->peer
) == BGP_PEER_IBGP
739 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
740 && (mpath_cfg
== NULL
742 mpath_cfg
->ibgp_flags
,
743 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
744 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
745 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
750 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
751 pfx_buf
, new_buf
, exist_buf
,
759 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
760 pfx_buf
, new_buf
, exist_buf
,
767 /* 10. confed-external vs. confed-internal */
768 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
769 if (new_sort
== BGP_PEER_CONFED
770 && exist_sort
== BGP_PEER_IBGP
) {
773 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
774 pfx_buf
, new_buf
, exist_buf
);
778 if (exist_sort
== BGP_PEER_CONFED
779 && new_sort
== BGP_PEER_IBGP
) {
782 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
783 pfx_buf
, new_buf
, exist_buf
);
788 /* 11. Maximum path check. */
789 if (newm
== existm
) {
790 /* If one path has a label but the other does not, do not treat
791 * them as equals for multipath
793 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
795 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
798 "%s: %s and %s cannot be multipath, one has a label while the other does not",
799 pfx_buf
, new_buf
, exist_buf
);
800 } else if (bgp_flag_check(bgp
,
801 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
804 * For the two paths, all comparison steps till IGP
806 * have succeeded - including AS_PATH hop count. Since
808 * bestpath as-path multipath-relax' knob is on, we
810 * an exact match of AS_PATH. Thus, mark the paths are
812 * That will trigger both these paths to get into the
820 "%s: %s and %s are equal via multipath-relax",
821 pfx_buf
, new_buf
, exist_buf
);
822 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
823 if (aspath_cmp(new->attr
->aspath
,
824 exist
->attr
->aspath
)) {
829 "%s: %s and %s are equal via matching aspaths",
830 pfx_buf
, new_buf
, exist_buf
);
832 } else if (new->peer
->as
== exist
->peer
->as
) {
837 "%s: %s and %s are equal via same remote-as",
838 pfx_buf
, new_buf
, exist_buf
);
842 * TODO: If unequal cost ibgp multipath is enabled we can
843 * mark the paths as equal here instead of returning
848 "%s: %s wins over %s after IGP metric comparison",
849 pfx_buf
, new_buf
, exist_buf
);
852 "%s: %s loses to %s after IGP metric comparison",
853 pfx_buf
, new_buf
, exist_buf
);
858 /* 12. If both paths are external, prefer the path that was received
859 first (the oldest one). This step minimizes route-flap, since a
860 newer path won't displace an older one, even if it was the
861 preferred route based on the additional decision criteria below. */
862 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
863 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
864 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
867 "%s: %s wins over %s due to oldest external",
868 pfx_buf
, new_buf
, exist_buf
);
872 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
875 "%s: %s loses to %s due to oldest external",
876 pfx_buf
, new_buf
, exist_buf
);
881 /* 13. Router-ID comparision. */
882 /* If one of the paths is "stale", the corresponding peer router-id will
883 * be 0 and would always win over the other path. If originator id is
884 * used for the comparision, it will decide which path is better.
886 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
887 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
889 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
890 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
891 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
893 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
895 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
898 "%s: %s wins over %s due to Router-ID comparison",
899 pfx_buf
, new_buf
, exist_buf
);
903 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
906 "%s: %s loses to %s due to Router-ID comparison",
907 pfx_buf
, new_buf
, exist_buf
);
911 /* 14. Cluster length comparision. */
912 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
913 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
915 if (new_cluster
< exist_cluster
) {
918 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
919 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
924 if (new_cluster
> exist_cluster
) {
927 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
928 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
933 /* 15. Neighbor address comparision. */
934 /* Do this only if neither path is "stale" as stale paths do not have
935 * valid peer information (as the connection may or may not be up).
937 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
940 "%s: %s wins over %s due to latter path being STALE",
941 pfx_buf
, new_buf
, exist_buf
);
945 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
948 "%s: %s loses to %s due to former path being STALE",
949 pfx_buf
, new_buf
, exist_buf
);
953 /* locally configured routes to advertise do not have su_remote */
954 if (new->peer
->su_remote
== NULL
)
956 if (exist
->peer
->su_remote
== NULL
)
959 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
964 "%s: %s loses to %s due to Neighor IP comparison",
965 pfx_buf
, new_buf
, exist_buf
);
972 "%s: %s wins over %s due to Neighor IP comparison",
973 pfx_buf
, new_buf
, exist_buf
);
978 zlog_debug("%s: %s wins over %s due to nothing left to compare",
979 pfx_buf
, new_buf
, exist_buf
);
984 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
985 * is preferred, or 0 if they are the same (usually will only occur if
986 * multipath is enabled
987 * This version is compatible with */
988 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
989 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
994 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
1008 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1009 struct attr
*attr
, afi_t afi
,
1012 struct bgp_filter
*filter
;
1014 filter
= &peer
->filter
[afi
][safi
];
1016 #define FILTER_EXIST_WARN(F, f, filter) \
1017 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1018 zlog_warn("%s: Could not find configured input %s-list %s!", \
1019 peer->host, #f, F##_IN_NAME(filter));
1021 if (DISTRIBUTE_IN_NAME(filter
)) {
1022 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1024 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1028 if (PREFIX_LIST_IN_NAME(filter
)) {
1029 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1031 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1035 if (FILTER_LIST_IN_NAME(filter
)) {
1036 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1038 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1043 return FILTER_PERMIT
;
1044 #undef FILTER_EXIST_WARN
1047 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1048 struct attr
*attr
, afi_t afi
,
1051 struct bgp_filter
*filter
;
1053 filter
= &peer
->filter
[afi
][safi
];
1055 #define FILTER_EXIST_WARN(F, f, filter) \
1056 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1057 zlog_warn("%s: Could not find configured output %s-list %s!", \
1058 peer->host, #f, F##_OUT_NAME(filter));
1060 if (DISTRIBUTE_OUT_NAME(filter
)) {
1061 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1063 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1067 if (PREFIX_LIST_OUT_NAME(filter
)) {
1068 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1070 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1075 if (FILTER_LIST_OUT_NAME(filter
)) {
1076 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1078 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1083 return FILTER_PERMIT
;
1084 #undef FILTER_EXIST_WARN
1087 /* If community attribute includes no_export then return 1. */
1088 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1090 if (attr
->community
) {
1091 /* NO_ADVERTISE check. */
1092 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1095 /* NO_EXPORT check. */
1096 if (peer
->sort
== BGP_PEER_EBGP
1097 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1100 /* NO_EXPORT_SUBCONFED check. */
1101 if (peer
->sort
== BGP_PEER_EBGP
1102 || peer
->sort
== BGP_PEER_CONFED
)
1103 if (community_include(attr
->community
,
1104 COMMUNITY_NO_EXPORT_SUBCONFED
))
1110 /* Route reflection loop check. */
1111 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1113 struct in_addr cluster_id
;
1115 if (attr
->cluster
) {
1116 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1117 cluster_id
= peer
->bgp
->cluster_id
;
1119 cluster_id
= peer
->bgp
->router_id
;
1121 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1127 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1128 struct attr
*attr
, afi_t afi
, safi_t safi
,
1129 const char *rmap_name
)
1131 struct bgp_filter
*filter
;
1132 struct bgp_info info
;
1133 route_map_result_t ret
;
1134 struct route_map
*rmap
= NULL
;
1136 filter
= &peer
->filter
[afi
][safi
];
1138 /* Apply default weight value. */
1139 if (peer
->weight
[afi
][safi
])
1140 attr
->weight
= peer
->weight
[afi
][safi
];
1143 rmap
= route_map_lookup_by_name(rmap_name
);
1148 if (ROUTE_MAP_IN_NAME(filter
)) {
1149 rmap
= ROUTE_MAP_IN(filter
);
1156 /* Route map apply. */
1158 /* Duplicate current value to new strucutre for modification. */
1162 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1164 /* Apply BGP route map to the attribute. */
1165 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1167 peer
->rmap_type
= 0;
1169 if (ret
== RMAP_DENYMATCH
) {
1170 /* Free newly generated AS path and community by
1172 bgp_attr_flush(attr
);
1179 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1180 struct attr
*attr
, afi_t afi
, safi_t safi
,
1181 const char *rmap_name
)
1183 struct bgp_info info
;
1184 route_map_result_t ret
;
1185 struct route_map
*rmap
= NULL
;
1189 * So if we get to this point and have no rmap_name
1190 * we want to just show the output as it currently
1196 /* Apply default weight value. */
1197 if (peer
->weight
[afi
][safi
])
1198 attr
->weight
= peer
->weight
[afi
][safi
];
1200 rmap
= route_map_lookup_by_name(rmap_name
);
1203 * If we have a route map name and we do not find
1204 * the routemap that means we have an implicit
1210 /* Route map apply. */
1211 /* Duplicate current value to new strucutre for modification. */
1215 rmap_type
= peer
->rmap_type
;
1216 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1218 /* Apply BGP route map to the attribute. */
1219 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1221 peer
->rmap_type
= rmap_type
;
1223 if (ret
== RMAP_DENYMATCH
)
1225 * caller has multiple error paths with bgp_attr_flush()
1232 /* If this is an EBGP peer with remove-private-AS */
1233 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1234 struct peer
*peer
, struct attr
*attr
)
1236 if (peer
->sort
== BGP_PEER_EBGP
1237 && (peer_af_flag_check(peer
, afi
, safi
,
1238 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1239 || peer_af_flag_check(peer
, afi
, safi
,
1240 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1241 || peer_af_flag_check(peer
, afi
, safi
,
1242 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1243 || peer_af_flag_check(peer
, afi
, safi
,
1244 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1245 // Take action on the entire aspath
1246 if (peer_af_flag_check(peer
, afi
, safi
,
1247 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1248 || peer_af_flag_check(peer
, afi
, safi
,
1249 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1250 if (peer_af_flag_check(
1252 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1253 attr
->aspath
= aspath_replace_private_asns(
1254 attr
->aspath
, bgp
->as
);
1256 // The entire aspath consists of private ASNs so create
1258 else if (aspath_private_as_check(attr
->aspath
))
1259 attr
->aspath
= aspath_empty_get();
1261 // There are some public and some private ASNs, remove
1264 attr
->aspath
= aspath_remove_private_asns(
1268 // 'all' was not specified so the entire aspath must be private
1270 // for us to do anything
1271 else if (aspath_private_as_check(attr
->aspath
)) {
1272 if (peer_af_flag_check(
1274 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1275 attr
->aspath
= aspath_replace_private_asns(
1276 attr
->aspath
, bgp
->as
);
1278 attr
->aspath
= aspath_empty_get();
1283 /* If this is an EBGP peer with as-override */
1284 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1285 struct peer
*peer
, struct attr
*attr
)
1287 if (peer
->sort
== BGP_PEER_EBGP
1288 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1289 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1290 attr
->aspath
= aspath_replace_specific_asn(
1291 attr
->aspath
, peer
->as
, bgp
->as
);
1295 void bgp_attr_add_gshut_community(struct attr
*attr
)
1297 struct community
*old
;
1298 struct community
*new;
1299 struct community
*merge
;
1300 struct community
*gshut
;
1302 old
= attr
->community
;
1303 gshut
= community_str2com("graceful-shutdown");
1306 merge
= community_merge(community_dup(old
), gshut
);
1308 if (old
->refcnt
== 0)
1309 community_free(old
);
1311 new = community_uniq_sort(merge
);
1312 community_free(merge
);
1314 new = community_dup(gshut
);
1317 community_free(gshut
);
1318 attr
->community
= new;
1319 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1321 /* When we add the graceful-shutdown community we must also
1322 * lower the local-preference */
1323 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1324 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1328 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1330 if (family
== AF_INET
) {
1331 attr
->nexthop
.s_addr
= 0;
1332 attr
->mp_nexthop_global_in
.s_addr
= 0;
1334 if (family
== AF_INET6
)
1335 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1338 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1339 struct update_subgroup
*subgrp
, struct prefix
*p
,
1342 struct bgp_filter
*filter
;
1345 struct peer
*onlypeer
;
1347 struct attr
*riattr
;
1348 char buf
[PREFIX_STRLEN
];
1354 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1356 if (DISABLE_BGP_ANNOUNCE
)
1359 afi
= SUBGRP_AFI(subgrp
);
1360 safi
= SUBGRP_SAFI(subgrp
);
1361 peer
= SUBGRP_PEER(subgrp
);
1363 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1364 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1367 filter
= &peer
->filter
[afi
][safi
];
1368 bgp
= SUBGRP_INST(subgrp
);
1369 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1372 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1373 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1374 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1377 * direct and direct_ext type routes originate internally even
1378 * though they can have peer pointers that reference other
1381 prefix2str(p
, buf
, PREFIX_STRLEN
);
1382 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1388 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1389 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1390 && (ri
->type
== ZEBRA_ROUTE_BGP
)
1391 && (ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1393 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1398 /* With addpath we may be asked to TX all kinds of paths so make sure
1400 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1401 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1402 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1406 /* If this is not the bestpath then check to see if there is an enabled
1408 * feature that requires us to advertise it */
1409 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1410 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1415 /* Aggregate-address suppress check. */
1416 if (ri
->extra
&& ri
->extra
->suppress
)
1417 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1421 /* If it's labeled safi, make sure the route has a valid label. */
1422 if (safi
== SAFI_LABELED_UNICAST
) {
1423 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1424 if (!bgp_is_valid_label(&label
)) {
1425 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1426 zlog_debug("u%" PRIu64
":s%" PRIu64
1427 " %s/%d is filtered - no label (%p)",
1428 subgrp
->update_group
->id
, subgrp
->id
,
1429 inet_ntop(p
->family
, &p
->u
.prefix
,
1430 buf
, SU_ADDRSTRLEN
),
1431 p
->prefixlen
, &label
);
1436 /* Do not send back route to sender. */
1437 if (onlypeer
&& from
== onlypeer
) {
1441 /* Do not send the default route in the BGP table if the neighbor is
1442 * configured for default-originate */
1443 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1444 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1445 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1447 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1451 /* Transparency check. */
1452 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1453 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1458 /* If community is not disabled check the no-export and local. */
1459 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1460 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1462 "subgrpannouncecheck: community filter check fail");
1466 /* If the attribute has originator-id and it is same as remote
1468 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1469 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1470 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1472 "%s [Update:SEND] %s originator-id is same as "
1475 prefix2str(p
, buf
, sizeof(buf
)));
1479 /* ORF prefix-list filter check */
1480 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1481 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1482 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1483 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1484 if (peer
->orf_plist
[afi
][safi
]) {
1485 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1487 if (bgp_debug_update(NULL
, p
,
1488 subgrp
->update_group
, 0))
1490 "%s [Update:SEND] %s is filtered via ORF",
1498 /* Output filter check. */
1499 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1500 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1501 zlog_debug("%s [Update:SEND] %s is filtered",
1502 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1506 #ifdef BGP_SEND_ASPATH_CHECK
1507 /* AS path loop check. */
1508 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1509 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1511 "%s [Update:SEND] suppress announcement to peer AS %u "
1512 "that is part of AS path.",
1513 onlypeer
->host
, onlypeer
->as
);
1516 #endif /* BGP_SEND_ASPATH_CHECK */
1518 /* If we're a CONFED we need to loop check the CONFED ID too */
1519 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1520 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1521 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1523 "%s [Update:SEND] suppress announcement to peer AS %u"
1525 peer
->host
, bgp
->confed_id
);
1530 /* Route-Reflect check. */
1531 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1536 /* IBGP reflection check. */
1537 if (reflect
&& !samepeer_safe
) {
1538 /* A route from a Client peer. */
1539 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1540 PEER_FLAG_REFLECTOR_CLIENT
)) {
1541 /* Reflect to all the Non-Client peers and also to the
1542 Client peers other than the originator. Originator
1544 is already done. So there is noting to do. */
1545 /* no bgp client-to-client reflection check. */
1546 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1547 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1548 PEER_FLAG_REFLECTOR_CLIENT
))
1551 /* A route from a Non-client peer. Reflect to all other
1553 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1554 PEER_FLAG_REFLECTOR_CLIENT
))
1559 /* For modify attribute, copy it to temporary structure. */
1560 bgp_attr_dup(attr
, riattr
);
1562 /* If local-preference is not set. */
1563 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1564 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1565 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1566 attr
->local_pref
= bgp
->default_local_pref
;
1569 /* If originator-id is not set and the route is to be reflected,
1570 set the originator id */
1572 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1573 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1574 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1577 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1579 if (peer
->sort
== BGP_PEER_EBGP
1580 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1581 if (from
!= bgp
->peer_self
&& !transparent
1582 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1583 PEER_FLAG_MED_UNCHANGED
))
1585 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1588 /* Since the nexthop attribute can vary per peer, it is not explicitly
1590 * in announce check, only certain flags and length (or number of
1592 * -- for IPv6/MP_REACH) are set here in order to guide the update
1594 * code in setting the nexthop(s) on a per peer basis in
1596 * Typically, the source nexthop in the attribute is preserved but in
1598 * scenarios where we know it will always be overwritten, we reset the
1599 * nexthop to "0" in an attempt to achieve better Update packing. An
1600 * example of this is when a prefix from each of 2 IBGP peers needs to
1602 * announced to an EBGP peer (and they have the same attributes barring
1606 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1608 #define NEXTHOP_IS_V6 \
1609 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1610 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1611 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1612 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1614 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1616 * the peer (group) is configured to receive link-local nexthop
1618 * and it is available in the prefix OR we're not reflecting the route
1620 * the peer (group) to whom we're going to announce is on a shared
1622 * and this is either a self-originated route or the peer is EBGP.
1624 if (NEXTHOP_IS_V6
) {
1625 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1626 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1627 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1628 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1629 || (!reflect
&& peer
->shared_network
1630 && (from
== bgp
->peer_self
1631 || peer
->sort
== BGP_PEER_EBGP
))) {
1632 attr
->mp_nexthop_len
=
1633 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1636 /* Clear off link-local nexthop in source, whenever it is not
1638 * ensure more prefixes share the same attribute for
1641 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1642 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1643 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1646 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1647 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1649 /* Route map & unsuppress-map apply. */
1650 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1651 struct bgp_info info
;
1652 struct bgp_info_extra dummy_info_extra
;
1653 struct attr dummy_attr
;
1659 memcpy(&dummy_info_extra
, ri
->extra
,
1660 sizeof(struct bgp_info_extra
));
1661 info
.extra
= &dummy_info_extra
;
1664 /* don't confuse inbound and outbound setting */
1665 RESET_FLAG(attr
->rmap_change_flags
);
1668 * The route reflector is not allowed to modify the attributes
1669 * of the reflected IBGP routes unless explicitly allowed.
1671 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1672 && !bgp_flag_check(bgp
,
1673 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1674 bgp_attr_dup(&dummy_attr
, attr
);
1675 info
.attr
= &dummy_attr
;
1678 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1680 if (ri
->extra
&& ri
->extra
->suppress
)
1681 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1684 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1687 peer
->rmap_type
= 0;
1689 if (ret
== RMAP_DENYMATCH
) {
1690 bgp_attr_flush(attr
);
1695 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1696 if (peer
->sort
== BGP_PEER_IBGP
1697 || peer
->sort
== BGP_PEER_CONFED
) {
1698 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1699 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1701 bgp_attr_add_gshut_community(attr
);
1705 /* After route-map has been applied, we check to see if the nexthop to
1706 * be carried in the attribute (that is used for the announcement) can
1707 * be cleared off or not. We do this in all cases where we would be
1708 * setting the nexthop to "ourselves". For IPv6, we only need to
1710 * the global nexthop here; the link-local nexthop would have been
1712 * already, and if not, it is required by the update formation code.
1713 * Also see earlier comments in this function.
1716 * If route-map has performed some operation on the nexthop or the peer
1717 * configuration says to pass it unchanged, we cannot reset the nexthop
1718 * here, so only attempt to do it if these aren't true. Note that the
1719 * route-map handler itself might have cleared the nexthop, if for
1721 * it is configured as 'peer-address'.
1723 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1724 riattr
->rmap_change_flags
)
1726 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1727 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1728 /* We can reset the nexthop, if setting (or forcing) it to
1730 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1731 PEER_FLAG_NEXTHOP_SELF
)
1732 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1733 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1735 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1736 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1737 subgroup_announce_reset_nhop(
1738 (peer_cap_enhe(peer
, afi
, safi
)
1742 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1743 /* Can also reset the nexthop if announcing to EBGP, but
1745 * no peer in the subgroup is on a shared subnet.
1746 * Note: 3rd party nexthop currently implemented for
1749 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1751 subgroup_announce_reset_nhop(
1752 (peer_cap_enhe(peer
, afi
, safi
)
1756 } else if (CHECK_FLAG(ri
->flags
, BGP_INFO_ANNC_NH_SELF
)) {
1758 * This flag is used for leaked vpn-vrf routes
1760 int family
= p
->family
;
1762 if (peer_cap_enhe(peer
, afi
, safi
))
1765 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1767 "%s: BGP_INFO_ANNC_NH_SELF, family=%s",
1768 __func__
, family2str(family
));
1769 subgroup_announce_reset_nhop(family
, attr
);
1772 /* If IPv6/MP and nexthop does not have any override and happens
1774 * be a link-local address, reset it so that we don't pass along
1776 * source's link-local IPv6 address to recipients who may not be
1778 * the same interface.
1780 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1781 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1782 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1789 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1790 struct bgp_maxpaths_cfg
*mpath_cfg
,
1791 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1793 struct bgp_info
*new_select
;
1794 struct bgp_info
*old_select
;
1795 struct bgp_info
*ri
;
1796 struct bgp_info
*ri1
;
1797 struct bgp_info
*ri2
;
1798 struct bgp_info
*nextri
= NULL
;
1799 int paths_eq
, do_mpath
, debug
;
1800 struct list mp_list
;
1801 char pfx_buf
[PREFIX2STR_BUFFER
];
1802 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1804 bgp_mp_list_init(&mp_list
);
1806 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1808 debug
= bgp_debug_bestpath(&rn
->p
);
1811 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1813 /* bgp deterministic-med */
1815 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1817 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1818 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1819 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1821 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1822 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1824 if (BGP_INFO_HOLDDOWN(ri1
))
1826 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1827 if (ri1
->peer
->status
!= Established
)
1832 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1833 if (CHECK_FLAG(ri2
->flags
,
1834 BGP_INFO_DMED_CHECK
))
1836 if (BGP_INFO_HOLDDOWN(ri2
))
1839 && ri2
->peer
!= bgp
->peer_self
1842 PEER_STATUS_NSF_WAIT
))
1843 if (ri2
->peer
->status
1847 if (aspath_cmp_left(ri1
->attr
->aspath
,
1849 || aspath_cmp_left_confed(
1851 ri2
->attr
->aspath
)) {
1852 if (bgp_info_cmp(bgp
, ri2
,
1858 bgp_info_unset_flag(
1860 BGP_INFO_DMED_SELECTED
);
1866 BGP_INFO_DMED_CHECK
);
1870 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1871 bgp_info_set_flag(rn
, new_select
,
1872 BGP_INFO_DMED_SELECTED
);
1875 bgp_info_path_with_addpath_rx_str(new_select
,
1877 zlog_debug("%s: %s is the bestpath from AS %d",
1879 aspath_get_first_as(
1880 new_select
->attr
->aspath
));
1885 /* Check old selected route and new selected route. */
1888 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1890 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1893 if (BGP_INFO_HOLDDOWN(ri
)) {
1894 /* reap REMOVED routes, if needs be
1895 * selected route must stay for a while longer though
1897 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1898 && (ri
!= old_select
))
1899 bgp_info_reap(rn
, ri
);
1902 zlog_debug("%s: ri %p in holddown", __func__
,
1908 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1909 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1910 if (ri
->peer
->status
!= Established
) {
1914 "%s: ri %p non self peer %s not estab state",
1915 __func__
, ri
, ri
->peer
->host
);
1920 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1921 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1922 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1924 zlog_debug("%s: ri %p dmed", __func__
, ri
);
1928 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1930 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1931 debug
, pfx_buf
, afi
, safi
)) {
1936 /* Now that we know which path is the bestpath see if any of the other
1938 * qualify as multipaths
1942 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1944 sprintf(path_buf
, "NONE");
1946 "%s: After path selection, newbest is %s oldbest was %s",
1948 old_select
? old_select
->peer
->host
: "NONE");
1951 if (do_mpath
&& new_select
) {
1952 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1956 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1958 if (ri
== new_select
) {
1961 "%s: %s is the bestpath, add to the multipath list",
1963 bgp_mp_list_add(&mp_list
, ri
);
1967 if (BGP_INFO_HOLDDOWN(ri
))
1970 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1971 && !CHECK_FLAG(ri
->peer
->sflags
,
1972 PEER_STATUS_NSF_WAIT
))
1973 if (ri
->peer
->status
!= Established
)
1976 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1979 "%s: %s has the same nexthop as the bestpath, skip it",
1984 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1985 debug
, pfx_buf
, afi
, safi
);
1990 "%s: %s is equivalent to the bestpath, add to the multipath list",
1992 bgp_mp_list_add(&mp_list
, ri
);
1997 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1998 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1999 bgp_mp_list_clear(&mp_list
);
2001 result
->old
= old_select
;
2002 result
->new = new_select
;
2008 * A new route/change in bestpath of an existing route. Evaluate the path
2009 * for advertisement to the subgroup.
2011 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2012 struct bgp_info
*selected
,
2013 struct bgp_node
*rn
,
2014 uint32_t addpath_tx_id
)
2017 struct peer
*onlypeer
;
2023 afi
= SUBGRP_AFI(subgrp
);
2024 safi
= SUBGRP_SAFI(subgrp
);
2025 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2028 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2029 char buf_prefix
[PREFIX_STRLEN
];
2030 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2031 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2035 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2036 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2037 PEER_STATUS_ORF_WAIT_REFRESH
))
2040 memset(&attr
, 0, sizeof(struct attr
));
2041 /* It's initialized in bgp_announce_check() */
2043 /* Announcement to the subgroup. If the route is filtered withdraw it.
2046 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2047 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2049 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2050 selected
->addpath_tx_id
);
2053 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2055 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2062 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2063 * This is called at the end of route processing.
2065 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2067 struct bgp_info
*ri
;
2069 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2070 if (BGP_INFO_HOLDDOWN(ri
))
2072 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2073 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2078 * Has the route changed from the RIB's perspective? This is invoked only
2079 * if the route selection returns the same best route as earlier - to
2080 * determine if we need to update zebra or not.
2082 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2084 struct bgp_info
*mpinfo
;
2086 /* If this is multipath, check all selected paths for any nexthop change
2088 * attribute change. Some attribute changes (e.g., community) aren't of
2089 * relevance to the RIB, but we'll update zebra to ensure we handle the
2090 * case of BGP nexthop change. This is the behavior when the best path
2092 * an attribute change anyway.
2094 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2095 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2098 /* If this is multipath, check all selected paths for any nexthop change
2100 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2101 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2102 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2103 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2107 /* Nothing has changed from the RIB's perspective. */
2111 struct bgp_process_queue
{
2113 STAILQ_HEAD(, bgp_node
) pqueue
;
2114 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2116 unsigned int queued
;
2120 * old_select = The old best path
2121 * new_select = the new best path
2123 * if (!old_select && new_select)
2124 * We are sending new information on.
2126 * if (old_select && new_select) {
2127 * if (new_select != old_select)
2128 * We have a new best path send a change
2130 * We've received a update with new attributes that needs
2134 * if (old_select && !new_select)
2135 * We have no eligible route that we can announce or the rn
2138 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2139 afi_t afi
, safi_t safi
)
2141 struct prefix
*p
= &rn
->p
;
2142 struct bgp_info
*new_select
;
2143 struct bgp_info
*old_select
;
2144 struct bgp_info_pair old_and_new
;
2145 char pfx_buf
[PREFIX2STR_BUFFER
];
2148 /* Is it end of initial update? (after startup) */
2150 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2151 sizeof(bgp
->update_delay_zebra_resume_time
));
2153 bgp
->main_zebra_update_hold
= 0;
2154 FOREACH_AFI_SAFI (afi
, safi
) {
2155 if (bgp_fibupd_safi(safi
))
2156 bgp_zebra_announce_table(bgp
, afi
, safi
);
2158 bgp
->main_peers_update_hold
= 0;
2160 bgp_start_routeadv(bgp
);
2164 debug
= bgp_debug_bestpath(&rn
->p
);
2166 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2167 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2168 afi2str(afi
), safi2str(safi
));
2171 /* Best path selection. */
2172 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2174 old_select
= old_and_new
.old
;
2175 new_select
= old_and_new
.new;
2177 /* Do we need to allocate or free labels?
2178 * Right now, since we only deal with per-prefix labels, it is not
2179 * necessary to do this upon changes to best path except if the label
2182 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2185 || bgp_label_index_differs(new_select
, old_select
)
2186 || new_select
->sub_type
!= old_select
->sub_type
) {
2187 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2188 && new_select
->attr
->flag
2190 BGP_ATTR_PREFIX_SID
)
2191 && new_select
->attr
->label_index
2192 != BGP_INVALID_LABEL_INDEX
) {
2195 BGP_NODE_REGISTERED_FOR_LABEL
))
2196 bgp_unregister_for_label(rn
);
2197 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2199 bgp_set_valid_label(&rn
->local_label
);
2201 bgp_register_for_label(rn
, new_select
);
2203 } else if (CHECK_FLAG(rn
->flags
,
2204 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2205 bgp_unregister_for_label(rn
);
2207 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2208 bgp_unregister_for_label(rn
);
2212 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2214 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2215 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2216 old_select
, new_select
);
2219 /* If best route remains the same and this is not due to user-initiated
2220 * clear, see exactly what needs to be done.
2223 if (old_select
&& old_select
== new_select
2224 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2225 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2226 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2227 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2229 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2230 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2232 if (bgp_fibupd_safi(safi
)
2233 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2235 if (new_select
->type
== ZEBRA_ROUTE_BGP
2236 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2237 || new_select
->sub_type
2238 == BGP_ROUTE_IMPORTED
))
2240 bgp_zebra_announce(rn
, p
, old_select
,
2244 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2245 bgp_zebra_clear_route_change_flags(rn
);
2247 /* If there is a change of interest to peers, reannounce the
2249 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2250 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2251 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2253 /* unicast routes must also be annouced to
2254 * labeled-unicast update-groups */
2255 if (safi
== SAFI_UNICAST
)
2256 group_announce_route(bgp
, afi
,
2257 SAFI_LABELED_UNICAST
, rn
,
2260 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2261 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2264 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2268 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2270 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2272 /* bestpath has changed; bump version */
2273 if (old_select
|| new_select
) {
2274 bgp_bump_version(rn
);
2276 if (!bgp
->t_rmap_def_originate_eval
) {
2280 update_group_refresh_default_originate_route_map
,
2281 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2282 &bgp
->t_rmap_def_originate_eval
);
2287 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2290 zlog_debug("%s: setting SELECTED flag", __func__
);
2291 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2292 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2293 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2297 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2298 if (old_select
!= new_select
) {
2300 vnc_import_bgp_exterior_del_route(bgp
, p
,
2302 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2305 vnc_import_bgp_exterior_add_route(bgp
, p
,
2307 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2313 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2315 /* unicast routes must also be annouced to labeled-unicast update-groups
2317 if (safi
== SAFI_UNICAST
)
2318 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2322 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2323 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2324 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2325 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2326 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2327 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2329 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2331 /* Withdraw the route from the kernel. */
2332 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2333 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2334 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2335 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2337 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2341 /* advertise/withdraw type-5 routes */
2342 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2343 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2344 (!new_select
->extra
|| !new_select
->extra
->parent
))
2345 bgp_evpn_advertise_type5_route(bgp
, &rn
->p
,
2348 else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2349 (!old_select
->extra
|| !old_select
->extra
->parent
))
2350 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2353 /* Clear any route change flags. */
2354 bgp_zebra_clear_route_change_flags(rn
);
2356 /* Reap old select bgp_info, if it has been removed */
2357 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2358 bgp_info_reap(rn
, old_select
);
2360 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2364 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2366 struct bgp_process_queue
*pqnode
= data
;
2367 struct bgp
*bgp
= pqnode
->bgp
;
2368 struct bgp_table
*table
;
2369 struct bgp_node
*rn
;
2372 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2373 bgp_process_main_one(bgp
, NULL
, 0, 0);
2374 /* should always have dedicated wq call */
2375 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2379 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2380 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2381 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2382 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2383 table
= bgp_node_table(rn
);
2384 /* note, new RNs may be added as part of processing */
2385 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2387 bgp_unlock_node(rn
);
2388 bgp_table_unlock(table
);
2394 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2396 struct bgp_process_queue
*pqnode
= data
;
2398 bgp_unlock(pqnode
->bgp
);
2400 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2403 void bgp_process_queue_init(void)
2405 if (!bm
->process_main_queue
) {
2406 bm
->process_main_queue
=
2407 work_queue_new(bm
->master
, "process_main_queue");
2409 if (!bm
->process_main_queue
) {
2410 zlog_err("%s: Failed to allocate work queue", __func__
);
2415 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2416 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2417 bm
->process_main_queue
->spec
.max_retries
= 0;
2418 bm
->process_main_queue
->spec
.hold
= 50;
2419 /* Use a higher yield value of 50ms for main queue processing */
2420 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2423 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2425 struct bgp_process_queue
*pqnode
;
2427 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2428 sizeof(struct bgp_process_queue
));
2430 /* unlocked in bgp_processq_del */
2431 pqnode
->bgp
= bgp_lock(bgp
);
2432 STAILQ_INIT(&pqnode
->pqueue
);
2437 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2439 #define ARBITRARY_PROCESS_QLEN 10000
2440 struct work_queue
*wq
= bm
->process_main_queue
;
2441 struct bgp_process_queue
*pqnode
;
2442 int pqnode_reuse
= 0;
2444 /* already scheduled for processing? */
2445 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2451 /* Add route nodes to an existing work queue item until reaching the
2452 limit only if is from the same BGP view and it's not an EOIU marker
2454 if (work_queue_item_count(wq
)) {
2455 struct work_queue_item
*item
= work_queue_last_item(wq
);
2456 pqnode
= item
->data
;
2458 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2459 || pqnode
->bgp
!= bgp
2460 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2461 pqnode
= bgp_processq_alloc(bgp
);
2465 pqnode
= bgp_processq_alloc(bgp
);
2466 /* all unlocked in bgp_process_wq */
2467 bgp_table_lock(bgp_node_table(rn
));
2469 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2472 /* can't be enqueued twice */
2473 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2474 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2478 work_queue_add(wq
, pqnode
);
2483 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2485 struct bgp_process_queue
*pqnode
;
2487 if (bm
->process_main_queue
== NULL
)
2490 pqnode
= bgp_processq_alloc(bgp
);
2492 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2493 work_queue_add(bm
->process_main_queue
, pqnode
);
2496 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2500 peer
= THREAD_ARG(thread
);
2501 peer
->t_pmax_restart
= NULL
;
2503 if (bgp_debug_neighbor_events(peer
))
2505 "%s Maximum-prefix restart timer expired, restore peering",
2508 peer_clear(peer
, NULL
);
2513 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2517 iana_safi_t pkt_safi
;
2519 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2522 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2523 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2524 PEER_STATUS_PREFIX_LIMIT
)
2529 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2531 afi_safi_print(afi
, safi
), peer
->host
,
2532 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2533 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2535 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2536 PEER_FLAG_MAX_PREFIX_WARNING
))
2539 /* Convert AFI, SAFI to values for packet. */
2540 pkt_afi
= afi_int2iana(afi
);
2541 pkt_safi
= safi_int2iana(safi
);
2545 ndata
[0] = (pkt_afi
>> 8);
2547 ndata
[2] = pkt_safi
;
2548 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2549 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2550 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2551 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2553 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2554 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2555 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2559 /* Dynamic peers will just close their connection. */
2560 if (peer_dynamic_neighbor(peer
))
2563 /* restart timer start */
2564 if (peer
->pmax_restart
[afi
][safi
]) {
2565 peer
->v_pmax_restart
=
2566 peer
->pmax_restart
[afi
][safi
] * 60;
2568 if (bgp_debug_neighbor_events(peer
))
2570 "%s Maximum-prefix restart timer started for %d secs",
2571 peer
->host
, peer
->v_pmax_restart
);
2573 BGP_TIMER_ON(peer
->t_pmax_restart
,
2574 bgp_maximum_prefix_restart_timer
,
2575 peer
->v_pmax_restart
);
2580 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2581 PEER_STATUS_PREFIX_LIMIT
);
2583 if (peer
->pcount
[afi
][safi
]
2584 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2585 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2586 PEER_STATUS_PREFIX_THRESHOLD
)
2591 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2592 afi_safi_print(afi
, safi
), peer
->host
,
2593 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2594 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2595 PEER_STATUS_PREFIX_THRESHOLD
);
2597 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2598 PEER_STATUS_PREFIX_THRESHOLD
);
2602 /* Unconditionally remove the route from the RIB, without taking
2603 * damping into consideration (eg, because the session went down)
2605 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2606 afi_t afi
, safi_t safi
)
2608 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2610 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2611 bgp_info_delete(rn
, ri
); /* keep historical info */
2613 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2616 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2617 struct peer
*peer
, afi_t afi
, safi_t safi
,
2618 struct prefix_rd
*prd
)
2620 int status
= BGP_DAMP_NONE
;
2622 /* apply dampening, if result is suppressed, we'll be retaining
2623 * the bgp_info in the RIB for historical reference.
2625 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2626 && peer
->sort
== BGP_PEER_EBGP
)
2627 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2628 == BGP_DAMP_SUPPRESSED
) {
2629 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2635 if (safi
== SAFI_MPLS_VPN
) {
2636 struct bgp_node
*prn
= NULL
;
2637 struct bgp_table
*table
= NULL
;
2639 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2640 (struct prefix
*)prd
);
2642 table
= (struct bgp_table
*)(prn
->info
);
2644 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2645 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2647 bgp_unlock_node(prn
);
2649 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2650 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2652 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2653 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2659 /* If this is an EVPN route, process for un-import. */
2660 if (safi
== SAFI_EVPN
)
2661 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2663 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2666 struct bgp_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2667 struct peer
*peer
, struct attr
*attr
,
2668 struct bgp_node
*rn
)
2670 struct bgp_info
*new;
2672 /* Make new BGP info. */
2673 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2675 new->instance
= instance
;
2676 new->sub_type
= sub_type
;
2679 new->uptime
= bgp_clock();
2681 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2685 static void overlay_index_update(struct attr
*attr
,
2686 struct eth_segment_id
*eth_s_id
,
2687 union gw_addr
*gw_ip
)
2692 if (eth_s_id
== NULL
) {
2693 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2694 sizeof(struct eth_segment_id
));
2696 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2697 sizeof(struct eth_segment_id
));
2699 if (gw_ip
== NULL
) {
2700 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2702 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2703 sizeof(union gw_addr
));
2707 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2708 struct eth_segment_id
*eth_s_id
,
2709 union gw_addr
*gw_ip
)
2711 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2712 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2715 if (afi
!= AFI_L2VPN
)
2718 memset(&temp
, 0, 16);
2719 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2720 info_gw_ip
= (union gw_addr
*)&temp
;
2721 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2724 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2725 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2728 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2730 info_gw_ip_remote
= gw_ip
;
2731 if (eth_s_id
== NULL
)
2732 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2734 info_eth_s_id_remote
= eth_s_id
;
2735 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2737 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2738 sizeof(struct eth_segment_id
));
2741 /* Check if received nexthop is valid or not. */
2742 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2747 /* Only validated for unicast and multicast currently. */
2748 /* Also valid for EVPN where the nexthop is an IP address. */
2749 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2752 /* If NEXT_HOP is present, validate it. */
2753 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2754 if (attr
->nexthop
.s_addr
== 0
2755 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2756 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2760 /* If MP_NEXTHOP is present, validate it. */
2761 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2762 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2763 * it is not an IPv6 link-local address.
2765 if (attr
->mp_nexthop_len
) {
2766 switch (attr
->mp_nexthop_len
) {
2767 case BGP_ATTR_NHLEN_IPV4
:
2768 case BGP_ATTR_NHLEN_VPNV4
:
2769 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2770 || IPV4_CLASS_DE(ntohl(
2771 attr
->mp_nexthop_global_in
.s_addr
))
2772 || bgp_nexthop_self(bgp
,
2773 attr
->mp_nexthop_global_in
));
2776 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2777 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2778 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2779 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2780 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2781 || IN6_IS_ADDR_MULTICAST(
2782 &attr
->mp_nexthop_global
));
2794 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2795 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2796 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2797 uint32_t num_labels
, int soft_reconfig
,
2798 struct bgp_route_evpn
*evpn
)
2801 int aspath_loop_count
= 0;
2802 struct bgp_node
*rn
;
2804 struct attr new_attr
;
2805 struct attr
*attr_new
;
2806 struct bgp_info
*ri
;
2807 struct bgp_info
*new;
2808 struct bgp_info_extra
*extra
;
2810 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2812 int do_loop_check
= 1;
2813 int has_valid_label
= 0;
2815 int vnc_implicit_withdraw
= 0;
2819 memset(&new_attr
, 0, sizeof(struct attr
));
2820 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2821 new_attr
.label
= MPLS_INVALID_LABEL
;
2824 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2825 /* TODO: Check to see if we can get rid of "is_valid_label" */
2826 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2827 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2829 has_valid_label
= bgp_is_valid_label(label
);
2831 /* When peer's soft reconfiguration enabled. Record input packet in
2834 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2835 && peer
!= bgp
->peer_self
)
2836 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2838 /* Check previously received route. */
2839 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2840 if (ri
->peer
== peer
&& ri
->type
== type
2841 && ri
->sub_type
== sub_type
2842 && ri
->addpath_rx_id
== addpath_id
)
2845 /* AS path local-as loop check. */
2846 if (peer
->change_local_as
) {
2847 if (peer
->allowas_in
[afi
][safi
])
2848 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2849 else if (!CHECK_FLAG(peer
->flags
,
2850 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2851 aspath_loop_count
= 1;
2853 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2854 > aspath_loop_count
) {
2855 reason
= "as-path contains our own AS;";
2860 /* If the peer is configured for "allowas-in origin" and the last ASN in
2862 * as-path is our ASN then we do not need to call aspath_loop_check
2864 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2865 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2868 /* AS path loop check. */
2869 if (do_loop_check
) {
2870 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2871 > peer
->allowas_in
[afi
][safi
]
2872 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2873 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2874 > peer
->allowas_in
[afi
][safi
])) {
2875 reason
= "as-path contains our own AS;";
2880 /* Route reflector originator ID check. */
2881 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2882 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2883 reason
= "originator is us;";
2887 /* Route reflector cluster ID check. */
2888 if (bgp_cluster_filter(peer
, attr
)) {
2889 reason
= "reflected from the same cluster;";
2893 /* Apply incoming filter. */
2894 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2899 bgp_attr_dup(&new_attr
, attr
);
2901 /* Apply incoming route-map.
2902 * NB: new_attr may now contain newly allocated values from route-map
2904 * commands, so we need bgp_attr_flush in the error paths, until we
2906 * the attr (which takes over the memory references) */
2907 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2909 reason
= "route-map;";
2910 bgp_attr_flush(&new_attr
);
2914 if (peer
->sort
== BGP_PEER_EBGP
) {
2916 /* If we receive the graceful-shutdown community from an eBGP
2917 * peer we must lower local-preference */
2918 if (new_attr
.community
2919 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2920 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2921 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2923 /* If graceful-shutdown is configured then add the GSHUT
2924 * community to all paths received from eBGP peers */
2925 } else if (bgp_flag_check(peer
->bgp
,
2926 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2927 bgp_attr_add_gshut_community(&new_attr
);
2931 /* next hop check. */
2932 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2933 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2934 reason
= "martian or self next-hop;";
2935 bgp_attr_flush(&new_attr
);
2939 attr_new
= bgp_attr_intern(&new_attr
);
2941 /* If the update is implicit withdraw. */
2943 ri
->uptime
= bgp_clock();
2944 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2946 /* Same attribute comes in. */
2947 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2948 && attrhash_cmp(ri
->attr
, attr_new
)
2949 && (!has_valid_label
2950 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2951 num_labels
* sizeof(mpls_label_t
))
2953 && (overlay_index_equal(
2954 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2955 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2956 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2957 BGP_CONFIG_DAMPENING
)
2958 && peer
->sort
== BGP_PEER_EBGP
2959 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2960 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2961 bgp_debug_rdpfxpath2str(
2962 afi
, safi
, prd
, p
, label
,
2963 num_labels
, addpath_id
? 1 : 0,
2964 addpath_id
, pfx_buf
,
2966 zlog_debug("%s rcvd %s", peer
->host
,
2970 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2971 != BGP_DAMP_SUPPRESSED
) {
2972 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2974 bgp_process(bgp
, rn
, afi
, safi
);
2976 } else /* Duplicate - odd */
2978 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2979 if (!peer
->rcvd_attr_printed
) {
2981 "%s rcvd UPDATE w/ attr: %s",
2983 peer
->rcvd_attr_str
);
2984 peer
->rcvd_attr_printed
= 1;
2987 bgp_debug_rdpfxpath2str(
2988 afi
, safi
, prd
, p
, label
,
2989 num_labels
, addpath_id
? 1 : 0,
2990 addpath_id
, pfx_buf
,
2993 "%s rcvd %s...duplicate ignored",
2994 peer
->host
, pfx_buf
);
2997 /* graceful restart STALE flag unset. */
2998 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2999 bgp_info_unset_flag(rn
, ri
,
3001 bgp_process(bgp
, rn
, afi
, safi
);
3005 bgp_unlock_node(rn
);
3006 bgp_attr_unintern(&attr_new
);
3011 /* Withdraw/Announce before we fully processed the withdraw */
3012 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
3013 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3014 bgp_debug_rdpfxpath2str(
3015 afi
, safi
, prd
, p
, label
, num_labels
,
3016 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3019 "%s rcvd %s, flapped quicker than processing",
3020 peer
->host
, pfx_buf
);
3023 bgp_info_restore(rn
, ri
);
3026 /* Received Logging. */
3027 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3028 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3029 num_labels
, addpath_id
? 1 : 0,
3030 addpath_id
, pfx_buf
,
3032 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3035 /* graceful restart STALE flag unset. */
3036 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3037 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
3039 /* The attribute is changed. */
3040 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
3042 /* implicit withdraw, decrement aggregate and pcount here.
3043 * only if update is accepted, they'll increment below.
3045 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
3047 /* Update bgp route dampening information. */
3048 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3049 && peer
->sort
== BGP_PEER_EBGP
) {
3050 /* This is implicit withdraw so we should update
3053 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3054 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
3057 if (safi
== SAFI_MPLS_VPN
) {
3058 struct bgp_node
*prn
= NULL
;
3059 struct bgp_table
*table
= NULL
;
3061 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3062 (struct prefix
*)prd
);
3064 table
= (struct bgp_table
*)(prn
->info
);
3066 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3067 bgp
, prd
, table
, p
, ri
);
3069 bgp_unlock_node(prn
);
3071 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3072 && (safi
== SAFI_UNICAST
)) {
3073 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
3075 * Implicit withdraw case.
3077 ++vnc_implicit_withdraw
;
3078 vnc_import_bgp_del_route(bgp
, p
, ri
);
3079 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
3084 /* Special handling for EVPN update of an existing route. If the
3085 * extended community attribute has changed, we need to
3087 * the route using its existing extended community. It will be
3088 * subsequently processed for import with the new extended
3091 if (safi
== SAFI_EVPN
&& !same_attr
) {
3093 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3095 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3098 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
3099 attr_new
->ecommunity
);
3101 if (bgp_debug_update(peer
, p
, NULL
, 1))
3103 "Change in EXT-COMM, existing %s new %s",
3105 ri
->attr
->ecommunity
),
3107 attr_new
->ecommunity
));
3108 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3114 /* Update to new attribute. */
3115 bgp_attr_unintern(&ri
->attr
);
3116 ri
->attr
= attr_new
;
3118 /* Update MPLS label */
3119 if (has_valid_label
) {
3120 extra
= bgp_info_extra_get(ri
);
3121 memcpy(&extra
->label
, label
,
3122 num_labels
* sizeof(mpls_label_t
));
3123 extra
->num_labels
= num_labels
;
3124 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3125 bgp_set_valid_label(&extra
->label
[0]);
3129 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3130 && (safi
== SAFI_UNICAST
)) {
3131 if (vnc_implicit_withdraw
) {
3133 * Add back the route with its new attributes
3135 * The route is still selected, until the route
3137 * queued by bgp_process actually runs. We have
3139 * update to the VNC side immediately to avoid
3141 * configuration changes (e.g., route-map
3143 * trigger re-importation of the entire RIB.
3145 vnc_import_bgp_add_route(bgp
, p
, ri
);
3146 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3150 /* Update Overlay Index */
3151 if (afi
== AFI_L2VPN
) {
3152 overlay_index_update(
3153 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3154 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3157 /* Update bgp route dampening information. */
3158 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3159 && peer
->sort
== BGP_PEER_EBGP
) {
3160 /* Now we do normal update dampening. */
3161 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3162 if (ret
== BGP_DAMP_SUPPRESSED
) {
3163 bgp_unlock_node(rn
);
3168 /* Nexthop reachability check - for unicast and
3169 * labeled-unicast.. */
3170 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3171 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3172 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3173 && !CHECK_FLAG(peer
->flags
,
3174 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3176 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3181 struct bgp
*bgp_nexthop
= bgp
;
3183 if (ri
->extra
&& ri
->extra
->bgp_orig
)
3184 bgp_nexthop
= ri
->extra
->bgp_orig
;
3186 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
,
3187 ri
, NULL
, connected
)
3188 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3189 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3191 if (BGP_DEBUG(nht
, NHT
)) {
3192 char buf1
[INET6_ADDRSTRLEN
];
3194 (const void *)&attr_new
3196 buf1
, INET6_ADDRSTRLEN
);
3197 zlog_debug("%s(%s): NH unresolved",
3198 __FUNCTION__
, buf1
);
3200 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3203 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3206 if (safi
== SAFI_MPLS_VPN
) {
3207 struct bgp_node
*prn
= NULL
;
3208 struct bgp_table
*table
= NULL
;
3210 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3211 (struct prefix
*)prd
);
3213 table
= (struct bgp_table
*)(prn
->info
);
3215 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3216 bgp
, prd
, table
, p
, ri
);
3218 bgp_unlock_node(prn
);
3222 /* If this is an EVPN route and some attribute has changed,
3224 * route for import. If the extended community has changed, we
3226 * have done the un-import earlier and the import would result
3228 * route getting injected into appropriate L2 VNIs. If it is
3230 * some other attribute change, the import will result in
3232 * the attributes for the route in the VNI(s).
3234 if (safi
== SAFI_EVPN
&& !same_attr
)
3235 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3237 /* Process change. */
3238 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3240 bgp_process(bgp
, rn
, afi
, safi
);
3241 bgp_unlock_node(rn
);
3243 if (SAFI_UNICAST
== safi
3244 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3245 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3247 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, ri
);
3249 if ((SAFI_MPLS_VPN
== safi
)
3250 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3252 vpn_leak_to_vrf_update(bgp
, ri
);
3256 if (SAFI_MPLS_VPN
== safi
) {
3257 mpls_label_t label_decoded
= decode_label(label
);
3259 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3260 type
, sub_type
, &label_decoded
);
3262 if (SAFI_ENCAP
== safi
) {
3263 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3264 type
, sub_type
, NULL
);
3269 } // End of implicit withdraw
3271 /* Received Logging. */
3272 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3273 if (!peer
->rcvd_attr_printed
) {
3274 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3275 peer
->rcvd_attr_str
);
3276 peer
->rcvd_attr_printed
= 1;
3279 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3280 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3282 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3285 /* Make new BGP info. */
3286 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3288 /* Update MPLS label */
3289 if (has_valid_label
) {
3290 extra
= bgp_info_extra_get(new);
3291 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3292 extra
->num_labels
= num_labels
;
3293 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3294 bgp_set_valid_label(&extra
->label
[0]);
3297 /* Update Overlay Index */
3298 if (afi
== AFI_L2VPN
) {
3299 overlay_index_update(new->attr
,
3300 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3301 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3303 /* Nexthop reachability check. */
3304 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3305 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3306 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3307 && !CHECK_FLAG(peer
->flags
,
3308 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3309 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3314 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3315 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3316 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3318 if (BGP_DEBUG(nht
, NHT
)) {
3319 char buf1
[INET6_ADDRSTRLEN
];
3321 (const void *)&attr_new
->nexthop
,
3322 buf1
, INET6_ADDRSTRLEN
);
3323 zlog_debug("%s(%s): NH unresolved",
3324 __FUNCTION__
, buf1
);
3326 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3329 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3332 new->addpath_rx_id
= addpath_id
;
3334 /* Increment prefix */
3335 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3337 /* Register new BGP information. */
3338 bgp_info_add(rn
, new);
3340 /* route_node_get lock */
3341 bgp_unlock_node(rn
);
3344 if (safi
== SAFI_MPLS_VPN
) {
3345 struct bgp_node
*prn
= NULL
;
3346 struct bgp_table
*table
= NULL
;
3348 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3350 table
= (struct bgp_table
*)(prn
->info
);
3352 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3353 bgp
, prd
, table
, p
, new);
3355 bgp_unlock_node(prn
);
3359 /* If maximum prefix count is configured and current prefix
3361 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3364 /* If this is an EVPN route, process for import. */
3365 if (safi
== SAFI_EVPN
)
3366 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3368 /* Process change. */
3369 bgp_process(bgp
, rn
, afi
, safi
);
3371 if (SAFI_UNICAST
== safi
3372 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3373 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3374 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3376 if ((SAFI_MPLS_VPN
== safi
)
3377 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3379 vpn_leak_to_vrf_update(bgp
, new);
3382 if (SAFI_MPLS_VPN
== safi
) {
3383 mpls_label_t label_decoded
= decode_label(label
);
3385 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3386 sub_type
, &label_decoded
);
3388 if (SAFI_ENCAP
== safi
) {
3389 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3396 /* This BGP update is filtered. Log the reason then update BGP
3399 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3400 if (!peer
->rcvd_attr_printed
) {
3401 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3402 peer
->rcvd_attr_str
);
3403 peer
->rcvd_attr_printed
= 1;
3406 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3407 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3409 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3410 peer
->host
, pfx_buf
, reason
);
3414 /* If this is an EVPN route, un-import it as it is now filtered.
3416 if (safi
== SAFI_EVPN
)
3417 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3419 if (SAFI_UNICAST
== safi
3420 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3421 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3423 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3425 if ((SAFI_MPLS_VPN
== safi
)
3426 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3428 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3431 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3434 bgp_unlock_node(rn
);
3438 * Filtered update is treated as an implicit withdrawal (see
3440 * a few lines above)
3442 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3443 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3451 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3452 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3453 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3454 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3457 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3458 struct bgp_node
*rn
;
3459 struct bgp_info
*ri
;
3462 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3463 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3471 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3473 /* If peer is soft reconfiguration enabled. Record input packet for
3474 * further calculation.
3476 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3477 * routes that are filtered. This tanks out Quagga RS pretty badly due
3479 * the iteration over all RS clients.
3480 * Since we need to remove the entry from adj_in anyway, do that first
3482 * if there was no entry, we don't need to do anything more.
3484 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3485 && peer
!= bgp
->peer_self
)
3486 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3487 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3488 bgp_debug_rdpfxpath2str(
3489 afi
, safi
, prd
, p
, label
, num_labels
,
3490 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3493 "%s withdrawing route %s not in adj-in",
3494 peer
->host
, pfx_buf
);
3496 bgp_unlock_node(rn
);
3500 /* Lookup withdrawn route. */
3501 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3502 if (ri
->peer
== peer
&& ri
->type
== type
3503 && ri
->sub_type
== sub_type
3504 && ri
->addpath_rx_id
== addpath_id
)
3508 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3509 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3510 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3512 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3516 /* Withdraw specified route from routing table. */
3517 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
3518 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3519 if (SAFI_UNICAST
== safi
3520 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3521 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3522 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
3524 if ((SAFI_MPLS_VPN
== safi
)
3525 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3527 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3529 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3530 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3531 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3533 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3536 /* Unlock bgp_node_get() lock. */
3537 bgp_unlock_node(rn
);
3542 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3545 struct update_subgroup
*subgrp
;
3546 subgrp
= peer_subgroup(peer
, afi
, safi
);
3547 subgroup_default_originate(subgrp
, withdraw
);
3552 * bgp_stop_announce_route_timer
3554 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3556 if (!paf
->t_announce_route
)
3559 THREAD_TIMER_OFF(paf
->t_announce_route
);
3563 * bgp_announce_route_timer_expired
3565 * Callback that is invoked when the route announcement timer for a
3568 static int bgp_announce_route_timer_expired(struct thread
*t
)
3570 struct peer_af
*paf
;
3573 paf
= THREAD_ARG(t
);
3576 if (peer
->status
!= Established
)
3579 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3582 peer_af_announce_route(paf
, 1);
3587 * bgp_announce_route
3589 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3591 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3593 struct peer_af
*paf
;
3594 struct update_subgroup
*subgrp
;
3596 paf
= peer_af_find(peer
, afi
, safi
);
3599 subgrp
= PAF_SUBGRP(paf
);
3602 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3603 * or a refresh has already been triggered.
3605 if (!subgrp
|| paf
->t_announce_route
)
3609 * Start a timer to stagger/delay the announce. This serves
3610 * two purposes - announcement can potentially be combined for
3611 * multiple peers and the announcement doesn't happen in the
3614 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3615 (subgrp
->peer_count
== 1)
3616 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3617 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3618 &paf
->t_announce_route
);
3622 * Announce routes from all AF tables to a peer.
3624 * This should ONLY be called when there is a need to refresh the
3625 * routes to the peer based on a policy change for this peer alone
3626 * or a route refresh request received from the peer.
3627 * The operation will result in splitting the peer from its existing
3628 * subgroups and putting it in new subgroups.
3630 void bgp_announce_route_all(struct peer
*peer
)
3635 FOREACH_AFI_SAFI (afi
, safi
)
3636 bgp_announce_route(peer
, afi
, safi
);
3639 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3640 struct bgp_table
*table
,
3641 struct prefix_rd
*prd
)
3644 struct bgp_node
*rn
;
3645 struct bgp_adj_in
*ain
;
3648 table
= peer
->bgp
->rib
[afi
][safi
];
3650 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3651 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3652 if (ain
->peer
!= peer
)
3655 struct bgp_info
*ri
= rn
->info
;
3656 uint32_t num_labels
= 0;
3657 mpls_label_t
*label_pnt
= NULL
;
3659 if (ri
&& ri
->extra
)
3660 num_labels
= ri
->extra
->num_labels
;
3662 label_pnt
= &ri
->extra
->label
[0];
3664 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3665 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3666 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3667 num_labels
, 1, NULL
);
3670 bgp_unlock_node(rn
);
3676 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3678 struct bgp_node
*rn
;
3679 struct bgp_table
*table
;
3681 if (peer
->status
!= Established
)
3684 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3685 && (safi
!= SAFI_EVPN
))
3686 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3688 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3689 rn
= bgp_route_next(rn
))
3690 if ((table
= rn
->info
) != NULL
) {
3691 struct prefix_rd prd
;
3692 prd
.family
= AF_UNSPEC
;
3694 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3696 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3702 struct bgp_clear_node_queue
{
3703 struct bgp_node
*rn
;
3706 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3708 struct bgp_clear_node_queue
*cnq
= data
;
3709 struct bgp_node
*rn
= cnq
->rn
;
3710 struct peer
*peer
= wq
->spec
.data
;
3711 struct bgp_info
*ri
;
3713 afi_t afi
= bgp_node_table(rn
)->afi
;
3714 safi_t safi
= bgp_node_table(rn
)->safi
;
3719 /* It is possible that we have multiple paths for a prefix from a peer
3720 * if that peer is using AddPath.
3722 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3723 if (ri
->peer
!= peer
)
3726 /* graceful restart STALE flag set. */
3727 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3728 && peer
->nsf
[afi
][safi
]
3729 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3730 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3731 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3733 /* If this is an EVPN route, process for
3735 if (safi
== SAFI_EVPN
)
3736 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3738 /* Handle withdraw for VRF route-leaking and L3VPN */
3739 if (SAFI_UNICAST
== safi
3740 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3741 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3742 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3745 if (SAFI_MPLS_VPN
== safi
&&
3746 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3747 vpn_leak_to_vrf_withdraw(bgp
, ri
);
3750 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3756 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3758 struct bgp_clear_node_queue
*cnq
= data
;
3759 struct bgp_node
*rn
= cnq
->rn
;
3760 struct bgp_table
*table
= bgp_node_table(rn
);
3762 bgp_unlock_node(rn
);
3763 bgp_table_unlock(table
);
3764 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3767 static void bgp_clear_node_complete(struct work_queue
*wq
)
3769 struct peer
*peer
= wq
->spec
.data
;
3771 /* Tickle FSM to start moving again */
3772 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3774 peer_unlock(peer
); /* bgp_clear_route */
3777 static void bgp_clear_node_queue_init(struct peer
*peer
)
3779 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3781 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3782 #undef CLEAR_QUEUE_NAME_LEN
3784 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3786 zlog_err("%s: Failed to allocate work queue", __func__
);
3789 peer
->clear_node_queue
->spec
.hold
= 10;
3790 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3791 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3792 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3793 peer
->clear_node_queue
->spec
.max_retries
= 0;
3795 /* we only 'lock' this peer reference when the queue is actually active
3797 peer
->clear_node_queue
->spec
.data
= peer
;
3800 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3801 struct bgp_table
*table
)
3803 struct bgp_node
*rn
;
3804 int force
= bm
->process_main_queue
? 0 : 1;
3807 table
= peer
->bgp
->rib
[afi
][safi
];
3809 /* If still no table => afi/safi isn't configured at all or smth. */
3813 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3814 struct bgp_info
*ri
, *next
;
3815 struct bgp_adj_in
*ain
;
3816 struct bgp_adj_in
*ain_next
;
3818 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3819 * queued for every clearing peer, regardless of whether it is
3820 * relevant to the peer at hand.
3822 * Overview: There are 3 different indices which need to be
3823 * scrubbed, potentially, when a peer is removed:
3825 * 1 peer's routes visible via the RIB (ie accepted routes)
3826 * 2 peer's routes visible by the (optional) peer's adj-in index
3827 * 3 other routes visible by the peer's adj-out index
3829 * 3 there is no hurry in scrubbing, once the struct peer is
3830 * removed from bgp->peer, we could just GC such deleted peer's
3831 * adj-outs at our leisure.
3833 * 1 and 2 must be 'scrubbed' in some way, at least made
3834 * invisible via RIB index before peer session is allowed to be
3835 * brought back up. So one needs to know when such a 'search' is
3840 * - there'd be a single global queue or a single RIB walker
3841 * - rather than tracking which route_nodes still need to be
3842 * examined on a peer basis, we'd track which peers still
3845 * Given that our per-peer prefix-counts now should be reliable,
3846 * this may actually be achievable. It doesn't seem to be a huge
3847 * problem at this time,
3849 * It is possible that we have multiple paths for a prefix from
3851 * if that peer is using AddPath.
3855 ain_next
= ain
->next
;
3857 if (ain
->peer
== peer
) {
3858 bgp_adj_in_remove(rn
, ain
);
3859 bgp_unlock_node(rn
);
3865 for (ri
= rn
->info
; ri
; ri
= next
) {
3867 if (ri
->peer
!= peer
)
3871 bgp_info_reap(rn
, ri
);
3873 struct bgp_clear_node_queue
*cnq
;
3875 /* both unlocked in bgp_clear_node_queue_del */
3876 bgp_table_lock(bgp_node_table(rn
));
3879 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3880 sizeof(struct bgp_clear_node_queue
));
3882 work_queue_add(peer
->clear_node_queue
, cnq
);
3890 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3892 struct bgp_node
*rn
;
3893 struct bgp_table
*table
;
3895 if (peer
->clear_node_queue
== NULL
)
3896 bgp_clear_node_queue_init(peer
);
3898 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3899 * Idle until it receives a Clearing_Completed event. This protects
3900 * against peers which flap faster than we can we clear, which could
3903 * a) race with routes from the new session being installed before
3904 * clear_route_node visits the node (to delete the route of that
3906 * b) resource exhaustion, clear_route_node likely leads to an entry
3907 * on the process_main queue. Fast-flapping could cause that queue
3911 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3912 * the unlock will happen upon work-queue completion; other wise, the
3913 * unlock happens at the end of this function.
3915 if (!peer
->clear_node_queue
->thread
)
3918 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3919 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3921 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3922 rn
= bgp_route_next(rn
))
3923 if ((table
= rn
->info
) != NULL
)
3924 bgp_clear_route_table(peer
, afi
, safi
, table
);
3926 /* unlock if no nodes got added to the clear-node-queue. */
3927 if (!peer
->clear_node_queue
->thread
)
3931 void bgp_clear_route_all(struct peer
*peer
)
3936 FOREACH_AFI_SAFI (afi
, safi
)
3937 bgp_clear_route(peer
, afi
, safi
);
3940 rfapiProcessPeerDown(peer
);
3944 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3946 struct bgp_table
*table
;
3947 struct bgp_node
*rn
;
3948 struct bgp_adj_in
*ain
;
3949 struct bgp_adj_in
*ain_next
;
3951 table
= peer
->bgp
->rib
[afi
][safi
];
3953 /* It is possible that we have multiple paths for a prefix from a peer
3954 * if that peer is using AddPath.
3956 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3960 ain_next
= ain
->next
;
3962 if (ain
->peer
== peer
) {
3963 bgp_adj_in_remove(rn
, ain
);
3964 bgp_unlock_node(rn
);
3972 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3974 struct bgp_node
*rn
;
3975 struct bgp_info
*ri
;
3976 struct bgp_table
*table
;
3978 if (safi
== SAFI_MPLS_VPN
) {
3979 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3980 rn
= bgp_route_next(rn
)) {
3981 struct bgp_node
*rm
;
3982 struct bgp_info
*ri
;
3984 /* look for neighbor in tables */
3985 if ((table
= rn
->info
) == NULL
)
3988 for (rm
= bgp_table_top(table
); rm
;
3989 rm
= bgp_route_next(rm
))
3990 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3991 if (ri
->peer
!= peer
)
3993 if (!CHECK_FLAG(ri
->flags
,
3997 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
4002 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4003 rn
= bgp_route_next(rn
))
4004 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4005 if (ri
->peer
!= peer
)
4007 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
4009 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
4015 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4018 struct bgp_node
*rn
;
4019 struct bgp_info
*ri
;
4020 struct bgp_info
*next
;
4022 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4023 for (ri
= rn
->info
; ri
; ri
= next
) {
4025 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
4026 && ri
->type
== ZEBRA_ROUTE_BGP
4027 && (ri
->sub_type
== BGP_ROUTE_NORMAL
4028 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
4029 || ri
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4031 if (bgp_fibupd_safi(safi
))
4032 bgp_zebra_withdraw(&rn
->p
, ri
,
4034 bgp_info_reap(rn
, ri
);
4039 /* Delete all kernel routes. */
4040 void bgp_cleanup_routes(struct bgp
*bgp
)
4043 struct bgp_node
*rn
;
4045 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4046 if (afi
== AFI_L2VPN
)
4048 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4051 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4053 if (afi
!= AFI_L2VPN
) {
4055 safi
= SAFI_MPLS_VPN
;
4056 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4057 rn
= bgp_route_next(rn
)) {
4059 bgp_cleanup_table(bgp
,
4060 (struct bgp_table
*)(rn
->info
),
4062 bgp_table_finish((struct bgp_table
**)&(
4065 bgp_unlock_node(rn
);
4069 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4070 rn
= bgp_route_next(rn
)) {
4072 bgp_cleanup_table(bgp
,
4073 (struct bgp_table
*)(rn
->info
),
4075 bgp_table_finish((struct bgp_table
**)&(
4078 bgp_unlock_node(rn
);
4083 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4084 rn
= bgp_route_next(rn
)) {
4086 bgp_cleanup_table(bgp
,
4087 (struct bgp_table
*)(rn
->info
),
4089 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4091 bgp_unlock_node(rn
);
4096 void bgp_reset(void)
4099 bgp_zclient_reset();
4100 access_list_reset();
4101 prefix_list_reset();
4104 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4106 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4107 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4108 PEER_CAP_ADDPATH_AF_TX_RCV
));
4111 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4113 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4114 struct bgp_nlri
*packet
)
4123 int addpath_encoded
;
4124 uint32_t addpath_id
;
4127 lim
= pnt
+ packet
->length
;
4129 safi
= packet
->safi
;
4131 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4133 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4134 syntactic validity. If the field is syntactically incorrect,
4135 then the Error Subcode is set to Invalid Network Field. */
4136 for (; pnt
< lim
; pnt
+= psize
) {
4137 /* Clear prefix structure. */
4138 memset(&p
, 0, sizeof(struct prefix
));
4140 if (addpath_encoded
) {
4142 /* When packet overflow occurs return immediately. */
4143 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4146 addpath_id
= ntohl(*((uint32_t *)pnt
));
4147 pnt
+= BGP_ADDPATH_ID_LEN
;
4150 /* Fetch prefix length. */
4151 p
.prefixlen
= *pnt
++;
4152 /* afi/safi validity already verified by caller,
4153 * bgp_update_receive */
4154 p
.family
= afi2family(afi
);
4156 /* Prefix length check. */
4157 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4159 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
4160 peer
->host
, p
.prefixlen
, packet
->afi
);
4164 /* Packet size overflow check. */
4165 psize
= PSIZE(p
.prefixlen
);
4167 /* When packet overflow occur return immediately. */
4168 if (pnt
+ psize
> lim
) {
4170 "%s [Error] Update packet error (prefix length %d overflows packet)",
4171 peer
->host
, p
.prefixlen
);
4175 /* Defensive coding, double-check the psize fits in a struct
4177 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4179 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4180 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4184 /* Fetch prefix from NLRI packet. */
4185 memcpy(&p
.u
.prefix
, pnt
, psize
);
4187 /* Check address. */
4188 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4189 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4190 /* From RFC4271 Section 6.3:
4192 * If a prefix in the NLRI field is semantically
4194 * (e.g., an unexpected multicast IP address),
4196 * be logged locally, and the prefix SHOULD be
4200 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4201 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4206 /* Check address. */
4207 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4208 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4212 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4214 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4219 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4223 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4225 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4232 /* Normal process. */
4234 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4235 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4236 NULL
, NULL
, 0, 0, NULL
);
4238 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4239 safi
, ZEBRA_ROUTE_BGP
,
4240 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4243 /* Address family configuration mismatch or maximum-prefix count
4249 /* Packet length consistency check. */
4252 "%s [Error] Update packet error (prefix length mismatch with total length)",
4260 static struct bgp_static
*bgp_static_new(void)
4262 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4265 static void bgp_static_free(struct bgp_static
*bgp_static
)
4267 if (bgp_static
->rmap
.name
)
4268 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4269 if (bgp_static
->eth_s_id
)
4270 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4271 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4274 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4275 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4277 struct bgp_node
*rn
;
4278 struct bgp_info
*ri
;
4279 struct bgp_info
*new;
4280 struct bgp_info info
;
4282 struct attr
*attr_new
;
4285 int vnc_implicit_withdraw
= 0;
4292 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4294 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4296 attr
.nexthop
= bgp_static
->igpnexthop
;
4297 attr
.med
= bgp_static
->igpmetric
;
4298 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4300 if (bgp_static
->atomic
)
4301 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4303 /* Store label index, if required. */
4304 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4305 attr
.label_index
= bgp_static
->label_index
;
4306 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4309 /* Apply route-map. */
4310 if (bgp_static
->rmap
.name
) {
4311 struct attr attr_tmp
= attr
;
4312 info
.peer
= bgp
->peer_self
;
4313 info
.attr
= &attr_tmp
;
4315 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4317 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4319 bgp
->peer_self
->rmap_type
= 0;
4321 if (ret
== RMAP_DENYMATCH
) {
4322 /* Free uninterned attribute. */
4323 bgp_attr_flush(&attr_tmp
);
4325 /* Unintern original. */
4326 aspath_unintern(&attr
.aspath
);
4327 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4331 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4332 bgp_attr_add_gshut_community(&attr_tmp
);
4334 attr_new
= bgp_attr_intern(&attr_tmp
);
4337 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4338 bgp_attr_add_gshut_community(&attr
);
4340 attr_new
= bgp_attr_intern(&attr
);
4343 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4344 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4345 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4349 if (attrhash_cmp(ri
->attr
, attr_new
)
4350 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4351 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4352 bgp_unlock_node(rn
);
4353 bgp_attr_unintern(&attr_new
);
4354 aspath_unintern(&attr
.aspath
);
4357 /* The attribute is changed. */
4358 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4360 /* Rewrite BGP route information. */
4361 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4362 bgp_info_restore(rn
, ri
);
4364 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4366 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4367 && (safi
== SAFI_UNICAST
)) {
4368 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4370 * Implicit withdraw case.
4371 * We have to do this before ri is
4374 ++vnc_implicit_withdraw
;
4375 vnc_import_bgp_del_route(bgp
, p
, ri
);
4376 vnc_import_bgp_exterior_del_route(
4381 bgp_attr_unintern(&ri
->attr
);
4382 ri
->attr
= attr_new
;
4383 ri
->uptime
= bgp_clock();
4385 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4386 && (safi
== SAFI_UNICAST
)) {
4387 if (vnc_implicit_withdraw
) {
4388 vnc_import_bgp_add_route(bgp
, p
, ri
);
4389 vnc_import_bgp_exterior_add_route(
4395 /* Nexthop reachability check. */
4396 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4397 && (safi
== SAFI_UNICAST
4398 || safi
== SAFI_LABELED_UNICAST
)) {
4400 struct bgp
*bgp_nexthop
= bgp
;
4402 if (ri
->extra
&& ri
->extra
->bgp_orig
)
4403 bgp_nexthop
= ri
->extra
->bgp_orig
;
4405 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4407 bgp_info_set_flag(rn
, ri
,
4410 if (BGP_DEBUG(nht
, NHT
)) {
4411 char buf1
[INET6_ADDRSTRLEN
];
4412 inet_ntop(p
->family
,
4416 "%s(%s): Route not in table, not advertising",
4417 __FUNCTION__
, buf1
);
4419 bgp_info_unset_flag(rn
, ri
,
4423 /* Delete the NHT structure if any, if we're
4425 * enabling/disabling import check. We
4426 * deregister the route
4427 * from NHT to avoid overloading NHT and the
4428 * process interaction
4430 bgp_unlink_nexthop(ri
);
4431 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4433 /* Process change. */
4434 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4435 bgp_process(bgp
, rn
, afi
, safi
);
4437 if (SAFI_UNICAST
== safi
4438 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4440 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4441 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4445 bgp_unlock_node(rn
);
4446 aspath_unintern(&attr
.aspath
);
4451 /* Make new BGP info. */
4452 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4454 /* Nexthop reachability check. */
4455 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4456 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4457 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4458 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4460 if (BGP_DEBUG(nht
, NHT
)) {
4461 char buf1
[INET6_ADDRSTRLEN
];
4462 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4465 "%s(%s): Route not in table, not advertising",
4466 __FUNCTION__
, buf1
);
4468 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4471 /* Delete the NHT structure if any, if we're toggling between
4472 * enabling/disabling import check. We deregister the route
4473 * from NHT to avoid overloading NHT and the process interaction
4475 bgp_unlink_nexthop(new);
4477 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4480 /* Aggregate address increment. */
4481 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4483 /* Register new BGP information. */
4484 bgp_info_add(rn
, new);
4486 /* route_node_get lock */
4487 bgp_unlock_node(rn
);
4489 /* Process change. */
4490 bgp_process(bgp
, rn
, afi
, safi
);
4492 if (SAFI_UNICAST
== safi
4493 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4494 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4495 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4498 /* Unintern original. */
4499 aspath_unintern(&attr
.aspath
);
4502 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4505 struct bgp_node
*rn
;
4506 struct bgp_info
*ri
;
4508 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4510 /* Check selected route and self inserted route. */
4511 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4512 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4513 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4516 /* Withdraw static BGP route from routing table. */
4518 if (SAFI_UNICAST
== safi
4519 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4520 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4521 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, ri
);
4523 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4524 bgp_unlink_nexthop(ri
);
4525 bgp_info_delete(rn
, ri
);
4526 bgp_process(bgp
, rn
, afi
, safi
);
4529 /* Unlock bgp_node_lookup. */
4530 bgp_unlock_node(rn
);
4534 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4536 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4537 afi_t afi
, safi_t safi
,
4538 struct prefix_rd
*prd
)
4540 struct bgp_node
*rn
;
4541 struct bgp_info
*ri
;
4543 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4545 /* Check selected route and self inserted route. */
4546 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4547 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4548 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4551 /* Withdraw static BGP route from routing table. */
4554 rfapiProcessWithdraw(
4555 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4556 1); /* Kill, since it is an administrative change */
4558 if (SAFI_MPLS_VPN
== safi
4559 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4560 vpn_leak_to_vrf_withdraw(bgp
, ri
);
4562 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4563 bgp_info_delete(rn
, ri
);
4564 bgp_process(bgp
, rn
, afi
, safi
);
4567 /* Unlock bgp_node_lookup. */
4568 bgp_unlock_node(rn
);
4571 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4572 struct bgp_static
*bgp_static
, afi_t afi
,
4575 struct bgp_node
*rn
;
4576 struct bgp_info
*new;
4577 struct attr
*attr_new
;
4578 struct attr attr
= {0};
4579 struct bgp_info
*ri
;
4581 mpls_label_t label
= 0;
4583 uint32_t num_labels
= 0;
4588 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4590 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4593 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4595 attr
.nexthop
= bgp_static
->igpnexthop
;
4596 attr
.med
= bgp_static
->igpmetric
;
4597 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4599 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4600 || (safi
== SAFI_ENCAP
)) {
4601 if (afi
== AFI_IP
) {
4602 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4603 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4606 if (afi
== AFI_L2VPN
) {
4607 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4609 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4610 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4611 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4612 sizeof(struct in6_addr
));
4613 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4614 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4615 struct bgp_encap_type_vxlan bet
;
4616 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4617 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4618 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4620 if (bgp_static
->router_mac
) {
4621 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4624 /* Apply route-map. */
4625 if (bgp_static
->rmap
.name
) {
4626 struct attr attr_tmp
= attr
;
4627 struct bgp_info info
;
4630 info
.peer
= bgp
->peer_self
;
4631 info
.attr
= &attr_tmp
;
4633 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4635 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4637 bgp
->peer_self
->rmap_type
= 0;
4639 if (ret
== RMAP_DENYMATCH
) {
4640 /* Free uninterned attribute. */
4641 bgp_attr_flush(&attr_tmp
);
4643 /* Unintern original. */
4644 aspath_unintern(&attr
.aspath
);
4645 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4650 attr_new
= bgp_attr_intern(&attr_tmp
);
4652 attr_new
= bgp_attr_intern(&attr
);
4655 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4656 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4657 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4662 memset(&add
, 0, sizeof(union gw_addr
));
4663 if (attrhash_cmp(ri
->attr
, attr_new
)
4664 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4665 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4666 bgp_unlock_node(rn
);
4667 bgp_attr_unintern(&attr_new
);
4668 aspath_unintern(&attr
.aspath
);
4671 /* The attribute is changed. */
4672 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4674 /* Rewrite BGP route information. */
4675 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4676 bgp_info_restore(rn
, ri
);
4678 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4679 bgp_attr_unintern(&ri
->attr
);
4680 ri
->attr
= attr_new
;
4681 ri
->uptime
= bgp_clock();
4684 label
= decode_label(&ri
->extra
->label
[0]);
4687 /* Process change. */
4688 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4689 bgp_process(bgp
, rn
, afi
, safi
);
4691 if (SAFI_MPLS_VPN
== safi
4692 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4693 vpn_leak_to_vrf_update(bgp
, ri
);
4696 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4697 ri
->attr
, afi
, safi
, ri
->type
,
4698 ri
->sub_type
, &label
);
4700 bgp_unlock_node(rn
);
4701 aspath_unintern(&attr
.aspath
);
4707 /* Make new BGP info. */
4708 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4710 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4711 new->extra
= bgp_info_extra_new();
4713 new->extra
->label
[0] = bgp_static
->label
;
4714 new->extra
->num_labels
= num_labels
;
4717 label
= decode_label(&bgp_static
->label
);
4720 /* Aggregate address increment. */
4721 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4723 /* Register new BGP information. */
4724 bgp_info_add(rn
, new);
4725 /* route_node_get lock */
4726 bgp_unlock_node(rn
);
4728 /* Process change. */
4729 bgp_process(bgp
, rn
, afi
, safi
);
4731 if (SAFI_MPLS_VPN
== safi
4732 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4733 vpn_leak_to_vrf_update(bgp
, new);
4736 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4737 safi
, new->type
, new->sub_type
, &label
);
4740 /* Unintern original. */
4741 aspath_unintern(&attr
.aspath
);
4744 /* Configure static BGP network. When user don't run zebra, static
4745 route should be installed as valid. */
4746 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4747 const char *ip_str
, afi_t afi
, safi_t safi
,
4748 const char *rmap
, int backdoor
, uint32_t label_index
)
4750 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4753 struct bgp_static
*bgp_static
;
4754 struct bgp_node
*rn
;
4755 uint8_t need_update
= 0;
4757 /* Convert IP prefix string to struct prefix. */
4758 ret
= str2prefix(ip_str
, &p
);
4760 vty_out(vty
, "%% Malformed prefix\n");
4761 return CMD_WARNING_CONFIG_FAILED
;
4763 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4764 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4765 return CMD_WARNING_CONFIG_FAILED
;
4772 /* Set BGP static route configuration. */
4773 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4776 vty_out(vty
, "%% Can't find static route specified\n");
4777 return CMD_WARNING_CONFIG_FAILED
;
4780 bgp_static
= rn
->info
;
4782 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4783 && (label_index
!= bgp_static
->label_index
)) {
4785 "%% label-index doesn't match static route\n");
4786 return CMD_WARNING_CONFIG_FAILED
;
4789 if ((rmap
&& bgp_static
->rmap
.name
)
4790 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4792 "%% route-map name doesn't match static route\n");
4793 return CMD_WARNING_CONFIG_FAILED
;
4796 /* Update BGP RIB. */
4797 if (!bgp_static
->backdoor
)
4798 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4800 /* Clear configuration. */
4801 bgp_static_free(bgp_static
);
4803 bgp_unlock_node(rn
);
4804 bgp_unlock_node(rn
);
4807 /* Set BGP static route configuration. */
4808 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4811 /* Configuration change. */
4812 bgp_static
= rn
->info
;
4814 /* Label index cannot be changed. */
4815 if (bgp_static
->label_index
!= label_index
) {
4816 vty_out(vty
, "%% cannot change label-index\n");
4817 return CMD_WARNING_CONFIG_FAILED
;
4820 /* Check previous routes are installed into BGP. */
4821 if (bgp_static
->valid
4822 && bgp_static
->backdoor
!= backdoor
)
4825 bgp_static
->backdoor
= backdoor
;
4828 if (bgp_static
->rmap
.name
)
4829 XFREE(MTYPE_ROUTE_MAP_NAME
,
4830 bgp_static
->rmap
.name
);
4831 bgp_static
->rmap
.name
=
4832 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4833 bgp_static
->rmap
.map
=
4834 route_map_lookup_by_name(rmap
);
4836 if (bgp_static
->rmap
.name
)
4837 XFREE(MTYPE_ROUTE_MAP_NAME
,
4838 bgp_static
->rmap
.name
);
4839 bgp_static
->rmap
.name
= NULL
;
4840 bgp_static
->rmap
.map
= NULL
;
4841 bgp_static
->valid
= 0;
4843 bgp_unlock_node(rn
);
4845 /* New configuration. */
4846 bgp_static
= bgp_static_new();
4847 bgp_static
->backdoor
= backdoor
;
4848 bgp_static
->valid
= 0;
4849 bgp_static
->igpmetric
= 0;
4850 bgp_static
->igpnexthop
.s_addr
= 0;
4851 bgp_static
->label_index
= label_index
;
4854 if (bgp_static
->rmap
.name
)
4855 XFREE(MTYPE_ROUTE_MAP_NAME
,
4856 bgp_static
->rmap
.name
);
4857 bgp_static
->rmap
.name
=
4858 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4859 bgp_static
->rmap
.map
=
4860 route_map_lookup_by_name(rmap
);
4862 rn
->info
= bgp_static
;
4865 bgp_static
->valid
= 1;
4867 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4869 if (!bgp_static
->backdoor
)
4870 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4876 void bgp_static_add(struct bgp
*bgp
)
4880 struct bgp_node
*rn
;
4881 struct bgp_node
*rm
;
4882 struct bgp_table
*table
;
4883 struct bgp_static
*bgp_static
;
4885 FOREACH_AFI_SAFI (afi
, safi
)
4886 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4887 rn
= bgp_route_next(rn
)) {
4888 if (rn
->info
== NULL
)
4891 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4892 || (safi
== SAFI_EVPN
)) {
4895 for (rm
= bgp_table_top(table
); rm
;
4896 rm
= bgp_route_next(rm
)) {
4897 bgp_static
= rm
->info
;
4898 bgp_static_update_safi(bgp
, &rm
->p
,
4903 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4909 /* Called from bgp_delete(). Delete all static routes from the BGP
4911 void bgp_static_delete(struct bgp
*bgp
)
4915 struct bgp_node
*rn
;
4916 struct bgp_node
*rm
;
4917 struct bgp_table
*table
;
4918 struct bgp_static
*bgp_static
;
4920 FOREACH_AFI_SAFI (afi
, safi
)
4921 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4922 rn
= bgp_route_next(rn
)) {
4923 if (rn
->info
== NULL
)
4926 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4927 || (safi
== SAFI_EVPN
)) {
4930 for (rm
= bgp_table_top(table
); rm
;
4931 rm
= bgp_route_next(rm
)) {
4932 bgp_static
= rm
->info
;
4933 bgp_static_withdraw_safi(
4934 bgp
, &rm
->p
, AFI_IP
, safi
,
4935 (struct prefix_rd
*)&rn
->p
);
4936 bgp_static_free(bgp_static
);
4938 bgp_unlock_node(rn
);
4941 bgp_static
= rn
->info
;
4942 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4943 bgp_static_free(bgp_static
);
4945 bgp_unlock_node(rn
);
4950 void bgp_static_redo_import_check(struct bgp
*bgp
)
4954 struct bgp_node
*rn
;
4955 struct bgp_node
*rm
;
4956 struct bgp_table
*table
;
4957 struct bgp_static
*bgp_static
;
4959 /* Use this flag to force reprocessing of the route */
4960 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4961 FOREACH_AFI_SAFI (afi
, safi
) {
4962 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4963 rn
= bgp_route_next(rn
)) {
4964 if (rn
->info
== NULL
)
4967 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4968 || (safi
== SAFI_EVPN
)) {
4971 for (rm
= bgp_table_top(table
); rm
;
4972 rm
= bgp_route_next(rm
)) {
4973 bgp_static
= rm
->info
;
4974 bgp_static_update_safi(bgp
, &rm
->p
,
4979 bgp_static
= rn
->info
;
4980 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4985 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4988 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4991 struct bgp_table
*table
;
4992 struct bgp_node
*rn
;
4993 struct bgp_info
*ri
;
4995 table
= bgp
->rib
[afi
][safi
];
4996 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4997 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4998 if (ri
->peer
== bgp
->peer_self
4999 && ((ri
->type
== ZEBRA_ROUTE_BGP
5000 && ri
->sub_type
== BGP_ROUTE_STATIC
)
5001 || (ri
->type
!= ZEBRA_ROUTE_BGP
5003 == BGP_ROUTE_REDISTRIBUTE
))) {
5004 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
5006 bgp_unlink_nexthop(ri
);
5007 bgp_info_delete(rn
, ri
);
5008 bgp_process(bgp
, rn
, afi
, safi
);
5015 * Purge all networks and redistributed routes from routing table.
5016 * Invoked upon the instance going down.
5018 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5023 FOREACH_AFI_SAFI (afi
, safi
)
5024 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5029 * Currently this is used to set static routes for VPN and ENCAP.
5030 * I think it can probably be factored with bgp_static_set.
5032 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5033 const char *ip_str
, const char *rd_str
,
5034 const char *label_str
, const char *rmap_str
,
5035 int evpn_type
, const char *esi
, const char *gwip
,
5036 const char *ethtag
, const char *routermac
)
5038 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5041 struct prefix_rd prd
;
5042 struct bgp_node
*prn
;
5043 struct bgp_node
*rn
;
5044 struct bgp_table
*table
;
5045 struct bgp_static
*bgp_static
;
5046 mpls_label_t label
= MPLS_INVALID_LABEL
;
5047 struct prefix gw_ip
;
5049 /* validate ip prefix */
5050 ret
= str2prefix(ip_str
, &p
);
5052 vty_out(vty
, "%% Malformed prefix\n");
5053 return CMD_WARNING_CONFIG_FAILED
;
5056 if ((afi
== AFI_L2VPN
)
5057 && (bgp_build_evpn_prefix(evpn_type
,
5058 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5059 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5060 return CMD_WARNING_CONFIG_FAILED
;
5063 ret
= str2prefix_rd(rd_str
, &prd
);
5065 vty_out(vty
, "%% Malformed rd\n");
5066 return CMD_WARNING_CONFIG_FAILED
;
5070 unsigned long label_val
;
5071 label_val
= strtoul(label_str
, NULL
, 10);
5072 encode_label(label_val
, &label
);
5075 if (safi
== SAFI_EVPN
) {
5076 if (esi
&& str2esi(esi
, NULL
) == 0) {
5077 vty_out(vty
, "%% Malformed ESI\n");
5078 return CMD_WARNING_CONFIG_FAILED
;
5080 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5081 vty_out(vty
, "%% Malformed Router MAC\n");
5082 return CMD_WARNING_CONFIG_FAILED
;
5085 memset(&gw_ip
, 0, sizeof(struct prefix
));
5086 ret
= str2prefix(gwip
, &gw_ip
);
5088 vty_out(vty
, "%% Malformed GatewayIp\n");
5089 return CMD_WARNING_CONFIG_FAILED
;
5091 if ((gw_ip
.family
== AF_INET
5092 && IS_EVPN_PREFIX_IPADDR_V6(
5093 (struct prefix_evpn
*)&p
))
5094 || (gw_ip
.family
== AF_INET6
5095 && IS_EVPN_PREFIX_IPADDR_V4(
5096 (struct prefix_evpn
*)&p
))) {
5098 "%% GatewayIp family differs with IP prefix\n");
5099 return CMD_WARNING_CONFIG_FAILED
;
5103 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5104 if (prn
->info
== NULL
)
5105 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5107 bgp_unlock_node(prn
);
5110 rn
= bgp_node_get(table
, &p
);
5113 vty_out(vty
, "%% Same network configuration exists\n");
5114 bgp_unlock_node(rn
);
5116 /* New configuration. */
5117 bgp_static
= bgp_static_new();
5118 bgp_static
->backdoor
= 0;
5119 bgp_static
->valid
= 0;
5120 bgp_static
->igpmetric
= 0;
5121 bgp_static
->igpnexthop
.s_addr
= 0;
5122 bgp_static
->label
= label
;
5123 bgp_static
->prd
= prd
;
5126 if (bgp_static
->rmap
.name
)
5127 XFREE(MTYPE_ROUTE_MAP_NAME
,
5128 bgp_static
->rmap
.name
);
5129 bgp_static
->rmap
.name
=
5130 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5131 bgp_static
->rmap
.map
=
5132 route_map_lookup_by_name(rmap_str
);
5135 if (safi
== SAFI_EVPN
) {
5137 bgp_static
->eth_s_id
=
5139 sizeof(struct eth_segment_id
));
5140 str2esi(esi
, bgp_static
->eth_s_id
);
5143 bgp_static
->router_mac
=
5144 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5145 prefix_str2mac(routermac
,
5146 bgp_static
->router_mac
);
5149 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5151 rn
->info
= bgp_static
;
5153 bgp_static
->valid
= 1;
5154 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5160 /* Configure static BGP network. */
5161 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5162 const char *ip_str
, const char *rd_str
,
5163 const char *label_str
, int evpn_type
, const char *esi
,
5164 const char *gwip
, const char *ethtag
)
5166 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5169 struct prefix_rd prd
;
5170 struct bgp_node
*prn
;
5171 struct bgp_node
*rn
;
5172 struct bgp_table
*table
;
5173 struct bgp_static
*bgp_static
;
5174 mpls_label_t label
= MPLS_INVALID_LABEL
;
5176 /* Convert IP prefix string to struct prefix. */
5177 ret
= str2prefix(ip_str
, &p
);
5179 vty_out(vty
, "%% Malformed prefix\n");
5180 return CMD_WARNING_CONFIG_FAILED
;
5183 if ((afi
== AFI_L2VPN
)
5184 && (bgp_build_evpn_prefix(evpn_type
,
5185 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5186 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5187 return CMD_WARNING_CONFIG_FAILED
;
5189 ret
= str2prefix_rd(rd_str
, &prd
);
5191 vty_out(vty
, "%% Malformed rd\n");
5192 return CMD_WARNING_CONFIG_FAILED
;
5196 unsigned long label_val
;
5197 label_val
= strtoul(label_str
, NULL
, 10);
5198 encode_label(label_val
, &label
);
5201 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5202 if (prn
->info
== NULL
)
5203 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5205 bgp_unlock_node(prn
);
5208 rn
= bgp_node_lookup(table
, &p
);
5211 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5213 bgp_static
= rn
->info
;
5214 bgp_static_free(bgp_static
);
5216 bgp_unlock_node(rn
);
5217 bgp_unlock_node(rn
);
5219 vty_out(vty
, "%% Can't find the route\n");
5224 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5225 const char *rmap_name
)
5227 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5228 struct bgp_rmap
*rmap
;
5230 rmap
= &bgp
->table_map
[afi
][safi
];
5233 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5234 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5235 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5238 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5243 if (bgp_fibupd_safi(safi
))
5244 bgp_zebra_announce_table(bgp
, afi
, safi
);
5249 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5250 const char *rmap_name
)
5252 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5253 struct bgp_rmap
*rmap
;
5255 rmap
= &bgp
->table_map
[afi
][safi
];
5257 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5261 if (bgp_fibupd_safi(safi
))
5262 bgp_zebra_announce_table(bgp
, afi
, safi
);
5267 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5270 if (bgp
->table_map
[afi
][safi
].name
) {
5271 vty_out(vty
, " table-map %s\n",
5272 bgp
->table_map
[afi
][safi
].name
);
5276 DEFUN (bgp_table_map
,
5279 "BGP table to RIB route download filter\n"
5280 "Name of the route map\n")
5283 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5284 argv
[idx_word
]->arg
);
5286 DEFUN (no_bgp_table_map
,
5287 no_bgp_table_map_cmd
,
5288 "no table-map WORD",
5290 "BGP table to RIB route download filter\n"
5291 "Name of the route map\n")
5294 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5295 argv
[idx_word
]->arg
);
5301 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5302 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5303 backdoor$backdoor}]",
5305 "Specify a network to announce via BGP\n"
5310 "Route-map to modify the attributes\n"
5311 "Name of the route map\n"
5312 "Label index to associate with the prefix\n"
5313 "Label index value\n"
5314 "Specify a BGP backdoor route\n")
5316 char addr_prefix_str
[BUFSIZ
];
5321 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5324 vty_out(vty
, "%% Inconsistent address and mask\n");
5325 return CMD_WARNING_CONFIG_FAILED
;
5329 return bgp_static_set(
5330 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5331 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5332 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5335 DEFPY(ipv6_bgp_network
,
5336 ipv6_bgp_network_cmd
,
5337 "[no] network X:X::X:X/M$prefix \
5338 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5340 "Specify a network to announce via BGP\n"
5342 "Route-map to modify the attributes\n"
5343 "Name of the route map\n"
5344 "Label index to associate with the prefix\n"
5345 "Label index value\n")
5347 return bgp_static_set(
5348 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5349 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5352 /* Aggreagete address:
5354 advertise-map Set condition to advertise attribute
5355 as-set Generate AS set path information
5356 attribute-map Set attributes of aggregate
5357 route-map Set parameters of aggregate
5358 summary-only Filter more specific routes from updates
5359 suppress-map Conditionally filter more specific routes from updates
5362 struct bgp_aggregate
{
5363 /* Summary-only flag. */
5364 uint8_t summary_only
;
5366 /* AS set generation. */
5369 /* Route-map for aggregated route. */
5370 struct route_map
*map
;
5372 /* Suppress-count. */
5373 unsigned long count
;
5375 /* SAFI configuration. */
5379 static struct bgp_aggregate
*bgp_aggregate_new(void)
5381 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5384 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5386 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5389 /* Update an aggregate as routes are added/removed from the BGP table */
5390 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5391 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5392 struct bgp_info
*del
,
5393 struct bgp_aggregate
*aggregate
)
5395 struct bgp_table
*table
;
5396 struct bgp_node
*top
;
5397 struct bgp_node
*rn
;
5399 struct aspath
*aspath
= NULL
;
5400 struct aspath
*asmerge
= NULL
;
5401 struct community
*community
= NULL
;
5402 struct community
*commerge
= NULL
;
5403 #if defined(AGGREGATE_NEXTHOP_CHECK)
5404 struct in_addr nexthop
;
5407 struct bgp_info
*ri
;
5408 struct bgp_info
*new;
5410 unsigned long match
= 0;
5411 uint8_t atomic_aggregate
= 0;
5413 /* Record adding route's nexthop and med. */
5415 #if defined(AGGREGATE_NEXTHOP_CHECK)
5416 nexthop
= rinew
->attr
->nexthop
;
5417 med
= rinew
->attr
->med
;
5421 /* ORIGIN attribute: If at least one route among routes that are
5422 aggregated has ORIGIN with the value INCOMPLETE, then the
5423 aggregated route must have the ORIGIN attribute with the value
5424 INCOMPLETE. Otherwise, if at least one route among routes that
5425 are aggregated has ORIGIN with the value EGP, then the aggregated
5426 route must have the origin attribute with the value EGP. In all
5427 other case the value of the ORIGIN attribute of the aggregated
5428 route is INTERNAL. */
5429 origin
= BGP_ORIGIN_IGP
;
5431 table
= bgp
->rib
[afi
][safi
];
5433 top
= bgp_node_get(table
, p
);
5434 for (rn
= bgp_node_get(table
, p
); rn
;
5435 rn
= bgp_route_next_until(rn
, top
))
5436 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5439 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5440 if (BGP_INFO_HOLDDOWN(ri
))
5443 if (del
&& ri
== del
)
5446 if (!rinew
&& first
) {
5447 #if defined(AGGREGATE_NEXTHOP_CHECK)
5448 nexthop
= ri
->attr
->nexthop
;
5449 med
= ri
->attr
->med
;
5454 #ifdef AGGREGATE_NEXTHOP_CHECK
5455 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5457 || ri
->attr
->med
!= med
) {
5459 aspath_free(aspath
);
5461 community_free(community
);
5462 bgp_unlock_node(rn
);
5463 bgp_unlock_node(top
);
5466 #endif /* AGGREGATE_NEXTHOP_CHECK */
5469 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5470 atomic_aggregate
= 1;
5472 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5473 if (aggregate
->summary_only
) {
5474 (bgp_info_extra_get(ri
))
5478 BGP_INFO_ATTR_CHANGED
);
5484 if (origin
< ri
->attr
->origin
)
5485 origin
= ri
->attr
->origin
;
5487 if (aggregate
->as_set
) {
5489 asmerge
= aspath_aggregate(
5492 aspath_free(aspath
);
5495 aspath
= aspath_dup(
5498 if (ri
->attr
->community
) {
5500 commerge
= community_merge(
5502 ri
->attr
->community
);
5503 community
= community_uniq_sort(
5508 community
= community_dup(
5509 ri
->attr
->community
);
5515 bgp_process(bgp
, rn
, afi
, safi
);
5517 bgp_unlock_node(top
);
5522 if (aggregate
->summary_only
)
5523 (bgp_info_extra_get(rinew
))->suppress
++;
5525 if (origin
< rinew
->attr
->origin
)
5526 origin
= rinew
->attr
->origin
;
5528 if (aggregate
->as_set
) {
5530 asmerge
= aspath_aggregate(aspath
,
5531 rinew
->attr
->aspath
);
5532 aspath_free(aspath
);
5535 aspath
= aspath_dup(rinew
->attr
->aspath
);
5537 if (rinew
->attr
->community
) {
5539 commerge
= community_merge(
5541 rinew
->attr
->community
);
5543 community_uniq_sort(commerge
);
5544 community_free(commerge
);
5546 community
= community_dup(
5547 rinew
->attr
->community
);
5552 if (aggregate
->count
> 0) {
5553 rn
= bgp_node_get(table
, p
);
5555 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5556 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5557 community
, aggregate
->as_set
,
5560 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5562 bgp_info_add(rn
, new);
5563 bgp_unlock_node(rn
);
5564 bgp_process(bgp
, rn
, afi
, safi
);
5567 aspath_free(aspath
);
5569 community_free(community
);
5573 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5574 struct bgp_aggregate
*);
5576 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5577 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5579 struct bgp_node
*child
;
5580 struct bgp_node
*rn
;
5581 struct bgp_aggregate
*aggregate
;
5582 struct bgp_table
*table
;
5584 /* MPLS-VPN aggregation is not yet supported. */
5585 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5586 || (safi
== SAFI_EVPN
)
5587 || (safi
== SAFI_FLOWSPEC
))
5590 table
= bgp
->aggregate
[afi
][safi
];
5592 /* No aggregates configured. */
5593 if (bgp_table_top_nolock(table
) == NULL
)
5596 if (p
->prefixlen
== 0)
5599 if (BGP_INFO_HOLDDOWN(ri
))
5602 child
= bgp_node_get(table
, p
);
5604 /* Aggregate address configuration check. */
5605 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5606 if ((aggregate
= rn
->info
) != NULL
5607 && rn
->p
.prefixlen
< p
->prefixlen
) {
5608 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5609 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5612 bgp_unlock_node(child
);
5615 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5616 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5618 struct bgp_node
*child
;
5619 struct bgp_node
*rn
;
5620 struct bgp_aggregate
*aggregate
;
5621 struct bgp_table
*table
;
5623 /* MPLS-VPN aggregation is not yet supported. */
5624 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5625 || (safi
== SAFI_EVPN
)
5626 || (safi
== SAFI_FLOWSPEC
))
5629 table
= bgp
->aggregate
[afi
][safi
];
5631 /* No aggregates configured. */
5632 if (bgp_table_top_nolock(table
) == NULL
)
5635 if (p
->prefixlen
== 0)
5638 child
= bgp_node_get(table
, p
);
5640 /* Aggregate address configuration check. */
5641 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5642 if ((aggregate
= rn
->info
) != NULL
5643 && rn
->p
.prefixlen
< p
->prefixlen
) {
5644 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5645 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5648 bgp_unlock_node(child
);
5651 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5652 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5653 safi_t safi
, struct bgp_aggregate
*aggregate
)
5655 struct bgp_table
*table
;
5656 struct bgp_node
*top
;
5657 struct bgp_node
*rn
;
5658 struct bgp_info
*new;
5659 struct bgp_info
*ri
;
5660 unsigned long match
;
5661 uint8_t origin
= BGP_ORIGIN_IGP
;
5662 struct aspath
*aspath
= NULL
;
5663 struct aspath
*asmerge
= NULL
;
5664 struct community
*community
= NULL
;
5665 struct community
*commerge
= NULL
;
5666 uint8_t atomic_aggregate
= 0;
5668 table
= bgp
->rib
[afi
][safi
];
5671 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5673 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5676 /* If routes exists below this node, generate aggregate routes. */
5677 top
= bgp_node_get(table
, p
);
5678 for (rn
= bgp_node_get(table
, p
); rn
;
5679 rn
= bgp_route_next_until(rn
, top
)) {
5680 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5685 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5686 if (BGP_INFO_HOLDDOWN(ri
))
5690 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5691 atomic_aggregate
= 1;
5693 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5696 /* summary-only aggregate route suppress
5697 * aggregated route announcement. */
5698 if (aggregate
->summary_only
) {
5699 (bgp_info_extra_get(ri
))->suppress
++;
5700 bgp_info_set_flag(rn
, ri
,
5701 BGP_INFO_ATTR_CHANGED
);
5705 /* If at least one route among routes that are
5706 * aggregated has ORIGIN with the value INCOMPLETE,
5707 * then the aggregated route MUST have the ORIGIN
5708 * attribute with the value INCOMPLETE. Otherwise, if
5709 * at least one route among routes that are aggregated
5710 * has ORIGIN with the value EGP, then the aggregated
5711 * route MUST have the ORIGIN attribute with the value
5714 if (origin
< ri
->attr
->origin
)
5715 origin
= ri
->attr
->origin
;
5717 /* as-set aggregate route generate origin, as path,
5718 * community aggregation. */
5719 if (aggregate
->as_set
) {
5721 asmerge
= aspath_aggregate(
5722 aspath
, ri
->attr
->aspath
);
5723 aspath_free(aspath
);
5726 aspath
= aspath_dup(ri
->attr
->aspath
);
5728 if (ri
->attr
->community
) {
5730 commerge
= community_merge(
5732 ri
->attr
->community
);
5733 community
= community_uniq_sort(
5735 community_free(commerge
);
5737 community
= community_dup(
5738 ri
->attr
->community
);
5744 /* If this node is suppressed, process the change. */
5746 bgp_process(bgp
, rn
, afi
, safi
);
5748 bgp_unlock_node(top
);
5750 /* Add aggregate route to BGP table. */
5751 if (aggregate
->count
) {
5752 rn
= bgp_node_get(table
, p
);
5754 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5755 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5756 community
, aggregate
->as_set
,
5759 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5761 bgp_info_add(rn
, new);
5762 bgp_unlock_node(rn
);
5764 /* Process change. */
5765 bgp_process(bgp
, rn
, afi
, safi
);
5768 aspath_free(aspath
);
5770 community_free(community
);
5774 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5775 safi_t safi
, struct bgp_aggregate
*aggregate
)
5777 struct bgp_table
*table
;
5778 struct bgp_node
*top
;
5779 struct bgp_node
*rn
;
5780 struct bgp_info
*ri
;
5781 unsigned long match
;
5783 table
= bgp
->rib
[afi
][safi
];
5785 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5787 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5790 /* If routes exists below this node, generate aggregate routes. */
5791 top
= bgp_node_get(table
, p
);
5792 for (rn
= bgp_node_get(table
, p
); rn
;
5793 rn
= bgp_route_next_until(rn
, top
)) {
5794 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5798 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5799 if (BGP_INFO_HOLDDOWN(ri
))
5802 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5805 if (aggregate
->summary_only
&& ri
->extra
) {
5806 ri
->extra
->suppress
--;
5808 if (ri
->extra
->suppress
== 0) {
5810 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5817 /* If this node was suppressed, process the change. */
5819 bgp_process(bgp
, rn
, afi
, safi
);
5821 bgp_unlock_node(top
);
5823 /* Delete aggregate route from BGP table. */
5824 rn
= bgp_node_get(table
, p
);
5826 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5827 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5828 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5831 /* Withdraw static BGP route from routing table. */
5833 bgp_info_delete(rn
, ri
);
5834 bgp_process(bgp
, rn
, afi
, safi
);
5837 /* Unlock bgp_node_lookup. */
5838 bgp_unlock_node(rn
);
5841 /* Aggregate route attribute. */
5842 #define AGGREGATE_SUMMARY_ONLY 1
5843 #define AGGREGATE_AS_SET 1
5845 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5846 afi_t afi
, safi_t safi
)
5848 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5851 struct bgp_node
*rn
;
5852 struct bgp_aggregate
*aggregate
;
5854 if (safi
== SAFI_FLOWSPEC
)
5855 return CMD_WARNING_CONFIG_FAILED
;
5857 /* Convert string to prefix structure. */
5858 ret
= str2prefix(prefix_str
, &p
);
5860 vty_out(vty
, "Malformed prefix\n");
5861 return CMD_WARNING_CONFIG_FAILED
;
5865 /* Old configuration check. */
5866 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5869 "%% There is no aggregate-address configuration.\n");
5870 return CMD_WARNING_CONFIG_FAILED
;
5873 aggregate
= rn
->info
;
5874 if (aggregate
->safi
== SAFI_UNICAST
)
5875 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5876 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5877 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5879 if (aggregate
->safi
== SAFI_MULTICAST
)
5880 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5882 /* Unlock aggregate address configuration. */
5884 bgp_aggregate_free(aggregate
);
5885 bgp_unlock_node(rn
);
5886 bgp_unlock_node(rn
);
5891 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5892 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5894 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5897 struct bgp_node
*rn
;
5898 struct bgp_aggregate
*aggregate
;
5900 if (safi
== SAFI_FLOWSPEC
)
5901 return CMD_WARNING_CONFIG_FAILED
;
5903 /* Convert string to prefix structure. */
5904 ret
= str2prefix(prefix_str
, &p
);
5906 vty_out(vty
, "Malformed prefix\n");
5907 return CMD_WARNING_CONFIG_FAILED
;
5911 /* Old configuration check. */
5912 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5915 vty_out(vty
, "There is already same aggregate network.\n");
5916 /* try to remove the old entry */
5917 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5919 vty_out(vty
, "Error deleting aggregate.\n");
5920 bgp_unlock_node(rn
);
5921 return CMD_WARNING_CONFIG_FAILED
;
5925 /* Make aggregate address structure. */
5926 aggregate
= bgp_aggregate_new();
5927 aggregate
->summary_only
= summary_only
;
5928 aggregate
->as_set
= as_set
;
5929 aggregate
->safi
= safi
;
5930 rn
->info
= aggregate
;
5932 /* Aggregate address insert into BGP routing table. */
5933 if (safi
== SAFI_UNICAST
)
5934 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5935 if (safi
== SAFI_LABELED_UNICAST
)
5936 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5938 if (safi
== SAFI_MULTICAST
)
5939 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5944 DEFUN (aggregate_address
,
5945 aggregate_address_cmd
,
5946 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5947 "Configure BGP aggregate entries\n"
5948 "Aggregate prefix\n"
5949 "Generate AS set path information\n"
5950 "Filter more specific routes from updates\n"
5951 "Filter more specific routes from updates\n"
5952 "Generate AS set path information\n")
5955 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5956 char *prefix
= argv
[idx
]->arg
;
5958 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5960 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5961 ? AGGREGATE_SUMMARY_ONLY
5964 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5965 summary_only
, as_set
);
5968 DEFUN (aggregate_address_mask
,
5969 aggregate_address_mask_cmd
,
5970 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5971 "Configure BGP aggregate entries\n"
5972 "Aggregate address\n"
5974 "Generate AS set path information\n"
5975 "Filter more specific routes from updates\n"
5976 "Filter more specific routes from updates\n"
5977 "Generate AS set path information\n")
5980 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5981 char *prefix
= argv
[idx
]->arg
;
5982 char *mask
= argv
[idx
+ 1]->arg
;
5984 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5986 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5987 ? AGGREGATE_SUMMARY_ONLY
5990 char prefix_str
[BUFSIZ
];
5991 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5994 vty_out(vty
, "%% Inconsistent address and mask\n");
5995 return CMD_WARNING_CONFIG_FAILED
;
5998 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5999 summary_only
, as_set
);
6002 DEFUN (no_aggregate_address
,
6003 no_aggregate_address_cmd
,
6004 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6006 "Configure BGP aggregate entries\n"
6007 "Aggregate prefix\n"
6008 "Generate AS set path information\n"
6009 "Filter more specific routes from updates\n"
6010 "Filter more specific routes from updates\n"
6011 "Generate AS set path information\n")
6014 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6015 char *prefix
= argv
[idx
]->arg
;
6016 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6019 DEFUN (no_aggregate_address_mask
,
6020 no_aggregate_address_mask_cmd
,
6021 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6023 "Configure BGP aggregate entries\n"
6024 "Aggregate address\n"
6026 "Generate AS set path information\n"
6027 "Filter more specific routes from updates\n"
6028 "Filter more specific routes from updates\n"
6029 "Generate AS set path information\n")
6032 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6033 char *prefix
= argv
[idx
]->arg
;
6034 char *mask
= argv
[idx
+ 1]->arg
;
6036 char prefix_str
[BUFSIZ
];
6037 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6040 vty_out(vty
, "%% Inconsistent address and mask\n");
6041 return CMD_WARNING_CONFIG_FAILED
;
6044 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6047 DEFUN (ipv6_aggregate_address
,
6048 ipv6_aggregate_address_cmd
,
6049 "aggregate-address X:X::X:X/M [summary-only]",
6050 "Configure BGP aggregate entries\n"
6051 "Aggregate prefix\n"
6052 "Filter more specific routes from updates\n")
6055 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6056 char *prefix
= argv
[idx
]->arg
;
6057 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6058 ? AGGREGATE_SUMMARY_ONLY
6060 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6064 DEFUN (no_ipv6_aggregate_address
,
6065 no_ipv6_aggregate_address_cmd
,
6066 "no aggregate-address X:X::X:X/M [summary-only]",
6068 "Configure BGP aggregate entries\n"
6069 "Aggregate prefix\n"
6070 "Filter more specific routes from updates\n")
6073 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6074 char *prefix
= argv
[idx
]->arg
;
6075 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6078 /* Redistribute route treatment. */
6079 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6080 const union g_addr
*nexthop
, ifindex_t ifindex
,
6081 enum nexthop_types_t nhtype
, uint32_t metric
,
6082 uint8_t type
, unsigned short instance
,
6085 struct bgp_info
*new;
6086 struct bgp_info
*bi
;
6087 struct bgp_info info
;
6088 struct bgp_node
*bn
;
6090 struct attr
*new_attr
;
6093 struct bgp_redist
*red
;
6095 /* Make default attribute. */
6096 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6099 case NEXTHOP_TYPE_IFINDEX
:
6101 case NEXTHOP_TYPE_IPV4
:
6102 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6103 attr
.nexthop
= nexthop
->ipv4
;
6105 case NEXTHOP_TYPE_IPV6
:
6106 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6107 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6108 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6110 case NEXTHOP_TYPE_BLACKHOLE
:
6111 switch (p
->family
) {
6113 attr
.nexthop
.s_addr
= INADDR_ANY
;
6116 memset(&attr
.mp_nexthop_global
, 0,
6117 sizeof(attr
.mp_nexthop_global
));
6118 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6123 attr
.nh_ifindex
= ifindex
;
6126 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6129 afi
= family2afi(p
->family
);
6131 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6133 struct attr attr_new
;
6135 /* Copy attribute for modification. */
6136 bgp_attr_dup(&attr_new
, &attr
);
6138 if (red
->redist_metric_flag
)
6139 attr_new
.med
= red
->redist_metric
;
6141 /* Apply route-map. */
6142 if (red
->rmap
.name
) {
6143 info
.peer
= bgp
->peer_self
;
6144 info
.attr
= &attr_new
;
6146 SET_FLAG(bgp
->peer_self
->rmap_type
,
6147 PEER_RMAP_TYPE_REDISTRIBUTE
);
6149 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6152 bgp
->peer_self
->rmap_type
= 0;
6154 if (ret
== RMAP_DENYMATCH
) {
6155 /* Free uninterned attribute. */
6156 bgp_attr_flush(&attr_new
);
6158 /* Unintern original. */
6159 aspath_unintern(&attr
.aspath
);
6160 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6165 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6166 bgp_attr_add_gshut_community(&attr_new
);
6168 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6169 SAFI_UNICAST
, p
, NULL
);
6171 new_attr
= bgp_attr_intern(&attr_new
);
6173 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6174 if (bi
->peer
== bgp
->peer_self
6175 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6179 /* Ensure the (source route) type is updated. */
6181 if (attrhash_cmp(bi
->attr
, new_attr
)
6182 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6183 bgp_attr_unintern(&new_attr
);
6184 aspath_unintern(&attr
.aspath
);
6185 bgp_unlock_node(bn
);
6188 /* The attribute is changed. */
6189 bgp_info_set_flag(bn
, bi
,
6190 BGP_INFO_ATTR_CHANGED
);
6192 /* Rewrite BGP route information. */
6193 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6194 bgp_info_restore(bn
, bi
);
6196 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6198 bgp_attr_unintern(&bi
->attr
);
6199 bi
->attr
= new_attr
;
6200 bi
->uptime
= bgp_clock();
6202 /* Process change. */
6203 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6205 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6206 bgp_unlock_node(bn
);
6207 aspath_unintern(&attr
.aspath
);
6209 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6211 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6213 vpn_leak_from_vrf_update(
6214 bgp_get_default(), bgp
, bi
);
6220 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6221 bgp
->peer_self
, new_attr
, bn
);
6222 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6224 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6225 bgp_info_add(bn
, new);
6226 bgp_unlock_node(bn
);
6227 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6229 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6230 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6232 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6236 /* Unintern original. */
6237 aspath_unintern(&attr
.aspath
);
6240 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6241 unsigned short instance
)
6244 struct bgp_node
*rn
;
6245 struct bgp_info
*ri
;
6246 struct bgp_redist
*red
;
6248 afi
= family2afi(p
->family
);
6250 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6252 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6253 SAFI_UNICAST
, p
, NULL
);
6255 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6256 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6260 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6261 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6263 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6266 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6267 bgp_info_delete(rn
, ri
);
6268 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6270 bgp_unlock_node(rn
);
6274 /* Withdraw specified route type's route. */
6275 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6276 unsigned short instance
)
6278 struct bgp_node
*rn
;
6279 struct bgp_info
*ri
;
6280 struct bgp_table
*table
;
6282 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6284 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6285 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6286 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6287 && ri
->instance
== instance
)
6291 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6292 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6294 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6297 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6299 bgp_info_delete(rn
, ri
);
6300 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6305 /* Static function to display route. */
6306 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6310 uint32_t destination
;
6313 if (p
->family
== AF_INET
) {
6315 len
= vty_out(vty
, "%s",
6316 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6318 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6320 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6321 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6322 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6323 || p
->u
.prefix4
.s_addr
== 0) {
6324 /* When mask is natural,
6325 mask is not displayed. */
6327 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6329 json_object_string_add(json
, "prefix",
6330 inet_ntop(p
->family
,
6333 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6335 } else if (p
->family
== AF_ETHERNET
) {
6336 prefix2str(p
, buf
, PREFIX_STRLEN
);
6337 len
= vty_out(vty
, "%s", buf
);
6338 } else if (p
->family
== AF_EVPN
) {
6339 #if defined(HAVE_CUMULUS)
6343 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6346 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6348 prefix2str(p
, buf
, PREFIX_STRLEN
);
6349 len
= vty_out(vty
, "%s", buf
);
6351 } else if (p
->family
== AF_FLOWSPEC
) {
6352 route_vty_out_flowspec(vty
, p
, NULL
,
6354 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6355 NLRI_STRING_FORMAT_MIN
, json
);
6360 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6367 vty_out(vty
, "\n%*s", 20, " ");
6369 vty_out(vty
, "%*s", len
, " ");
6373 enum bgp_display_type
{
6377 /* Print the short form route status for a bgp_info */
6378 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6379 json_object
*json_path
)
6383 /* Route status display. */
6384 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6385 json_object_boolean_true_add(json_path
, "removed");
6387 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6388 json_object_boolean_true_add(json_path
, "stale");
6390 if (binfo
->extra
&& binfo
->extra
->suppress
)
6391 json_object_boolean_true_add(json_path
, "suppressed");
6393 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6394 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6395 json_object_boolean_true_add(json_path
, "valid");
6398 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6399 json_object_boolean_true_add(json_path
, "history");
6401 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6402 json_object_boolean_true_add(json_path
, "damped");
6404 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6405 json_object_boolean_true_add(json_path
, "bestpath");
6407 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6408 json_object_boolean_true_add(json_path
, "multipath");
6410 /* Internal route. */
6411 if ((binfo
->peer
->as
)
6412 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6413 json_object_string_add(json_path
, "pathFrom",
6416 json_object_string_add(json_path
, "pathFrom",
6422 /* Route status display. */
6423 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6425 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6427 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6429 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6430 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6436 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6438 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6440 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6442 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6447 /* Internal route. */
6448 if (binfo
->peer
&& (binfo
->peer
->as
)
6449 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6455 /* called from terminal list command */
6456 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6457 int display
, safi_t safi
, json_object
*json_paths
)
6460 json_object
*json_path
= NULL
;
6461 json_object
*json_nexthops
= NULL
;
6462 json_object
*json_nexthop_global
= NULL
;
6463 json_object
*json_nexthop_ll
= NULL
;
6466 json_path
= json_object_new_object();
6468 /* short status lead text */
6469 route_vty_short_status_out(vty
, binfo
, json_path
);
6472 /* print prefix and mask */
6474 route_vty_out_route(p
, vty
, json_path
);
6476 vty_out(vty
, "%*s", 17, " ");
6478 route_vty_out_route(p
, vty
, json_path
);
6481 /* Print attribute */
6485 json_object_array_add(json_paths
, json_path
);
6493 * For ENCAP and EVPN routes, nexthop address family is not
6494 * neccessarily the same as the prefix address family.
6495 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6496 * EVPN routes are also exchanged with a MP nexthop. Currently,
6498 * is only IPv4, the value will be present in either
6500 * attr->mp_nexthop_global_in
6502 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6505 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6509 sprintf(nexthop
, "%s",
6510 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6514 sprintf(nexthop
, "%s",
6515 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6519 sprintf(nexthop
, "?");
6524 json_nexthop_global
= json_object_new_object();
6526 json_object_string_add(json_nexthop_global
, "afi",
6527 (af
== AF_INET
) ? "ip" : "ipv6");
6528 json_object_string_add(json_nexthop_global
,
6529 (af
== AF_INET
) ? "ip" : "ipv6",
6531 json_object_boolean_true_add(json_nexthop_global
,
6534 vty_out(vty
, "%s", nexthop
);
6535 } else if (safi
== SAFI_EVPN
) {
6537 json_nexthop_global
= json_object_new_object();
6539 json_object_string_add(json_nexthop_global
, "ip",
6540 inet_ntoa(attr
->nexthop
));
6541 json_object_string_add(json_nexthop_global
, "afi",
6543 json_object_boolean_true_add(json_nexthop_global
,
6546 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6547 } else if (safi
== SAFI_FLOWSPEC
) {
6550 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6552 json_nexthop_global
= json_object_new_object();
6554 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6555 json_object_string_add(
6556 json_nexthop_global
, "ip",
6557 inet_ntoa(attr
->mp_nexthop_global_in
));
6559 json_object_string_add(
6560 json_nexthop_global
, "ip",
6561 inet_ntoa(attr
->nexthop
));
6563 json_object_string_add(json_nexthop_global
, "afi",
6565 json_object_boolean_true_add(json_nexthop_global
,
6568 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6569 vty_out(vty
, "%-16s",
6570 inet_ntoa(attr
->mp_nexthop_global_in
));
6572 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6577 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6582 json_nexthop_global
= json_object_new_object();
6583 json_object_string_add(
6584 json_nexthop_global
, "ip",
6585 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6587 json_object_string_add(json_nexthop_global
, "afi",
6589 json_object_string_add(json_nexthop_global
, "scope",
6592 /* We display both LL & GL if both have been
6594 if ((attr
->mp_nexthop_len
== 32)
6595 || (binfo
->peer
->conf_if
)) {
6596 json_nexthop_ll
= json_object_new_object();
6597 json_object_string_add(
6598 json_nexthop_ll
, "ip",
6600 &attr
->mp_nexthop_local
, buf
,
6602 json_object_string_add(json_nexthop_ll
, "afi",
6604 json_object_string_add(json_nexthop_ll
, "scope",
6607 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6608 &attr
->mp_nexthop_local
)
6610 && !attr
->mp_nexthop_prefer_global
)
6611 json_object_boolean_true_add(
6612 json_nexthop_ll
, "used");
6614 json_object_boolean_true_add(
6615 json_nexthop_global
, "used");
6617 json_object_boolean_true_add(
6618 json_nexthop_global
, "used");
6620 /* Display LL if LL/Global both in table unless
6621 * prefer-global is set */
6622 if (((attr
->mp_nexthop_len
== 32)
6623 && !attr
->mp_nexthop_prefer_global
)
6624 || (binfo
->peer
->conf_if
)) {
6625 if (binfo
->peer
->conf_if
) {
6626 len
= vty_out(vty
, "%s",
6627 binfo
->peer
->conf_if
);
6628 len
= 16 - len
; /* len of IPv6
6634 vty_out(vty
, "\n%*s", 36, " ");
6636 vty_out(vty
, "%*s", len
, " ");
6642 &attr
->mp_nexthop_local
,
6647 vty_out(vty
, "\n%*s", 36, " ");
6649 vty_out(vty
, "%*s", len
, " ");
6655 &attr
->mp_nexthop_global
, buf
,
6660 vty_out(vty
, "\n%*s", 36, " ");
6662 vty_out(vty
, "%*s", len
, " ");
6668 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6670 json_object_int_add(json_path
, "med", attr
->med
);
6672 vty_out(vty
, "%10u", attr
->med
);
6673 else if (!json_paths
)
6677 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6679 json_object_int_add(json_path
, "localpref",
6682 vty_out(vty
, "%7u", attr
->local_pref
);
6683 else if (!json_paths
)
6687 json_object_int_add(json_path
, "weight", attr
->weight
);
6689 vty_out(vty
, "%7u ", attr
->weight
);
6693 json_object_string_add(
6694 json_path
, "peerId",
6695 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6701 json_object_string_add(json_path
, "aspath",
6704 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6709 json_object_string_add(json_path
, "origin",
6710 bgp_origin_long_str
[attr
->origin
]);
6712 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6715 if (json_nexthop_global
|| json_nexthop_ll
) {
6716 json_nexthops
= json_object_new_array();
6718 if (json_nexthop_global
)
6719 json_object_array_add(json_nexthops
,
6720 json_nexthop_global
);
6722 if (json_nexthop_ll
)
6723 json_object_array_add(json_nexthops
,
6726 json_object_object_add(json_path
, "nexthops",
6730 json_object_array_add(json_paths
, json_path
);
6734 /* prints an additional line, indented, with VNC info, if
6736 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6737 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6742 /* called from terminal list command */
6743 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6744 safi_t safi
, uint8_t use_json
, json_object
*json_ar
)
6746 json_object
*json_status
= NULL
;
6747 json_object
*json_net
= NULL
;
6749 /* Route status display. */
6751 json_status
= json_object_new_object();
6752 json_net
= json_object_new_object();
6759 /* print prefix and mask */
6761 json_object_string_add(
6762 json_net
, "addrPrefix",
6763 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6765 route_vty_out_route(p
, vty
, NULL
);
6767 /* Print attribute */
6770 if (p
->family
== AF_INET
6771 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6772 || safi
== SAFI_EVPN
6773 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6774 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6775 || safi
== SAFI_EVPN
)
6776 json_object_string_add(
6777 json_net
, "nextHop",
6779 attr
->mp_nexthop_global_in
));
6781 json_object_string_add(
6782 json_net
, "nextHop",
6783 inet_ntoa(attr
->nexthop
));
6784 } else if (p
->family
== AF_INET6
6785 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6788 json_object_string_add(
6789 json_net
, "netHopGloabal",
6791 &attr
->mp_nexthop_global
, buf
,
6796 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6797 json_object_int_add(json_net
, "metric",
6800 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6801 json_object_int_add(json_net
, "localPref",
6804 json_object_int_add(json_net
, "weight", attr
->weight
);
6808 json_object_string_add(json_net
, "asPath",
6812 json_object_string_add(json_net
, "bgpOriginCode",
6813 bgp_origin_str
[attr
->origin
]);
6815 if (p
->family
== AF_INET
6816 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6817 || safi
== SAFI_EVPN
6818 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6819 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6820 || safi
== SAFI_EVPN
)
6821 vty_out(vty
, "%-16s",
6823 attr
->mp_nexthop_global_in
));
6825 vty_out(vty
, "%-16s",
6826 inet_ntoa(attr
->nexthop
));
6827 } else if (p
->family
== AF_INET6
6828 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6835 &attr
->mp_nexthop_global
, buf
,
6839 vty_out(vty
, "\n%*s", 36, " ");
6841 vty_out(vty
, "%*s", len
, " ");
6844 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6845 vty_out(vty
, "%10u", attr
->med
);
6849 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6850 vty_out(vty
, "%7u", attr
->local_pref
);
6854 vty_out(vty
, "%7u ", attr
->weight
);
6858 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6861 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6865 json_object_boolean_true_add(json_status
, "*");
6866 json_object_boolean_true_add(json_status
, ">");
6867 json_object_object_add(json_net
, "appliedStatusSymbols",
6869 char buf_cut
[BUFSIZ
];
6870 json_object_object_add(
6872 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6878 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6879 struct bgp_info
*binfo
, int display
, safi_t safi
,
6882 json_object
*json_out
= NULL
;
6884 mpls_label_t label
= MPLS_INVALID_LABEL
;
6890 json_out
= json_object_new_object();
6892 /* short status lead text */
6893 route_vty_short_status_out(vty
, binfo
, json_out
);
6895 /* print prefix and mask */
6898 route_vty_out_route(p
, vty
, NULL
);
6900 vty_out(vty
, "%*s", 17, " ");
6903 /* Print attribute */
6906 if (((p
->family
== AF_INET
)
6907 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6908 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6909 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6910 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6911 || safi
== SAFI_EVPN
) {
6913 json_object_string_add(
6914 json_out
, "mpNexthopGlobalIn",
6916 attr
->mp_nexthop_global_in
));
6918 vty_out(vty
, "%-16s",
6920 attr
->mp_nexthop_global_in
));
6923 json_object_string_add(
6924 json_out
, "nexthop",
6925 inet_ntoa(attr
->nexthop
));
6927 vty_out(vty
, "%-16s",
6928 inet_ntoa(attr
->nexthop
));
6930 } else if (((p
->family
== AF_INET6
)
6931 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6932 || (safi
== SAFI_EVPN
6933 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6934 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6938 if (attr
->mp_nexthop_len
6939 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6941 json_object_string_add(
6942 json_out
, "mpNexthopGlobalIn",
6945 &attr
->mp_nexthop_global
,
6951 &attr
->mp_nexthop_global
,
6953 } else if (attr
->mp_nexthop_len
6954 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6957 &attr
->mp_nexthop_global
,
6960 &attr
->mp_nexthop_local
,
6962 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6963 json_object_string_add(
6965 "mpNexthopGlobalLocal", buf_c
);
6967 vty_out(vty
, "%s(%s)",
6970 &attr
->mp_nexthop_global
,
6974 &attr
->mp_nexthop_local
,
6980 label
= decode_label(&binfo
->extra
->label
[0]);
6982 if (bgp_is_valid_label(&label
)) {
6984 json_object_int_add(json_out
, "notag", label
);
6985 json_object_array_add(json
, json_out
);
6987 vty_out(vty
, "notag/%d", label
);
6993 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6994 struct bgp_info
*binfo
, int display
,
6995 json_object
*json_paths
)
6999 json_object
*json_path
= NULL
;
7002 json_path
= json_object_new_object();
7007 /* short status lead text */
7008 route_vty_short_status_out(vty
, binfo
, json_path
);
7010 /* print prefix and mask */
7012 route_vty_out_route(p
, vty
, NULL
);
7014 vty_out(vty
, "%*s", 17, " ");
7016 /* Print attribute */
7020 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7024 vty_out(vty
, "%-16s",
7025 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7029 vty_out(vty
, "%s(%s)",
7030 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7032 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7040 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
7041 char *str
= esi2str(id
);
7042 vty_out(vty
, "%s", str
);
7043 XFREE(MTYPE_TMP
, str
);
7044 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7045 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7046 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7048 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7051 if (attr
->ecommunity
) {
7053 struct ecommunity_val
*routermac
= ecommunity_lookup(
7054 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7055 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7057 mac
= ecom_mac2str((char *)routermac
->val
);
7059 vty_out(vty
, "/%s", (char *)mac
);
7060 XFREE(MTYPE_TMP
, mac
);
7066 /* dampening route */
7067 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7068 struct bgp_info
*binfo
, int display
, safi_t safi
,
7069 uint8_t use_json
, json_object
*json
)
7073 char timebuf
[BGP_UPTIME_LEN
];
7075 /* short status lead text */
7076 route_vty_short_status_out(vty
, binfo
, json
);
7078 /* print prefix and mask */
7081 route_vty_out_route(p
, vty
, NULL
);
7083 vty_out(vty
, "%*s", 17, " ");
7086 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7090 vty_out(vty
, "\n%*s", 34, " ");
7093 json_object_int_add(json
, "peerHost", len
);
7095 vty_out(vty
, "%*s", len
, " ");
7099 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7102 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7106 /* Print attribute */
7112 json_object_string_add(json
, "asPath",
7115 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7120 json_object_string_add(json
, "origin",
7121 bgp_origin_str
[attr
->origin
]);
7123 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7130 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7131 struct bgp_info
*binfo
, int display
, safi_t safi
,
7132 uint8_t use_json
, json_object
*json
)
7135 struct bgp_damp_info
*bdi
;
7136 char timebuf
[BGP_UPTIME_LEN
];
7142 bdi
= binfo
->extra
->damp_info
;
7144 /* short status lead text */
7145 route_vty_short_status_out(vty
, binfo
, json
);
7147 /* print prefix and mask */
7150 route_vty_out_route(p
, vty
, NULL
);
7152 vty_out(vty
, "%*s", 17, " ");
7155 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7159 vty_out(vty
, "\n%*s", 33, " ");
7162 json_object_int_add(json
, "peerHost", len
);
7164 vty_out(vty
, "%*s", len
, " ");
7167 len
= vty_out(vty
, "%d", bdi
->flap
);
7174 json_object_int_add(json
, "bdiFlap", len
);
7176 vty_out(vty
, "%*s", len
, " ");
7180 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7183 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7184 BGP_UPTIME_LEN
, 0, NULL
));
7186 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7187 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7189 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7190 BGP_UPTIME_LEN
, use_json
, json
);
7193 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7198 vty_out(vty
, "%*s ", 8, " ");
7201 /* Print attribute */
7207 json_object_string_add(json
, "asPath",
7210 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7215 json_object_string_add(json
, "origin",
7216 bgp_origin_str
[attr
->origin
]);
7218 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7224 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7225 int *first
, const char *header
,
7226 json_object
*json_adv_to
)
7228 char buf1
[INET6_ADDRSTRLEN
];
7229 json_object
*json_peer
= NULL
;
7232 /* 'advertised-to' is a dictionary of peers we have advertised
7234 * prefix too. The key is the peer's IP or swpX, the value is
7236 * hostname if we know it and "" if not.
7238 json_peer
= json_object_new_object();
7241 json_object_string_add(json_peer
, "hostname",
7245 json_object_object_add(json_adv_to
, peer
->conf_if
,
7248 json_object_object_add(
7250 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7254 vty_out(vty
, "%s", header
);
7259 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7261 vty_out(vty
, " %s(%s)", peer
->hostname
,
7264 vty_out(vty
, " %s(%s)", peer
->hostname
,
7265 sockunion2str(&peer
->su
, buf1
,
7269 vty_out(vty
, " %s", peer
->conf_if
);
7272 sockunion2str(&peer
->su
, buf1
,
7278 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7279 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7280 json_object
*json_paths
)
7282 char buf
[INET6_ADDRSTRLEN
];
7284 #if defined(HAVE_CUMULUS)
7285 char buf2
[EVPN_ROUTE_STRLEN
];
7288 int sockunion_vty_out(struct vty
*, union sockunion
*);
7290 json_object
*json_bestpath
= NULL
;
7291 json_object
*json_cluster_list
= NULL
;
7292 json_object
*json_cluster_list_list
= NULL
;
7293 json_object
*json_ext_community
= NULL
;
7294 json_object
*json_lcommunity
= NULL
;
7295 json_object
*json_last_update
= NULL
;
7296 json_object
*json_pmsi
= NULL
;
7297 json_object
*json_nexthop_global
= NULL
;
7298 json_object
*json_nexthop_ll
= NULL
;
7299 json_object
*json_nexthops
= NULL
;
7300 json_object
*json_path
= NULL
;
7301 json_object
*json_peer
= NULL
;
7302 json_object
*json_string
= NULL
;
7303 json_object
*json_adv_to
= NULL
;
7305 struct listnode
*node
, *nnode
;
7307 int addpath_capable
;
7309 unsigned int first_as
;
7312 json_path
= json_object_new_object();
7313 json_peer
= json_object_new_object();
7314 json_nexthop_global
= json_object_new_object();
7317 #if defined(HAVE_CUMULUS)
7318 if (!json_paths
&& safi
== SAFI_EVPN
) {
7321 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7322 vty_out(vty
, " Route %s", buf2
);
7324 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7325 bgp_evpn_label2str(binfo
->extra
->label
,
7326 binfo
->extra
->num_labels
, tag_buf
,
7328 vty_out(vty
, " VNI %s", tag_buf
);
7331 if (binfo
->extra
&& binfo
->extra
->parent
) {
7332 struct bgp_info
*parent_ri
;
7333 struct bgp_node
*rn
, *prn
;
7335 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7336 rn
= parent_ri
->net
;
7337 if (rn
&& rn
->prn
) {
7339 vty_out(vty
, " Imported from %s:%s\n",
7341 (struct prefix_rd
*)&prn
->p
,
7342 buf1
, sizeof(buf1
)),
7352 /* Line1 display AS-path, Aggregator */
7355 if (!attr
->aspath
->json
)
7356 aspath_str_update(attr
->aspath
, true);
7357 json_object_lock(attr
->aspath
->json
);
7358 json_object_object_add(json_path
, "aspath",
7359 attr
->aspath
->json
);
7361 if (attr
->aspath
->segments
)
7362 aspath_print_vty(vty
, " %s",
7365 vty_out(vty
, " Local");
7369 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7371 json_object_boolean_true_add(json_path
,
7374 vty_out(vty
, ", (removed)");
7377 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7379 json_object_boolean_true_add(json_path
,
7382 vty_out(vty
, ", (stale)");
7385 if (CHECK_FLAG(attr
->flag
,
7386 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7388 json_object_int_add(json_path
, "aggregatorAs",
7389 attr
->aggregator_as
);
7390 json_object_string_add(
7391 json_path
, "aggregatorId",
7392 inet_ntoa(attr
->aggregator_addr
));
7394 vty_out(vty
, ", (aggregated by %u %s)",
7395 attr
->aggregator_as
,
7396 inet_ntoa(attr
->aggregator_addr
));
7400 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7401 PEER_FLAG_REFLECTOR_CLIENT
)) {
7403 json_object_boolean_true_add(
7404 json_path
, "rxedFromRrClient");
7406 vty_out(vty
, ", (Received from a RR-client)");
7409 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7410 PEER_FLAG_RSERVER_CLIENT
)) {
7412 json_object_boolean_true_add(
7413 json_path
, "rxedFromRsClient");
7415 vty_out(vty
, ", (Received from a RS-client)");
7418 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7420 json_object_boolean_true_add(
7421 json_path
, "dampeningHistoryEntry");
7423 vty_out(vty
, ", (history entry)");
7424 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7426 json_object_boolean_true_add(
7427 json_path
, "dampeningSuppressed");
7429 vty_out(vty
, ", (suppressed due to dampening)");
7435 /* Line2 display Next-hop, Neighbor, Router-id */
7436 /* Display the nexthop */
7437 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7438 || p
->family
== AF_EVPN
)
7439 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7440 || safi
== SAFI_EVPN
7441 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7442 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7443 || safi
== SAFI_EVPN
) {
7445 json_object_string_add(
7446 json_nexthop_global
, "ip",
7448 attr
->mp_nexthop_global_in
));
7452 attr
->mp_nexthop_global_in
));
7455 json_object_string_add(
7456 json_nexthop_global
, "ip",
7457 inet_ntoa(attr
->nexthop
));
7460 inet_ntoa(attr
->nexthop
));
7464 json_object_string_add(json_nexthop_global
,
7468 json_object_string_add(
7469 json_nexthop_global
, "ip",
7471 &attr
->mp_nexthop_global
, buf
,
7473 json_object_string_add(json_nexthop_global
,
7475 json_object_string_add(json_nexthop_global
,
7480 &attr
->mp_nexthop_global
, buf
,
7485 /* Display the IGP cost or 'inaccessible' */
7486 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7488 json_object_boolean_false_add(
7489 json_nexthop_global
, "accessible");
7491 vty_out(vty
, " (inaccessible)");
7493 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7495 json_object_int_add(
7496 json_nexthop_global
, "metric",
7497 binfo
->extra
->igpmetric
);
7499 vty_out(vty
, " (metric %u)",
7500 binfo
->extra
->igpmetric
);
7503 /* IGP cost is 0, display this only for json */
7506 json_object_int_add(json_nexthop_global
,
7511 json_object_boolean_true_add(
7512 json_nexthop_global
, "accessible");
7515 /* Display peer "from" output */
7516 /* This path was originated locally */
7517 if (binfo
->peer
== bgp
->peer_self
) {
7519 if (safi
== SAFI_EVPN
7520 || (p
->family
== AF_INET
7521 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7523 json_object_string_add(
7524 json_peer
, "peerId", "0.0.0.0");
7526 vty_out(vty
, " from 0.0.0.0 ");
7529 json_object_string_add(json_peer
,
7532 vty_out(vty
, " from :: ");
7536 json_object_string_add(
7537 json_peer
, "routerId",
7538 inet_ntoa(bgp
->router_id
));
7540 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7543 /* We RXed this path from one of our peers */
7547 json_object_string_add(
7548 json_peer
, "peerId",
7549 sockunion2str(&binfo
->peer
->su
, buf
,
7551 json_object_string_add(
7552 json_peer
, "routerId",
7554 &binfo
->peer
->remote_id
, buf1
,
7557 if (binfo
->peer
->hostname
)
7558 json_object_string_add(
7559 json_peer
, "hostname",
7560 binfo
->peer
->hostname
);
7562 if (binfo
->peer
->domainname
)
7563 json_object_string_add(
7564 json_peer
, "domainname",
7565 binfo
->peer
->domainname
);
7567 if (binfo
->peer
->conf_if
)
7568 json_object_string_add(
7569 json_peer
, "interface",
7570 binfo
->peer
->conf_if
);
7572 if (binfo
->peer
->conf_if
) {
7573 if (binfo
->peer
->hostname
7576 BGP_FLAG_SHOW_HOSTNAME
))
7577 vty_out(vty
, " from %s(%s)",
7578 binfo
->peer
->hostname
,
7579 binfo
->peer
->conf_if
);
7581 vty_out(vty
, " from %s",
7582 binfo
->peer
->conf_if
);
7584 if (binfo
->peer
->hostname
7587 BGP_FLAG_SHOW_HOSTNAME
))
7588 vty_out(vty
, " from %s(%s)",
7589 binfo
->peer
->hostname
,
7592 vty_out(vty
, " from %s",
7601 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7602 vty_out(vty
, " (%s)",
7603 inet_ntoa(attr
->originator_id
));
7605 vty_out(vty
, " (%s)",
7608 &binfo
->peer
->remote_id
,
7609 buf1
, sizeof(buf1
)));
7616 /* display the link-local nexthop */
7617 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7619 json_nexthop_ll
= json_object_new_object();
7620 json_object_string_add(
7621 json_nexthop_ll
, "ip",
7623 &attr
->mp_nexthop_local
, buf
,
7625 json_object_string_add(json_nexthop_ll
, "afi",
7627 json_object_string_add(json_nexthop_ll
, "scope",
7630 json_object_boolean_true_add(json_nexthop_ll
,
7633 if (!attr
->mp_nexthop_prefer_global
)
7634 json_object_boolean_true_add(
7635 json_nexthop_ll
, "used");
7637 json_object_boolean_true_add(
7638 json_nexthop_global
, "used");
7640 vty_out(vty
, " (%s) %s\n",
7642 &attr
->mp_nexthop_local
, buf
,
7644 attr
->mp_nexthop_prefer_global
7649 /* If we do not have a link-local nexthop then we must flag the
7653 json_object_boolean_true_add(
7654 json_nexthop_global
, "used");
7657 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7658 * Int/Ext/Local, Atomic, best */
7660 json_object_string_add(
7661 json_path
, "origin",
7662 bgp_origin_long_str
[attr
->origin
]);
7664 vty_out(vty
, " Origin %s",
7665 bgp_origin_long_str
[attr
->origin
]);
7667 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7669 json_object_int_add(json_path
, "med",
7672 vty_out(vty
, ", metric %u", attr
->med
);
7675 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7677 json_object_int_add(json_path
, "localpref",
7680 vty_out(vty
, ", localpref %u",
7684 json_object_int_add(json_path
, "localpref",
7685 bgp
->default_local_pref
);
7687 vty_out(vty
, ", localpref %u",
7688 bgp
->default_local_pref
);
7691 if (attr
->weight
!= 0) {
7693 json_object_int_add(json_path
, "weight",
7696 vty_out(vty
, ", weight %u", attr
->weight
);
7699 if (attr
->tag
!= 0) {
7701 json_object_int_add(json_path
, "tag",
7704 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7708 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7710 json_object_boolean_false_add(json_path
,
7713 vty_out(vty
, ", invalid");
7714 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7716 json_object_boolean_true_add(json_path
,
7719 vty_out(vty
, ", valid");
7722 if (binfo
->peer
!= bgp
->peer_self
) {
7723 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7724 if (CHECK_FLAG(bgp
->config
,
7725 BGP_CONFIG_CONFEDERATION
)) {
7727 json_object_string_add(
7732 ", confed-internal");
7735 json_object_string_add(
7739 vty_out(vty
, ", internal");
7742 if (bgp_confederation_peers_check(
7743 bgp
, binfo
->peer
->as
)) {
7745 json_object_string_add(
7750 ", confed-external");
7753 json_object_string_add(
7757 vty_out(vty
, ", external");
7760 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7762 json_object_boolean_true_add(json_path
,
7764 json_object_boolean_true_add(json_path
,
7767 vty_out(vty
, ", aggregated, local");
7769 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7771 json_object_boolean_true_add(json_path
,
7774 vty_out(vty
, ", sourced");
7777 json_object_boolean_true_add(json_path
,
7779 json_object_boolean_true_add(json_path
,
7782 vty_out(vty
, ", sourced, local");
7786 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7788 json_object_boolean_true_add(json_path
,
7791 vty_out(vty
, ", atomic-aggregate");
7794 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7795 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7796 && bgp_info_mpath_count(binfo
))) {
7798 json_object_boolean_true_add(json_path
,
7801 vty_out(vty
, ", multipath");
7804 // Mark the bestpath(s)
7805 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7806 first_as
= aspath_get_first_as(attr
->aspath
);
7811 json_object_new_object();
7812 json_object_int_add(json_bestpath
,
7813 "bestpathFromAs", first_as
);
7816 vty_out(vty
, ", bestpath-from-AS %u",
7820 ", bestpath-from-AS Local");
7824 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7828 json_object_new_object();
7829 json_object_boolean_true_add(json_bestpath
,
7832 vty_out(vty
, ", best");
7836 json_object_object_add(json_path
, "bestpath",
7842 /* Line 4 display Community */
7843 if (attr
->community
) {
7845 if (!attr
->community
->json
)
7846 community_str(attr
->community
, true);
7847 json_object_lock(attr
->community
->json
);
7848 json_object_object_add(json_path
, "community",
7849 attr
->community
->json
);
7851 vty_out(vty
, " Community: %s\n",
7852 attr
->community
->str
);
7856 /* Line 5 display Extended-community */
7857 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7859 json_ext_community
= json_object_new_object();
7860 json_object_string_add(json_ext_community
,
7862 attr
->ecommunity
->str
);
7863 json_object_object_add(json_path
,
7864 "extendedCommunity",
7865 json_ext_community
);
7867 vty_out(vty
, " Extended Community: %s\n",
7868 attr
->ecommunity
->str
);
7872 /* Line 6 display Large community */
7873 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7875 json_lcommunity
= json_object_new_object();
7876 json_object_string_add(json_lcommunity
,
7878 attr
->lcommunity
->str
);
7879 json_object_object_add(json_path
,
7883 vty_out(vty
, " Large Community: %s\n",
7884 attr
->lcommunity
->str
);
7888 /* Line 7 display Originator, Cluster-id */
7889 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7890 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7892 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7894 json_object_string_add(
7895 json_path
, "originatorId",
7896 inet_ntoa(attr
->originator_id
));
7898 vty_out(vty
, " Originator: %s",
7899 inet_ntoa(attr
->originator_id
));
7902 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7907 json_object_new_object();
7908 json_cluster_list_list
=
7909 json_object_new_array();
7912 i
< attr
->cluster
->length
/ 4;
7914 json_string
= json_object_new_string(
7918 json_object_array_add(
7919 json_cluster_list_list
,
7923 /* struct cluster_list does not have
7925 * aspath and community do. Add this
7928 json_object_string_add(json_cluster_list,
7929 "string", attr->cluster->str);
7931 json_object_object_add(
7932 json_cluster_list
, "list",
7933 json_cluster_list_list
);
7934 json_object_object_add(
7935 json_path
, "clusterList",
7938 vty_out(vty
, ", Cluster list: ");
7941 i
< attr
->cluster
->length
/ 4;
7955 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7956 bgp_damp_info_vty(vty
, binfo
, json_path
);
7959 #if defined(HAVE_CUMULUS)
7960 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
7961 && safi
!= SAFI_EVPN
)
7963 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
7966 mpls_label_t label
=
7967 label_pton(&binfo
->extra
->label
[0]);
7969 json_object_int_add(json_path
, "remoteLabel",
7972 vty_out(vty
, " Remote label: %d\n", label
);
7976 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7978 json_object_int_add(json_path
, "labelIndex",
7981 vty_out(vty
, " Label Index: %d\n",
7985 /* Line 8 display Addpath IDs */
7986 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7988 json_object_int_add(json_path
, "addpathRxId",
7989 binfo
->addpath_rx_id
);
7990 json_object_int_add(json_path
, "addpathTxId",
7991 binfo
->addpath_tx_id
);
7993 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7994 binfo
->addpath_rx_id
,
7995 binfo
->addpath_tx_id
);
7999 /* If we used addpath to TX a non-bestpath we need to display
8000 * "Advertised to" on a path-by-path basis */
8001 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8004 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8006 bgp_addpath_encode_tx(peer
, afi
, safi
);
8007 has_adj
= bgp_adj_out_lookup(
8008 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8010 if ((addpath_capable
&& has_adj
)
8011 || (!addpath_capable
&& has_adj
8012 && CHECK_FLAG(binfo
->flags
,
8013 BGP_INFO_SELECTED
))) {
8014 if (json_path
&& !json_adv_to
)
8016 json_object_new_object();
8018 route_vty_out_advertised_to(
8027 json_object_object_add(json_path
,
8038 /* Line 9 display Uptime */
8039 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8041 json_last_update
= json_object_new_object();
8042 json_object_int_add(json_last_update
, "epoch", tbuf
);
8043 json_object_string_add(json_last_update
, "string",
8045 json_object_object_add(json_path
, "lastUpdate",
8048 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8050 /* Line 10 display PMSI tunnel attribute, if present */
8051 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8052 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8053 attr
->pmsi_tnl_type
,
8054 PMSI_TNLTYPE_STR_DEFAULT
);
8057 json_pmsi
= json_object_new_object();
8058 json_object_string_add(json_pmsi
,
8060 json_object_object_add(json_path
, "pmsi",
8063 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8069 /* We've constructed the json object for this path, add it to the json
8073 if (json_nexthop_global
|| json_nexthop_ll
) {
8074 json_nexthops
= json_object_new_array();
8076 if (json_nexthop_global
)
8077 json_object_array_add(json_nexthops
,
8078 json_nexthop_global
);
8080 if (json_nexthop_ll
)
8081 json_object_array_add(json_nexthops
,
8084 json_object_object_add(json_path
, "nexthops",
8088 json_object_object_add(json_path
, "peer", json_peer
);
8089 json_object_array_add(json_paths
, json_path
);
8094 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8095 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8096 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8098 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8099 const char *prefix_list_str
, afi_t afi
,
8100 safi_t safi
, enum bgp_show_type type
);
8101 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8102 const char *filter
, afi_t afi
, safi_t safi
,
8103 enum bgp_show_type type
);
8104 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8105 const char *rmap_str
, afi_t afi
, safi_t safi
,
8106 enum bgp_show_type type
);
8107 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8108 const char *com
, int exact
, afi_t afi
,
8110 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8111 const char *prefix
, afi_t afi
, safi_t safi
,
8112 enum bgp_show_type type
);
8113 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8114 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8115 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8116 const char *comstr
, int exact
, afi_t afi
,
8120 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8121 struct bgp_table
*table
, enum bgp_show_type type
,
8122 void *output_arg
, uint8_t use_json
, char *rd
,
8123 int is_last
, unsigned long *output_cum
,
8124 unsigned long *total_cum
,
8125 unsigned long *json_header_depth
)
8127 struct bgp_info
*ri
;
8128 struct bgp_node
*rn
;
8131 unsigned long output_count
= 0;
8132 unsigned long total_count
= 0;
8136 json_object
*json_paths
= NULL
;
8139 if (output_cum
&& *output_cum
!= 0)
8142 if (use_json
&& !*json_header_depth
) {
8144 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8145 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8146 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8147 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8149 table
->version
, inet_ntoa(bgp
->router_id
));
8150 *json_header_depth
= 2;
8152 vty_out(vty
, " \"routeDistinguishers\" : {");
8153 ++*json_header_depth
;
8155 json_paths
= json_object_new_object();
8158 if (use_json
&& rd
) {
8159 vty_out(vty
, " \"%s\" : { ", rd
);
8162 /* Start processing of routes. */
8163 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8164 if (rn
->info
== NULL
)
8169 json_paths
= json_object_new_array();
8173 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8175 if (type
== bgp_show_type_flap_statistics
8176 || type
== bgp_show_type_flap_neighbor
8177 || type
== bgp_show_type_dampend_paths
8178 || type
== bgp_show_type_damp_neighbor
) {
8179 if (!(ri
->extra
&& ri
->extra
->damp_info
))
8182 if (type
== bgp_show_type_regexp
) {
8183 regex_t
*regex
= output_arg
;
8185 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8189 if (type
== bgp_show_type_prefix_list
) {
8190 struct prefix_list
*plist
= output_arg
;
8192 if (prefix_list_apply(plist
, &rn
->p
)
8196 if (type
== bgp_show_type_filter_list
) {
8197 struct as_list
*as_list
= output_arg
;
8199 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8200 != AS_FILTER_PERMIT
)
8203 if (type
== bgp_show_type_route_map
) {
8204 struct route_map
*rmap
= output_arg
;
8205 struct bgp_info binfo
;
8206 struct attr dummy_attr
;
8209 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8211 binfo
.peer
= ri
->peer
;
8212 binfo
.attr
= &dummy_attr
;
8214 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8216 if (ret
== RMAP_DENYMATCH
)
8219 if (type
== bgp_show_type_neighbor
8220 || type
== bgp_show_type_flap_neighbor
8221 || type
== bgp_show_type_damp_neighbor
) {
8222 union sockunion
*su
= output_arg
;
8224 if (ri
->peer
== NULL
8225 || ri
->peer
->su_remote
== NULL
8226 || !sockunion_same(ri
->peer
->su_remote
, su
))
8229 if (type
== bgp_show_type_cidr_only
) {
8230 uint32_t destination
;
8232 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8233 if (IN_CLASSC(destination
)
8234 && rn
->p
.prefixlen
== 24)
8236 if (IN_CLASSB(destination
)
8237 && rn
->p
.prefixlen
== 16)
8239 if (IN_CLASSA(destination
)
8240 && rn
->p
.prefixlen
== 8)
8243 if (type
== bgp_show_type_prefix_longer
) {
8244 struct prefix
*p
= output_arg
;
8246 if (!prefix_match(p
, &rn
->p
))
8249 if (type
== bgp_show_type_community_all
) {
8250 if (!ri
->attr
->community
)
8253 if (type
== bgp_show_type_community
) {
8254 struct community
*com
= output_arg
;
8256 if (!ri
->attr
->community
8257 || !community_match(ri
->attr
->community
,
8261 if (type
== bgp_show_type_community_exact
) {
8262 struct community
*com
= output_arg
;
8264 if (!ri
->attr
->community
8265 || !community_cmp(ri
->attr
->community
, com
))
8268 if (type
== bgp_show_type_community_list
) {
8269 struct community_list
*list
= output_arg
;
8271 if (!community_list_match(ri
->attr
->community
,
8275 if (type
== bgp_show_type_community_list_exact
) {
8276 struct community_list
*list
= output_arg
;
8278 if (!community_list_exact_match(
8279 ri
->attr
->community
, list
))
8282 if (type
== bgp_show_type_lcommunity
) {
8283 struct lcommunity
*lcom
= output_arg
;
8285 if (!ri
->attr
->lcommunity
8286 || !lcommunity_match(ri
->attr
->lcommunity
,
8290 if (type
== bgp_show_type_lcommunity_list
) {
8291 struct community_list
*list
= output_arg
;
8293 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8297 if (type
== bgp_show_type_lcommunity_all
) {
8298 if (!ri
->attr
->lcommunity
)
8301 if (type
== bgp_show_type_dampend_paths
8302 || type
== bgp_show_type_damp_neighbor
) {
8303 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8304 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8308 if (!use_json
&& header
) {
8309 vty_out(vty
, "BGP table version is %" PRIu64
8310 ", local router ID is %s\n",
8312 inet_ntoa(bgp
->router_id
));
8313 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8314 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8315 if (type
== bgp_show_type_dampend_paths
8316 || type
== bgp_show_type_damp_neighbor
)
8317 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8318 else if (type
== bgp_show_type_flap_statistics
8319 || type
== bgp_show_type_flap_neighbor
)
8320 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8322 vty_out(vty
, BGP_SHOW_HEADER
);
8325 if (rd
!= NULL
&& !display
&& !output_count
) {
8328 "Route Distinguisher: %s\n",
8331 if (type
== bgp_show_type_dampend_paths
8332 || type
== bgp_show_type_damp_neighbor
)
8333 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8334 safi
, use_json
, json_paths
);
8335 else if (type
== bgp_show_type_flap_statistics
8336 || type
== bgp_show_type_flap_neighbor
)
8337 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8338 safi
, use_json
, json_paths
);
8340 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8351 sprintf(buf2
, "%s/%d",
8352 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8355 vty_out(vty
, "\"%s\": ", buf2
);
8357 vty_out(vty
, ",\"%s\": ", buf2
);
8360 json_object_to_json_string(json_paths
));
8361 json_object_free(json_paths
);
8368 output_count
+= *output_cum
;
8369 *output_cum
= output_count
;
8372 total_count
+= *total_cum
;
8373 *total_cum
= total_count
;
8377 json_object_free(json_paths
);
8379 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8383 for (i
= 0; i
< *json_header_depth
; ++i
)
8384 vty_out(vty
, " } ");
8388 /* No route is displayed */
8389 if (output_count
== 0) {
8390 if (type
== bgp_show_type_normal
)
8392 "No BGP prefixes displayed, %ld exist\n",
8396 "\nDisplayed %ld routes and %ld total paths\n",
8397 output_count
, total_count
);
8404 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8405 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8406 enum bgp_show_type type
, void *output_arg
,
8409 struct bgp_node
*rn
, *next
;
8410 unsigned long output_cum
= 0;
8411 unsigned long total_cum
= 0;
8412 unsigned long json_header_depth
= 0;
8415 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8417 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8418 next
= bgp_route_next(rn
);
8419 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8421 if (rn
->info
!= NULL
) {
8422 struct prefix_rd prd
;
8423 char rd
[RD_ADDRSTRLEN
];
8425 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8426 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8427 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8428 output_arg
, use_json
, rd
, next
== NULL
,
8429 &output_cum
, &total_cum
,
8430 &json_header_depth
);
8436 if (output_cum
== 0)
8437 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8441 "\nDisplayed %ld routes and %ld total paths\n",
8442 output_cum
, total_cum
);
8446 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8447 enum bgp_show_type type
, void *output_arg
, uint8_t use_json
)
8449 struct bgp_table
*table
;
8450 unsigned long json_header_depth
= 0;
8453 bgp
= bgp_get_default();
8458 vty_out(vty
, "No BGP process is configured\n");
8460 vty_out(vty
, "{}\n");
8464 table
= bgp
->rib
[afi
][safi
];
8465 /* use MPLS and ENCAP specific shows until they are merged */
8466 if (safi
== SAFI_MPLS_VPN
) {
8467 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8468 output_arg
, use_json
);
8471 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8472 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8473 output_arg
, use_json
,
8476 /* labeled-unicast routes live in the unicast table */
8477 else if (safi
== SAFI_LABELED_UNICAST
)
8478 safi
= SAFI_UNICAST
;
8480 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8481 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8484 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8485 safi_t safi
, uint8_t use_json
)
8487 struct listnode
*node
, *nnode
;
8492 vty_out(vty
, "{\n");
8494 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8497 vty_out(vty
, ",\n");
8501 vty_out(vty
, "\"%s\":",
8502 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8506 vty_out(vty
, "\nInstance %s:\n",
8507 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8511 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8516 vty_out(vty
, "}\n");
8519 /* Header of detailed BGP route information */
8520 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8521 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8522 afi_t afi
, safi_t safi
, json_object
*json
)
8524 struct bgp_info
*ri
;
8527 struct listnode
*node
, *nnode
;
8528 char buf1
[RD_ADDRSTRLEN
];
8529 char buf2
[INET6_ADDRSTRLEN
];
8530 #if defined(HAVE_CUMULUS)
8531 char buf3
[EVPN_ROUTE_STRLEN
];
8533 char prefix_str
[BUFSIZ
];
8538 int no_advertise
= 0;
8541 int has_valid_label
= 0;
8542 mpls_label_t label
= 0;
8543 json_object
*json_adv_to
= NULL
;
8546 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8548 if (has_valid_label
)
8549 label
= label_pton(&rn
->local_label
);
8552 if (has_valid_label
)
8553 json_object_int_add(json
, "localLabel", label
);
8555 json_object_string_add(
8557 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8559 #if defined(HAVE_CUMULUS)
8560 if (safi
== SAFI_EVPN
)
8561 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8562 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8565 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8566 buf3
, sizeof(buf3
)));
8568 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8569 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8570 ? prefix_rd2str(prd
, buf1
,
8573 safi
== SAFI_MPLS_VPN
? ":" : "",
8574 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8578 if (p
->family
== AF_ETHERNET
)
8579 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8581 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8583 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8584 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8585 || safi
== SAFI_EVPN
)
8586 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8588 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8590 buf2
, p
->prefixlen
);
8593 if (has_valid_label
)
8594 vty_out(vty
, "Local label: %d\n", label
);
8595 #if defined(HAVE_CUMULUS)
8596 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8598 if (bgp_labeled_safi(safi
))
8600 vty_out(vty
, "not allocated\n");
8603 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8605 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8607 if (ri
->extra
&& ri
->extra
->suppress
)
8609 if (ri
->attr
->community
!= NULL
) {
8610 if (community_include(ri
->attr
->community
,
8611 COMMUNITY_NO_ADVERTISE
))
8613 if (community_include(ri
->attr
->community
,
8614 COMMUNITY_NO_EXPORT
))
8616 if (community_include(ri
->attr
->community
,
8617 COMMUNITY_LOCAL_AS
))
8624 vty_out(vty
, "Paths: (%d available", count
);
8626 vty_out(vty
, ", best #%d", best
);
8627 if (safi
== SAFI_UNICAST
)
8628 vty_out(vty
, ", table %s",
8630 == BGP_INSTANCE_TYPE_DEFAULT
)
8631 ? "Default-IP-Routing-Table"
8634 vty_out(vty
, ", no best path");
8637 vty_out(vty
, ", not advertised to any peer");
8639 vty_out(vty
, ", not advertised to EBGP peer");
8641 vty_out(vty
, ", not advertised outside local AS");
8645 ", Advertisements suppressed by an aggregate.");
8646 vty_out(vty
, ")\n");
8649 /* If we are not using addpath then we can display Advertised to and
8651 * show what peers we advertised the bestpath to. If we are using
8653 * though then we must display Advertised to on a path-by-path basis. */
8654 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8655 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8656 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8657 if (json
&& !json_adv_to
)
8658 json_adv_to
= json_object_new_object();
8660 route_vty_out_advertised_to(
8662 " Advertised to non peer-group peers:\n ",
8669 json_object_object_add(json
, "advertisedTo",
8674 vty_out(vty
, " Not advertised to any peer");
8680 /* Display specified route of BGP table. */
8681 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8682 struct bgp_table
*rib
, const char *ip_str
,
8683 afi_t afi
, safi_t safi
,
8684 struct prefix_rd
*prd
, int prefix_check
,
8685 enum bgp_path_type pathtype
,
8691 struct prefix match
;
8692 struct bgp_node
*rn
;
8693 struct bgp_node
*rm
;
8694 struct bgp_info
*ri
;
8695 struct bgp_table
*table
;
8696 json_object
*json
= NULL
;
8697 json_object
*json_paths
= NULL
;
8699 /* Check IP address argument. */
8700 ret
= str2prefix(ip_str
, &match
);
8702 vty_out(vty
, "address is malformed\n");
8706 match
.family
= afi2family(afi
);
8709 json
= json_object_new_object();
8710 json_paths
= json_object_new_array();
8713 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8714 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8715 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8718 if ((table
= rn
->info
) == NULL
)
8723 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8727 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8728 bgp_unlock_node(rm
);
8732 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8734 route_vty_out_detail_header(
8736 (struct prefix_rd
*)&rn
->p
,
8737 AFI_IP
, safi
, json
);
8742 if (pathtype
== BGP_PATH_ALL
8743 || (pathtype
== BGP_PATH_BESTPATH
8744 && CHECK_FLAG(ri
->flags
,
8746 || (pathtype
== BGP_PATH_MULTIPATH
8747 && (CHECK_FLAG(ri
->flags
,
8749 || CHECK_FLAG(ri
->flags
,
8750 BGP_INFO_SELECTED
))))
8751 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8756 bgp_unlock_node(rm
);
8758 } else if (safi
== SAFI_FLOWSPEC
) {
8759 rn
= bgp_flowspec_get_match_per_ip(afi
, rib
,
8760 &match
, prefix_check
);
8762 route_vty_out_flowspec(vty
, &rn
->p
,
8763 rn
->info
, use_json
?
8764 NLRI_STRING_FORMAT_JSON
:
8765 NLRI_STRING_FORMAT_LARGE
,
8768 bgp_unlock_node(rn
);
8773 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8775 || rn
->p
.prefixlen
== match
.prefixlen
) {
8776 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8778 route_vty_out_detail_header(
8779 vty
, bgp
, rn
, NULL
, afi
,
8785 if (pathtype
== BGP_PATH_ALL
8786 || (pathtype
== BGP_PATH_BESTPATH
8790 || (pathtype
== BGP_PATH_MULTIPATH
8796 BGP_INFO_SELECTED
))))
8797 route_vty_out_detail(
8798 vty
, bgp
, &rn
->p
, ri
,
8799 afi
, safi
, json_paths
);
8803 bgp_unlock_node(rn
);
8809 json_object_object_add(json
, "paths", json_paths
);
8811 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8812 json
, JSON_C_TO_STRING_PRETTY
));
8813 json_object_free(json
);
8816 vty_out(vty
, "%% Network not in table\n");
8824 /* Display specified route of Main RIB */
8825 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8826 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8827 int prefix_check
, enum bgp_path_type pathtype
,
8831 bgp
= bgp_get_default();
8834 vty_out(vty
, "No BGP process is configured\n");
8836 vty_out(vty
, "{}\n");
8841 /* labeled-unicast routes live in the unicast table */
8842 if (safi
== SAFI_LABELED_UNICAST
)
8843 safi
= SAFI_UNICAST
;
8845 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8846 afi
, safi
, prd
, prefix_check
, pathtype
,
8850 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8851 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8854 struct lcommunity
*lcom
;
8860 b
= buffer_new(1024);
8861 for (i
= 0; i
< argc
; i
++) {
8863 buffer_putc(b
, ' ');
8865 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8867 buffer_putstr(b
, argv
[i
]->arg
);
8871 buffer_putc(b
, '\0');
8873 str
= buffer_getstr(b
);
8876 lcom
= lcommunity_str2com(str
);
8877 XFREE(MTYPE_TMP
, str
);
8879 vty_out(vty
, "%% Large-community malformed\n");
8883 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8887 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8888 const char *lcom
, afi_t afi
, safi_t safi
,
8891 struct community_list
*list
;
8893 list
= community_list_lookup(bgp_clist
, lcom
,
8894 LARGE_COMMUNITY_LIST_MASTER
);
8896 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8901 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8905 DEFUN (show_ip_bgp_large_community_list
,
8906 show_ip_bgp_large_community_list_cmd
,
8907 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8911 BGP_INSTANCE_HELP_STR
8913 BGP_SAFI_WITH_LABEL_HELP_STR
8914 "Display routes matching the large-community-list\n"
8915 "large-community-list number\n"
8916 "large-community-list name\n"
8920 afi_t afi
= AFI_IP6
;
8921 safi_t safi
= SAFI_UNICAST
;
8924 if (argv_find(argv
, argc
, "ip", &idx
))
8926 if (argv_find(argv
, argc
, "view", &idx
)
8927 || argv_find(argv
, argc
, "vrf", &idx
))
8928 vrf
= argv
[++idx
]->arg
;
8929 if (argv_find(argv
, argc
, "ipv4", &idx
)
8930 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8931 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8932 if (argv_find(argv
, argc
, "unicast", &idx
)
8933 || argv_find(argv
, argc
, "multicast", &idx
))
8934 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8937 int uj
= use_json(argc
, argv
);
8939 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8941 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8945 argv_find(argv
, argc
, "large-community-list", &idx
);
8946 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8949 DEFUN (show_ip_bgp_large_community
,
8950 show_ip_bgp_large_community_cmd
,
8951 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8955 BGP_INSTANCE_HELP_STR
8957 BGP_SAFI_WITH_LABEL_HELP_STR
8958 "Display routes matching the large-communities\n"
8959 "List of large-community numbers\n"
8963 afi_t afi
= AFI_IP6
;
8964 safi_t safi
= SAFI_UNICAST
;
8967 if (argv_find(argv
, argc
, "ip", &idx
))
8969 if (argv_find(argv
, argc
, "view", &idx
)
8970 || argv_find(argv
, argc
, "vrf", &idx
))
8971 vrf
= argv
[++idx
]->arg
;
8972 if (argv_find(argv
, argc
, "ipv4", &idx
)
8973 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8974 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8975 if (argv_find(argv
, argc
, "unicast", &idx
)
8976 || argv_find(argv
, argc
, "multicast", &idx
))
8977 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8980 int uj
= use_json(argc
, argv
);
8982 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8984 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8988 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8989 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8991 return bgp_show(vty
, bgp
, afi
, safi
,
8992 bgp_show_type_lcommunity_all
, NULL
, uj
);
8995 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8999 /* BGP route print out function without JSON */
9002 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9003 <dampening <parameters>\
9008 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
9009 |community-list <(1-500)|WORD> [exact-match]\
9010 |A.B.C.D/M longer-prefixes\
9011 |X:X::X:X/M longer-prefixes\
9016 BGP_INSTANCE_HELP_STR
9018 BGP_SAFI_WITH_LABEL_HELP_STR
9019 "Display detailed information about dampening\n"
9020 "Display detail of configured dampening parameters\n"
9021 "Display routes matching the route-map\n"
9022 "A route-map to match on\n"
9023 "Display routes conforming to the prefix-list\n"
9024 "Prefix-list name\n"
9025 "Display routes conforming to the filter-list\n"
9026 "Regular expression access list name\n"
9027 "BGP RIB advertisement statistics\n"
9028 "Display routes matching the communities\n"
9030 "Do not send outside local AS (well-known community)\n"
9031 "Do not advertise to any peer (well-known community)\n"
9032 "Do not export to next AS (well-known community)\n"
9033 "Graceful shutdown (well-known community)\n"
9034 "Exact match of the communities\n"
9035 "Display routes matching the community-list\n"
9036 "community-list number\n"
9037 "community-list name\n"
9038 "Exact match of the communities\n"
9040 "Display route and more specific routes\n"
9042 "Display route and more specific routes\n")
9044 afi_t afi
= AFI_IP6
;
9045 safi_t safi
= SAFI_UNICAST
;
9046 int exact_match
= 0;
9047 struct bgp
*bgp
= NULL
;
9049 int idx_community_type
= 0;
9051 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9056 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9057 if (argv_find(argv
, argc
, "parameters", &idx
))
9058 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9061 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9062 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9063 safi
, bgp_show_type_prefix_list
);
9065 if (argv_find(argv
, argc
, "filter-list", &idx
))
9066 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9067 safi
, bgp_show_type_filter_list
);
9069 if (argv_find(argv
, argc
, "statistics", &idx
))
9070 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9072 if (argv_find(argv
, argc
, "route-map", &idx
))
9073 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9074 safi
, bgp_show_type_route_map
);
9076 if (argv_find(argv
, argc
, "community", &idx
)) {
9077 /* show a specific community */
9078 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9079 || argv_find(argv
, argc
, "no-advertise",
9080 &idx_community_type
)
9081 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9082 || argv_find(argv
, argc
, "graceful-shutdown",
9083 &idx_community_type
)
9084 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9086 if (argv_find(argv
, argc
, "exact-match", &idx
))
9088 return bgp_show_community(vty
, bgp
,
9089 argv
[idx_community_type
]->arg
,
9090 exact_match
, afi
, safi
);
9094 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9095 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9096 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9098 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9099 exact_match
, afi
, safi
);
9102 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9103 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9104 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9106 bgp_show_type_prefix_longer
);
9111 /* BGP route print out function with JSON */
9112 DEFUN (show_ip_bgp_json
,
9113 show_ip_bgp_json_cmd
,
9114 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9117 |dampening <flap-statistics|dampened-paths>\
9123 BGP_INSTANCE_HELP_STR
9125 BGP_SAFI_WITH_LABEL_HELP_STR
9126 "Display only routes with non-natural netmasks\n"
9127 "Display detailed information about dampening\n"
9128 "Display flap statistics of routes\n"
9129 "Display paths suppressed due to dampening\n"
9130 "Display routes matching the communities\n"
9133 afi_t afi
= AFI_IP6
;
9134 safi_t safi
= SAFI_UNICAST
;
9135 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9136 struct bgp
*bgp
= NULL
;
9139 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9144 int uj
= use_json(argc
, argv
);
9148 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9149 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9152 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9153 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9154 return bgp_show(vty
, bgp
, afi
, safi
,
9155 bgp_show_type_dampend_paths
, NULL
, uj
);
9156 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9157 return bgp_show(vty
, bgp
, afi
, safi
,
9158 bgp_show_type_flap_statistics
, NULL
,
9162 if (argv_find(argv
, argc
, "community", &idx
)) {
9163 /* show all communities */
9164 return bgp_show(vty
, bgp
, afi
, safi
,
9165 bgp_show_type_community_all
, NULL
, uj
);
9167 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9170 DEFUN (show_ip_bgp_route
,
9171 show_ip_bgp_route_cmd
,
9172 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9173 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9177 BGP_INSTANCE_HELP_STR
9179 BGP_SAFI_WITH_LABEL_HELP_STR
9180 "Network in the BGP routing table to display\n"
9182 "Network in the BGP routing table to display\n"
9184 "Display only the bestpath\n"
9185 "Display only multipaths\n"
9188 int prefix_check
= 0;
9190 afi_t afi
= AFI_IP6
;
9191 safi_t safi
= SAFI_UNICAST
;
9192 char *prefix
= NULL
;
9193 struct bgp
*bgp
= NULL
;
9194 enum bgp_path_type path_type
;
9195 uint8_t uj
= use_json(argc
, argv
);
9199 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9206 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9210 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9211 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9212 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9214 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9215 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9218 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9219 && afi
!= AFI_IP6
) {
9221 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9224 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9227 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9231 prefix
= argv
[idx
]->arg
;
9233 /* [<bestpath|multipath>] */
9234 if (argv_find(argv
, argc
, "bestpath", &idx
))
9235 path_type
= BGP_PATH_BESTPATH
;
9236 else if (argv_find(argv
, argc
, "multipath", &idx
))
9237 path_type
= BGP_PATH_MULTIPATH
;
9239 path_type
= BGP_PATH_ALL
;
9241 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9245 DEFUN (show_ip_bgp_regexp
,
9246 show_ip_bgp_regexp_cmd
,
9247 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9251 BGP_INSTANCE_HELP_STR
9253 BGP_SAFI_WITH_LABEL_HELP_STR
9254 "Display routes matching the AS path regular expression\n"
9255 "A regular-expression to match the BGP AS paths\n")
9257 afi_t afi
= AFI_IP6
;
9258 safi_t safi
= SAFI_UNICAST
;
9259 struct bgp
*bgp
= NULL
;
9262 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9267 // get index of regex
9268 argv_find(argv
, argc
, "regexp", &idx
);
9271 char *regstr
= argv_concat(argv
, argc
, idx
);
9272 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9273 bgp_show_type_regexp
);
9274 XFREE(MTYPE_TMP
, regstr
);
9278 DEFUN (show_ip_bgp_instance_all
,
9279 show_ip_bgp_instance_all_cmd
,
9280 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9284 BGP_INSTANCE_ALL_HELP_STR
9286 BGP_SAFI_WITH_LABEL_HELP_STR
9290 safi_t safi
= SAFI_UNICAST
;
9291 struct bgp
*bgp
= NULL
;
9294 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9299 int uj
= use_json(argc
, argv
);
9303 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9307 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9308 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9313 regex
= bgp_regcomp(regstr
);
9315 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9319 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9320 bgp_regex_free(regex
);
9324 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9325 const char *prefix_list_str
, afi_t afi
,
9326 safi_t safi
, enum bgp_show_type type
)
9328 struct prefix_list
*plist
;
9330 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9331 if (plist
== NULL
) {
9332 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9337 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9340 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9341 const char *filter
, afi_t afi
, safi_t safi
,
9342 enum bgp_show_type type
)
9344 struct as_list
*as_list
;
9346 as_list
= as_list_lookup(filter
);
9347 if (as_list
== NULL
) {
9348 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9353 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9356 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9357 const char *rmap_str
, afi_t afi
, safi_t safi
,
9358 enum bgp_show_type type
)
9360 struct route_map
*rmap
;
9362 rmap
= route_map_lookup_by_name(rmap_str
);
9364 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9368 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9371 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9372 const char *comstr
, int exact
, afi_t afi
,
9375 struct community
*com
;
9378 com
= community_str2com(comstr
);
9380 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9384 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9385 (exact
? bgp_show_type_community_exact
9386 : bgp_show_type_community
),
9388 community_free(com
);
9393 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9394 const char *com
, int exact
, afi_t afi
,
9397 struct community_list
*list
;
9399 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9401 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9405 return bgp_show(vty
, bgp
, afi
, safi
,
9406 (exact
? bgp_show_type_community_list_exact
9407 : bgp_show_type_community_list
),
9411 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9412 const char *prefix
, afi_t afi
, safi_t safi
,
9413 enum bgp_show_type type
)
9420 ret
= str2prefix(prefix
, p
);
9422 vty_out(vty
, "%% Malformed Prefix\n");
9426 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9431 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9432 const char *ip_str
, uint8_t use_json
)
9438 /* Get peer sockunion. */
9439 ret
= str2sockunion(ip_str
, &su
);
9441 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9443 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9447 json_object
*json_no
= NULL
;
9448 json_no
= json_object_new_object();
9449 json_object_string_add(
9451 "malformedAddressOrName",
9453 vty_out(vty
, "%s\n",
9454 json_object_to_json_string_ext(
9456 JSON_C_TO_STRING_PRETTY
));
9457 json_object_free(json_no
);
9460 "%% Malformed address or name: %s\n",
9468 /* Peer structure lookup. */
9469 peer
= peer_lookup(bgp
, &su
);
9472 json_object
*json_no
= NULL
;
9473 json_no
= json_object_new_object();
9474 json_object_string_add(json_no
, "warning",
9475 "No such neighbor");
9476 vty_out(vty
, "%s\n",
9477 json_object_to_json_string_ext(
9478 json_no
, JSON_C_TO_STRING_PRETTY
));
9479 json_object_free(json_no
);
9481 vty_out(vty
, "No such neighbor\n");
9489 BGP_STATS_MAXBITLEN
= 0,
9493 BGP_STATS_UNAGGREGATEABLE
,
9494 BGP_STATS_MAX_AGGREGATEABLE
,
9495 BGP_STATS_AGGREGATES
,
9497 BGP_STATS_ASPATH_COUNT
,
9498 BGP_STATS_ASPATH_MAXHOPS
,
9499 BGP_STATS_ASPATH_TOTHOPS
,
9500 BGP_STATS_ASPATH_MAXSIZE
,
9501 BGP_STATS_ASPATH_TOTSIZE
,
9502 BGP_STATS_ASN_HIGHEST
,
9506 static const char *table_stats_strs
[] = {
9507 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9508 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9509 [BGP_STATS_RIB
] = "Total Advertisements",
9510 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9511 [BGP_STATS_MAX_AGGREGATEABLE
] =
9512 "Maximum aggregateable prefixes",
9513 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9514 [BGP_STATS_SPACE
] = "Address space advertised",
9515 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9516 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9517 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9518 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9519 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9520 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9521 [BGP_STATS_MAX
] = NULL
,
9524 struct bgp_table_stats
{
9525 struct bgp_table
*table
;
9526 unsigned long long counts
[BGP_STATS_MAX
];
9531 #define TALLY_SIGFIG 100000
9532 static unsigned long
9533 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9535 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9536 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9537 unsigned long ret
= newtot
/ count
;
9539 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9546 static int bgp_table_stats_walker(struct thread
*t
)
9548 struct bgp_node
*rn
;
9549 struct bgp_node
*top
;
9550 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9551 unsigned int space
= 0;
9553 if (!(top
= bgp_table_top(ts
->table
)))
9556 switch (top
->p
.family
) {
9558 space
= IPV4_MAX_BITLEN
;
9561 space
= IPV6_MAX_BITLEN
;
9565 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9567 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9568 struct bgp_info
*ri
;
9569 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9570 unsigned int rinum
= 0;
9578 ts
->counts
[BGP_STATS_PREFIXES
]++;
9579 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9582 ts
->counts
[BGP_STATS_AVGPLEN
]
9583 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9584 ts
->counts
[BGP_STATS_AVGPLEN
],
9588 /* check if the prefix is included by any other announcements */
9589 while (prn
&& !prn
->info
)
9590 prn
= bgp_node_parent_nolock(prn
);
9592 if (prn
== NULL
|| prn
== top
) {
9593 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9594 /* announced address space */
9597 pow(2.0, space
- rn
->p
.prefixlen
);
9598 } else if (prn
->info
)
9599 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9601 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9603 ts
->counts
[BGP_STATS_RIB
]++;
9606 && (CHECK_FLAG(ri
->attr
->flag
,
9608 BGP_ATTR_ATOMIC_AGGREGATE
))))
9609 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9612 if (ri
->attr
&& ri
->attr
->aspath
) {
9614 aspath_count_hops(ri
->attr
->aspath
);
9616 aspath_size(ri
->attr
->aspath
);
9617 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9619 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9621 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9622 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9625 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9626 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9629 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9630 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9632 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9633 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9634 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9636 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9637 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9638 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9641 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9642 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9650 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9653 struct bgp_table_stats ts
;
9656 if (!bgp
->rib
[afi
][safi
]) {
9657 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9662 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9664 /* labeled-unicast routes live in the unicast table */
9665 if (safi
== SAFI_LABELED_UNICAST
)
9666 safi
= SAFI_UNICAST
;
9668 memset(&ts
, 0, sizeof(ts
));
9669 ts
.table
= bgp
->rib
[afi
][safi
];
9670 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9672 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9673 if (!table_stats_strs
[i
])
9678 case BGP_STATS_ASPATH_AVGHOPS
:
9679 case BGP_STATS_ASPATH_AVGSIZE
:
9680 case BGP_STATS_AVGPLEN
:
9681 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9682 vty_out (vty
, "%12.2f",
9683 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9686 case BGP_STATS_ASPATH_TOTHOPS
:
9687 case BGP_STATS_ASPATH_TOTSIZE
:
9688 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9689 vty_out(vty
, "%12.2f",
9691 ? (float)ts
.counts
[i
]
9693 [BGP_STATS_ASPATH_COUNT
]
9696 case BGP_STATS_TOTPLEN
:
9697 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9698 vty_out(vty
, "%12.2f",
9700 ? (float)ts
.counts
[i
]
9702 [BGP_STATS_PREFIXES
]
9705 case BGP_STATS_SPACE
:
9706 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9707 vty_out(vty
, "%12g\n", ts
.total_space
);
9709 if (afi
== AFI_IP6
) {
9710 vty_out(vty
, "%30s: ", "/32 equivalent ");
9711 vty_out(vty
, "%12g\n",
9712 ts
.total_space
* pow(2.0, -128 + 32));
9713 vty_out(vty
, "%30s: ", "/48 equivalent ");
9714 vty_out(vty
, "%12g\n",
9715 ts
.total_space
* pow(2.0, -128 + 48));
9717 vty_out(vty
, "%30s: ", "% announced ");
9718 vty_out(vty
, "%12.2f\n",
9719 ts
.total_space
* 100. * pow(2.0, -32));
9720 vty_out(vty
, "%30s: ", "/8 equivalent ");
9721 vty_out(vty
, "%12.2f\n",
9722 ts
.total_space
* pow(2.0, -32 + 8));
9723 vty_out(vty
, "%30s: ", "/24 equivalent ");
9724 vty_out(vty
, "%12.2f\n",
9725 ts
.total_space
* pow(2.0, -32 + 24));
9729 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9730 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9747 PCOUNT_PFCNT
, /* the figure we display to users */
9751 static const char *pcount_strs
[] = {
9752 [PCOUNT_ADJ_IN
] = "Adj-in",
9753 [PCOUNT_DAMPED
] = "Damped",
9754 [PCOUNT_REMOVED
] = "Removed",
9755 [PCOUNT_HISTORY
] = "History",
9756 [PCOUNT_STALE
] = "Stale",
9757 [PCOUNT_VALID
] = "Valid",
9758 [PCOUNT_ALL
] = "All RIB",
9759 [PCOUNT_COUNTED
] = "PfxCt counted",
9760 [PCOUNT_PFCNT
] = "Useable",
9761 [PCOUNT_MAX
] = NULL
,
9764 struct peer_pcounts
{
9765 unsigned int count
[PCOUNT_MAX
];
9766 const struct peer
*peer
;
9767 const struct bgp_table
*table
;
9770 static int bgp_peer_count_walker(struct thread
*t
)
9772 struct bgp_node
*rn
;
9773 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9774 const struct peer
*peer
= pc
->peer
;
9776 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9777 struct bgp_adj_in
*ain
;
9778 struct bgp_info
*ri
;
9780 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9781 if (ain
->peer
== peer
)
9782 pc
->count
[PCOUNT_ADJ_IN
]++;
9784 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9785 char buf
[SU_ADDRSTRLEN
];
9787 if (ri
->peer
!= peer
)
9790 pc
->count
[PCOUNT_ALL
]++;
9792 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9793 pc
->count
[PCOUNT_DAMPED
]++;
9794 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9795 pc
->count
[PCOUNT_HISTORY
]++;
9796 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9797 pc
->count
[PCOUNT_REMOVED
]++;
9798 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9799 pc
->count
[PCOUNT_STALE
]++;
9800 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9801 pc
->count
[PCOUNT_VALID
]++;
9802 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9803 pc
->count
[PCOUNT_PFCNT
]++;
9805 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9806 pc
->count
[PCOUNT_COUNTED
]++;
9807 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9809 "%s [pcount] %s/%d is counted but flags 0x%x",
9811 inet_ntop(rn
->p
.family
,
9812 &rn
->p
.u
.prefix
, buf
,
9814 rn
->p
.prefixlen
, ri
->flags
);
9816 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9818 "%s [pcount] %s/%d not counted but flags 0x%x",
9820 inet_ntop(rn
->p
.family
,
9821 &rn
->p
.u
.prefix
, buf
,
9823 rn
->p
.prefixlen
, ri
->flags
);
9830 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9831 safi_t safi
, uint8_t use_json
)
9833 struct peer_pcounts pcounts
= {.peer
= peer
};
9835 json_object
*json
= NULL
;
9836 json_object
*json_loop
= NULL
;
9839 json
= json_object_new_object();
9840 json_loop
= json_object_new_object();
9843 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9844 || !peer
->bgp
->rib
[afi
][safi
]) {
9846 json_object_string_add(
9848 "No such neighbor or address family");
9849 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9850 json_object_free(json
);
9852 vty_out(vty
, "%% No such neighbor or address family\n");
9857 memset(&pcounts
, 0, sizeof(pcounts
));
9858 pcounts
.peer
= peer
;
9859 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9861 /* in-place call via thread subsystem so as to record execution time
9862 * stats for the thread-walk (i.e. ensure this can't be blamed on
9863 * on just vty_read()).
9865 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9868 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9869 json_object_string_add(json
, "multiProtocol",
9870 afi_safi_print(afi
, safi
));
9871 json_object_int_add(json
, "pfxCounter",
9872 peer
->pcount
[afi
][safi
]);
9874 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9875 json_object_int_add(json_loop
, pcount_strs
[i
],
9878 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9880 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9881 json_object_string_add(json
, "pfxctDriftFor",
9883 json_object_string_add(
9884 json
, "recommended",
9885 "Please report this bug, with the above command output");
9887 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9888 json
, JSON_C_TO_STRING_PRETTY
));
9889 json_object_free(json
);
9893 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9894 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9895 peer
->hostname
, peer
->host
,
9896 afi_safi_print(afi
, safi
));
9898 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9899 afi_safi_print(afi
, safi
));
9902 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9903 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9905 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9906 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9909 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9910 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9912 "Please report this bug, with the above command output\n");
9919 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9920 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9921 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9922 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9926 BGP_INSTANCE_HELP_STR
9929 "Detailed information on TCP and BGP neighbor connections\n"
9930 "Neighbor to display information about\n"
9931 "Neighbor to display information about\n"
9932 "Neighbor on BGP configured interface\n"
9933 "Display detailed prefix count information\n"
9936 afi_t afi
= AFI_IP6
;
9937 safi_t safi
= SAFI_UNICAST
;
9940 struct bgp
*bgp
= NULL
;
9942 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9947 int uj
= use_json(argc
, argv
);
9951 argv_find(argv
, argc
, "neighbors", &idx
);
9952 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9956 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9959 #ifdef KEEP_OLD_VPN_COMMANDS
9960 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9961 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9962 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9967 "Display information about all VPNv4 NLRIs\n"
9968 "Detailed information on TCP and BGP neighbor connections\n"
9969 "Neighbor to display information about\n"
9970 "Neighbor to display information about\n"
9971 "Neighbor on BGP configured interface\n"
9972 "Display detailed prefix count information\n"
9977 uint8_t uj
= use_json(argc
, argv
);
9979 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9983 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9986 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9987 show_ip_bgp_vpn_all_route_prefix_cmd
,
9988 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9993 "Display information about all VPNv4 NLRIs\n"
9994 "Network in the BGP routing table to display\n"
9995 "Network in the BGP routing table to display\n"
9999 char *network
= NULL
;
10000 struct bgp
*bgp
= bgp_get_default();
10002 vty_out(vty
, "Can't find default instance\n");
10003 return CMD_WARNING
;
10006 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10007 network
= argv
[idx
]->arg
;
10008 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10009 network
= argv
[idx
]->arg
;
10011 vty_out(vty
, "Unable to figure out Network\n");
10012 return CMD_WARNING
;
10015 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10016 BGP_PATH_ALL
, use_json(argc
, argv
));
10018 #endif /* KEEP_OLD_VPN_COMMANDS */
10020 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10021 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10022 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10028 "Display information about all EVPN NLRIs\n"
10029 "Network in the BGP routing table to display\n"
10030 "Network in the BGP routing table to display\n"
10034 char *network
= NULL
;
10036 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10037 network
= argv
[idx
]->arg
;
10038 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10039 network
= argv
[idx
]->arg
;
10041 vty_out(vty
, "Unable to figure out Network\n");
10042 return CMD_WARNING
;
10044 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10045 BGP_PATH_ALL
, use_json(argc
, argv
));
10048 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10049 safi_t safi
, int in
, const char *rmap_name
,
10050 uint8_t use_json
, json_object
*json
)
10052 struct bgp_table
*table
;
10053 struct bgp_adj_in
*ain
;
10054 struct bgp_adj_out
*adj
;
10055 unsigned long output_count
;
10056 unsigned long filtered_count
;
10057 struct bgp_node
*rn
;
10063 struct update_subgroup
*subgrp
;
10064 json_object
*json_scode
= NULL
;
10065 json_object
*json_ocode
= NULL
;
10066 json_object
*json_ar
= NULL
;
10067 struct peer_af
*paf
;
10070 json_scode
= json_object_new_object();
10071 json_ocode
= json_object_new_object();
10072 json_ar
= json_object_new_object();
10074 json_object_string_add(json_scode
, "suppressed", "s");
10075 json_object_string_add(json_scode
, "damped", "d");
10076 json_object_string_add(json_scode
, "history", "h");
10077 json_object_string_add(json_scode
, "valid", "*");
10078 json_object_string_add(json_scode
, "best", ">");
10079 json_object_string_add(json_scode
, "multipath", "=");
10080 json_object_string_add(json_scode
, "internal", "i");
10081 json_object_string_add(json_scode
, "ribFailure", "r");
10082 json_object_string_add(json_scode
, "stale", "S");
10083 json_object_string_add(json_scode
, "removed", "R");
10085 json_object_string_add(json_ocode
, "igp", "i");
10086 json_object_string_add(json_ocode
, "egp", "e");
10087 json_object_string_add(json_ocode
, "incomplete", "?");
10094 json_object_string_add(json
, "alert", "no BGP");
10095 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10096 json_object_free(json
);
10098 vty_out(vty
, "%% No bgp\n");
10102 table
= bgp
->rib
[afi
][safi
];
10104 output_count
= filtered_count
= 0;
10105 subgrp
= peer_subgroup(peer
, afi
, safi
);
10108 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10110 json_object_int_add(json
, "bgpTableVersion",
10112 json_object_string_add(json
, "bgpLocalRouterId",
10113 inet_ntoa(bgp
->router_id
));
10114 json_object_object_add(json
, "bgpStatusCodes",
10116 json_object_object_add(json
, "bgpOriginCodes",
10118 json_object_string_add(json
,
10119 "bgpOriginatingDefaultNetwork",
10122 vty_out(vty
, "BGP table version is %" PRIu64
10123 ", local router ID is %s\n",
10124 table
->version
, inet_ntoa(bgp
->router_id
));
10125 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10126 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10128 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10133 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10135 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10136 if (ain
->peer
!= peer
)
10140 json_object_int_add(
10141 json
, "bgpTableVersion",
10143 json_object_string_add(
10145 "bgpLocalRouterId",
10148 json_object_object_add(
10149 json
, "bgpStatusCodes",
10151 json_object_object_add(
10152 json
, "bgpOriginCodes",
10156 "BGP table version is 0, local router ID is %s\n",
10160 BGP_SHOW_SCODE_HEADER
);
10162 BGP_SHOW_OCODE_HEADER
);
10168 vty_out(vty
, BGP_SHOW_HEADER
);
10172 bgp_attr_dup(&attr
, ain
->attr
);
10173 if (bgp_input_modifier(peer
, &rn
->p
,
10177 route_vty_out_tmp(vty
, &rn
->p
,
10187 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10188 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10189 if (paf
->peer
!= peer
)
10194 json_object_int_add(
10198 json_object_string_add(
10200 "bgpLocalRouterId",
10203 json_object_object_add(
10207 json_object_object_add(
10213 "BGP table version is %" PRIu64
10214 ", local router ID is %s\n",
10219 BGP_SHOW_SCODE_HEADER
);
10221 BGP_SHOW_OCODE_HEADER
);
10234 bgp_attr_dup(&attr
, adj
->attr
);
10235 ret
= bgp_output_modifier(
10236 peer
, &rn
->p
, &attr
,
10237 afi
, safi
, rmap_name
);
10238 if (ret
!= RMAP_DENY
) {
10248 bgp_attr_undup(&attr
,
10255 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10257 if (output_count
!= 0) {
10259 json_object_int_add(json
, "totalPrefixCounter",
10262 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10266 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10267 json
, JSON_C_TO_STRING_PRETTY
));
10268 json_object_free(json
);
10272 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10273 safi_t safi
, int in
, const char *rmap_name
,
10276 json_object
*json
= NULL
;
10279 json
= json_object_new_object();
10281 /* labeled-unicast routes live in the unicast table */
10282 if (safi
== SAFI_LABELED_UNICAST
)
10283 safi
= SAFI_UNICAST
;
10285 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10287 json_object_string_add(
10289 "No such neighbor or address family");
10290 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10291 json_object_free(json
);
10293 vty_out(vty
, "%% No such neighbor or address family\n");
10295 return CMD_WARNING
;
10299 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10300 PEER_FLAG_SOFT_RECONFIG
)) {
10302 json_object_string_add(
10304 "Inbound soft reconfiguration not enabled");
10305 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10306 json_object_free(json
);
10309 "%% Inbound soft reconfiguration not enabled\n");
10311 return CMD_WARNING
;
10314 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10316 return CMD_SUCCESS
;
10319 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10320 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10322 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10326 BGP_INSTANCE_HELP_STR
10328 BGP_SAFI_WITH_LABEL_HELP_STR
10329 "Detailed information on TCP and BGP neighbor connections\n"
10330 "Neighbor to display information about\n"
10331 "Neighbor to display information about\n"
10332 "Neighbor on BGP configured interface\n"
10333 "Display the received routes from neighbor\n"
10334 "Display the routes advertised to a BGP neighbor\n"
10335 "Route-map to modify the attributes\n"
10336 "Name of the route map\n"
10339 afi_t afi
= AFI_IP6
;
10340 safi_t safi
= SAFI_UNICAST
;
10341 char *rmap_name
= NULL
;
10342 char *peerstr
= NULL
;
10344 struct bgp
*bgp
= NULL
;
10349 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10352 return CMD_WARNING
;
10354 int uj
= use_json(argc
, argv
);
10358 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10359 argv_find(argv
, argc
, "neighbors", &idx
);
10360 peerstr
= argv
[++idx
]->arg
;
10362 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10364 return CMD_WARNING
;
10366 if (argv_find(argv
, argc
, "received-routes", &idx
))
10368 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10370 if (argv_find(argv
, argc
, "route-map", &idx
))
10371 rmap_name
= argv
[++idx
]->arg
;
10373 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10376 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10377 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10378 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10384 "Address Family modifier\n"
10385 "Detailed information on TCP and BGP neighbor connections\n"
10386 "Neighbor to display information about\n"
10387 "Neighbor to display information about\n"
10388 "Neighbor on BGP configured interface\n"
10389 "Display information received from a BGP neighbor\n"
10390 "Display the prefixlist filter\n"
10393 afi_t afi
= AFI_IP6
;
10394 safi_t safi
= SAFI_UNICAST
;
10395 char *peerstr
= NULL
;
10398 union sockunion su
;
10404 /* show [ip] bgp */
10405 if (argv_find(argv
, argc
, "ip", &idx
))
10407 /* [<ipv4|ipv6> [unicast]] */
10408 if (argv_find(argv
, argc
, "ipv4", &idx
))
10410 if (argv_find(argv
, argc
, "ipv6", &idx
))
10412 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10413 argv_find(argv
, argc
, "neighbors", &idx
);
10414 peerstr
= argv
[++idx
]->arg
;
10416 uint8_t uj
= use_json(argc
, argv
);
10418 ret
= str2sockunion(peerstr
, &su
);
10420 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10423 vty_out(vty
, "{}\n");
10426 "%% Malformed address or name: %s\n",
10428 return CMD_WARNING
;
10431 peer
= peer_lookup(NULL
, &su
);
10434 vty_out(vty
, "{}\n");
10436 vty_out(vty
, "No peer\n");
10437 return CMD_WARNING
;
10441 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10442 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10445 vty_out(vty
, "Address Family: %s\n",
10446 afi_safi_print(afi
, safi
));
10447 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10450 vty_out(vty
, "{}\n");
10452 vty_out(vty
, "No functional output\n");
10455 return CMD_SUCCESS
;
10458 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10459 afi_t afi
, safi_t safi
,
10460 enum bgp_show_type type
, uint8_t use_json
)
10462 /* labeled-unicast routes live in the unicast table */
10463 if (safi
== SAFI_LABELED_UNICAST
)
10464 safi
= SAFI_UNICAST
;
10466 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10468 json_object
*json_no
= NULL
;
10469 json_no
= json_object_new_object();
10470 json_object_string_add(
10471 json_no
, "warning",
10472 "No such neighbor or address family");
10473 vty_out(vty
, "%s\n",
10474 json_object_to_json_string(json_no
));
10475 json_object_free(json_no
);
10477 vty_out(vty
, "%% No such neighbor or address family\n");
10478 return CMD_WARNING
;
10481 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10484 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10485 show_ip_bgp_flowspec_routes_detailed_cmd
,
10486 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10490 BGP_INSTANCE_HELP_STR
10493 "Detailed information on flowspec entries\n"
10496 afi_t afi
= AFI_IP
;
10497 safi_t safi
= SAFI_UNICAST
;
10498 struct bgp
*bgp
= NULL
;
10501 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10504 return CMD_WARNING
;
10506 return bgp_show(vty
, bgp
, afi
, safi
,
10507 bgp_show_type_detail
, NULL
, use_json(argc
, argv
));
10510 DEFUN (show_ip_bgp_neighbor_routes
,
10511 show_ip_bgp_neighbor_routes_cmd
,
10512 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10513 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10517 BGP_INSTANCE_HELP_STR
10519 BGP_SAFI_WITH_LABEL_HELP_STR
10520 "Detailed information on TCP and BGP neighbor connections\n"
10521 "Neighbor to display information about\n"
10522 "Neighbor to display information about\n"
10523 "Neighbor on BGP configured interface\n"
10524 "Display flap statistics of the routes learned from neighbor\n"
10525 "Display the dampened routes received from neighbor\n"
10526 "Display routes learned from neighbor\n"
10529 char *peerstr
= NULL
;
10530 struct bgp
*bgp
= NULL
;
10531 afi_t afi
= AFI_IP6
;
10532 safi_t safi
= SAFI_UNICAST
;
10534 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10538 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10541 return CMD_WARNING
;
10543 int uj
= use_json(argc
, argv
);
10547 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10548 argv_find(argv
, argc
, "neighbors", &idx
);
10549 peerstr
= argv
[++idx
]->arg
;
10551 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10553 vty_out(vty
, "No such neighbor\n");
10554 return CMD_WARNING
;
10557 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10558 sh_type
= bgp_show_type_flap_neighbor
;
10559 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10560 sh_type
= bgp_show_type_damp_neighbor
;
10561 else if (argv_find(argv
, argc
, "routes", &idx
))
10562 sh_type
= bgp_show_type_neighbor
;
10564 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10567 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10569 struct bgp_distance
{
10570 /* Distance value for the IP source prefix. */
10573 /* Name of the access-list to be matched. */
10577 DEFUN (show_bgp_afi_vpn_rd_route
,
10578 show_bgp_afi_vpn_rd_route_cmd
,
10579 "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]",
10583 "Address Family modifier\n"
10584 "Display information for a route distinguisher\n"
10585 "Route Distinguisher\n"
10586 "Network in the BGP routing table to display\n"
10587 "Network in the BGP routing table to display\n"
10591 struct prefix_rd prd
;
10592 afi_t afi
= AFI_MAX
;
10595 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10596 vty_out(vty
, "%% Malformed Address Family\n");
10597 return CMD_WARNING
;
10600 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10602 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10603 return CMD_WARNING
;
10606 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10607 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10610 static struct bgp_distance
*bgp_distance_new(void)
10612 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10615 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10617 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10620 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10621 const char *ip_str
, const char *access_list_str
)
10628 struct bgp_node
*rn
;
10629 struct bgp_distance
*bdistance
;
10631 afi
= bgp_node_afi(vty
);
10632 safi
= bgp_node_safi(vty
);
10634 ret
= str2prefix(ip_str
, &p
);
10636 vty_out(vty
, "Malformed prefix\n");
10637 return CMD_WARNING_CONFIG_FAILED
;
10640 distance
= atoi(distance_str
);
10642 /* Get BGP distance node. */
10643 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10645 bdistance
= rn
->info
;
10646 bgp_unlock_node(rn
);
10648 bdistance
= bgp_distance_new();
10649 rn
->info
= bdistance
;
10652 /* Set distance value. */
10653 bdistance
->distance
= distance
;
10655 /* Reset access-list configuration. */
10656 if (bdistance
->access_list
) {
10657 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10658 bdistance
->access_list
= NULL
;
10660 if (access_list_str
)
10661 bdistance
->access_list
=
10662 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10664 return CMD_SUCCESS
;
10667 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10668 const char *ip_str
, const char *access_list_str
)
10675 struct bgp_node
*rn
;
10676 struct bgp_distance
*bdistance
;
10678 afi
= bgp_node_afi(vty
);
10679 safi
= bgp_node_safi(vty
);
10681 ret
= str2prefix(ip_str
, &p
);
10683 vty_out(vty
, "Malformed prefix\n");
10684 return CMD_WARNING_CONFIG_FAILED
;
10687 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10688 (struct prefix
*)&p
);
10690 vty_out(vty
, "Can't find specified prefix\n");
10691 return CMD_WARNING_CONFIG_FAILED
;
10694 bdistance
= rn
->info
;
10695 distance
= atoi(distance_str
);
10697 if (bdistance
->distance
!= distance
) {
10698 vty_out(vty
, "Distance does not match configured\n");
10699 return CMD_WARNING_CONFIG_FAILED
;
10702 if (bdistance
->access_list
)
10703 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10704 bgp_distance_free(bdistance
);
10707 bgp_unlock_node(rn
);
10708 bgp_unlock_node(rn
);
10710 return CMD_SUCCESS
;
10713 /* Apply BGP information to distance method. */
10714 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10715 safi_t safi
, struct bgp
*bgp
)
10717 struct bgp_node
*rn
;
10720 struct bgp_distance
*bdistance
;
10721 struct access_list
*alist
;
10722 struct bgp_static
*bgp_static
;
10727 peer
= rinfo
->peer
;
10729 /* Check source address. */
10730 sockunion2hostprefix(&peer
->su
, &q
);
10731 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10733 bdistance
= rn
->info
;
10734 bgp_unlock_node(rn
);
10736 if (bdistance
->access_list
) {
10737 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10739 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10740 return bdistance
->distance
;
10742 return bdistance
->distance
;
10745 /* Backdoor check. */
10746 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10748 bgp_static
= rn
->info
;
10749 bgp_unlock_node(rn
);
10751 if (bgp_static
->backdoor
) {
10752 if (bgp
->distance_local
[afi
][safi
])
10753 return bgp
->distance_local
[afi
][safi
];
10755 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10759 if (peer
->sort
== BGP_PEER_EBGP
) {
10760 if (bgp
->distance_ebgp
[afi
][safi
])
10761 return bgp
->distance_ebgp
[afi
][safi
];
10762 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10764 if (bgp
->distance_ibgp
[afi
][safi
])
10765 return bgp
->distance_ibgp
[afi
][safi
];
10766 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10770 DEFUN (bgp_distance
,
10772 "distance bgp (1-255) (1-255) (1-255)",
10773 "Define an administrative distance\n"
10775 "Distance for routes external to the AS\n"
10776 "Distance for routes internal to the AS\n"
10777 "Distance for local routes\n")
10779 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10780 int idx_number
= 2;
10781 int idx_number_2
= 3;
10782 int idx_number_3
= 4;
10786 afi
= bgp_node_afi(vty
);
10787 safi
= bgp_node_safi(vty
);
10789 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10790 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10791 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10792 return CMD_SUCCESS
;
10795 DEFUN (no_bgp_distance
,
10796 no_bgp_distance_cmd
,
10797 "no 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
);
10809 afi
= bgp_node_afi(vty
);
10810 safi
= bgp_node_safi(vty
);
10812 bgp
->distance_ebgp
[afi
][safi
] = 0;
10813 bgp
->distance_ibgp
[afi
][safi
] = 0;
10814 bgp
->distance_local
[afi
][safi
] = 0;
10815 return CMD_SUCCESS
;
10819 DEFUN (bgp_distance_source
,
10820 bgp_distance_source_cmd
,
10821 "distance (1-255) A.B.C.D/M",
10822 "Define an administrative distance\n"
10823 "Administrative distance\n"
10824 "IP source prefix\n")
10826 int idx_number
= 1;
10827 int idx_ipv4_prefixlen
= 2;
10828 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10829 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10830 return CMD_SUCCESS
;
10833 DEFUN (no_bgp_distance_source
,
10834 no_bgp_distance_source_cmd
,
10835 "no distance (1-255) A.B.C.D/M",
10837 "Define an administrative distance\n"
10838 "Administrative distance\n"
10839 "IP source prefix\n")
10841 int idx_number
= 2;
10842 int idx_ipv4_prefixlen
= 3;
10843 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10844 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10845 return CMD_SUCCESS
;
10848 DEFUN (bgp_distance_source_access_list
,
10849 bgp_distance_source_access_list_cmd
,
10850 "distance (1-255) A.B.C.D/M WORD",
10851 "Define an administrative distance\n"
10852 "Administrative distance\n"
10853 "IP source prefix\n"
10854 "Access list name\n")
10856 int idx_number
= 1;
10857 int idx_ipv4_prefixlen
= 2;
10859 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10860 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10861 return CMD_SUCCESS
;
10864 DEFUN (no_bgp_distance_source_access_list
,
10865 no_bgp_distance_source_access_list_cmd
,
10866 "no distance (1-255) A.B.C.D/M WORD",
10868 "Define an administrative distance\n"
10869 "Administrative distance\n"
10870 "IP source prefix\n"
10871 "Access list name\n")
10873 int idx_number
= 2;
10874 int idx_ipv4_prefixlen
= 3;
10876 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10877 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10878 return CMD_SUCCESS
;
10881 DEFUN (ipv6_bgp_distance_source
,
10882 ipv6_bgp_distance_source_cmd
,
10883 "distance (1-255) X:X::X:X/M",
10884 "Define an administrative distance\n"
10885 "Administrative distance\n"
10886 "IP source prefix\n")
10888 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10889 return CMD_SUCCESS
;
10892 DEFUN (no_ipv6_bgp_distance_source
,
10893 no_ipv6_bgp_distance_source_cmd
,
10894 "no distance (1-255) X:X::X:X/M",
10896 "Define an administrative distance\n"
10897 "Administrative distance\n"
10898 "IP source prefix\n")
10900 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10901 return CMD_SUCCESS
;
10904 DEFUN (ipv6_bgp_distance_source_access_list
,
10905 ipv6_bgp_distance_source_access_list_cmd
,
10906 "distance (1-255) X:X::X:X/M WORD",
10907 "Define an administrative distance\n"
10908 "Administrative distance\n"
10909 "IP source prefix\n"
10910 "Access list name\n")
10912 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10913 return CMD_SUCCESS
;
10916 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10917 no_ipv6_bgp_distance_source_access_list_cmd
,
10918 "no distance (1-255) X:X::X:X/M WORD",
10920 "Define an administrative distance\n"
10921 "Administrative distance\n"
10922 "IP source prefix\n"
10923 "Access list name\n")
10925 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10926 return CMD_SUCCESS
;
10929 DEFUN (bgp_damp_set
,
10931 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10932 "BGP Specific commands\n"
10933 "Enable route-flap dampening\n"
10934 "Half-life time for the penalty\n"
10935 "Value to start reusing a route\n"
10936 "Value to start suppressing a route\n"
10937 "Maximum duration to suppress a stable route\n")
10939 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10940 int idx_half_life
= 2;
10942 int idx_suppress
= 4;
10943 int idx_max_suppress
= 5;
10944 int half
= DEFAULT_HALF_LIFE
* 60;
10945 int reuse
= DEFAULT_REUSE
;
10946 int suppress
= DEFAULT_SUPPRESS
;
10947 int max
= 4 * half
;
10950 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10951 reuse
= atoi(argv
[idx_reuse
]->arg
);
10952 suppress
= atoi(argv
[idx_suppress
]->arg
);
10953 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10954 } else if (argc
== 3) {
10955 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10959 if (suppress
< reuse
) {
10961 "Suppress value cannot be less than reuse value \n");
10965 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10966 reuse
, suppress
, max
);
10969 DEFUN (bgp_damp_unset
,
10970 bgp_damp_unset_cmd
,
10971 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10973 "BGP Specific commands\n"
10974 "Enable route-flap dampening\n"
10975 "Half-life time for the penalty\n"
10976 "Value to start reusing a route\n"
10977 "Value to start suppressing a route\n"
10978 "Maximum duration to suppress a stable route\n")
10980 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10981 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10984 /* Display specified route of BGP table. */
10985 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10986 const char *ip_str
, afi_t afi
, safi_t safi
,
10987 struct prefix_rd
*prd
, int prefix_check
)
10990 struct prefix match
;
10991 struct bgp_node
*rn
;
10992 struct bgp_node
*rm
;
10993 struct bgp_info
*ri
;
10994 struct bgp_info
*ri_temp
;
10996 struct bgp_table
*table
;
10998 /* BGP structure lookup. */
11000 bgp
= bgp_lookup_by_name(view_name
);
11002 vty_out(vty
, "%% Can't find BGP instance %s\n",
11004 return CMD_WARNING
;
11007 bgp
= bgp_get_default();
11009 vty_out(vty
, "%% No BGP process is configured\n");
11010 return CMD_WARNING
;
11014 /* Check IP address argument. */
11015 ret
= str2prefix(ip_str
, &match
);
11017 vty_out(vty
, "%% address is malformed\n");
11018 return CMD_WARNING
;
11021 match
.family
= afi2family(afi
);
11023 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11024 || (safi
== SAFI_EVPN
)) {
11025 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11026 rn
= bgp_route_next(rn
)) {
11027 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11029 if ((table
= rn
->info
) == NULL
)
11031 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11035 || rm
->p
.prefixlen
== match
.prefixlen
) {
11038 if (ri
->extra
&& ri
->extra
->damp_info
) {
11039 ri_temp
= ri
->next
;
11040 bgp_damp_info_free(
11041 ri
->extra
->damp_info
,
11049 bgp_unlock_node(rm
);
11052 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11055 || rn
->p
.prefixlen
== match
.prefixlen
) {
11058 if (ri
->extra
&& ri
->extra
->damp_info
) {
11059 ri_temp
= ri
->next
;
11060 bgp_damp_info_free(
11061 ri
->extra
->damp_info
,
11069 bgp_unlock_node(rn
);
11073 return CMD_SUCCESS
;
11076 DEFUN (clear_ip_bgp_dampening
,
11077 clear_ip_bgp_dampening_cmd
,
11078 "clear ip bgp dampening",
11082 "Clear route flap dampening information\n")
11084 bgp_damp_info_clean();
11085 return CMD_SUCCESS
;
11088 DEFUN (clear_ip_bgp_dampening_prefix
,
11089 clear_ip_bgp_dampening_prefix_cmd
,
11090 "clear ip bgp dampening A.B.C.D/M",
11094 "Clear route flap dampening information\n"
11097 int idx_ipv4_prefixlen
= 4;
11098 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11099 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11102 DEFUN (clear_ip_bgp_dampening_address
,
11103 clear_ip_bgp_dampening_address_cmd
,
11104 "clear ip bgp dampening A.B.C.D",
11108 "Clear route flap dampening information\n"
11109 "Network to clear damping information\n")
11112 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11113 SAFI_UNICAST
, NULL
, 0);
11116 DEFUN (clear_ip_bgp_dampening_address_mask
,
11117 clear_ip_bgp_dampening_address_mask_cmd
,
11118 "clear ip bgp dampening A.B.C.D A.B.C.D",
11122 "Clear route flap dampening information\n"
11123 "Network to clear damping information\n"
11127 int idx_ipv4_2
= 5;
11129 char prefix_str
[BUFSIZ
];
11131 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11134 vty_out(vty
, "%% Inconsistent address and mask\n");
11135 return CMD_WARNING
;
11138 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11142 /* also used for encap safi */
11143 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11144 afi_t afi
, safi_t safi
)
11146 struct bgp_node
*prn
;
11147 struct bgp_node
*rn
;
11148 struct bgp_table
*table
;
11150 struct prefix_rd
*prd
;
11151 struct bgp_static
*bgp_static
;
11152 mpls_label_t label
;
11153 char buf
[SU_ADDRSTRLEN
];
11154 char rdbuf
[RD_ADDRSTRLEN
];
11156 /* Network configuration. */
11157 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11158 prn
= bgp_route_next(prn
)) {
11159 if ((table
= prn
->info
) == NULL
)
11162 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11163 if ((bgp_static
= rn
->info
) == NULL
)
11167 prd
= (struct prefix_rd
*)&prn
->p
;
11169 /* "network" configuration display. */
11170 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11171 label
= decode_label(&bgp_static
->label
);
11173 vty_out(vty
, " network %s/%d rd %s",
11174 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11176 p
->prefixlen
, rdbuf
);
11177 if (safi
== SAFI_MPLS_VPN
)
11178 vty_out(vty
, " label %u", label
);
11180 if (bgp_static
->rmap
.name
)
11181 vty_out(vty
, " route-map %s",
11182 bgp_static
->rmap
.name
);
11184 if (bgp_static
->backdoor
)
11185 vty_out(vty
, " backdoor");
11187 vty_out(vty
, "\n");
11192 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11193 afi_t afi
, safi_t safi
)
11195 struct bgp_node
*prn
;
11196 struct bgp_node
*rn
;
11197 struct bgp_table
*table
;
11199 struct prefix_rd
*prd
;
11200 struct bgp_static
*bgp_static
;
11201 char buf
[PREFIX_STRLEN
];
11202 char buf2
[SU_ADDRSTRLEN
];
11203 char rdbuf
[RD_ADDRSTRLEN
];
11205 /* Network configuration. */
11206 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11207 prn
= bgp_route_next(prn
)) {
11208 if ((table
= prn
->info
) == NULL
)
11211 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11212 if ((bgp_static
= rn
->info
) == NULL
)
11215 char *macrouter
= NULL
;
11218 if (bgp_static
->router_mac
)
11219 macrouter
= prefix_mac2str(
11220 bgp_static
->router_mac
, NULL
, 0);
11221 if (bgp_static
->eth_s_id
)
11222 esi
= esi2str(bgp_static
->eth_s_id
);
11224 prd
= (struct prefix_rd
*)&prn
->p
;
11226 /* "network" configuration display. */
11227 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11228 if (p
->u
.prefix_evpn
.route_type
== 5) {
11229 char local_buf
[PREFIX_STRLEN
];
11230 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((
11231 struct prefix_evpn
*)p
)
11234 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
,
11235 local_buf
, PREFIX_STRLEN
);
11236 sprintf(buf
, "%s/%u", local_buf
,
11237 p
->u
.prefix_evpn
.ip_prefix_length
);
11239 prefix2str(p
, buf
, sizeof(buf
));
11242 if (bgp_static
->gatewayIp
.family
== AF_INET
11243 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11244 inet_ntop(bgp_static
->gatewayIp
.family
,
11245 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11248 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11249 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11250 decode_label(&bgp_static
->label
), esi
, buf2
,
11254 XFREE(MTYPE_TMP
, macrouter
);
11256 XFREE(MTYPE_TMP
, esi
);
11261 /* Configuration of static route announcement and aggregate
11263 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11266 struct bgp_node
*rn
;
11268 struct bgp_static
*bgp_static
;
11269 struct bgp_aggregate
*bgp_aggregate
;
11270 char buf
[SU_ADDRSTRLEN
];
11272 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11273 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11277 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11278 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11282 /* Network configuration. */
11283 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11284 rn
= bgp_route_next(rn
)) {
11285 if ((bgp_static
= rn
->info
) == NULL
)
11290 /* "network" configuration display. */
11291 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11292 uint32_t destination
;
11293 struct in_addr netmask
;
11295 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11296 masklen2ip(p
->prefixlen
, &netmask
);
11297 vty_out(vty
, " network %s",
11298 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11301 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11302 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11303 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11304 || p
->u
.prefix4
.s_addr
== 0) {
11305 /* Natural mask is not display. */
11307 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11309 vty_out(vty
, " network %s/%d",
11310 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11315 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11316 vty_out(vty
, " label-index %u",
11317 bgp_static
->label_index
);
11319 if (bgp_static
->rmap
.name
)
11320 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11322 if (bgp_static
->backdoor
)
11323 vty_out(vty
, " backdoor");
11325 vty_out(vty
, "\n");
11328 /* Aggregate-address configuration. */
11329 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11330 rn
= bgp_route_next(rn
)) {
11331 if ((bgp_aggregate
= rn
->info
) == NULL
)
11336 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11337 struct in_addr netmask
;
11339 masklen2ip(p
->prefixlen
, &netmask
);
11340 vty_out(vty
, " aggregate-address %s %s",
11341 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11343 inet_ntoa(netmask
));
11345 vty_out(vty
, " aggregate-address %s/%d",
11346 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11351 if (bgp_aggregate
->as_set
)
11352 vty_out(vty
, " as-set");
11354 if (bgp_aggregate
->summary_only
)
11355 vty_out(vty
, " summary-only");
11357 vty_out(vty
, "\n");
11361 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11364 struct bgp_node
*rn
;
11365 struct bgp_distance
*bdistance
;
11367 /* Distance configuration. */
11368 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11369 && bgp
->distance_local
[afi
][safi
]
11370 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11371 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11372 || bgp
->distance_local
[afi
][safi
]
11373 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11374 vty_out(vty
, " distance bgp %d %d %d\n",
11375 bgp
->distance_ebgp
[afi
][safi
],
11376 bgp
->distance_ibgp
[afi
][safi
],
11377 bgp
->distance_local
[afi
][safi
]);
11380 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11381 rn
= bgp_route_next(rn
))
11382 if ((bdistance
= rn
->info
) != NULL
) {
11383 char buf
[PREFIX_STRLEN
];
11385 vty_out(vty
, " distance %d %s %s\n",
11386 bdistance
->distance
,
11387 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11388 bdistance
->access_list
? bdistance
->access_list
11393 /* Allocate routing table structure and install commands. */
11394 void bgp_route_init(void)
11399 /* Init BGP distance table. */
11400 FOREACH_AFI_SAFI (afi
, safi
)
11401 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11403 /* IPv4 BGP commands. */
11404 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11405 install_element(BGP_NODE
, &bgp_network_cmd
);
11406 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11408 install_element(BGP_NODE
, &aggregate_address_cmd
);
11409 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11410 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11411 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11413 /* IPv4 unicast configuration. */
11414 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11415 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11416 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11418 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11419 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11420 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11421 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11423 /* IPv4 multicast configuration. */
11424 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11425 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11426 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11427 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11428 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11429 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11430 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11432 /* IPv4 labeled-unicast configuration. */
11433 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11434 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11435 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11436 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11437 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11439 install_element(VIEW_NODE
,
11440 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11441 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11442 install_element(VIEW_NODE
,
11443 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11444 #ifdef KEEP_OLD_VPN_COMMANDS
11445 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11446 #endif /* KEEP_OLD_VPN_COMMANDS */
11447 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11448 install_element(VIEW_NODE
,
11449 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11451 /* BGP dampening clear commands */
11452 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11453 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11455 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11456 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11459 install_element(ENABLE_NODE
,
11460 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11461 #ifdef KEEP_OLD_VPN_COMMANDS
11462 install_element(ENABLE_NODE
,
11463 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11464 #endif /* KEEP_OLD_VPN_COMMANDS */
11466 /* New config IPv6 BGP commands. */
11467 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11468 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11469 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11471 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11472 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11474 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11476 install_element(BGP_NODE
, &bgp_distance_cmd
);
11477 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11478 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11479 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11480 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11481 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11482 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11483 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11484 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11485 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11486 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11487 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11488 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11489 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11490 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11491 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11492 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11493 install_element(BGP_IPV4M_NODE
,
11494 &no_bgp_distance_source_access_list_cmd
);
11495 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11496 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11497 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11498 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11499 install_element(BGP_IPV6_NODE
,
11500 &ipv6_bgp_distance_source_access_list_cmd
);
11501 install_element(BGP_IPV6_NODE
,
11502 &no_ipv6_bgp_distance_source_access_list_cmd
);
11503 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11504 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11505 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11506 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11507 install_element(BGP_IPV6M_NODE
,
11508 &ipv6_bgp_distance_source_access_list_cmd
);
11509 install_element(BGP_IPV6M_NODE
,
11510 &no_ipv6_bgp_distance_source_access_list_cmd
);
11512 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11513 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11514 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11515 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11517 /* IPv4 Multicast Mode */
11518 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11519 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11521 /* Large Communities */
11522 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11523 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11525 /* show bgp ipv4 flowspec detailed */
11526 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11530 void bgp_route_finish(void)
11535 FOREACH_AFI_SAFI (afi
, safi
) {
11536 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11537 bgp_distance_table
[afi
][safi
] = NULL
;