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"
78 /* Extern from bgp_dump.c */
79 extern const char *bgp_origin_str
[];
80 extern const char *bgp_origin_long_str
[];
82 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
83 safi_t safi
, struct prefix
*p
,
84 struct prefix_rd
*prd
)
87 struct bgp_node
*prn
= NULL
;
93 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
94 || (safi
== SAFI_EVPN
)) {
95 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
97 if (prn
->info
== NULL
)
98 prn
->info
= bgp_table_init(afi
, safi
);
100 bgp_unlock_node(prn
);
104 rn
= bgp_node_get(table
, p
);
106 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
107 || (safi
== SAFI_EVPN
))
113 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
114 safi_t safi
, struct prefix
*p
,
115 struct prefix_rd
*prd
)
118 struct bgp_node
*prn
= NULL
;
123 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
124 || (safi
== SAFI_EVPN
)) {
125 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
129 if (prn
->info
== NULL
) {
130 bgp_unlock_node(prn
);
137 rn
= bgp_node_lookup(table
, p
);
142 /* Allocate bgp_info_extra */
143 static struct bgp_info_extra
*bgp_info_extra_new(void)
145 struct bgp_info_extra
*new;
146 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
147 new->label
= MPLS_INVALID_LABEL
;
151 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
153 if (extra
&& *extra
) {
154 if ((*extra
)->damp_info
)
155 bgp_damp_info_free((*extra
)->damp_info
, 0);
157 (*extra
)->damp_info
= NULL
;
159 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
165 /* Get bgp_info extra information for the given bgp_info, lazy allocated
168 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
171 ri
->extra
= bgp_info_extra_new();
175 /* Allocate new bgp info structure. */
176 struct bgp_info
*bgp_info_new(void)
178 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
181 /* Free bgp route information. */
182 static void bgp_info_free(struct bgp_info
*binfo
)
185 bgp_attr_unintern(&binfo
->attr
);
187 bgp_unlink_nexthop(binfo
);
188 bgp_info_extra_free(&binfo
->extra
);
189 bgp_info_mpath_free(&binfo
->mpath
);
191 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
193 XFREE(MTYPE_BGP_ROUTE
, binfo
);
196 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
202 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
204 assert(binfo
&& binfo
->lock
> 0);
207 if (binfo
->lock
== 0) {
209 zlog_debug ("%s: unlocked and freeing", __func__
);
210 zlog_backtrace (LOG_DEBUG
);
212 bgp_info_free(binfo
);
217 if (binfo
->lock
== 1)
219 zlog_debug ("%s: unlocked to 1", __func__
);
220 zlog_backtrace (LOG_DEBUG
);
227 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
229 struct bgp_info
*top
;
241 peer_lock(ri
->peer
); /* bgp_info peer reference */
244 /* Do the actual removal of info from RIB, for use by bgp_process
245 completion callback *only* */
246 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
249 ri
->next
->prev
= ri
->prev
;
251 ri
->prev
->next
= ri
->next
;
255 bgp_info_mpath_dequeue(ri
);
260 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
262 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
263 /* set of previous already took care of pcount */
264 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
267 /* undo the effects of a previous call to bgp_info_delete; typically
268 called when a route is deleted and then quickly re-added before the
269 deletion has been processed */
270 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
272 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
273 /* unset of previous already took care of pcount */
274 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
277 /* Adjust pcount as required */
278 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
280 struct bgp_table
*table
;
282 assert(rn
&& bgp_node_table(rn
));
283 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
285 table
= bgp_node_table(rn
);
287 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
290 if (!BGP_INFO_COUNTABLE(ri
)
291 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
293 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
295 /* slight hack, but more robust against errors. */
296 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
297 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
300 "%s: Asked to decrement 0 prefix count for peer %s",
301 __func__
, ri
->peer
->host
);
302 zlog_backtrace(LOG_WARNING
);
303 zlog_warn("%s: Please report to Quagga bugzilla",
306 } else if (BGP_INFO_COUNTABLE(ri
)
307 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
308 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
309 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
313 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
315 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
318 /* Set/unset bgp_info flags, adjusting any other state as needed.
319 * This is here primarily to keep prefix-count in check.
321 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, u_int32_t flag
)
323 SET_FLAG(ri
->flags
, flag
);
325 /* early bath if we know it's not a flag that changes countability state
327 if (!CHECK_FLAG(flag
,
328 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
331 bgp_pcount_adjust(rn
, ri
);
334 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
337 UNSET_FLAG(ri
->flags
, flag
);
339 /* early bath if we know it's not a flag that changes countability state
341 if (!CHECK_FLAG(flag
,
342 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
345 bgp_pcount_adjust(rn
, ri
);
348 /* Get MED value. If MED value is missing and "bgp bestpath
349 missing-as-worst" is specified, treat it as the worst value. */
350 static u_int32_t
bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
352 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
355 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
362 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
364 if (ri
->addpath_rx_id
)
365 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
368 sprintf(buf
, "path %s", ri
->peer
->host
);
371 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
373 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
374 struct bgp_info
*exist
, int *paths_eq
,
375 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
376 char *pfx_buf
, afi_t afi
, safi_t safi
)
378 struct attr
*newattr
, *existattr
;
379 bgp_peer_sort_t new_sort
;
380 bgp_peer_sort_t exist_sort
;
382 u_int32_t exist_pref
;
385 u_int32_t new_weight
;
386 u_int32_t exist_weight
;
387 uint32_t newm
, existm
;
388 struct in_addr new_id
;
389 struct in_addr exist_id
;
392 int internal_as_route
;
395 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
396 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
397 u_int32_t new_mm_seq
;
398 u_int32_t exist_mm_seq
;
405 zlog_debug("%s: new is NULL", pfx_buf
);
410 bgp_info_path_with_addpath_rx_str(new, new_buf
);
414 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
420 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
421 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
422 pfx_buf
, new_buf
, new->flags
, exist_buf
,
427 existattr
= exist
->attr
;
429 /* For EVPN routes, we cannot just go by local vs remote, we have to
430 * look at the MAC mobility sequence number, if present.
432 if (safi
== SAFI_EVPN
) {
433 /* This is an error condition described in RFC 7432 Section
435 * states that in this scenario "the PE MUST alert the operator"
437 * does not state what other action to take. In order to provide
439 * consistency in this scenario we are going to prefer the path
443 if (newattr
->sticky
!= existattr
->sticky
) {
445 prefix2str(&new->net
->p
, pfx_buf
,
447 * PREFIX2STR_BUFFER
);
448 bgp_info_path_with_addpath_rx_str(new, new_buf
);
449 bgp_info_path_with_addpath_rx_str(exist
,
453 if (newattr
->sticky
&& !existattr
->sticky
) {
455 "%s: %s wins over %s due to sticky MAC flag",
456 pfx_buf
, new_buf
, exist_buf
);
460 if (!newattr
->sticky
&& existattr
->sticky
) {
462 "%s: %s loses to %s due to sticky MAC flag",
463 pfx_buf
, new_buf
, exist_buf
);
468 new_mm_seq
= mac_mobility_seqnum(newattr
);
469 exist_mm_seq
= mac_mobility_seqnum(existattr
);
471 if (new_mm_seq
> exist_mm_seq
) {
474 "%s: %s wins over %s due to MM seq %u > %u",
475 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
480 if (new_mm_seq
< exist_mm_seq
) {
483 "%s: %s loses to %s due to MM seq %u < %u",
484 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
490 /* 1. Weight check. */
491 new_weight
= exist_weight
= 0;
493 new_weight
= newattr
->weight
;
494 exist_weight
= existattr
->weight
;
496 if (new_weight
> exist_weight
) {
498 zlog_debug("%s: %s wins over %s due to weight %d > %d",
499 pfx_buf
, new_buf
, exist_buf
, new_weight
,
504 if (new_weight
< exist_weight
) {
506 zlog_debug("%s: %s loses to %s due to weight %d < %d",
507 pfx_buf
, new_buf
, exist_buf
, new_weight
,
512 /* 2. Local preference check. */
513 new_pref
= exist_pref
= bgp
->default_local_pref
;
515 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
516 new_pref
= newattr
->local_pref
;
517 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
518 exist_pref
= existattr
->local_pref
;
520 if (new_pref
> exist_pref
) {
523 "%s: %s wins over %s due to localpref %d > %d",
524 pfx_buf
, new_buf
, exist_buf
, new_pref
,
529 if (new_pref
< exist_pref
) {
532 "%s: %s loses to %s due to localpref %d < %d",
533 pfx_buf
, new_buf
, exist_buf
, new_pref
,
538 /* 3. Local route check. We prefer:
540 * - BGP_ROUTE_AGGREGATE
541 * - BGP_ROUTE_REDISTRIBUTE
543 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
546 "%s: %s wins over %s due to preferred BGP_ROUTE type",
547 pfx_buf
, new_buf
, exist_buf
);
551 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
554 "%s: %s loses to %s due to preferred BGP_ROUTE type",
555 pfx_buf
, new_buf
, exist_buf
);
559 /* 4. AS path length check. */
560 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
561 int exist_hops
= aspath_count_hops(existattr
->aspath
);
562 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
564 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
567 aspath_hops
= aspath_count_hops(newattr
->aspath
);
568 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
570 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
573 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
574 pfx_buf
, new_buf
, exist_buf
,
576 (exist_hops
+ exist_confeds
));
580 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
583 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
584 pfx_buf
, new_buf
, exist_buf
,
586 (exist_hops
+ exist_confeds
));
590 int newhops
= aspath_count_hops(newattr
->aspath
);
592 if (newhops
< exist_hops
) {
595 "%s: %s wins over %s due to aspath hopcount %d < %d",
596 pfx_buf
, new_buf
, exist_buf
,
597 newhops
, exist_hops
);
601 if (newhops
> exist_hops
) {
604 "%s: %s loses to %s due to aspath hopcount %d > %d",
605 pfx_buf
, new_buf
, exist_buf
,
606 newhops
, exist_hops
);
612 /* 5. Origin check. */
613 if (newattr
->origin
< existattr
->origin
) {
615 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
616 pfx_buf
, new_buf
, exist_buf
,
617 bgp_origin_long_str
[newattr
->origin
],
618 bgp_origin_long_str
[existattr
->origin
]);
622 if (newattr
->origin
> existattr
->origin
) {
624 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
625 pfx_buf
, new_buf
, exist_buf
,
626 bgp_origin_long_str
[newattr
->origin
],
627 bgp_origin_long_str
[existattr
->origin
]);
632 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
633 && aspath_count_hops(existattr
->aspath
) == 0);
634 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
635 && aspath_count_confeds(existattr
->aspath
) > 0
636 && aspath_count_hops(newattr
->aspath
) == 0
637 && aspath_count_hops(existattr
->aspath
) == 0);
639 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
640 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
641 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
642 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
643 || internal_as_route
) {
644 new_med
= bgp_med_value(new->attr
, bgp
);
645 exist_med
= bgp_med_value(exist
->attr
, bgp
);
647 if (new_med
< exist_med
) {
650 "%s: %s wins over %s due to MED %d < %d",
651 pfx_buf
, new_buf
, exist_buf
, new_med
,
656 if (new_med
> exist_med
) {
659 "%s: %s loses to %s due to MED %d > %d",
660 pfx_buf
, new_buf
, exist_buf
, new_med
,
666 /* 7. Peer type check. */
667 new_sort
= new->peer
->sort
;
668 exist_sort
= exist
->peer
->sort
;
670 if (new_sort
== BGP_PEER_EBGP
671 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
674 "%s: %s wins over %s due to eBGP peer > iBGP peer",
675 pfx_buf
, new_buf
, exist_buf
);
679 if (exist_sort
== BGP_PEER_EBGP
680 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
683 "%s: %s loses to %s due to iBGP peer < eBGP peer",
684 pfx_buf
, new_buf
, exist_buf
);
688 /* 8. IGP metric check. */
692 newm
= new->extra
->igpmetric
;
694 existm
= exist
->extra
->igpmetric
;
699 "%s: %s wins over %s due to IGP metric %d < %d",
700 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
707 "%s: %s loses to %s due to IGP metric %d > %d",
708 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
712 /* 9. Same IGP metric. Compare the cluster list length as
713 representative of IGP hops metric. Rewrite the metric value
714 pair (newm, existm) with the cluster list length. Prefer the
715 path with smaller cluster list length. */
716 if (newm
== existm
) {
717 if (peer_sort(new->peer
) == BGP_PEER_IBGP
718 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
719 && (mpath_cfg
== NULL
721 mpath_cfg
->ibgp_flags
,
722 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
723 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
724 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
729 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
730 pfx_buf
, new_buf
, exist_buf
,
738 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
739 pfx_buf
, new_buf
, exist_buf
,
746 /* 10. confed-external vs. confed-internal */
747 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
748 if (new_sort
== BGP_PEER_CONFED
749 && exist_sort
== BGP_PEER_IBGP
) {
752 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
753 pfx_buf
, new_buf
, exist_buf
);
757 if (exist_sort
== BGP_PEER_CONFED
758 && new_sort
== BGP_PEER_IBGP
) {
761 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
762 pfx_buf
, new_buf
, exist_buf
);
767 /* 11. Maximum path check. */
768 if (newm
== existm
) {
769 /* If one path has a label but the other does not, do not treat
770 * them as equals for multipath
772 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
))
774 && bgp_is_valid_label(&exist
->extra
->label
))) {
777 "%s: %s and %s cannot be multipath, one has a label while the other does not",
778 pfx_buf
, new_buf
, exist_buf
);
779 } else if (bgp_flag_check(bgp
,
780 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
783 * For the two paths, all comparison steps till IGP
785 * have succeeded - including AS_PATH hop count. Since
787 * bestpath as-path multipath-relax' knob is on, we
789 * an exact match of AS_PATH. Thus, mark the paths are
791 * That will trigger both these paths to get into the
799 "%s: %s and %s are equal via multipath-relax",
800 pfx_buf
, new_buf
, exist_buf
);
801 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
802 if (aspath_cmp(new->attr
->aspath
,
803 exist
->attr
->aspath
)) {
808 "%s: %s and %s are equal via matching aspaths",
809 pfx_buf
, new_buf
, exist_buf
);
811 } else if (new->peer
->as
== exist
->peer
->as
) {
816 "%s: %s and %s are equal via same remote-as",
817 pfx_buf
, new_buf
, exist_buf
);
821 * TODO: If unequal cost ibgp multipath is enabled we can
822 * mark the paths as equal here instead of returning
827 "%s: %s wins over %s after IGP metric comparison",
828 pfx_buf
, new_buf
, exist_buf
);
831 "%s: %s loses to %s after IGP metric comparison",
832 pfx_buf
, new_buf
, exist_buf
);
837 /* 12. If both paths are external, prefer the path that was received
838 first (the oldest one). This step minimizes route-flap, since a
839 newer path won't displace an older one, even if it was the
840 preferred route based on the additional decision criteria below. */
841 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
842 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
843 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
846 "%s: %s wins over %s due to oldest external",
847 pfx_buf
, new_buf
, exist_buf
);
851 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
854 "%s: %s loses to %s due to oldest external",
855 pfx_buf
, new_buf
, exist_buf
);
860 /* 13. Router-ID comparision. */
861 /* If one of the paths is "stale", the corresponding peer router-id will
862 * be 0 and would always win over the other path. If originator id is
863 * used for the comparision, it will decide which path is better.
865 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
866 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
868 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
869 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
870 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
872 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
874 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
877 "%s: %s wins over %s due to Router-ID comparison",
878 pfx_buf
, new_buf
, exist_buf
);
882 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
885 "%s: %s loses to %s due to Router-ID comparison",
886 pfx_buf
, new_buf
, exist_buf
);
890 /* 14. Cluster length comparision. */
891 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
892 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
894 if (new_cluster
< exist_cluster
) {
897 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
898 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
903 if (new_cluster
> exist_cluster
) {
906 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
907 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
912 /* 15. Neighbor address comparision. */
913 /* Do this only if neither path is "stale" as stale paths do not have
914 * valid peer information (as the connection may or may not be up).
916 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
919 "%s: %s wins over %s due to latter path being STALE",
920 pfx_buf
, new_buf
, exist_buf
);
924 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
927 "%s: %s loses to %s due to former path being STALE",
928 pfx_buf
, new_buf
, exist_buf
);
932 /* locally configured routes to advertise do not have su_remote */
933 if (new->peer
->su_remote
== NULL
)
935 if (exist
->peer
->su_remote
== NULL
)
938 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
943 "%s: %s loses to %s due to Neighor IP comparison",
944 pfx_buf
, new_buf
, exist_buf
);
951 "%s: %s wins over %s due to Neighor IP comparison",
952 pfx_buf
, new_buf
, exist_buf
);
957 zlog_debug("%s: %s wins over %s due to nothing left to compare",
958 pfx_buf
, new_buf
, exist_buf
);
963 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
964 * is preferred, or 0 if they are the same (usually will only occur if
965 * multipath is enabled
966 * This version is compatible with */
967 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
968 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
973 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
987 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
988 struct attr
*attr
, afi_t afi
,
991 struct bgp_filter
*filter
;
993 filter
= &peer
->filter
[afi
][safi
];
995 #define FILTER_EXIST_WARN(F, f, filter) \
996 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
997 zlog_warn("%s: Could not find configured input %s-list %s!", \
998 peer->host, #f, F##_IN_NAME(filter));
1000 if (DISTRIBUTE_IN_NAME(filter
)) {
1001 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1003 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1007 if (PREFIX_LIST_IN_NAME(filter
)) {
1008 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1010 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1014 if (FILTER_LIST_IN_NAME(filter
)) {
1015 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1017 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1022 return FILTER_PERMIT
;
1023 #undef FILTER_EXIST_WARN
1026 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1027 struct attr
*attr
, afi_t afi
,
1030 struct bgp_filter
*filter
;
1032 filter
= &peer
->filter
[afi
][safi
];
1034 #define FILTER_EXIST_WARN(F, f, filter) \
1035 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1036 zlog_warn("%s: Could not find configured output %s-list %s!", \
1037 peer->host, #f, F##_OUT_NAME(filter));
1039 if (DISTRIBUTE_OUT_NAME(filter
)) {
1040 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1042 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1046 if (PREFIX_LIST_OUT_NAME(filter
)) {
1047 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1049 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1054 if (FILTER_LIST_OUT_NAME(filter
)) {
1055 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1057 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1062 return FILTER_PERMIT
;
1063 #undef FILTER_EXIST_WARN
1066 /* If community attribute includes no_export then return 1. */
1067 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1069 if (attr
->community
) {
1070 /* NO_ADVERTISE check. */
1071 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1074 /* NO_EXPORT check. */
1075 if (peer
->sort
== BGP_PEER_EBGP
1076 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1079 /* NO_EXPORT_SUBCONFED check. */
1080 if (peer
->sort
== BGP_PEER_EBGP
1081 || peer
->sort
== BGP_PEER_CONFED
)
1082 if (community_include(attr
->community
,
1083 COMMUNITY_NO_EXPORT_SUBCONFED
))
1089 /* Route reflection loop check. */
1090 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1092 struct in_addr cluster_id
;
1094 if (attr
->cluster
) {
1095 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1096 cluster_id
= peer
->bgp
->cluster_id
;
1098 cluster_id
= peer
->bgp
->router_id
;
1100 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1106 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1107 struct attr
*attr
, afi_t afi
, safi_t safi
,
1108 const char *rmap_name
)
1110 struct bgp_filter
*filter
;
1111 struct bgp_info info
;
1112 route_map_result_t ret
;
1113 struct route_map
*rmap
= NULL
;
1115 filter
= &peer
->filter
[afi
][safi
];
1117 /* Apply default weight value. */
1118 if (peer
->weight
[afi
][safi
])
1119 attr
->weight
= peer
->weight
[afi
][safi
];
1122 rmap
= route_map_lookup_by_name(rmap_name
);
1127 if (ROUTE_MAP_IN_NAME(filter
)) {
1128 rmap
= ROUTE_MAP_IN(filter
);
1135 /* Route map apply. */
1137 /* Duplicate current value to new strucutre for modification. */
1141 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1143 /* Apply BGP route map to the attribute. */
1144 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1146 peer
->rmap_type
= 0;
1148 if (ret
== RMAP_DENYMATCH
) {
1149 /* Free newly generated AS path and community by
1151 bgp_attr_flush(attr
);
1158 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1159 struct attr
*attr
, afi_t afi
, safi_t safi
,
1160 const char *rmap_name
)
1162 struct bgp_filter
*filter
;
1163 struct bgp_info info
;
1164 route_map_result_t ret
;
1165 struct route_map
*rmap
= NULL
;
1167 filter
= &peer
->filter
[afi
][safi
];
1169 /* Apply default weight value. */
1170 if (peer
->weight
[afi
][safi
])
1171 attr
->weight
= peer
->weight
[afi
][safi
];
1174 rmap
= route_map_lookup_by_name(rmap_name
);
1179 if (ROUTE_MAP_OUT_NAME(filter
)) {
1180 rmap
= ROUTE_MAP_OUT(filter
);
1187 /* Route map apply. */
1189 /* Duplicate current value to new strucutre for modification. */
1193 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1195 /* Apply BGP route map to the attribute. */
1196 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1198 peer
->rmap_type
= 0;
1200 if (ret
== RMAP_DENYMATCH
)
1201 /* caller has multiple error paths with bgp_attr_flush()
1208 /* If this is an EBGP peer with remove-private-AS */
1209 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1210 struct peer
*peer
, struct attr
*attr
)
1212 if (peer
->sort
== BGP_PEER_EBGP
1213 && (peer_af_flag_check(peer
, afi
, safi
,
1214 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1215 || peer_af_flag_check(peer
, afi
, safi
,
1216 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1217 || peer_af_flag_check(peer
, afi
, safi
,
1218 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1219 || peer_af_flag_check(peer
, afi
, safi
,
1220 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1221 // Take action on the entire aspath
1222 if (peer_af_flag_check(peer
, afi
, safi
,
1223 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1224 || peer_af_flag_check(peer
, afi
, safi
,
1225 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1226 if (peer_af_flag_check(
1228 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1229 attr
->aspath
= aspath_replace_private_asns(
1230 attr
->aspath
, bgp
->as
);
1232 // The entire aspath consists of private ASNs so create
1234 else if (aspath_private_as_check(attr
->aspath
))
1235 attr
->aspath
= aspath_empty_get();
1237 // There are some public and some private ASNs, remove
1240 attr
->aspath
= aspath_remove_private_asns(
1244 // 'all' was not specified so the entire aspath must be private
1246 // for us to do anything
1247 else if (aspath_private_as_check(attr
->aspath
)) {
1248 if (peer_af_flag_check(
1250 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1251 attr
->aspath
= aspath_replace_private_asns(
1252 attr
->aspath
, bgp
->as
);
1254 attr
->aspath
= aspath_empty_get();
1259 /* If this is an EBGP peer with as-override */
1260 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1261 struct peer
*peer
, struct attr
*attr
)
1263 if (peer
->sort
== BGP_PEER_EBGP
1264 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1265 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1266 attr
->aspath
= aspath_replace_specific_asn(
1267 attr
->aspath
, peer
->as
, bgp
->as
);
1271 void bgp_attr_add_gshut_community(struct attr
*attr
)
1273 struct community
*old
;
1274 struct community
*new;
1275 struct community
*merge
;
1276 struct community
*gshut
;
1278 old
= attr
->community
;
1279 gshut
= community_str2com("graceful-shutdown");
1282 merge
= community_merge(community_dup(old
), gshut
);
1284 if (old
->refcnt
== 0)
1285 community_free(old
);
1287 new = community_uniq_sort(merge
);
1288 community_free(merge
);
1290 new = community_dup(gshut
);
1293 community_free(gshut
);
1294 attr
->community
= new;
1295 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1297 /* When we add the graceful-shutdown community we must also
1298 * lower the local-preference */
1299 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1300 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1304 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1306 if (family
== AF_INET
)
1307 attr
->nexthop
.s_addr
= 0;
1308 if (family
== AF_INET6
)
1309 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1312 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1313 struct update_subgroup
*subgrp
, struct prefix
*p
,
1316 struct bgp_filter
*filter
;
1319 struct peer
*onlypeer
;
1321 struct attr
*riattr
;
1322 char buf
[PREFIX_STRLEN
];
1328 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1330 if (DISABLE_BGP_ANNOUNCE
)
1333 afi
= SUBGRP_AFI(subgrp
);
1334 safi
= SUBGRP_SAFI(subgrp
);
1335 peer
= SUBGRP_PEER(subgrp
);
1337 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1338 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1341 filter
= &peer
->filter
[afi
][safi
];
1342 bgp
= SUBGRP_INST(subgrp
);
1343 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1346 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1347 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1348 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1351 * direct and direct_ext type routes originate internally even
1352 * though they can have peer pointers that reference other
1355 prefix2str(p
, buf
, PREFIX_STRLEN
);
1356 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1362 /* With addpath we may be asked to TX all kinds of paths so make sure
1364 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1365 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1366 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1370 /* If this is not the bestpath then check to see if there is an enabled
1372 * feature that requires us to advertise it */
1373 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1374 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1379 /* Aggregate-address suppress check. */
1380 if (ri
->extra
&& ri
->extra
->suppress
)
1381 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1385 /* If it's labeled safi, make sure the route has a valid label. */
1386 if (safi
== SAFI_LABELED_UNICAST
) {
1387 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1388 if (!bgp_is_valid_label(&label
)) {
1389 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1390 zlog_debug("u%" PRIu64
":s%" PRIu64
1391 " %s/%d is filtered - no label (%p)",
1392 subgrp
->update_group
->id
, subgrp
->id
,
1393 inet_ntop(p
->family
, &p
->u
.prefix
,
1394 buf
, SU_ADDRSTRLEN
),
1395 p
->prefixlen
, &label
);
1400 /* Do not send back route to sender. */
1401 if (onlypeer
&& from
== onlypeer
) {
1405 /* Do not send the default route in the BGP table if the neighbor is
1406 * configured for default-originate */
1407 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1408 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1409 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1411 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1415 /* Transparency check. */
1416 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1417 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1422 /* If community is not disabled check the no-export and local. */
1423 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1424 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1426 "subgrpannouncecheck: community filter check fail");
1430 /* If the attribute has originator-id and it is same as remote
1432 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1433 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1434 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1436 "%s [Update:SEND] %s originator-id is same as "
1439 prefix2str(p
, buf
, sizeof(buf
)));
1443 /* ORF prefix-list filter check */
1444 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1445 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1446 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1447 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1448 if (peer
->orf_plist
[afi
][safi
]) {
1449 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1451 if (bgp_debug_update(NULL
, p
,
1452 subgrp
->update_group
, 0))
1454 "%s [Update:SEND] %s is filtered via ORF",
1462 /* Output filter check. */
1463 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1464 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1465 zlog_debug("%s [Update:SEND] %s is filtered",
1466 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1470 #ifdef BGP_SEND_ASPATH_CHECK
1471 /* AS path loop check. */
1472 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1473 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1475 "%s [Update:SEND] suppress announcement to peer AS %u "
1476 "that is part of AS path.",
1477 onlypeer
->host
, onlypeer
->as
);
1480 #endif /* BGP_SEND_ASPATH_CHECK */
1482 /* If we're a CONFED we need to loop check the CONFED ID too */
1483 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1484 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1485 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1487 "%s [Update:SEND] suppress announcement to peer AS %u"
1489 peer
->host
, bgp
->confed_id
);
1494 /* Route-Reflect check. */
1495 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1500 /* IBGP reflection check. */
1501 if (reflect
&& !samepeer_safe
) {
1502 /* A route from a Client peer. */
1503 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1504 PEER_FLAG_REFLECTOR_CLIENT
)) {
1505 /* Reflect to all the Non-Client peers and also to the
1506 Client peers other than the originator. Originator
1508 is already done. So there is noting to do. */
1509 /* no bgp client-to-client reflection check. */
1510 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1511 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1512 PEER_FLAG_REFLECTOR_CLIENT
))
1515 /* A route from a Non-client peer. Reflect to all other
1517 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1518 PEER_FLAG_REFLECTOR_CLIENT
))
1523 /* For modify attribute, copy it to temporary structure. */
1524 bgp_attr_dup(attr
, riattr
);
1526 /* If local-preference is not set. */
1527 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1528 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1529 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1530 attr
->local_pref
= bgp
->default_local_pref
;
1533 /* If originator-id is not set and the route is to be reflected,
1534 set the originator id */
1536 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1537 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1538 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1541 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1543 if (peer
->sort
== BGP_PEER_EBGP
1544 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1545 if (from
!= bgp
->peer_self
&& !transparent
1546 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1547 PEER_FLAG_MED_UNCHANGED
))
1549 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1552 /* Since the nexthop attribute can vary per peer, it is not explicitly
1554 * in announce check, only certain flags and length (or number of
1556 * -- for IPv6/MP_REACH) are set here in order to guide the update
1558 * code in setting the nexthop(s) on a per peer basis in
1560 * Typically, the source nexthop in the attribute is preserved but in
1562 * scenarios where we know it will always be overwritten, we reset the
1563 * nexthop to "0" in an attempt to achieve better Update packing. An
1564 * example of this is when a prefix from each of 2 IBGP peers needs to
1566 * announced to an EBGP peer (and they have the same attributes barring
1570 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1572 #define NEXTHOP_IS_V6 \
1573 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1574 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1575 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1576 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1578 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1580 * the peer (group) is configured to receive link-local nexthop
1582 * and it is available in the prefix OR we're not reflecting the route
1584 * the peer (group) to whom we're going to announce is on a shared
1586 * and this is either a self-originated route or the peer is EBGP.
1588 if (NEXTHOP_IS_V6
) {
1589 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1590 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1591 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1592 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1593 || (!reflect
&& peer
->shared_network
1594 && (from
== bgp
->peer_self
1595 || peer
->sort
== BGP_PEER_EBGP
))) {
1596 attr
->mp_nexthop_len
=
1597 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1600 /* Clear off link-local nexthop in source, whenever it is not
1602 * ensure more prefixes share the same attribute for
1605 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1606 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1607 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1610 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1611 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1613 /* Route map & unsuppress-map apply. */
1614 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1615 struct bgp_info info
;
1616 struct bgp_info_extra dummy_info_extra
;
1617 struct attr dummy_attr
;
1623 memcpy(&dummy_info_extra
, ri
->extra
,
1624 sizeof(struct bgp_info_extra
));
1625 info
.extra
= &dummy_info_extra
;
1628 /* don't confuse inbound and outbound setting */
1629 RESET_FLAG(attr
->rmap_change_flags
);
1632 * The route reflector is not allowed to modify the attributes
1633 * of the reflected IBGP routes unless explicitly allowed.
1635 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1636 && !bgp_flag_check(bgp
,
1637 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1638 bgp_attr_dup(&dummy_attr
, attr
);
1639 info
.attr
= &dummy_attr
;
1642 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1644 if (ri
->extra
&& ri
->extra
->suppress
)
1645 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1648 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1651 peer
->rmap_type
= 0;
1653 if (ret
== RMAP_DENYMATCH
) {
1654 bgp_attr_flush(attr
);
1659 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1660 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
1661 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1662 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1664 bgp_attr_add_gshut_community(attr
);
1668 /* After route-map has been applied, we check to see if the nexthop to
1669 * be carried in the attribute (that is used for the announcement) can
1670 * be cleared off or not. We do this in all cases where we would be
1671 * setting the nexthop to "ourselves". For IPv6, we only need to
1673 * the global nexthop here; the link-local nexthop would have been
1675 * already, and if not, it is required by the update formation code.
1676 * Also see earlier comments in this function.
1679 * If route-map has performed some operation on the nexthop or the peer
1680 * configuration says to pass it unchanged, we cannot reset the nexthop
1681 * here, so only attempt to do it if these aren't true. Note that the
1682 * route-map handler itself might have cleared the nexthop, if for
1684 * it is configured as 'peer-address'.
1686 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1687 riattr
->rmap_change_flags
)
1689 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1690 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1691 /* We can reset the nexthop, if setting (or forcing) it to
1693 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1694 PEER_FLAG_NEXTHOP_SELF
)
1695 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1696 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1698 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1699 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1700 subgroup_announce_reset_nhop(
1701 (peer_cap_enhe(peer
, afi
, safi
)
1705 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1706 /* Can also reset the nexthop if announcing to EBGP, but
1708 * no peer in the subgroup is on a shared subnet.
1709 * Note: 3rd party nexthop currently implemented for
1712 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1714 subgroup_announce_reset_nhop(
1715 (peer_cap_enhe(peer
, afi
, safi
)
1720 /* If IPv6/MP and nexthop does not have any override and happens
1722 * be a link-local address, reset it so that we don't pass along
1724 * source's link-local IPv6 address to recipients who may not be
1726 * the same interface.
1728 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1729 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1730 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1737 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1738 struct bgp_maxpaths_cfg
*mpath_cfg
,
1739 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1741 struct bgp_info
*new_select
;
1742 struct bgp_info
*old_select
;
1743 struct bgp_info
*ri
;
1744 struct bgp_info
*ri1
;
1745 struct bgp_info
*ri2
;
1746 struct bgp_info
*nextri
= NULL
;
1747 int paths_eq
, do_mpath
, debug
;
1748 struct list mp_list
;
1749 char pfx_buf
[PREFIX2STR_BUFFER
];
1750 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1752 bgp_mp_list_init(&mp_list
);
1754 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1756 debug
= bgp_debug_bestpath(&rn
->p
);
1759 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1761 /* bgp deterministic-med */
1763 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1765 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1766 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1767 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1769 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1770 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1772 if (BGP_INFO_HOLDDOWN(ri1
))
1774 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1775 if (ri1
->peer
->status
!= Established
)
1780 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1781 if (CHECK_FLAG(ri2
->flags
,
1782 BGP_INFO_DMED_CHECK
))
1784 if (BGP_INFO_HOLDDOWN(ri2
))
1787 && ri2
->peer
!= bgp
->peer_self
1790 PEER_STATUS_NSF_WAIT
))
1791 if (ri2
->peer
->status
1795 if (aspath_cmp_left(ri1
->attr
->aspath
,
1797 || aspath_cmp_left_confed(
1799 ri2
->attr
->aspath
)) {
1800 if (bgp_info_cmp(bgp
, ri2
,
1806 bgp_info_unset_flag(
1808 BGP_INFO_DMED_SELECTED
);
1814 BGP_INFO_DMED_CHECK
);
1818 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1819 bgp_info_set_flag(rn
, new_select
,
1820 BGP_INFO_DMED_SELECTED
);
1823 bgp_info_path_with_addpath_rx_str(new_select
,
1825 zlog_debug("%s: %s is the bestpath from AS %d",
1827 aspath_get_first_as(
1828 new_select
->attr
->aspath
));
1833 /* Check old selected route and new selected route. */
1836 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1838 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1841 if (BGP_INFO_HOLDDOWN(ri
)) {
1842 /* reap REMOVED routes, if needs be
1843 * selected route must stay for a while longer though
1845 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1846 && (ri
!= old_select
))
1847 bgp_info_reap(rn
, ri
);
1852 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1853 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1854 if (ri
->peer
->status
!= Established
)
1857 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1858 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1859 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1863 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1865 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1866 debug
, pfx_buf
, afi
, safi
)) {
1871 /* Now that we know which path is the bestpath see if any of the other
1873 * qualify as multipaths
1877 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1879 sprintf(path_buf
, "NONE");
1881 "%s: After path selection, newbest is %s oldbest was %s",
1883 old_select
? old_select
->peer
->host
: "NONE");
1886 if (do_mpath
&& new_select
) {
1887 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1891 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1893 if (ri
== new_select
) {
1896 "%s: %s is the bestpath, add to the multipath list",
1898 bgp_mp_list_add(&mp_list
, ri
);
1902 if (BGP_INFO_HOLDDOWN(ri
))
1905 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1906 && !CHECK_FLAG(ri
->peer
->sflags
,
1907 PEER_STATUS_NSF_WAIT
))
1908 if (ri
->peer
->status
!= Established
)
1911 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1914 "%s: %s has the same nexthop as the bestpath, skip it",
1919 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1920 debug
, pfx_buf
, afi
, safi
);
1925 "%s: %s is equivalent to the bestpath, add to the multipath list",
1927 bgp_mp_list_add(&mp_list
, ri
);
1932 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1933 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1934 bgp_mp_list_clear(&mp_list
);
1936 result
->old
= old_select
;
1937 result
->new = new_select
;
1943 * A new route/change in bestpath of an existing route. Evaluate the path
1944 * for advertisement to the subgroup.
1946 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1947 struct bgp_info
*selected
,
1948 struct bgp_node
*rn
,
1949 u_int32_t addpath_tx_id
)
1952 struct peer
*onlypeer
;
1958 afi
= SUBGRP_AFI(subgrp
);
1959 safi
= SUBGRP_SAFI(subgrp
);
1960 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1963 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1964 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1965 PEER_STATUS_ORF_WAIT_REFRESH
))
1968 memset(&attr
, 0, sizeof(struct attr
));
1969 /* It's initialized in bgp_announce_check() */
1971 /* Announcement to the subgroup. If the route is filtered withdraw it.
1974 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1975 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1977 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1978 selected
->addpath_tx_id
);
1981 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1983 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1990 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1991 * This is called at the end of route processing.
1993 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1995 struct bgp_info
*ri
;
1997 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1998 if (BGP_INFO_HOLDDOWN(ri
))
2000 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2001 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2006 * Has the route changed from the RIB's perspective? This is invoked only
2007 * if the route selection returns the same best route as earlier - to
2008 * determine if we need to update zebra or not.
2010 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2012 struct bgp_info
*mpinfo
;
2014 /* If this is multipath, check all selected paths for any nexthop change
2016 * attribute change. Some attribute changes (e.g., community) aren't of
2017 * relevance to the RIB, but we'll update zebra to ensure we handle the
2018 * case of BGP nexthop change. This is the behavior when the best path
2020 * an attribute change anyway.
2022 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2023 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2026 /* If this is multipath, check all selected paths for any nexthop change
2028 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2029 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2030 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2031 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2035 /* Nothing has changed from the RIB's perspective. */
2039 struct bgp_process_queue
{
2041 STAILQ_HEAD(, bgp_node
)pqueue
;
2042 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2044 unsigned int queued
;
2047 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2048 afi_t afi
, safi_t safi
)
2050 struct prefix
*p
= &rn
->p
;
2051 struct bgp_info
*new_select
;
2052 struct bgp_info
*old_select
;
2053 struct bgp_info_pair old_and_new
;
2055 /* Is it end of initial update? (after startup) */
2057 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2058 sizeof(bgp
->update_delay_zebra_resume_time
));
2060 bgp
->main_zebra_update_hold
= 0;
2061 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
2062 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
2063 if (bgp_fibupd_safi(safi
))
2064 bgp_zebra_announce_table(bgp
, afi
,
2067 bgp
->main_peers_update_hold
= 0;
2069 bgp_start_routeadv(bgp
);
2073 /* Best path selection. */
2074 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2076 old_select
= old_and_new
.old
;
2077 new_select
= old_and_new
.new;
2079 /* Do we need to allocate or free labels?
2080 * Right now, since we only deal with per-prefix labels, it is not
2081 * necessary to do this upon changes to best path except if the label
2084 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2087 || bgp_label_index_differs(new_select
, old_select
)
2088 || new_select
->sub_type
!= old_select
->sub_type
) {
2089 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2090 && new_select
->attr
->flag
2092 BGP_ATTR_PREFIX_SID
)
2093 && new_select
->attr
->label_index
2094 != BGP_INVALID_LABEL_INDEX
) {
2097 BGP_NODE_REGISTERED_FOR_LABEL
))
2098 bgp_unregister_for_label(rn
);
2099 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2101 bgp_set_valid_label(&rn
->local_label
);
2103 bgp_register_for_label(rn
, new_select
);
2105 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2106 bgp_unregister_for_label(rn
);
2108 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2109 bgp_unregister_for_label(rn
);
2112 /* If best route remains the same and this is not due to user-initiated
2113 * clear, see exactly what needs to be done.
2116 if (old_select
&& old_select
== new_select
2117 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2118 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2119 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2120 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2122 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2123 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2125 if (bgp_fibupd_safi(safi
)
2126 && !bgp_option_check(BGP_OPT_NO_FIB
)
2127 && new_select
->type
== ZEBRA_ROUTE_BGP
2128 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2129 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2132 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2133 bgp_zebra_clear_route_change_flags(rn
);
2135 /* If there is a change of interest to peers, reannounce the
2137 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2138 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2139 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2141 /* unicast routes must also be annouced to
2142 * labeled-unicast update-groups */
2143 if (safi
== SAFI_UNICAST
)
2144 group_announce_route(bgp
, afi
,
2145 SAFI_LABELED_UNICAST
, rn
,
2148 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2149 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2152 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2156 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2158 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2160 /* bestpath has changed; bump version */
2161 if (old_select
|| new_select
) {
2162 bgp_bump_version(rn
);
2164 if (!bgp
->t_rmap_def_originate_eval
) {
2168 update_group_refresh_default_originate_route_map
,
2169 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2170 &bgp
->t_rmap_def_originate_eval
);
2175 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2177 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2178 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2179 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2183 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2184 if (old_select
!= new_select
) {
2186 vnc_import_bgp_exterior_del_route(bgp
, p
,
2188 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2191 vnc_import_bgp_exterior_add_route(bgp
, p
,
2193 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2199 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2201 /* unicast routes must also be annouced to labeled-unicast update-groups
2203 if (safi
== SAFI_UNICAST
)
2204 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2208 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2209 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2210 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2211 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2212 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2213 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2215 /* Withdraw the route from the kernel. */
2216 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2217 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2218 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2219 bgp_zebra_withdraw(p
, old_select
, safi
);
2223 /* Clear any route change flags. */
2224 bgp_zebra_clear_route_change_flags(rn
);
2226 /* Reap old select bgp_info, if it has been removed */
2227 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2228 bgp_info_reap(rn
, old_select
);
2230 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2234 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2236 struct bgp_process_queue
*pqnode
= data
;
2237 struct bgp
*bgp
= pqnode
->bgp
;
2238 struct bgp_table
*table
;
2239 struct bgp_node
*rn
;
2242 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2243 bgp_process_main_one(bgp
, NULL
, 0, 0);
2244 /* should always have dedicated wq call */
2245 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2249 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2250 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2251 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2252 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2253 table
= bgp_node_table(rn
);
2254 /* note, new RNs may be added as part of processing */
2255 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2257 bgp_unlock_node(rn
);
2258 bgp_table_unlock(table
);
2264 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2266 struct bgp_process_queue
*pqnode
= data
;
2268 bgp_unlock(pqnode
->bgp
);
2270 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2273 void bgp_process_queue_init(void)
2275 if (!bm
->process_main_queue
) {
2276 bm
->process_main_queue
=
2277 work_queue_new(bm
->master
, "process_main_queue");
2279 if (!bm
->process_main_queue
) {
2280 zlog_err("%s: Failed to allocate work queue", __func__
);
2285 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2286 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2287 bm
->process_main_queue
->spec
.max_retries
= 0;
2288 bm
->process_main_queue
->spec
.hold
= 50;
2289 /* Use a higher yield value of 50ms for main queue processing */
2290 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2293 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2295 struct bgp_process_queue
*pqnode
;
2297 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
, sizeof(struct bgp_process_queue
));
2299 /* unlocked in bgp_processq_del */
2300 pqnode
->bgp
= bgp_lock(bgp
);
2301 STAILQ_INIT(&pqnode
->pqueue
);
2306 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2308 #define ARBITRARY_PROCESS_QLEN 10000
2309 struct work_queue
*wq
= bm
->process_main_queue
;
2310 struct bgp_process_queue
*pqnode
;
2311 int pqnode_reuse
= 0;
2313 /* already scheduled for processing? */
2314 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2320 /* Add route nodes to an existing work queue item until reaching the
2321 limit only if is from the same BGP view and it's not an EOIU marker */
2322 if (work_queue_item_count(wq
)) {
2323 struct work_queue_item
*item
= work_queue_last_item(wq
);
2324 pqnode
= item
->data
;
2326 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
) ||
2327 pqnode
->bgp
!= bgp
|| pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2328 pqnode
= bgp_processq_alloc(bgp
);
2332 pqnode
= bgp_processq_alloc(bgp
);
2333 /* all unlocked in bgp_process_wq */
2334 bgp_table_lock(bgp_node_table(rn
));
2336 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2339 /* can't be enqueued twice */
2340 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2341 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2345 work_queue_add(wq
, pqnode
);
2350 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2352 struct bgp_process_queue
*pqnode
;
2354 if (bm
->process_main_queue
== NULL
)
2357 pqnode
= bgp_processq_alloc(bgp
);
2359 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2360 work_queue_add(bm
->process_main_queue
, pqnode
);
2363 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2367 peer
= THREAD_ARG(thread
);
2368 peer
->t_pmax_restart
= NULL
;
2370 if (bgp_debug_neighbor_events(peer
))
2372 "%s Maximum-prefix restart timer expired, restore peering",
2375 peer_clear(peer
, NULL
);
2380 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2384 iana_safi_t pkt_safi
;
2386 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2389 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2390 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2391 PEER_STATUS_PREFIX_LIMIT
)
2396 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2398 afi_safi_print(afi
, safi
), peer
->host
,
2399 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2400 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2402 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2403 PEER_FLAG_MAX_PREFIX_WARNING
))
2406 /* Convert AFI, SAFI to values for packet. */
2407 pkt_afi
= afi_int2iana(afi
);
2408 pkt_safi
= safi_int2iana(safi
);
2412 ndata
[0] = (pkt_afi
>> 8);
2414 ndata
[2] = pkt_safi
;
2415 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2416 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2417 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2418 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2420 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2421 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2422 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2426 /* Dynamic peers will just close their connection. */
2427 if (peer_dynamic_neighbor(peer
))
2430 /* restart timer start */
2431 if (peer
->pmax_restart
[afi
][safi
]) {
2432 peer
->v_pmax_restart
=
2433 peer
->pmax_restart
[afi
][safi
] * 60;
2435 if (bgp_debug_neighbor_events(peer
))
2437 "%s Maximum-prefix restart timer started for %d secs",
2438 peer
->host
, peer
->v_pmax_restart
);
2440 BGP_TIMER_ON(peer
->t_pmax_restart
,
2441 bgp_maximum_prefix_restart_timer
,
2442 peer
->v_pmax_restart
);
2447 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2448 PEER_STATUS_PREFIX_LIMIT
);
2450 if (peer
->pcount
[afi
][safi
]
2451 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2452 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2453 PEER_STATUS_PREFIX_THRESHOLD
)
2458 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2459 afi_safi_print(afi
, safi
), peer
->host
,
2460 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2461 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2462 PEER_STATUS_PREFIX_THRESHOLD
);
2464 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2465 PEER_STATUS_PREFIX_THRESHOLD
);
2469 /* Unconditionally remove the route from the RIB, without taking
2470 * damping into consideration (eg, because the session went down)
2472 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2473 afi_t afi
, safi_t safi
)
2475 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2477 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2478 bgp_info_delete(rn
, ri
); /* keep historical info */
2480 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2483 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2484 struct peer
*peer
, afi_t afi
, safi_t safi
,
2485 struct prefix_rd
*prd
)
2487 int status
= BGP_DAMP_NONE
;
2489 /* apply dampening, if result is suppressed, we'll be retaining
2490 * the bgp_info in the RIB for historical reference.
2492 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2493 && peer
->sort
== BGP_PEER_EBGP
)
2494 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2495 == BGP_DAMP_SUPPRESSED
) {
2496 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2502 if (safi
== SAFI_MPLS_VPN
) {
2503 struct bgp_node
*prn
= NULL
;
2504 struct bgp_table
*table
= NULL
;
2506 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2507 (struct prefix
*)prd
);
2509 table
= (struct bgp_table
*)(prn
->info
);
2511 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2512 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2514 bgp_unlock_node(prn
);
2516 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2517 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2519 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2520 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2526 /* If this is an EVPN route, process for un-import. */
2527 if (safi
== SAFI_EVPN
)
2528 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2530 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2533 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2534 struct peer
*peer
, struct attr
*attr
,
2535 struct bgp_node
*rn
)
2537 struct bgp_info
*new;
2539 /* Make new BGP info. */
2540 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2542 new->instance
= instance
;
2543 new->sub_type
= sub_type
;
2546 new->uptime
= bgp_clock();
2548 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2552 static void overlay_index_update(struct attr
*attr
,
2553 struct eth_segment_id
*eth_s_id
,
2554 union gw_addr
*gw_ip
)
2559 if (eth_s_id
== NULL
) {
2560 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2561 sizeof(struct eth_segment_id
));
2563 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2564 sizeof(struct eth_segment_id
));
2566 if (gw_ip
== NULL
) {
2567 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2569 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2570 sizeof(union gw_addr
));
2574 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2575 struct eth_segment_id
*eth_s_id
,
2576 union gw_addr
*gw_ip
)
2578 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2579 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2582 if (afi
!= AFI_L2VPN
)
2585 memset(&temp
, 0, 16);
2586 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2587 info_gw_ip
= (union gw_addr
*)&temp
;
2588 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2591 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2592 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2595 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2597 info_gw_ip_remote
= gw_ip
;
2598 if (eth_s_id
== NULL
)
2599 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2601 info_eth_s_id_remote
= eth_s_id
;
2602 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2604 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2605 sizeof(struct eth_segment_id
));
2608 /* Check if received nexthop is valid or not. */
2609 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2614 /* Only validated for unicast and multicast currently. */
2615 /* Also valid for EVPN where the nexthop is an IP address. */
2616 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2619 /* If NEXT_HOP is present, validate it. */
2620 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2621 if (attr
->nexthop
.s_addr
== 0
2622 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2623 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2627 /* If MP_NEXTHOP is present, validate it. */
2628 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2629 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2630 * it is not an IPv6 link-local address.
2632 if (attr
->mp_nexthop_len
) {
2633 switch (attr
->mp_nexthop_len
) {
2634 case BGP_ATTR_NHLEN_IPV4
:
2635 case BGP_ATTR_NHLEN_VPNV4
:
2636 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2637 || IPV4_CLASS_DE(ntohl(
2638 attr
->mp_nexthop_global_in
.s_addr
))
2639 || bgp_nexthop_self(bgp
,
2640 attr
->mp_nexthop_global_in
));
2643 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2644 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2645 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2646 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2647 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2648 || IN6_IS_ADDR_MULTICAST(
2649 &attr
->mp_nexthop_global
));
2661 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2662 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2663 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2664 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2667 int aspath_loop_count
= 0;
2668 struct bgp_node
*rn
;
2670 struct attr new_attr
;
2671 struct attr
*attr_new
;
2672 struct bgp_info
*ri
;
2673 struct bgp_info
*new;
2675 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2678 int do_loop_check
= 1;
2679 int has_valid_label
= 0;
2681 int vnc_implicit_withdraw
= 0;
2685 memset(&new_attr
, 0, sizeof(struct attr
));
2686 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2687 new_attr
.label
= MPLS_INVALID_LABEL
;
2690 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2691 has_valid_label
= bgp_is_valid_label(label
);
2693 if (has_valid_label
)
2694 sprintf(label_buf
, "label %u", label_pton(label
));
2696 /* When peer's soft reconfiguration enabled. Record input packet in
2699 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2700 && peer
!= bgp
->peer_self
)
2701 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2703 /* Check previously received route. */
2704 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2705 if (ri
->peer
== peer
&& ri
->type
== type
2706 && ri
->sub_type
== sub_type
2707 && ri
->addpath_rx_id
== addpath_id
)
2710 /* AS path local-as loop check. */
2711 if (peer
->change_local_as
) {
2712 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2713 aspath_loop_count
= 1;
2715 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2716 > aspath_loop_count
) {
2717 reason
= "as-path contains our own AS;";
2722 /* If the peer is configured for "allowas-in origin" and the last ASN in
2724 * as-path is our ASN then we do not need to call aspath_loop_check
2726 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2727 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2730 /* AS path loop check. */
2731 if (do_loop_check
) {
2732 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2733 > peer
->allowas_in
[afi
][safi
]
2734 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2735 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2736 > peer
->allowas_in
[afi
][safi
])) {
2737 reason
= "as-path contains our own AS;";
2742 /* Route reflector originator ID check. */
2743 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2744 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2745 reason
= "originator is us;";
2749 /* Route reflector cluster ID check. */
2750 if (bgp_cluster_filter(peer
, attr
)) {
2751 reason
= "reflected from the same cluster;";
2755 /* Apply incoming filter. */
2756 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2761 bgp_attr_dup(&new_attr
, attr
);
2763 /* Apply incoming route-map.
2764 * NB: new_attr may now contain newly allocated values from route-map
2766 * commands, so we need bgp_attr_flush in the error paths, until we
2768 * the attr (which takes over the memory references) */
2769 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2771 reason
= "route-map;";
2772 bgp_attr_flush(&new_attr
);
2776 if (peer
->sort
== BGP_PEER_EBGP
) {
2778 /* If we receive the graceful-shutdown community from an eBGP peer we
2779 * must lower local-preference */
2780 if (new_attr
.community
&&
2781 community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2782 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2783 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2785 /* If graceful-shutdown is configured then add the GSHUT community to
2786 * all paths received from eBGP peers */
2787 } else if (bgp_flag_check(peer
->bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2788 bgp_attr_add_gshut_community(&new_attr
);
2792 /* next hop check. */
2793 if (bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2794 reason
= "martian or self next-hop;";
2795 bgp_attr_flush(&new_attr
);
2799 attr_new
= bgp_attr_intern(&new_attr
);
2801 /* If the update is implicit withdraw. */
2803 ri
->uptime
= bgp_clock();
2804 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2806 /* Same attribute comes in. */
2807 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2808 && attrhash_cmp(ri
->attr
, attr_new
)
2809 && (!has_valid_label
2810 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2813 && (overlay_index_equal(
2814 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2815 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2816 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2817 BGP_CONFIG_DAMPENING
)
2818 && peer
->sort
== BGP_PEER_EBGP
2819 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2820 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2821 bgp_debug_rdpfxpath2str(
2822 afi
, safi
, prd
, p
, label
,
2823 addpath_id
? 1 : 0, addpath_id
,
2824 pfx_buf
, sizeof(pfx_buf
));
2825 zlog_debug("%s rcvd %s", peer
->host
,
2829 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2830 != BGP_DAMP_SUPPRESSED
) {
2831 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2833 bgp_process(bgp
, rn
, afi
, safi
);
2835 } else /* Duplicate - odd */
2837 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2838 if (!peer
->rcvd_attr_printed
) {
2840 "%s rcvd UPDATE w/ attr: %s",
2842 peer
->rcvd_attr_str
);
2843 peer
->rcvd_attr_printed
= 1;
2846 bgp_debug_rdpfxpath2str(
2847 afi
, safi
, prd
, p
, label
,
2848 addpath_id
? 1 : 0, addpath_id
,
2849 pfx_buf
, sizeof(pfx_buf
));
2851 "%s rcvd %s...duplicate ignored",
2852 peer
->host
, pfx_buf
);
2855 /* graceful restart STALE flag unset. */
2856 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2857 bgp_info_unset_flag(rn
, ri
,
2859 bgp_process(bgp
, rn
, afi
, safi
);
2863 bgp_unlock_node(rn
);
2864 bgp_attr_unintern(&attr_new
);
2869 /* Withdraw/Announce before we fully processed the withdraw */
2870 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2871 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2872 bgp_debug_rdpfxpath2str(
2873 afi
, safi
, prd
, p
, label
,
2874 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2877 "%s rcvd %s, flapped quicker than processing",
2878 peer
->host
, pfx_buf
);
2881 bgp_info_restore(rn
, ri
);
2884 /* Received Logging. */
2885 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2886 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2887 addpath_id
? 1 : 0, addpath_id
,
2888 pfx_buf
, sizeof(pfx_buf
));
2889 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2892 /* graceful restart STALE flag unset. */
2893 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2894 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2896 /* The attribute is changed. */
2897 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2899 /* implicit withdraw, decrement aggregate and pcount here.
2900 * only if update is accepted, they'll increment below.
2902 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2904 /* Update bgp route dampening information. */
2905 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2906 && peer
->sort
== BGP_PEER_EBGP
) {
2907 /* This is implicit withdraw so we should update
2910 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2911 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2914 if (safi
== SAFI_MPLS_VPN
) {
2915 struct bgp_node
*prn
= NULL
;
2916 struct bgp_table
*table
= NULL
;
2918 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2919 (struct prefix
*)prd
);
2921 table
= (struct bgp_table
*)(prn
->info
);
2923 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2924 bgp
, prd
, table
, p
, ri
);
2926 bgp_unlock_node(prn
);
2928 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2929 && (safi
== SAFI_UNICAST
)) {
2930 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2932 * Implicit withdraw case.
2934 ++vnc_implicit_withdraw
;
2935 vnc_import_bgp_del_route(bgp
, p
, ri
);
2936 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2941 /* Special handling for EVPN update of an existing route. If the
2942 * extended community attribute has changed, we need to
2944 * the route using its existing extended community. It will be
2945 * subsequently processed for import with the new extended
2948 if (safi
== SAFI_EVPN
&& !same_attr
) {
2950 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2952 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2955 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2956 attr_new
->ecommunity
);
2958 if (bgp_debug_update(peer
, p
, NULL
, 1))
2960 "Change in EXT-COMM, existing %s new %s",
2962 ri
->attr
->ecommunity
),
2964 attr_new
->ecommunity
));
2965 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2971 /* Update to new attribute. */
2972 bgp_attr_unintern(&ri
->attr
);
2973 ri
->attr
= attr_new
;
2975 /* Update MPLS label */
2976 if (has_valid_label
) {
2977 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2979 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2983 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2984 && (safi
== SAFI_UNICAST
)) {
2985 if (vnc_implicit_withdraw
) {
2987 * Add back the route with its new attributes
2989 * The route is still selected, until the route
2991 * queued by bgp_process actually runs. We have
2993 * update to the VNC side immediately to avoid
2995 * configuration changes (e.g., route-map
2997 * trigger re-importation of the entire RIB.
2999 vnc_import_bgp_add_route(bgp
, p
, ri
);
3000 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3004 /* Update Overlay Index */
3005 if (afi
== AFI_L2VPN
) {
3006 overlay_index_update(
3007 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3008 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3011 /* Update bgp route dampening information. */
3012 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3013 && peer
->sort
== BGP_PEER_EBGP
) {
3014 /* Now we do normal update dampening. */
3015 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3016 if (ret
== BGP_DAMP_SUPPRESSED
) {
3017 bgp_unlock_node(rn
);
3022 /* Nexthop reachability check - for unicast and
3023 * labeled-unicast.. */
3024 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3025 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3026 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3027 && !CHECK_FLAG(peer
->flags
,
3028 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3030 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3035 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
3037 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3039 if (BGP_DEBUG(nht
, NHT
)) {
3040 char buf1
[INET6_ADDRSTRLEN
];
3042 (const void *)&attr_new
3044 buf1
, INET6_ADDRSTRLEN
);
3045 zlog_debug("%s(%s): NH unresolved",
3046 __FUNCTION__
, buf1
);
3048 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3051 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3054 if (safi
== SAFI_MPLS_VPN
) {
3055 struct bgp_node
*prn
= NULL
;
3056 struct bgp_table
*table
= NULL
;
3058 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3059 (struct prefix
*)prd
);
3061 table
= (struct bgp_table
*)(prn
->info
);
3063 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3064 bgp
, prd
, table
, p
, ri
);
3066 bgp_unlock_node(prn
);
3070 /* If this is an EVPN route and some attribute has changed,
3072 * route for import. If the extended community has changed, we
3074 * have done the un-import earlier and the import would result
3076 * route getting injected into appropriate L2 VNIs. If it is
3078 * some other attribute change, the import will result in
3080 * the attributes for the route in the VNI(s).
3082 if (safi
== SAFI_EVPN
&& !same_attr
)
3083 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3085 /* Process change. */
3086 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3088 bgp_process(bgp
, rn
, afi
, safi
);
3089 bgp_unlock_node(rn
);
3092 if (SAFI_MPLS_VPN
== safi
) {
3093 mpls_label_t label_decoded
= decode_label(label
);
3095 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3096 type
, sub_type
, &label_decoded
);
3098 if (SAFI_ENCAP
== safi
) {
3099 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3100 type
, sub_type
, NULL
);
3105 } // End of implicit withdraw
3107 /* Received Logging. */
3108 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3109 if (!peer
->rcvd_attr_printed
) {
3110 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3111 peer
->rcvd_attr_str
);
3112 peer
->rcvd_attr_printed
= 1;
3115 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3116 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3118 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3121 /* Make new BGP info. */
3122 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3124 /* Update MPLS label */
3125 if (has_valid_label
) {
3126 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3128 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3131 /* Update Overlay Index */
3132 if (afi
== AFI_L2VPN
) {
3133 overlay_index_update(new->attr
,
3134 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3135 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3137 /* Nexthop reachability check. */
3138 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3139 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3140 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3141 && !CHECK_FLAG(peer
->flags
,
3142 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3143 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3148 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
))
3149 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3151 if (BGP_DEBUG(nht
, NHT
)) {
3152 char buf1
[INET6_ADDRSTRLEN
];
3154 (const void *)&attr_new
->nexthop
,
3155 buf1
, INET6_ADDRSTRLEN
);
3156 zlog_debug("%s(%s): NH unresolved",
3157 __FUNCTION__
, buf1
);
3159 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3162 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3165 new->addpath_rx_id
= addpath_id
;
3167 /* Increment prefix */
3168 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3170 /* Register new BGP information. */
3171 bgp_info_add(rn
, new);
3173 /* route_node_get lock */
3174 bgp_unlock_node(rn
);
3177 if (safi
== SAFI_MPLS_VPN
) {
3178 struct bgp_node
*prn
= NULL
;
3179 struct bgp_table
*table
= NULL
;
3181 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3183 table
= (struct bgp_table
*)(prn
->info
);
3185 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3186 bgp
, prd
, table
, p
, new);
3188 bgp_unlock_node(prn
);
3192 /* If maximum prefix count is configured and current prefix
3194 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3197 /* If this is an EVPN route, process for import. */
3198 if (safi
== SAFI_EVPN
)
3199 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3201 /* Process change. */
3202 bgp_process(bgp
, rn
, afi
, safi
);
3205 if (SAFI_MPLS_VPN
== safi
) {
3206 mpls_label_t label_decoded
= decode_label(label
);
3208 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3209 sub_type
, &label_decoded
);
3211 if (SAFI_ENCAP
== safi
) {
3212 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3219 /* This BGP update is filtered. Log the reason then update BGP
3222 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3223 if (!peer
->rcvd_attr_printed
) {
3224 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3225 peer
->rcvd_attr_str
);
3226 peer
->rcvd_attr_printed
= 1;
3229 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3230 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3232 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3233 peer
->host
, pfx_buf
, reason
);
3237 /* If this is an EVPN route, un-import it as it is now filtered.
3239 if (safi
== SAFI_EVPN
)
3240 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3242 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3245 bgp_unlock_node(rn
);
3249 * Filtered update is treated as an implicit withdrawal (see
3251 * a few lines above)
3253 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3254 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3262 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3263 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3264 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3265 struct bgp_route_evpn
*evpn
)
3268 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3269 struct bgp_node
*rn
;
3270 struct bgp_info
*ri
;
3273 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3274 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3282 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3284 /* If peer is soft reconfiguration enabled. Record input packet for
3285 * further calculation.
3287 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3288 * routes that are filtered. This tanks out Quagga RS pretty badly due
3290 * the iteration over all RS clients.
3291 * Since we need to remove the entry from adj_in anyway, do that first
3293 * if there was no entry, we don't need to do anything more.
3295 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3296 && peer
!= bgp
->peer_self
)
3297 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3298 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3299 bgp_debug_rdpfxpath2str(
3300 afi
, safi
, prd
, p
, label
,
3301 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3304 "%s withdrawing route %s not in adj-in",
3305 peer
->host
, pfx_buf
);
3307 bgp_unlock_node(rn
);
3311 /* Lookup withdrawn route. */
3312 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3313 if (ri
->peer
== peer
&& ri
->type
== type
3314 && ri
->sub_type
== sub_type
3315 && ri
->addpath_rx_id
== addpath_id
)
3319 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3320 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3321 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3323 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3327 /* Withdraw specified route from routing table. */
3328 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3329 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3330 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3331 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3332 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3334 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3337 /* Unlock bgp_node_get() lock. */
3338 bgp_unlock_node(rn
);
3343 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3346 struct update_subgroup
*subgrp
;
3347 subgrp
= peer_subgroup(peer
, afi
, safi
);
3348 subgroup_default_originate(subgrp
, withdraw
);
3353 * bgp_stop_announce_route_timer
3355 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3357 if (!paf
->t_announce_route
)
3360 THREAD_TIMER_OFF(paf
->t_announce_route
);
3364 * bgp_announce_route_timer_expired
3366 * Callback that is invoked when the route announcement timer for a
3369 static int bgp_announce_route_timer_expired(struct thread
*t
)
3371 struct peer_af
*paf
;
3374 paf
= THREAD_ARG(t
);
3377 if (peer
->status
!= Established
)
3380 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3383 peer_af_announce_route(paf
, 1);
3388 * bgp_announce_route
3390 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3392 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3394 struct peer_af
*paf
;
3395 struct update_subgroup
*subgrp
;
3397 paf
= peer_af_find(peer
, afi
, safi
);
3400 subgrp
= PAF_SUBGRP(paf
);
3403 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3404 * or a refresh has already been triggered.
3406 if (!subgrp
|| paf
->t_announce_route
)
3410 * Start a timer to stagger/delay the announce. This serves
3411 * two purposes - announcement can potentially be combined for
3412 * multiple peers and the announcement doesn't happen in the
3415 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3416 (subgrp
->peer_count
== 1)
3417 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3418 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3419 &paf
->t_announce_route
);
3423 * Announce routes from all AF tables to a peer.
3425 * This should ONLY be called when there is a need to refresh the
3426 * routes to the peer based on a policy change for this peer alone
3427 * or a route refresh request received from the peer.
3428 * The operation will result in splitting the peer from its existing
3429 * subgroups and putting it in new subgroups.
3431 void bgp_announce_route_all(struct peer
*peer
)
3436 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3437 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3438 bgp_announce_route(peer
, afi
, safi
);
3441 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3442 struct bgp_table
*table
,
3443 struct prefix_rd
*prd
)
3446 struct bgp_node
*rn
;
3447 struct bgp_adj_in
*ain
;
3450 table
= peer
->bgp
->rib
[afi
][safi
];
3452 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3453 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3454 if (ain
->peer
!= peer
)
3457 struct bgp_info
*ri
= rn
->info
;
3458 mpls_label_t label
= (ri
&& ri
->extra
)
3460 : MPLS_INVALID_LABEL
;
3462 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3463 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3464 BGP_ROUTE_NORMAL
, prd
, &label
, 1,
3468 bgp_unlock_node(rn
);
3474 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3476 struct bgp_node
*rn
;
3477 struct bgp_table
*table
;
3479 if (peer
->status
!= Established
)
3482 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3483 && (safi
!= SAFI_EVPN
))
3484 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3486 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3487 rn
= bgp_route_next(rn
))
3488 if ((table
= rn
->info
) != NULL
) {
3489 struct prefix_rd prd
;
3490 prd
.family
= AF_UNSPEC
;
3492 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3494 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3500 struct bgp_clear_node_queue
{
3501 struct bgp_node
*rn
;
3504 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3506 struct bgp_clear_node_queue
*cnq
= data
;
3507 struct bgp_node
*rn
= cnq
->rn
;
3508 struct peer
*peer
= wq
->spec
.data
;
3509 struct bgp_info
*ri
;
3510 afi_t afi
= bgp_node_table(rn
)->afi
;
3511 safi_t safi
= bgp_node_table(rn
)->safi
;
3515 /* It is possible that we have multiple paths for a prefix from a peer
3516 * if that peer is using AddPath.
3518 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3519 if (ri
->peer
!= peer
)
3522 /* graceful restart STALE flag set. */
3523 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3524 && peer
->nsf
[afi
][safi
]
3525 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3526 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3527 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3529 /* If this is an EVPN route, process for
3531 if (safi
== SAFI_EVPN
)
3532 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
,
3534 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3540 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3542 struct bgp_clear_node_queue
*cnq
= data
;
3543 struct bgp_node
*rn
= cnq
->rn
;
3544 struct bgp_table
*table
= bgp_node_table(rn
);
3546 bgp_unlock_node(rn
);
3547 bgp_table_unlock(table
);
3548 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3551 static void bgp_clear_node_complete(struct work_queue
*wq
)
3553 struct peer
*peer
= wq
->spec
.data
;
3555 /* Tickle FSM to start moving again */
3556 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3558 peer_unlock(peer
); /* bgp_clear_route */
3561 static void bgp_clear_node_queue_init(struct peer
*peer
)
3563 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3565 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3566 #undef CLEAR_QUEUE_NAME_LEN
3568 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3570 zlog_err("%s: Failed to allocate work queue", __func__
);
3573 peer
->clear_node_queue
->spec
.hold
= 10;
3574 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3575 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3576 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3577 peer
->clear_node_queue
->spec
.max_retries
= 0;
3579 /* we only 'lock' this peer reference when the queue is actually active
3581 peer
->clear_node_queue
->spec
.data
= peer
;
3584 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3585 struct bgp_table
*table
)
3587 struct bgp_node
*rn
;
3588 int force
= bm
->process_main_queue
? 0 : 1;
3591 table
= peer
->bgp
->rib
[afi
][safi
];
3593 /* If still no table => afi/safi isn't configured at all or smth. */
3597 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3598 struct bgp_info
*ri
, *next
;
3599 struct bgp_adj_in
*ain
;
3600 struct bgp_adj_in
*ain_next
;
3602 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3603 * queued for every clearing peer, regardless of whether it is
3604 * relevant to the peer at hand.
3606 * Overview: There are 3 different indices which need to be
3607 * scrubbed, potentially, when a peer is removed:
3609 * 1 peer's routes visible via the RIB (ie accepted routes)
3610 * 2 peer's routes visible by the (optional) peer's adj-in index
3611 * 3 other routes visible by the peer's adj-out index
3613 * 3 there is no hurry in scrubbing, once the struct peer is
3614 * removed from bgp->peer, we could just GC such deleted peer's
3615 * adj-outs at our leisure.
3617 * 1 and 2 must be 'scrubbed' in some way, at least made
3618 * invisible via RIB index before peer session is allowed to be
3619 * brought back up. So one needs to know when such a 'search' is
3624 * - there'd be a single global queue or a single RIB walker
3625 * - rather than tracking which route_nodes still need to be
3626 * examined on a peer basis, we'd track which peers still
3629 * Given that our per-peer prefix-counts now should be reliable,
3630 * this may actually be achievable. It doesn't seem to be a huge
3631 * problem at this time,
3633 * It is possible that we have multiple paths for a prefix from
3635 * if that peer is using AddPath.
3639 ain_next
= ain
->next
;
3641 if (ain
->peer
== peer
) {
3642 bgp_adj_in_remove(rn
, ain
);
3643 bgp_unlock_node(rn
);
3649 for (ri
= rn
->info
; ri
; ri
= next
) {
3651 if (ri
->peer
!= peer
)
3655 bgp_info_reap(rn
, ri
);
3657 struct bgp_clear_node_queue
*cnq
;
3659 /* both unlocked in bgp_clear_node_queue_del */
3660 bgp_table_lock(bgp_node_table(rn
));
3663 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3664 sizeof(struct bgp_clear_node_queue
));
3666 work_queue_add(peer
->clear_node_queue
, cnq
);
3674 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3676 struct bgp_node
*rn
;
3677 struct bgp_table
*table
;
3679 if (peer
->clear_node_queue
== NULL
)
3680 bgp_clear_node_queue_init(peer
);
3682 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3683 * Idle until it receives a Clearing_Completed event. This protects
3684 * against peers which flap faster than we can we clear, which could
3687 * a) race with routes from the new session being installed before
3688 * clear_route_node visits the node (to delete the route of that
3690 * b) resource exhaustion, clear_route_node likely leads to an entry
3691 * on the process_main queue. Fast-flapping could cause that queue
3695 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3696 * the unlock will happen upon work-queue completion; other wise, the
3697 * unlock happens at the end of this function.
3699 if (!peer
->clear_node_queue
->thread
)
3702 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3703 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3705 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3706 rn
= bgp_route_next(rn
))
3707 if ((table
= rn
->info
) != NULL
)
3708 bgp_clear_route_table(peer
, afi
, safi
, table
);
3710 /* unlock if no nodes got added to the clear-node-queue. */
3711 if (!peer
->clear_node_queue
->thread
)
3715 void bgp_clear_route_all(struct peer
*peer
)
3720 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3721 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3722 bgp_clear_route(peer
, afi
, safi
);
3725 rfapiProcessPeerDown(peer
);
3729 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3731 struct bgp_table
*table
;
3732 struct bgp_node
*rn
;
3733 struct bgp_adj_in
*ain
;
3734 struct bgp_adj_in
*ain_next
;
3736 table
= peer
->bgp
->rib
[afi
][safi
];
3738 /* It is possible that we have multiple paths for a prefix from a peer
3739 * if that peer is using AddPath.
3741 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3745 ain_next
= ain
->next
;
3747 if (ain
->peer
== peer
) {
3748 bgp_adj_in_remove(rn
, ain
);
3749 bgp_unlock_node(rn
);
3757 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3759 struct bgp_node
*rn
;
3760 struct bgp_info
*ri
;
3761 struct bgp_table
*table
;
3763 if (safi
== SAFI_MPLS_VPN
) {
3764 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3765 rn
= bgp_route_next(rn
)) {
3766 struct bgp_node
*rm
;
3767 struct bgp_info
*ri
;
3769 /* look for neighbor in tables */
3770 if ((table
= rn
->info
) == NULL
)
3773 for (rm
= bgp_table_top(table
); rm
;
3774 rm
= bgp_route_next(rm
))
3775 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3776 if (ri
->peer
!= peer
)
3778 if (!CHECK_FLAG(ri
->flags
,
3782 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
3787 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3788 rn
= bgp_route_next(rn
))
3789 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3790 if (ri
->peer
!= peer
)
3792 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3794 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3800 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3802 struct bgp_node
*rn
;
3803 struct bgp_info
*ri
;
3804 struct bgp_info
*next
;
3806 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3807 for (ri
= rn
->info
; ri
; ri
= next
) {
3809 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3810 && ri
->type
== ZEBRA_ROUTE_BGP
3811 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3812 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3813 if (bgp_fibupd_safi(safi
))
3814 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3815 bgp_info_reap(rn
, ri
);
3820 /* Delete all kernel routes. */
3821 void bgp_cleanup_routes(struct bgp
*bgp
)
3824 struct bgp_node
*rn
;
3826 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3827 if (afi
== AFI_L2VPN
)
3829 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3831 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3833 if (afi
!= AFI_L2VPN
) {
3835 safi
= SAFI_MPLS_VPN
;
3836 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3837 rn
= bgp_route_next(rn
)) {
3840 (struct bgp_table
*)(rn
->info
),
3842 bgp_table_finish((struct bgp_table
**)&(
3845 bgp_unlock_node(rn
);
3849 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3850 rn
= bgp_route_next(rn
)) {
3853 (struct bgp_table
*)(rn
->info
),
3855 bgp_table_finish((struct bgp_table
**)&(
3858 bgp_unlock_node(rn
);
3863 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3864 rn
= bgp_route_next(rn
)) {
3866 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3868 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3870 bgp_unlock_node(rn
);
3875 void bgp_reset(void)
3878 bgp_zclient_reset();
3879 access_list_reset();
3880 prefix_list_reset();
3883 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3885 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3886 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3887 PEER_CAP_ADDPATH_AF_TX_RCV
));
3890 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3892 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3893 struct bgp_nlri
*packet
)
3902 int addpath_encoded
;
3903 u_int32_t addpath_id
;
3905 /* Check peer status. */
3906 if (peer
->status
!= Established
)
3910 lim
= pnt
+ packet
->length
;
3912 safi
= packet
->safi
;
3914 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3916 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3917 syntactic validity. If the field is syntactically incorrect,
3918 then the Error Subcode is set to Invalid Network Field. */
3919 for (; pnt
< lim
; pnt
+= psize
) {
3920 /* Clear prefix structure. */
3921 memset(&p
, 0, sizeof(struct prefix
));
3923 if (addpath_encoded
) {
3925 /* When packet overflow occurs return immediately. */
3926 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3929 addpath_id
= ntohl(*((uint32_t *)pnt
));
3930 pnt
+= BGP_ADDPATH_ID_LEN
;
3933 /* Fetch prefix length. */
3934 p
.prefixlen
= *pnt
++;
3935 /* afi/safi validity already verified by caller,
3936 * bgp_update_receive */
3937 p
.family
= afi2family(afi
);
3939 /* Prefix length check. */
3940 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3942 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3943 peer
->host
, p
.prefixlen
, packet
->afi
);
3947 /* Packet size overflow check. */
3948 psize
= PSIZE(p
.prefixlen
);
3950 /* When packet overflow occur return immediately. */
3951 if (pnt
+ psize
> lim
) {
3953 "%s [Error] Update packet error (prefix length %d overflows packet)",
3954 peer
->host
, p
.prefixlen
);
3958 /* Defensive coding, double-check the psize fits in a struct
3960 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3962 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3963 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3967 /* Fetch prefix from NLRI packet. */
3968 memcpy(&p
.u
.prefix
, pnt
, psize
);
3970 /* Check address. */
3971 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3972 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3973 /* From RFC4271 Section 6.3:
3975 * If a prefix in the NLRI field is semantically
3977 * (e.g., an unexpected multicast IP address),
3979 * be logged locally, and the prefix SHOULD be
3983 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3984 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3989 /* Check address. */
3990 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3991 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3995 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3997 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4002 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4006 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4008 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4015 /* Normal process. */
4017 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4018 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4019 NULL
, NULL
, 0, NULL
);
4021 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4022 safi
, ZEBRA_ROUTE_BGP
,
4023 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
4025 /* Address family configuration mismatch or maximum-prefix count
4031 /* Packet length consistency check. */
4034 "%s [Error] Update packet error (prefix length mismatch with total length)",
4042 static struct bgp_static
*bgp_static_new(void)
4044 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4047 static void bgp_static_free(struct bgp_static
*bgp_static
)
4049 if (bgp_static
->rmap
.name
)
4050 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4051 if (bgp_static
->eth_s_id
)
4052 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4053 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4056 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4057 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4059 struct bgp_node
*rn
;
4060 struct bgp_info
*ri
;
4061 struct bgp_info
*new;
4062 struct bgp_info info
;
4064 struct attr
*attr_new
;
4067 int vnc_implicit_withdraw
= 0;
4074 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4076 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4078 attr
.nexthop
= bgp_static
->igpnexthop
;
4079 attr
.med
= bgp_static
->igpmetric
;
4080 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4082 if (bgp_static
->atomic
)
4083 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4085 /* Store label index, if required. */
4086 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4087 attr
.label_index
= bgp_static
->label_index
;
4088 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4091 /* Apply route-map. */
4092 if (bgp_static
->rmap
.name
) {
4093 struct attr attr_tmp
= attr
;
4094 info
.peer
= bgp
->peer_self
;
4095 info
.attr
= &attr_tmp
;
4097 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4099 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4101 bgp
->peer_self
->rmap_type
= 0;
4103 if (ret
== RMAP_DENYMATCH
) {
4104 /* Free uninterned attribute. */
4105 bgp_attr_flush(&attr_tmp
);
4107 /* Unintern original. */
4108 aspath_unintern(&attr
.aspath
);
4109 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4113 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4114 bgp_attr_add_gshut_community(&attr_tmp
);
4116 attr_new
= bgp_attr_intern(&attr_tmp
);
4119 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4120 bgp_attr_add_gshut_community(&attr
);
4122 attr_new
= bgp_attr_intern(&attr
);
4125 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4126 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4127 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4131 if (attrhash_cmp(ri
->attr
, attr_new
)
4132 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4133 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4134 bgp_unlock_node(rn
);
4135 bgp_attr_unintern(&attr_new
);
4136 aspath_unintern(&attr
.aspath
);
4139 /* The attribute is changed. */
4140 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4142 /* Rewrite BGP route information. */
4143 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4144 bgp_info_restore(rn
, ri
);
4146 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4148 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4149 && (safi
== SAFI_UNICAST
)) {
4150 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4152 * Implicit withdraw case.
4153 * We have to do this before ri is
4156 ++vnc_implicit_withdraw
;
4157 vnc_import_bgp_del_route(bgp
, p
, ri
);
4158 vnc_import_bgp_exterior_del_route(
4163 bgp_attr_unintern(&ri
->attr
);
4164 ri
->attr
= attr_new
;
4165 ri
->uptime
= bgp_clock();
4167 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4168 && (safi
== SAFI_UNICAST
)) {
4169 if (vnc_implicit_withdraw
) {
4170 vnc_import_bgp_add_route(bgp
, p
, ri
);
4171 vnc_import_bgp_exterior_add_route(
4177 /* Nexthop reachability check. */
4178 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4179 && (safi
== SAFI_UNICAST
4180 || safi
== SAFI_LABELED_UNICAST
)) {
4181 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4183 bgp_info_set_flag(rn
, ri
,
4186 if (BGP_DEBUG(nht
, NHT
)) {
4187 char buf1
[INET6_ADDRSTRLEN
];
4188 inet_ntop(p
->family
,
4192 "%s(%s): Route not in table, not advertising",
4193 __FUNCTION__
, buf1
);
4195 bgp_info_unset_flag(rn
, ri
,
4199 /* Delete the NHT structure if any, if we're
4201 * enabling/disabling import check. We
4202 * deregister the route
4203 * from NHT to avoid overloading NHT and the
4204 * process interaction
4206 bgp_unlink_nexthop(ri
);
4207 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4209 /* Process change. */
4210 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4211 bgp_process(bgp
, rn
, afi
, safi
);
4212 bgp_unlock_node(rn
);
4213 aspath_unintern(&attr
.aspath
);
4218 /* Make new BGP info. */
4219 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4221 /* Nexthop reachability check. */
4222 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4223 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4224 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4225 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4227 if (BGP_DEBUG(nht
, NHT
)) {
4228 char buf1
[INET6_ADDRSTRLEN
];
4229 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4232 "%s(%s): Route not in table, not advertising",
4233 __FUNCTION__
, buf1
);
4235 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4238 /* Delete the NHT structure if any, if we're toggling between
4239 * enabling/disabling import check. We deregister the route
4240 * from NHT to avoid overloading NHT and the process interaction
4242 bgp_unlink_nexthop(new);
4244 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4247 /* Aggregate address increment. */
4248 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4250 /* Register new BGP information. */
4251 bgp_info_add(rn
, new);
4253 /* route_node_get lock */
4254 bgp_unlock_node(rn
);
4256 /* Process change. */
4257 bgp_process(bgp
, rn
, afi
, safi
);
4259 /* Unintern original. */
4260 aspath_unintern(&attr
.aspath
);
4263 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4266 struct bgp_node
*rn
;
4267 struct bgp_info
*ri
;
4269 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4271 /* Check selected route and self inserted route. */
4272 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4273 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4274 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4277 /* Withdraw static BGP route from routing table. */
4279 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4280 bgp_unlink_nexthop(ri
);
4281 bgp_info_delete(rn
, ri
);
4282 bgp_process(bgp
, rn
, afi
, safi
);
4285 /* Unlock bgp_node_lookup. */
4286 bgp_unlock_node(rn
);
4290 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4292 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4293 afi_t afi
, safi_t safi
,
4294 struct prefix_rd
*prd
)
4296 struct bgp_node
*rn
;
4297 struct bgp_info
*ri
;
4299 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4301 /* Check selected route and self inserted route. */
4302 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4303 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4304 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4307 /* Withdraw static BGP route from routing table. */
4310 rfapiProcessWithdraw(
4311 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4312 1); /* Kill, since it is an administrative change */
4314 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4315 bgp_info_delete(rn
, ri
);
4316 bgp_process(bgp
, rn
, afi
, safi
);
4319 /* Unlock bgp_node_lookup. */
4320 bgp_unlock_node(rn
);
4323 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4324 struct bgp_static
*bgp_static
, afi_t afi
,
4327 struct bgp_node
*rn
;
4328 struct bgp_info
*new;
4329 struct attr
*attr_new
;
4330 struct attr attr
= {0};
4331 struct bgp_info
*ri
;
4333 mpls_label_t label
= 0;
4339 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4342 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4344 attr
.nexthop
= bgp_static
->igpnexthop
;
4345 attr
.med
= bgp_static
->igpmetric
;
4346 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4348 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4349 || (safi
== SAFI_ENCAP
)) {
4350 if (afi
== AFI_IP
) {
4351 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4352 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4355 if (afi
== AFI_L2VPN
) {
4356 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4358 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4359 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4360 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4361 sizeof(struct in6_addr
));
4362 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4363 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4364 struct bgp_encap_type_vxlan bet
;
4365 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4366 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4367 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4369 if (bgp_static
->router_mac
) {
4370 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4373 /* Apply route-map. */
4374 if (bgp_static
->rmap
.name
) {
4375 struct attr attr_tmp
= attr
;
4376 struct bgp_info info
;
4379 info
.peer
= bgp
->peer_self
;
4380 info
.attr
= &attr_tmp
;
4382 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4384 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4386 bgp
->peer_self
->rmap_type
= 0;
4388 if (ret
== RMAP_DENYMATCH
) {
4389 /* Free uninterned attribute. */
4390 bgp_attr_flush(&attr_tmp
);
4392 /* Unintern original. */
4393 aspath_unintern(&attr
.aspath
);
4394 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4399 attr_new
= bgp_attr_intern(&attr_tmp
);
4401 attr_new
= bgp_attr_intern(&attr
);
4404 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4405 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4406 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4411 memset(&add
, 0, sizeof(union gw_addr
));
4412 if (attrhash_cmp(ri
->attr
, attr_new
)
4413 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4414 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4415 bgp_unlock_node(rn
);
4416 bgp_attr_unintern(&attr_new
);
4417 aspath_unintern(&attr
.aspath
);
4420 /* The attribute is changed. */
4421 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4423 /* Rewrite BGP route information. */
4424 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4425 bgp_info_restore(rn
, ri
);
4427 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4428 bgp_attr_unintern(&ri
->attr
);
4429 ri
->attr
= attr_new
;
4430 ri
->uptime
= bgp_clock();
4433 label
= decode_label(&ri
->extra
->label
);
4436 /* Process change. */
4437 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4438 bgp_process(bgp
, rn
, afi
, safi
);
4440 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4441 ri
->attr
, afi
, safi
, ri
->type
,
4442 ri
->sub_type
, &label
);
4444 bgp_unlock_node(rn
);
4445 aspath_unintern(&attr
.aspath
);
4451 /* Make new BGP info. */
4452 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4454 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4455 new->extra
= bgp_info_extra_new();
4456 new->extra
->label
= bgp_static
->label
;
4458 label
= decode_label(&bgp_static
->label
);
4461 /* Aggregate address increment. */
4462 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4464 /* Register new BGP information. */
4465 bgp_info_add(rn
, new);
4466 /* route_node_get lock */
4467 bgp_unlock_node(rn
);
4469 /* Process change. */
4470 bgp_process(bgp
, rn
, afi
, safi
);
4473 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4474 safi
, new->type
, new->sub_type
, &label
);
4477 /* Unintern original. */
4478 aspath_unintern(&attr
.aspath
);
4481 /* Configure static BGP network. When user don't run zebra, static
4482 route should be installed as valid. */
4483 static int bgp_static_set(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4484 safi_t safi
, const char *rmap
, int backdoor
,
4485 u_int32_t label_index
)
4487 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4490 struct bgp_static
*bgp_static
;
4491 struct bgp_node
*rn
;
4492 u_char need_update
= 0;
4494 /* Convert IP prefix string to struct prefix. */
4495 ret
= str2prefix(ip_str
, &p
);
4497 vty_out(vty
, "%% Malformed prefix\n");
4498 return CMD_WARNING_CONFIG_FAILED
;
4500 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4501 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4502 return CMD_WARNING_CONFIG_FAILED
;
4507 /* Set BGP static route configuration. */
4508 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4511 /* Configuration change. */
4512 bgp_static
= rn
->info
;
4514 /* Label index cannot be changed. */
4515 if (bgp_static
->label_index
!= label_index
) {
4516 vty_out(vty
, "%% Label index cannot be changed\n");
4517 return CMD_WARNING_CONFIG_FAILED
;
4520 /* Check previous routes are installed into BGP. */
4521 if (bgp_static
->valid
&& bgp_static
->backdoor
!= backdoor
)
4524 bgp_static
->backdoor
= backdoor
;
4527 if (bgp_static
->rmap
.name
)
4528 XFREE(MTYPE_ROUTE_MAP_NAME
,
4529 bgp_static
->rmap
.name
);
4530 bgp_static
->rmap
.name
=
4531 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4532 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4534 if (bgp_static
->rmap
.name
)
4535 XFREE(MTYPE_ROUTE_MAP_NAME
,
4536 bgp_static
->rmap
.name
);
4537 bgp_static
->rmap
.name
= NULL
;
4538 bgp_static
->rmap
.map
= NULL
;
4539 bgp_static
->valid
= 0;
4541 bgp_unlock_node(rn
);
4543 /* New configuration. */
4544 bgp_static
= bgp_static_new();
4545 bgp_static
->backdoor
= backdoor
;
4546 bgp_static
->valid
= 0;
4547 bgp_static
->igpmetric
= 0;
4548 bgp_static
->igpnexthop
.s_addr
= 0;
4549 bgp_static
->label_index
= label_index
;
4552 if (bgp_static
->rmap
.name
)
4553 XFREE(MTYPE_ROUTE_MAP_NAME
,
4554 bgp_static
->rmap
.name
);
4555 bgp_static
->rmap
.name
=
4556 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4557 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4559 rn
->info
= bgp_static
;
4562 bgp_static
->valid
= 1;
4564 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4566 if (!bgp_static
->backdoor
)
4567 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4572 /* Configure static BGP network. */
4573 static int bgp_static_unset(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4576 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4579 struct bgp_static
*bgp_static
;
4580 struct bgp_node
*rn
;
4582 /* Convert IP prefix string to struct prefix. */
4583 ret
= str2prefix(ip_str
, &p
);
4585 vty_out(vty
, "%% Malformed prefix\n");
4586 return CMD_WARNING_CONFIG_FAILED
;
4588 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4589 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4590 return CMD_WARNING_CONFIG_FAILED
;
4595 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4598 "%% Can't find specified static route configuration.\n");
4599 return CMD_WARNING_CONFIG_FAILED
;
4602 bgp_static
= rn
->info
;
4604 /* Update BGP RIB. */
4605 if (!bgp_static
->backdoor
)
4606 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4608 /* Clear configuration. */
4609 bgp_static_free(bgp_static
);
4611 bgp_unlock_node(rn
);
4612 bgp_unlock_node(rn
);
4617 void bgp_static_add(struct bgp
*bgp
)
4621 struct bgp_node
*rn
;
4622 struct bgp_node
*rm
;
4623 struct bgp_table
*table
;
4624 struct bgp_static
*bgp_static
;
4626 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4627 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4628 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4629 rn
= bgp_route_next(rn
)) {
4630 if (rn
->info
== NULL
)
4633 if ((safi
== SAFI_MPLS_VPN
)
4634 || (safi
== SAFI_ENCAP
)
4635 || (safi
== SAFI_EVPN
)) {
4638 for (rm
= bgp_table_top(table
); rm
;
4639 rm
= bgp_route_next(rm
)) {
4640 bgp_static
= rm
->info
;
4641 bgp_static_update_safi(
4642 bgp
, &rm
->p
, bgp_static
,
4646 bgp_static_update(bgp
, &rn
->p
, rn
->info
,
4652 /* Called from bgp_delete(). Delete all static routes from the BGP
4654 void bgp_static_delete(struct bgp
*bgp
)
4658 struct bgp_node
*rn
;
4659 struct bgp_node
*rm
;
4660 struct bgp_table
*table
;
4661 struct bgp_static
*bgp_static
;
4663 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4664 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4665 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4666 rn
= bgp_route_next(rn
)) {
4667 if (rn
->info
== NULL
)
4670 if ((safi
== SAFI_MPLS_VPN
)
4671 || (safi
== SAFI_ENCAP
)
4672 || (safi
== SAFI_EVPN
)) {
4675 for (rm
= bgp_table_top(table
); rm
;
4676 rm
= bgp_route_next(rm
)) {
4677 bgp_static
= rm
->info
;
4678 bgp_static_withdraw_safi(
4679 bgp
, &rm
->p
, AFI_IP
,
4681 (struct prefix_rd
*)&rn
4683 bgp_static_free(bgp_static
);
4685 bgp_unlock_node(rn
);
4688 bgp_static
= rn
->info
;
4689 bgp_static_withdraw(bgp
, &rn
->p
, afi
,
4691 bgp_static_free(bgp_static
);
4693 bgp_unlock_node(rn
);
4698 void bgp_static_redo_import_check(struct bgp
*bgp
)
4702 struct bgp_node
*rn
;
4703 struct bgp_node
*rm
;
4704 struct bgp_table
*table
;
4705 struct bgp_static
*bgp_static
;
4707 /* Use this flag to force reprocessing of the route */
4708 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4709 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4710 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4711 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4712 rn
= bgp_route_next(rn
)) {
4713 if (rn
->info
== NULL
)
4716 if ((safi
== SAFI_MPLS_VPN
)
4717 || (safi
== SAFI_ENCAP
)
4718 || (safi
== SAFI_EVPN
)) {
4721 for (rm
= bgp_table_top(table
); rm
;
4722 rm
= bgp_route_next(rm
)) {
4723 bgp_static
= rm
->info
;
4724 bgp_static_update_safi(
4725 bgp
, &rm
->p
, bgp_static
,
4729 bgp_static
= rn
->info
;
4730 bgp_static_update(bgp
, &rn
->p
,
4735 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4738 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4741 struct bgp_table
*table
;
4742 struct bgp_node
*rn
;
4743 struct bgp_info
*ri
;
4745 table
= bgp
->rib
[afi
][safi
];
4746 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4747 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4748 if (ri
->peer
== bgp
->peer_self
4749 && ((ri
->type
== ZEBRA_ROUTE_BGP
4750 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4751 || (ri
->type
!= ZEBRA_ROUTE_BGP
4753 == BGP_ROUTE_REDISTRIBUTE
))) {
4754 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4756 bgp_unlink_nexthop(ri
);
4757 bgp_info_delete(rn
, ri
);
4758 bgp_process(bgp
, rn
, afi
, safi
);
4765 * Purge all networks and redistributed routes from routing table.
4766 * Invoked upon the instance going down.
4768 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4773 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4774 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4775 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4780 * Currently this is used to set static routes for VPN and ENCAP.
4781 * I think it can probably be factored with bgp_static_set.
4783 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4784 const char *ip_str
, const char *rd_str
,
4785 const char *label_str
, const char *rmap_str
,
4786 int evpn_type
, const char *esi
, const char *gwip
,
4787 const char *ethtag
, const char *routermac
)
4789 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4792 struct prefix_rd prd
;
4793 struct bgp_node
*prn
;
4794 struct bgp_node
*rn
;
4795 struct bgp_table
*table
;
4796 struct bgp_static
*bgp_static
;
4797 mpls_label_t label
= MPLS_INVALID_LABEL
;
4798 struct prefix gw_ip
;
4800 /* validate ip prefix */
4801 ret
= str2prefix(ip_str
, &p
);
4803 vty_out(vty
, "%% Malformed prefix\n");
4804 return CMD_WARNING_CONFIG_FAILED
;
4807 if ((afi
== AFI_L2VPN
)
4808 && (bgp_build_evpn_prefix(evpn_type
,
4809 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4810 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4811 return CMD_WARNING_CONFIG_FAILED
;
4814 ret
= str2prefix_rd(rd_str
, &prd
);
4816 vty_out(vty
, "%% Malformed rd\n");
4817 return CMD_WARNING_CONFIG_FAILED
;
4821 unsigned long label_val
;
4822 label_val
= strtoul(label_str
, NULL
, 10);
4823 encode_label(label_val
, &label
);
4826 if (safi
== SAFI_EVPN
) {
4827 if (esi
&& str2esi(esi
, NULL
) == 0) {
4828 vty_out(vty
, "%% Malformed ESI\n");
4829 return CMD_WARNING_CONFIG_FAILED
;
4831 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4832 vty_out(vty
, "%% Malformed Router MAC\n");
4833 return CMD_WARNING_CONFIG_FAILED
;
4836 memset(&gw_ip
, 0, sizeof(struct prefix
));
4837 ret
= str2prefix(gwip
, &gw_ip
);
4839 vty_out(vty
, "%% Malformed GatewayIp\n");
4840 return CMD_WARNING_CONFIG_FAILED
;
4842 if ((gw_ip
.family
== AF_INET
4843 && IS_EVPN_PREFIX_IPADDR_V6(
4844 (struct prefix_evpn
*)&p
))
4845 || (gw_ip
.family
== AF_INET6
4846 && IS_EVPN_PREFIX_IPADDR_V4(
4847 (struct prefix_evpn
*)&p
))) {
4849 "%% GatewayIp family differs with IP prefix\n");
4850 return CMD_WARNING_CONFIG_FAILED
;
4854 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4855 if (prn
->info
== NULL
)
4856 prn
->info
= bgp_table_init(afi
, safi
);
4858 bgp_unlock_node(prn
);
4861 rn
= bgp_node_get(table
, &p
);
4864 vty_out(vty
, "%% Same network configuration exists\n");
4865 bgp_unlock_node(rn
);
4867 /* New configuration. */
4868 bgp_static
= bgp_static_new();
4869 bgp_static
->backdoor
= 0;
4870 bgp_static
->valid
= 0;
4871 bgp_static
->igpmetric
= 0;
4872 bgp_static
->igpnexthop
.s_addr
= 0;
4873 bgp_static
->label
= label
;
4874 bgp_static
->prd
= prd
;
4877 if (bgp_static
->rmap
.name
)
4878 XFREE(MTYPE_ROUTE_MAP_NAME
,
4879 bgp_static
->rmap
.name
);
4880 bgp_static
->rmap
.name
=
4881 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4882 bgp_static
->rmap
.map
=
4883 route_map_lookup_by_name(rmap_str
);
4886 if (safi
== SAFI_EVPN
) {
4888 bgp_static
->eth_s_id
=
4890 sizeof(struct eth_segment_id
));
4891 str2esi(esi
, bgp_static
->eth_s_id
);
4894 bgp_static
->router_mac
=
4895 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
4896 prefix_str2mac(routermac
,
4897 bgp_static
->router_mac
);
4900 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4902 rn
->info
= bgp_static
;
4904 bgp_static
->valid
= 1;
4905 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4911 /* Configure static BGP network. */
4912 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4913 const char *ip_str
, const char *rd_str
,
4914 const char *label_str
, int evpn_type
, const char *esi
,
4915 const char *gwip
, const char *ethtag
)
4917 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4920 struct prefix_rd prd
;
4921 struct bgp_node
*prn
;
4922 struct bgp_node
*rn
;
4923 struct bgp_table
*table
;
4924 struct bgp_static
*bgp_static
;
4925 mpls_label_t label
= MPLS_INVALID_LABEL
;
4927 /* Convert IP prefix string to struct prefix. */
4928 ret
= str2prefix(ip_str
, &p
);
4930 vty_out(vty
, "%% Malformed prefix\n");
4931 return CMD_WARNING_CONFIG_FAILED
;
4934 if ((afi
== AFI_L2VPN
)
4935 && (bgp_build_evpn_prefix(evpn_type
,
4936 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4937 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4938 return CMD_WARNING_CONFIG_FAILED
;
4940 ret
= str2prefix_rd(rd_str
, &prd
);
4942 vty_out(vty
, "%% Malformed rd\n");
4943 return CMD_WARNING_CONFIG_FAILED
;
4947 unsigned long label_val
;
4948 label_val
= strtoul(label_str
, NULL
, 10);
4949 encode_label(label_val
, &label
);
4952 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4953 if (prn
->info
== NULL
)
4954 prn
->info
= bgp_table_init(afi
, safi
);
4956 bgp_unlock_node(prn
);
4959 rn
= bgp_node_lookup(table
, &p
);
4962 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4964 bgp_static
= rn
->info
;
4965 bgp_static_free(bgp_static
);
4967 bgp_unlock_node(rn
);
4968 bgp_unlock_node(rn
);
4970 vty_out(vty
, "%% Can't find the route\n");
4975 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4976 const char *rmap_name
)
4978 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4979 struct bgp_rmap
*rmap
;
4981 rmap
= &bgp
->table_map
[afi
][safi
];
4984 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4985 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4986 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4989 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4994 if (bgp_fibupd_safi(safi
))
4995 bgp_zebra_announce_table(bgp
, afi
, safi
);
5000 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5001 const char *rmap_name
)
5003 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5004 struct bgp_rmap
*rmap
;
5006 rmap
= &bgp
->table_map
[afi
][safi
];
5008 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5012 if (bgp_fibupd_safi(safi
))
5013 bgp_zebra_announce_table(bgp
, afi
, safi
);
5018 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5021 if (bgp
->table_map
[afi
][safi
].name
) {
5022 vty_out(vty
, " table-map %s\n",
5023 bgp
->table_map
[afi
][safi
].name
);
5027 DEFUN (bgp_table_map
,
5030 "BGP table to RIB route download filter\n"
5031 "Name of the route map\n")
5034 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5035 argv
[idx_word
]->arg
);
5037 DEFUN (no_bgp_table_map
,
5038 no_bgp_table_map_cmd
,
5039 "no table-map WORD",
5041 "BGP table to RIB route download filter\n"
5042 "Name of the route map\n")
5045 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5046 argv
[idx_word
]->arg
);
5051 "network A.B.C.D/M",
5052 "Specify a network to announce via BGP\n"
5055 int idx_ipv4_prefixlen
= 1;
5056 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5057 bgp_node_safi(vty
), NULL
, 0,
5058 BGP_INVALID_LABEL_INDEX
);
5061 DEFUN (bgp_network_route_map
,
5062 bgp_network_route_map_cmd
,
5063 "network A.B.C.D/M route-map WORD",
5064 "Specify a network to announce via BGP\n"
5066 "Route-map to modify the attributes\n"
5067 "Name of the route map\n")
5069 int idx_ipv4_prefixlen
= 1;
5071 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5072 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5073 BGP_INVALID_LABEL_INDEX
);
5076 DEFUN (bgp_network_backdoor
,
5077 bgp_network_backdoor_cmd
,
5078 "network A.B.C.D/M backdoor",
5079 "Specify a network to announce via BGP\n"
5081 "Specify a BGP backdoor route\n")
5083 int idx_ipv4_prefixlen
= 1;
5084 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5085 SAFI_UNICAST
, NULL
, 1, BGP_INVALID_LABEL_INDEX
);
5088 DEFUN (bgp_network_mask
,
5089 bgp_network_mask_cmd
,
5090 "network A.B.C.D mask A.B.C.D",
5091 "Specify a network to announce via BGP\n"
5099 char prefix_str
[BUFSIZ
];
5101 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5104 vty_out(vty
, "%% Inconsistent address and mask\n");
5105 return CMD_WARNING_CONFIG_FAILED
;
5108 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5109 0, BGP_INVALID_LABEL_INDEX
);
5112 DEFUN (bgp_network_mask_route_map
,
5113 bgp_network_mask_route_map_cmd
,
5114 "network A.B.C.D mask A.B.C.D route-map WORD",
5115 "Specify a network to announce via BGP\n"
5119 "Route-map to modify the attributes\n"
5120 "Name of the route map\n")
5126 char prefix_str
[BUFSIZ
];
5128 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5131 vty_out(vty
, "%% Inconsistent address and mask\n");
5132 return CMD_WARNING_CONFIG_FAILED
;
5135 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5136 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5139 DEFUN (bgp_network_mask_backdoor
,
5140 bgp_network_mask_backdoor_cmd
,
5141 "network A.B.C.D mask A.B.C.D backdoor",
5142 "Specify a network to announce via BGP\n"
5146 "Specify a BGP backdoor route\n")
5151 char prefix_str
[BUFSIZ
];
5153 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5156 vty_out(vty
, "%% Inconsistent address and mask\n");
5157 return CMD_WARNING_CONFIG_FAILED
;
5160 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5161 BGP_INVALID_LABEL_INDEX
);
5164 DEFUN (bgp_network_mask_natural
,
5165 bgp_network_mask_natural_cmd
,
5167 "Specify a network to announce via BGP\n"
5172 char prefix_str
[BUFSIZ
];
5174 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5176 vty_out(vty
, "%% Inconsistent address and mask\n");
5177 return CMD_WARNING_CONFIG_FAILED
;
5180 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5181 0, BGP_INVALID_LABEL_INDEX
);
5184 DEFUN (bgp_network_mask_natural_route_map
,
5185 bgp_network_mask_natural_route_map_cmd
,
5186 "network A.B.C.D route-map WORD",
5187 "Specify a network to announce via BGP\n"
5189 "Route-map to modify the attributes\n"
5190 "Name of the route map\n")
5195 char prefix_str
[BUFSIZ
];
5197 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5199 vty_out(vty
, "%% Inconsistent address and mask\n");
5200 return CMD_WARNING_CONFIG_FAILED
;
5203 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5204 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5207 DEFUN (bgp_network_mask_natural_backdoor
,
5208 bgp_network_mask_natural_backdoor_cmd
,
5209 "network A.B.C.D backdoor",
5210 "Specify a network to announce via BGP\n"
5212 "Specify a BGP backdoor route\n")
5216 char prefix_str
[BUFSIZ
];
5218 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5220 vty_out(vty
, "%% Inconsistent address and mask\n");
5221 return CMD_WARNING_CONFIG_FAILED
;
5224 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5225 BGP_INVALID_LABEL_INDEX
);
5228 DEFUN (bgp_network_label_index
,
5229 bgp_network_label_index_cmd
,
5230 "network A.B.C.D/M label-index (0-1048560)",
5231 "Specify a network to announce via BGP\n"
5232 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5233 "Label index to associate with the prefix\n"
5234 "Label index value\n")
5236 u_int32_t label_index
;
5238 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5239 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5240 NULL
, 0, label_index
);
5243 DEFUN (bgp_network_label_index_route_map
,
5244 bgp_network_label_index_route_map_cmd
,
5245 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
5246 "Specify a network to announce via BGP\n"
5248 "Label index to associate with the prefix\n"
5249 "Label index value\n"
5250 "Route-map to modify the attributes\n"
5251 "Name of the route map\n")
5253 u_int32_t label_index
;
5255 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5256 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5257 argv
[5]->arg
, 0, label_index
);
5260 DEFUN (no_bgp_network
,
5262 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
5264 "Specify a network to announce via BGP\n"
5266 "Specify a BGP backdoor route\n"
5267 "Route-map to modify the attributes\n"
5268 "Name of the route map\n")
5270 int idx_ipv4_prefixlen
= 2;
5271 return bgp_static_unset(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5272 bgp_node_safi(vty
));
5275 DEFUN (no_bgp_network_mask
,
5276 no_bgp_network_mask_cmd
,
5277 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
5279 "Specify a network to announce via BGP\n"
5283 "Specify a BGP backdoor route\n"
5284 "Route-map to modify the attributes\n"
5285 "Name of the route map\n")
5290 char prefix_str
[BUFSIZ
];
5292 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5295 vty_out(vty
, "%% Inconsistent address and mask\n");
5296 return CMD_WARNING_CONFIG_FAILED
;
5299 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5302 DEFUN (no_bgp_network_mask_natural
,
5303 no_bgp_network_mask_natural_cmd
,
5304 "no network A.B.C.D [<backdoor|route-map WORD>]",
5306 "Specify a network to announce via BGP\n"
5308 "Specify a BGP backdoor route\n"
5309 "Route-map to modify the attributes\n"
5310 "Name of the route map\n")
5314 char prefix_str
[BUFSIZ
];
5316 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5318 vty_out(vty
, "%% Inconsistent address and mask\n");
5319 return CMD_WARNING_CONFIG_FAILED
;
5322 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5325 ALIAS(no_bgp_network
, no_bgp_network_label_index_cmd
,
5326 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
5327 "Specify a network to announce via BGP\n"
5328 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5329 "Label index to associate with the prefix\n"
5330 "Label index value\n")
5332 ALIAS(no_bgp_network
, no_bgp_network_label_index_route_map_cmd
,
5333 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
5334 "Specify a network to announce via BGP\n"
5336 "Label index to associate with the prefix\n"
5337 "Label index value\n"
5338 "Route-map to modify the attributes\n"
5339 "Name of the route map\n")
5341 DEFUN (ipv6_bgp_network
,
5342 ipv6_bgp_network_cmd
,
5343 "network X:X::X:X/M",
5344 "Specify a network to announce via BGP\n"
5347 int idx_ipv6_prefixlen
= 1;
5348 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5349 bgp_node_safi(vty
), NULL
, 0,
5350 BGP_INVALID_LABEL_INDEX
);
5353 DEFUN (ipv6_bgp_network_route_map
,
5354 ipv6_bgp_network_route_map_cmd
,
5355 "network X:X::X:X/M route-map WORD",
5356 "Specify a network to announce via BGP\n"
5358 "Route-map to modify the attributes\n"
5359 "Name of the route map\n")
5361 int idx_ipv6_prefixlen
= 1;
5363 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5364 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5365 BGP_INVALID_LABEL_INDEX
);
5368 DEFUN (ipv6_bgp_network_label_index
,
5369 ipv6_bgp_network_label_index_cmd
,
5370 "network X:X::X:X/M label-index (0-1048560)",
5371 "Specify a network to announce via BGP\n"
5372 "IPv6 prefix <network>/<length>\n"
5373 "Label index to associate with the prefix\n"
5374 "Label index value\n")
5376 u_int32_t label_index
;
5378 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5379 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5380 NULL
, 0, label_index
);
5383 DEFUN (ipv6_bgp_network_label_index_route_map
,
5384 ipv6_bgp_network_label_index_route_map_cmd
,
5385 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
5386 "Specify a network to announce via BGP\n"
5388 "Label index to associate with the prefix\n"
5389 "Label index value\n"
5390 "Route-map to modify the attributes\n"
5391 "Name of the route map\n")
5393 u_int32_t label_index
;
5395 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5396 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5397 argv
[5]->arg
, 0, label_index
);
5400 DEFUN (no_ipv6_bgp_network
,
5401 no_ipv6_bgp_network_cmd
,
5402 "no network X:X::X:X/M [route-map WORD]",
5404 "Specify a network to announce via BGP\n"
5406 "Route-map to modify the attributes\n"
5407 "Name of the route map\n")
5409 int idx_ipv6_prefixlen
= 2;
5410 return bgp_static_unset(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5411 bgp_node_safi(vty
));
5414 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_cmd
,
5415 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
5416 "Specify a network to announce via BGP\n"
5417 "IPv6 prefix <network>/<length>\n"
5418 "Label index to associate with the prefix\n"
5419 "Label index value\n")
5421 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_route_map_cmd
,
5422 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
5423 "Specify a network to announce via BGP\n"
5425 "Label index to associate with the prefix\n"
5426 "Label index value\n"
5427 "Route-map to modify the attributes\n"
5428 "Name of the route map\n")
5430 /* Aggreagete address:
5432 advertise-map Set condition to advertise attribute
5433 as-set Generate AS set path information
5434 attribute-map Set attributes of aggregate
5435 route-map Set parameters of aggregate
5436 summary-only Filter more specific routes from updates
5437 suppress-map Conditionally filter more specific routes from updates
5440 struct bgp_aggregate
{
5441 /* Summary-only flag. */
5442 u_char summary_only
;
5444 /* AS set generation. */
5447 /* Route-map for aggregated route. */
5448 struct route_map
*map
;
5450 /* Suppress-count. */
5451 unsigned long count
;
5453 /* SAFI configuration. */
5457 static struct bgp_aggregate
*bgp_aggregate_new(void)
5459 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5462 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5464 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5467 /* Update an aggregate as routes are added/removed from the BGP table */
5468 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5469 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5470 struct bgp_info
*del
,
5471 struct bgp_aggregate
*aggregate
)
5473 struct bgp_table
*table
;
5474 struct bgp_node
*top
;
5475 struct bgp_node
*rn
;
5477 struct aspath
*aspath
= NULL
;
5478 struct aspath
*asmerge
= NULL
;
5479 struct community
*community
= NULL
;
5480 struct community
*commerge
= NULL
;
5481 #if defined(AGGREGATE_NEXTHOP_CHECK)
5482 struct in_addr nexthop
;
5485 struct bgp_info
*ri
;
5486 struct bgp_info
*new;
5488 unsigned long match
= 0;
5489 u_char atomic_aggregate
= 0;
5491 /* Record adding route's nexthop and med. */
5493 #if defined(AGGREGATE_NEXTHOP_CHECK)
5494 nexthop
= rinew
->attr
->nexthop
;
5495 med
= rinew
->attr
->med
;
5499 /* ORIGIN attribute: If at least one route among routes that are
5500 aggregated has ORIGIN with the value INCOMPLETE, then the
5501 aggregated route must have the ORIGIN attribute with the value
5502 INCOMPLETE. Otherwise, if at least one route among routes that
5503 are aggregated has ORIGIN with the value EGP, then the aggregated
5504 route must have the origin attribute with the value EGP. In all
5505 other case the value of the ORIGIN attribute of the aggregated
5506 route is INTERNAL. */
5507 origin
= BGP_ORIGIN_IGP
;
5509 table
= bgp
->rib
[afi
][safi
];
5511 top
= bgp_node_get(table
, p
);
5512 for (rn
= bgp_node_get(table
, p
); rn
;
5513 rn
= bgp_route_next_until(rn
, top
))
5514 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5517 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5518 if (BGP_INFO_HOLDDOWN(ri
))
5521 if (del
&& ri
== del
)
5524 if (!rinew
&& first
) {
5525 #if defined(AGGREGATE_NEXTHOP_CHECK)
5526 nexthop
= ri
->attr
->nexthop
;
5527 med
= ri
->attr
->med
;
5532 #ifdef AGGREGATE_NEXTHOP_CHECK
5533 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5535 || ri
->attr
->med
!= med
) {
5537 aspath_free(aspath
);
5539 community_free(community
);
5540 bgp_unlock_node(rn
);
5541 bgp_unlock_node(top
);
5544 #endif /* AGGREGATE_NEXTHOP_CHECK */
5547 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5548 atomic_aggregate
= 1;
5550 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5551 if (aggregate
->summary_only
) {
5552 (bgp_info_extra_get(ri
))
5556 BGP_INFO_ATTR_CHANGED
);
5562 if (origin
< ri
->attr
->origin
)
5563 origin
= ri
->attr
->origin
;
5565 if (aggregate
->as_set
) {
5567 asmerge
= aspath_aggregate(
5570 aspath_free(aspath
);
5573 aspath
= aspath_dup(
5576 if (ri
->attr
->community
) {
5578 commerge
= community_merge(
5580 ri
->attr
->community
);
5581 community
= community_uniq_sort(
5586 community
= community_dup(
5587 ri
->attr
->community
);
5593 bgp_process(bgp
, rn
, afi
, safi
);
5595 bgp_unlock_node(top
);
5600 if (aggregate
->summary_only
)
5601 (bgp_info_extra_get(rinew
))->suppress
++;
5603 if (origin
< rinew
->attr
->origin
)
5604 origin
= rinew
->attr
->origin
;
5606 if (aggregate
->as_set
) {
5608 asmerge
= aspath_aggregate(aspath
,
5609 rinew
->attr
->aspath
);
5610 aspath_free(aspath
);
5613 aspath
= aspath_dup(rinew
->attr
->aspath
);
5615 if (rinew
->attr
->community
) {
5617 commerge
= community_merge(
5619 rinew
->attr
->community
);
5621 community_uniq_sort(commerge
);
5622 community_free(commerge
);
5624 community
= community_dup(
5625 rinew
->attr
->community
);
5630 if (aggregate
->count
> 0) {
5631 rn
= bgp_node_get(table
, p
);
5633 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5634 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5635 community
, aggregate
->as_set
,
5638 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5640 bgp_info_add(rn
, new);
5641 bgp_unlock_node(rn
);
5642 bgp_process(bgp
, rn
, afi
, safi
);
5645 aspath_free(aspath
);
5647 community_free(community
);
5651 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5652 struct bgp_aggregate
*);
5654 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5655 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5657 struct bgp_node
*child
;
5658 struct bgp_node
*rn
;
5659 struct bgp_aggregate
*aggregate
;
5660 struct bgp_table
*table
;
5662 /* MPLS-VPN aggregation is not yet supported. */
5663 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5664 || (safi
== SAFI_EVPN
))
5667 table
= bgp
->aggregate
[afi
][safi
];
5669 /* No aggregates configured. */
5670 if (bgp_table_top_nolock(table
) == NULL
)
5673 if (p
->prefixlen
== 0)
5676 if (BGP_INFO_HOLDDOWN(ri
))
5679 child
= bgp_node_get(table
, p
);
5681 /* Aggregate address configuration check. */
5682 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5683 if ((aggregate
= rn
->info
) != NULL
5684 && rn
->p
.prefixlen
< p
->prefixlen
) {
5685 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5686 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5689 bgp_unlock_node(child
);
5692 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5693 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5695 struct bgp_node
*child
;
5696 struct bgp_node
*rn
;
5697 struct bgp_aggregate
*aggregate
;
5698 struct bgp_table
*table
;
5700 /* MPLS-VPN aggregation is not yet supported. */
5701 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5702 || (safi
== SAFI_EVPN
))
5705 table
= bgp
->aggregate
[afi
][safi
];
5707 /* No aggregates configured. */
5708 if (bgp_table_top_nolock(table
) == NULL
)
5711 if (p
->prefixlen
== 0)
5714 child
= bgp_node_get(table
, p
);
5716 /* Aggregate address configuration check. */
5717 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5718 if ((aggregate
= rn
->info
) != NULL
5719 && rn
->p
.prefixlen
< p
->prefixlen
) {
5720 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5721 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5724 bgp_unlock_node(child
);
5727 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5728 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5729 safi_t safi
, struct bgp_aggregate
*aggregate
)
5731 struct bgp_table
*table
;
5732 struct bgp_node
*top
;
5733 struct bgp_node
*rn
;
5734 struct bgp_info
*new;
5735 struct bgp_info
*ri
;
5736 unsigned long match
;
5737 u_char origin
= BGP_ORIGIN_IGP
;
5738 struct aspath
*aspath
= NULL
;
5739 struct aspath
*asmerge
= NULL
;
5740 struct community
*community
= NULL
;
5741 struct community
*commerge
= NULL
;
5742 u_char atomic_aggregate
= 0;
5744 table
= bgp
->rib
[afi
][safi
];
5747 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5749 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5752 /* If routes exists below this node, generate aggregate routes. */
5753 top
= bgp_node_get(table
, p
);
5754 for (rn
= bgp_node_get(table
, p
); rn
;
5755 rn
= bgp_route_next_until(rn
, top
)) {
5756 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5761 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5762 if (BGP_INFO_HOLDDOWN(ri
))
5766 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5767 atomic_aggregate
= 1;
5769 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5772 /* summary-only aggregate route suppress
5773 * aggregated route announcement. */
5774 if (aggregate
->summary_only
) {
5775 (bgp_info_extra_get(ri
))->suppress
++;
5776 bgp_info_set_flag(rn
, ri
,
5777 BGP_INFO_ATTR_CHANGED
);
5781 /* If at least one route among routes that are
5782 * aggregated has ORIGIN with the value INCOMPLETE,
5783 * then the aggregated route MUST have the ORIGIN
5784 * attribute with the value INCOMPLETE. Otherwise, if
5785 * at least one route among routes that are aggregated
5786 * has ORIGIN with the value EGP, then the aggregated
5787 * route MUST have the ORIGIN attribute with the value
5790 if (origin
< ri
->attr
->origin
)
5791 origin
= ri
->attr
->origin
;
5793 /* as-set aggregate route generate origin, as path,
5794 * community aggregation. */
5795 if (aggregate
->as_set
) {
5797 asmerge
= aspath_aggregate(
5798 aspath
, ri
->attr
->aspath
);
5799 aspath_free(aspath
);
5802 aspath
= aspath_dup(ri
->attr
->aspath
);
5804 if (ri
->attr
->community
) {
5806 commerge
= community_merge(
5808 ri
->attr
->community
);
5809 community
= community_uniq_sort(
5811 community_free(commerge
);
5813 community
= community_dup(
5814 ri
->attr
->community
);
5820 /* If this node is suppressed, process the change. */
5822 bgp_process(bgp
, rn
, afi
, safi
);
5824 bgp_unlock_node(top
);
5826 /* Add aggregate route to BGP table. */
5827 if (aggregate
->count
) {
5828 rn
= bgp_node_get(table
, p
);
5830 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5831 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5832 community
, aggregate
->as_set
,
5835 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5837 bgp_info_add(rn
, new);
5838 bgp_unlock_node(rn
);
5840 /* Process change. */
5841 bgp_process(bgp
, rn
, afi
, safi
);
5844 aspath_free(aspath
);
5846 community_free(community
);
5850 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5851 safi_t safi
, struct bgp_aggregate
*aggregate
)
5853 struct bgp_table
*table
;
5854 struct bgp_node
*top
;
5855 struct bgp_node
*rn
;
5856 struct bgp_info
*ri
;
5857 unsigned long match
;
5859 table
= bgp
->rib
[afi
][safi
];
5861 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5863 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5866 /* If routes exists below this node, generate aggregate routes. */
5867 top
= bgp_node_get(table
, p
);
5868 for (rn
= bgp_node_get(table
, p
); rn
;
5869 rn
= bgp_route_next_until(rn
, top
)) {
5870 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5874 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5875 if (BGP_INFO_HOLDDOWN(ri
))
5878 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5881 if (aggregate
->summary_only
&& ri
->extra
) {
5882 ri
->extra
->suppress
--;
5884 if (ri
->extra
->suppress
== 0) {
5886 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5893 /* If this node was suppressed, process the change. */
5895 bgp_process(bgp
, rn
, afi
, safi
);
5897 bgp_unlock_node(top
);
5899 /* Delete aggregate route from BGP table. */
5900 rn
= bgp_node_get(table
, p
);
5902 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5903 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5904 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5907 /* Withdraw static BGP route from routing table. */
5909 bgp_info_delete(rn
, ri
);
5910 bgp_process(bgp
, rn
, afi
, safi
);
5913 /* Unlock bgp_node_lookup. */
5914 bgp_unlock_node(rn
);
5917 /* Aggregate route attribute. */
5918 #define AGGREGATE_SUMMARY_ONLY 1
5919 #define AGGREGATE_AS_SET 1
5921 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5922 afi_t afi
, safi_t safi
)
5924 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5927 struct bgp_node
*rn
;
5928 struct bgp_aggregate
*aggregate
;
5930 /* Convert string to prefix structure. */
5931 ret
= str2prefix(prefix_str
, &p
);
5933 vty_out(vty
, "Malformed prefix\n");
5934 return CMD_WARNING_CONFIG_FAILED
;
5938 /* Old configuration check. */
5939 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5942 "%% There is no aggregate-address configuration.\n");
5943 return CMD_WARNING_CONFIG_FAILED
;
5946 aggregate
= rn
->info
;
5947 if (aggregate
->safi
== SAFI_UNICAST
)
5948 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5949 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5950 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5952 if (aggregate
->safi
== SAFI_MULTICAST
)
5953 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5955 /* Unlock aggregate address configuration. */
5957 bgp_aggregate_free(aggregate
);
5958 bgp_unlock_node(rn
);
5959 bgp_unlock_node(rn
);
5964 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5965 safi_t safi
, u_char summary_only
, u_char as_set
)
5967 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5970 struct bgp_node
*rn
;
5971 struct bgp_aggregate
*aggregate
;
5973 /* Convert string to prefix structure. */
5974 ret
= str2prefix(prefix_str
, &p
);
5976 vty_out(vty
, "Malformed prefix\n");
5977 return CMD_WARNING_CONFIG_FAILED
;
5981 /* Old configuration check. */
5982 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5985 vty_out(vty
, "There is already same aggregate network.\n");
5986 /* try to remove the old entry */
5987 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5989 vty_out(vty
, "Error deleting aggregate.\n");
5990 bgp_unlock_node(rn
);
5991 return CMD_WARNING_CONFIG_FAILED
;
5995 /* Make aggregate address structure. */
5996 aggregate
= bgp_aggregate_new();
5997 aggregate
->summary_only
= summary_only
;
5998 aggregate
->as_set
= as_set
;
5999 aggregate
->safi
= safi
;
6000 rn
->info
= aggregate
;
6002 /* Aggregate address insert into BGP routing table. */
6003 if (safi
== SAFI_UNICAST
)
6004 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
6005 if (safi
== SAFI_LABELED_UNICAST
)
6006 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
6008 if (safi
== SAFI_MULTICAST
)
6009 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
6014 DEFUN (aggregate_address
,
6015 aggregate_address_cmd
,
6016 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6017 "Configure BGP aggregate entries\n"
6018 "Aggregate prefix\n"
6019 "Generate AS set path information\n"
6020 "Filter more specific routes from updates\n"
6021 "Filter more specific routes from updates\n"
6022 "Generate AS set path information\n")
6025 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6026 char *prefix
= argv
[idx
]->arg
;
6028 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6030 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6031 ? AGGREGATE_SUMMARY_ONLY
6034 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6035 summary_only
, as_set
);
6038 DEFUN (aggregate_address_mask
,
6039 aggregate_address_mask_cmd
,
6040 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6041 "Configure BGP aggregate entries\n"
6042 "Aggregate address\n"
6044 "Generate AS set path information\n"
6045 "Filter more specific routes from updates\n"
6046 "Filter more specific routes from updates\n"
6047 "Generate AS set path information\n")
6050 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6051 char *prefix
= argv
[idx
]->arg
;
6052 char *mask
= argv
[idx
+ 1]->arg
;
6054 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6056 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6057 ? AGGREGATE_SUMMARY_ONLY
6060 char prefix_str
[BUFSIZ
];
6061 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6064 vty_out(vty
, "%% Inconsistent address and mask\n");
6065 return CMD_WARNING_CONFIG_FAILED
;
6068 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6069 summary_only
, as_set
);
6072 DEFUN (no_aggregate_address
,
6073 no_aggregate_address_cmd
,
6074 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6076 "Configure BGP aggregate entries\n"
6077 "Aggregate prefix\n"
6078 "Generate AS set path information\n"
6079 "Filter more specific routes from updates\n"
6080 "Filter more specific routes from updates\n"
6081 "Generate AS set path information\n")
6084 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6085 char *prefix
= argv
[idx
]->arg
;
6086 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6089 DEFUN (no_aggregate_address_mask
,
6090 no_aggregate_address_mask_cmd
,
6091 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6093 "Configure BGP aggregate entries\n"
6094 "Aggregate address\n"
6096 "Generate AS set path information\n"
6097 "Filter more specific routes from updates\n"
6098 "Filter more specific routes from updates\n"
6099 "Generate AS set path information\n")
6102 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6103 char *prefix
= argv
[idx
]->arg
;
6104 char *mask
= argv
[idx
+ 1]->arg
;
6106 char prefix_str
[BUFSIZ
];
6107 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6110 vty_out(vty
, "%% Inconsistent address and mask\n");
6111 return CMD_WARNING_CONFIG_FAILED
;
6114 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6117 DEFUN (ipv6_aggregate_address
,
6118 ipv6_aggregate_address_cmd
,
6119 "aggregate-address X:X::X:X/M [summary-only]",
6120 "Configure BGP aggregate entries\n"
6121 "Aggregate prefix\n"
6122 "Filter more specific routes from updates\n")
6125 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6126 char *prefix
= argv
[idx
]->arg
;
6127 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6128 ? AGGREGATE_SUMMARY_ONLY
6130 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6134 DEFUN (no_ipv6_aggregate_address
,
6135 no_ipv6_aggregate_address_cmd
,
6136 "no aggregate-address X:X::X:X/M [summary-only]",
6138 "Configure BGP aggregate entries\n"
6139 "Aggregate prefix\n"
6140 "Filter more specific routes from updates\n")
6143 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6144 char *prefix
= argv
[idx
]->arg
;
6145 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6148 /* Redistribute route treatment. */
6149 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6150 const union g_addr
*nexthop
, unsigned int ifindex
,
6151 u_int32_t metric
, u_char type
, u_short instance
,
6154 struct bgp_info
*new;
6155 struct bgp_info
*bi
;
6156 struct bgp_info info
;
6157 struct bgp_node
*bn
;
6159 struct attr
*new_attr
;
6162 struct bgp_redist
*red
;
6164 /* Make default attribute. */
6165 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6167 switch (p
->family
) {
6169 attr
.nexthop
= nexthop
->ipv4
;
6172 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6173 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6176 attr
.nh_ifindex
= ifindex
;
6179 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6182 afi
= family2afi(p
->family
);
6184 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6186 struct attr attr_new
;
6188 /* Copy attribute for modification. */
6189 bgp_attr_dup(&attr_new
, &attr
);
6191 if (red
->redist_metric_flag
)
6192 attr_new
.med
= red
->redist_metric
;
6194 /* Apply route-map. */
6195 if (red
->rmap
.name
) {
6196 info
.peer
= bgp
->peer_self
;
6197 info
.attr
= &attr_new
;
6199 SET_FLAG(bgp
->peer_self
->rmap_type
,
6200 PEER_RMAP_TYPE_REDISTRIBUTE
);
6202 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6205 bgp
->peer_self
->rmap_type
= 0;
6207 if (ret
== RMAP_DENYMATCH
) {
6208 /* Free uninterned attribute. */
6209 bgp_attr_flush(&attr_new
);
6211 /* Unintern original. */
6212 aspath_unintern(&attr
.aspath
);
6213 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6218 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6219 bgp_attr_add_gshut_community(&attr_new
);
6221 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6222 SAFI_UNICAST
, p
, NULL
);
6224 new_attr
= bgp_attr_intern(&attr_new
);
6226 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6227 if (bi
->peer
== bgp
->peer_self
6228 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6232 /* Ensure the (source route) type is updated. */
6234 if (attrhash_cmp(bi
->attr
, new_attr
)
6235 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6236 bgp_attr_unintern(&new_attr
);
6237 aspath_unintern(&attr
.aspath
);
6238 bgp_unlock_node(bn
);
6241 /* The attribute is changed. */
6242 bgp_info_set_flag(bn
, bi
,
6243 BGP_INFO_ATTR_CHANGED
);
6245 /* Rewrite BGP route information. */
6246 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6247 bgp_info_restore(bn
, bi
);
6249 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6251 bgp_attr_unintern(&bi
->attr
);
6252 bi
->attr
= new_attr
;
6253 bi
->uptime
= bgp_clock();
6255 /* Process change. */
6256 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6258 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6259 bgp_unlock_node(bn
);
6260 aspath_unintern(&attr
.aspath
);
6265 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6266 bgp
->peer_self
, new_attr
, bn
);
6267 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6269 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6270 bgp_info_add(bn
, new);
6271 bgp_unlock_node(bn
);
6272 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6275 /* Unintern original. */
6276 aspath_unintern(&attr
.aspath
);
6279 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6283 struct bgp_node
*rn
;
6284 struct bgp_info
*ri
;
6285 struct bgp_redist
*red
;
6287 afi
= family2afi(p
->family
);
6289 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6291 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6292 SAFI_UNICAST
, p
, NULL
);
6294 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6295 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6299 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6300 bgp_info_delete(rn
, ri
);
6301 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6303 bgp_unlock_node(rn
);
6307 /* Withdraw specified route type's route. */
6308 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6311 struct bgp_node
*rn
;
6312 struct bgp_info
*ri
;
6313 struct bgp_table
*table
;
6315 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6317 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6318 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6319 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6320 && ri
->instance
== instance
)
6324 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6326 bgp_info_delete(rn
, ri
);
6327 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6332 /* Static function to display route. */
6333 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6337 u_int32_t destination
;
6340 if (p
->family
== AF_INET
) {
6342 len
= vty_out(vty
, "%s",
6343 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6345 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6347 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6348 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6349 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6350 || p
->u
.prefix4
.s_addr
== 0) {
6351 /* When mask is natural,
6352 mask is not displayed. */
6354 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6356 json_object_string_add(json
, "prefix",
6357 inet_ntop(p
->family
,
6360 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6362 } else if (p
->family
== AF_ETHERNET
) {
6363 prefix2str(p
, buf
, PREFIX_STRLEN
);
6364 len
= vty_out(vty
, "%s", buf
);
6365 } else if (p
->family
== AF_EVPN
) {
6366 #if defined(HAVE_CUMULUS)
6370 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6373 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6375 prefix2str(p
, buf
, PREFIX_STRLEN
);
6376 len
= vty_out(vty
, "%s", buf
);
6382 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6389 vty_out(vty
, "\n%*s", 20, " ");
6391 vty_out(vty
, "%*s", len
, " ");
6395 enum bgp_display_type
{
6399 /* Print the short form route status for a bgp_info */
6400 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6401 json_object
*json_path
)
6405 /* Route status display. */
6406 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6407 json_object_boolean_true_add(json_path
, "removed");
6409 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6410 json_object_boolean_true_add(json_path
, "stale");
6412 if (binfo
->extra
&& binfo
->extra
->suppress
)
6413 json_object_boolean_true_add(json_path
, "suppressed");
6415 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6416 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6417 json_object_boolean_true_add(json_path
, "valid");
6420 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6421 json_object_boolean_true_add(json_path
, "history");
6423 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6424 json_object_boolean_true_add(json_path
, "damped");
6426 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6427 json_object_boolean_true_add(json_path
, "bestpath");
6429 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6430 json_object_boolean_true_add(json_path
, "multipath");
6432 /* Internal route. */
6433 if ((binfo
->peer
->as
)
6434 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6435 json_object_string_add(json_path
, "pathFrom",
6438 json_object_string_add(json_path
, "pathFrom",
6444 /* Route status display. */
6445 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6447 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6449 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6451 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6452 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6458 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6460 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6462 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6464 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6469 /* Internal route. */
6470 if (binfo
->peer
&& (binfo
->peer
->as
)
6471 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6477 /* called from terminal list command */
6478 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6479 int display
, safi_t safi
, json_object
*json_paths
)
6482 json_object
*json_path
= NULL
;
6483 json_object
*json_nexthops
= NULL
;
6484 json_object
*json_nexthop_global
= NULL
;
6485 json_object
*json_nexthop_ll
= NULL
;
6488 json_path
= json_object_new_object();
6490 /* short status lead text */
6491 route_vty_short_status_out(vty
, binfo
, json_path
);
6494 /* print prefix and mask */
6496 route_vty_out_route(p
, vty
, json_path
);
6498 vty_out(vty
, "%*s", 17, " ");
6500 route_vty_out_route(p
, vty
, json_path
);
6503 /* Print attribute */
6507 * For ENCAP and EVPN routes, nexthop address family is not
6508 * neccessarily the same as the prefix address family.
6509 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6510 * EVPN routes are also exchanged with a MP nexthop. Currently,
6512 * is only IPv4, the value will be present in either
6514 * attr->mp_nexthop_global_in
6516 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6518 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6524 &attr
->mp_nexthop_global_in
,
6529 inet_ntop(af
, &attr
->mp_nexthop_global
,
6536 } else if (safi
== SAFI_EVPN
) {
6538 json_nexthop_global
= json_object_new_object();
6540 json_object_string_add(
6541 json_nexthop_global
, "ip",
6542 inet_ntoa(attr
->nexthop
));
6543 json_object_string_add(json_nexthop_global
,
6545 json_object_boolean_true_add(
6546 json_nexthop_global
, "used");
6548 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6551 else if (p
->family
== AF_INET
6552 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6554 json_nexthop_global
= json_object_new_object();
6556 if ((safi
== SAFI_MPLS_VPN
)
6557 || (safi
== SAFI_EVPN
))
6558 json_object_string_add(
6559 json_nexthop_global
, "ip",
6561 attr
->mp_nexthop_global_in
));
6563 json_object_string_add(
6564 json_nexthop_global
, "ip",
6565 inet_ntoa(attr
->nexthop
));
6567 json_object_string_add(json_nexthop_global
,
6569 json_object_boolean_true_add(
6570 json_nexthop_global
, "used");
6572 if ((safi
== SAFI_MPLS_VPN
)
6573 || (safi
== SAFI_EVPN
))
6574 vty_out(vty
, "%-16s",
6576 attr
->mp_nexthop_global_in
));
6578 vty_out(vty
, "%-16s",
6579 inet_ntoa(attr
->nexthop
));
6584 else if (p
->family
== AF_INET6
6585 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6590 json_nexthop_global
= json_object_new_object();
6591 json_object_string_add(
6592 json_nexthop_global
, "ip",
6594 &attr
->mp_nexthop_global
, buf
,
6596 json_object_string_add(json_nexthop_global
,
6598 json_object_string_add(json_nexthop_global
,
6601 /* We display both LL & GL if both have been
6603 if ((attr
->mp_nexthop_len
== 32)
6604 || (binfo
->peer
->conf_if
)) {
6606 json_object_new_object();
6607 json_object_string_add(
6608 json_nexthop_ll
, "ip",
6611 &attr
->mp_nexthop_local
,
6613 json_object_string_add(json_nexthop_ll
,
6615 json_object_string_add(json_nexthop_ll
,
6620 &attr
->mp_nexthop_global
,
6621 &attr
->mp_nexthop_local
)
6623 && !attr
->mp_nexthop_prefer_global
)
6624 json_object_boolean_true_add(
6628 json_object_boolean_true_add(
6629 json_nexthop_global
,
6632 json_object_boolean_true_add(
6633 json_nexthop_global
, "used");
6635 /* Display LL if LL/Global both in table unless
6636 * prefer-global is set */
6637 if (((attr
->mp_nexthop_len
== 32)
6638 && !attr
->mp_nexthop_prefer_global
)
6639 || (binfo
->peer
->conf_if
)) {
6640 if (binfo
->peer
->conf_if
) {
6643 binfo
->peer
->conf_if
);
6644 len
= 16 - len
; /* len of IPv6
6650 vty_out(vty
, "\n%*s",
6653 vty_out(vty
, "%*s", len
,
6660 &attr
->mp_nexthop_local
,
6665 vty_out(vty
, "\n%*s",
6668 vty_out(vty
, "%*s", len
,
6676 &attr
->mp_nexthop_global
,
6681 vty_out(vty
, "\n%*s", 36, " ");
6683 vty_out(vty
, "%*s", len
, " ");
6689 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6691 json_object_int_add(json_path
, "med",
6694 vty_out(vty
, "%10u", attr
->med
);
6695 else if (!json_paths
)
6699 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6701 json_object_int_add(json_path
, "localpref",
6704 vty_out(vty
, "%7u", attr
->local_pref
);
6705 else if (!json_paths
)
6709 json_object_int_add(json_path
, "weight", attr
->weight
);
6711 vty_out(vty
, "%7u ", attr
->weight
);
6715 json_object_string_add(json_path
, "peerId",
6716 sockunion2str(&binfo
->peer
->su
,
6724 json_object_string_add(json_path
, "aspath",
6727 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6732 json_object_string_add(
6733 json_path
, "origin",
6734 bgp_origin_long_str
[attr
->origin
]);
6736 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6739 json_object_string_add(json_path
, "alert",
6742 vty_out(vty
, "No attributes to print\n");
6746 if (json_nexthop_global
|| json_nexthop_ll
) {
6747 json_nexthops
= json_object_new_array();
6749 if (json_nexthop_global
)
6750 json_object_array_add(json_nexthops
,
6751 json_nexthop_global
);
6753 if (json_nexthop_ll
)
6754 json_object_array_add(json_nexthops
,
6757 json_object_object_add(json_path
, "nexthops",
6761 json_object_array_add(json_paths
, json_path
);
6765 /* prints an additional line, indented, with VNC info, if
6767 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6768 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6773 /* called from terminal list command */
6774 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6775 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6777 json_object
*json_status
= NULL
;
6778 json_object
*json_net
= NULL
;
6780 /* Route status display. */
6782 json_status
= json_object_new_object();
6783 json_net
= json_object_new_object();
6790 /* print prefix and mask */
6792 json_object_string_add(
6793 json_net
, "addrPrefix",
6794 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6796 route_vty_out_route(p
, vty
, NULL
);
6798 /* Print attribute */
6801 if (p
->family
== AF_INET
6802 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6803 || safi
== SAFI_EVPN
6804 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6805 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6806 || safi
== SAFI_EVPN
)
6807 json_object_string_add(
6808 json_net
, "nextHop",
6810 attr
->mp_nexthop_global_in
));
6812 json_object_string_add(
6813 json_net
, "nextHop",
6814 inet_ntoa(attr
->nexthop
));
6815 } else if (p
->family
== AF_INET6
6816 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6819 json_object_string_add(
6820 json_net
, "netHopGloabal",
6822 &attr
->mp_nexthop_global
, buf
,
6827 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6828 json_object_int_add(json_net
, "metric",
6831 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6832 json_object_int_add(json_net
, "localPref",
6835 json_object_int_add(json_net
, "weight", attr
->weight
);
6839 json_object_string_add(json_net
, "asPath",
6843 json_object_string_add(json_net
, "bgpOriginCode",
6844 bgp_origin_str
[attr
->origin
]);
6846 if (p
->family
== AF_INET
6847 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6848 || safi
== SAFI_EVPN
6849 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6850 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6851 || safi
== SAFI_EVPN
)
6852 vty_out(vty
, "%-16s",
6854 attr
->mp_nexthop_global_in
));
6856 vty_out(vty
, "%-16s",
6857 inet_ntoa(attr
->nexthop
));
6858 } else if (p
->family
== AF_INET6
6859 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6866 &attr
->mp_nexthop_global
, buf
,
6870 vty_out(vty
, "\n%*s", 36, " ");
6872 vty_out(vty
, "%*s", len
, " ");
6875 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6876 vty_out(vty
, "%10u", attr
->med
);
6880 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6881 vty_out(vty
, "%7u", attr
->local_pref
);
6885 vty_out(vty
, "%7u ", attr
->weight
);
6889 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6892 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6896 json_object_boolean_true_add(json_status
, "*");
6897 json_object_boolean_true_add(json_status
, ">");
6898 json_object_object_add(json_net
, "appliedStatusSymbols",
6900 char buf_cut
[BUFSIZ
];
6901 json_object_object_add(
6903 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6909 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6910 struct bgp_info
*binfo
, int display
, safi_t safi
,
6913 json_object
*json_out
= NULL
;
6915 mpls_label_t label
= MPLS_INVALID_LABEL
;
6921 json_out
= json_object_new_object();
6923 /* short status lead text */
6924 route_vty_short_status_out(vty
, binfo
, json_out
);
6926 /* print prefix and mask */
6929 route_vty_out_route(p
, vty
, NULL
);
6931 vty_out(vty
, "%*s", 17, " ");
6934 /* Print attribute */
6937 if (((p
->family
== AF_INET
)
6938 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6939 || (safi
== SAFI_EVPN
6940 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6941 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6942 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6943 || safi
== SAFI_EVPN
) {
6945 json_object_string_add(
6946 json_out
, "mpNexthopGlobalIn",
6948 attr
->mp_nexthop_global_in
));
6950 vty_out(vty
, "%-16s",
6952 attr
->mp_nexthop_global_in
));
6955 json_object_string_add(
6956 json_out
, "nexthop",
6957 inet_ntoa(attr
->nexthop
));
6959 vty_out(vty
, "%-16s",
6960 inet_ntoa(attr
->nexthop
));
6962 } else if (((p
->family
== AF_INET6
)
6963 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6964 || (safi
== SAFI_EVPN
6965 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6966 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6970 if (attr
->mp_nexthop_len
6971 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6973 json_object_string_add(
6974 json_out
, "mpNexthopGlobalIn",
6977 &attr
->mp_nexthop_global
,
6983 &attr
->mp_nexthop_global
,
6985 } else if (attr
->mp_nexthop_len
6986 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6989 &attr
->mp_nexthop_global
,
6992 &attr
->mp_nexthop_local
,
6994 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6995 json_object_string_add(
6997 "mpNexthopGlobalLocal", buf_c
);
6999 vty_out(vty
, "%s(%s)",
7002 &attr
->mp_nexthop_global
,
7006 &attr
->mp_nexthop_local
,
7012 label
= decode_label(&binfo
->extra
->label
);
7014 if (bgp_is_valid_label(&label
)) {
7016 json_object_int_add(json_out
, "notag", label
);
7017 json_object_array_add(json
, json_out
);
7019 vty_out(vty
, "notag/%d", label
);
7025 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7026 struct bgp_info
*binfo
, int display
,
7027 json_object
*json_paths
)
7031 json_object
*json_path
= NULL
;
7034 json_path
= json_object_new_object();
7039 /* short status lead text */
7040 route_vty_short_status_out(vty
, binfo
, json_path
);
7042 /* print prefix and mask */
7044 route_vty_out_route(p
, vty
, NULL
);
7046 vty_out(vty
, "%*s", 17, " ");
7048 /* Print attribute */
7052 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7056 vty_out(vty
, "%-16s",
7057 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7061 vty_out(vty
, "%s(%s)",
7062 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7064 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7072 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
7073 char *str
= esi2str(id
);
7074 vty_out(vty
, "%s", str
);
7075 XFREE(MTYPE_TMP
, str
);
7076 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7077 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7078 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7080 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7083 if (attr
->ecommunity
) {
7085 struct ecommunity_val
*routermac
= ecommunity_lookup(
7086 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7087 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7089 mac
= ecom_mac2str((char *)routermac
->val
);
7091 vty_out(vty
, "/%s", (char *)mac
);
7092 XFREE(MTYPE_TMP
, mac
);
7098 /* dampening route */
7099 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7100 struct bgp_info
*binfo
, int display
, safi_t safi
,
7101 u_char use_json
, json_object
*json
)
7105 char timebuf
[BGP_UPTIME_LEN
];
7107 /* short status lead text */
7108 route_vty_short_status_out(vty
, binfo
, json
);
7110 /* print prefix and mask */
7113 route_vty_out_route(p
, vty
, NULL
);
7115 vty_out(vty
, "%*s", 17, " ");
7118 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7122 vty_out(vty
, "\n%*s", 34, " ");
7125 json_object_int_add(json
, "peerHost", len
);
7127 vty_out(vty
, "%*s", len
, " ");
7131 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7134 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7138 /* Print attribute */
7144 json_object_string_add(json
, "asPath",
7147 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7152 json_object_string_add(json
, "origin",
7153 bgp_origin_str
[attr
->origin
]);
7155 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7162 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7163 struct bgp_info
*binfo
, int display
, safi_t safi
,
7164 u_char use_json
, json_object
*json
)
7167 struct bgp_damp_info
*bdi
;
7168 char timebuf
[BGP_UPTIME_LEN
];
7174 bdi
= binfo
->extra
->damp_info
;
7176 /* short status lead text */
7177 route_vty_short_status_out(vty
, binfo
, json
);
7179 /* print prefix and mask */
7182 route_vty_out_route(p
, vty
, NULL
);
7184 vty_out(vty
, "%*s", 17, " ");
7187 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7191 vty_out(vty
, "\n%*s", 33, " ");
7194 json_object_int_add(json
, "peerHost", len
);
7196 vty_out(vty
, "%*s", len
, " ");
7199 len
= vty_out(vty
, "%d", bdi
->flap
);
7206 json_object_int_add(json
, "bdiFlap", len
);
7208 vty_out(vty
, "%*s", len
, " ");
7212 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7215 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7216 BGP_UPTIME_LEN
, 0, NULL
));
7218 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7219 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7221 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7222 BGP_UPTIME_LEN
, use_json
, json
);
7225 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7230 vty_out(vty
, "%*s ", 8, " ");
7233 /* Print attribute */
7239 json_object_string_add(json
, "asPath",
7242 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7247 json_object_string_add(json
, "origin",
7248 bgp_origin_str
[attr
->origin
]);
7250 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7256 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7257 int *first
, const char *header
,
7258 json_object
*json_adv_to
)
7260 char buf1
[INET6_ADDRSTRLEN
];
7261 json_object
*json_peer
= NULL
;
7264 /* 'advertised-to' is a dictionary of peers we have advertised
7266 * prefix too. The key is the peer's IP or swpX, the value is
7268 * hostname if we know it and "" if not.
7270 json_peer
= json_object_new_object();
7273 json_object_string_add(json_peer
, "hostname",
7277 json_object_object_add(json_adv_to
, peer
->conf_if
,
7280 json_object_object_add(
7282 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7286 vty_out(vty
, "%s", header
);
7291 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7293 vty_out(vty
, " %s(%s)", peer
->hostname
,
7296 vty_out(vty
, " %s(%s)", peer
->hostname
,
7297 sockunion2str(&peer
->su
, buf1
,
7301 vty_out(vty
, " %s", peer
->conf_if
);
7304 sockunion2str(&peer
->su
, buf1
,
7310 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7311 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7312 json_object
*json_paths
)
7314 char buf
[INET6_ADDRSTRLEN
];
7316 #if defined(HAVE_CUMULUS)
7317 char buf2
[EVPN_ROUTE_STRLEN
];
7320 int sockunion_vty_out(struct vty
*, union sockunion
*);
7322 json_object
*json_bestpath
= NULL
;
7323 json_object
*json_cluster_list
= NULL
;
7324 json_object
*json_cluster_list_list
= NULL
;
7325 json_object
*json_ext_community
= NULL
;
7326 json_object
*json_lcommunity
= NULL
;
7327 json_object
*json_last_update
= NULL
;
7328 json_object
*json_nexthop_global
= NULL
;
7329 json_object
*json_nexthop_ll
= NULL
;
7330 json_object
*json_nexthops
= NULL
;
7331 json_object
*json_path
= NULL
;
7332 json_object
*json_peer
= NULL
;
7333 json_object
*json_string
= NULL
;
7334 json_object
*json_adv_to
= NULL
;
7336 struct listnode
*node
, *nnode
;
7338 int addpath_capable
;
7340 unsigned int first_as
;
7343 json_path
= json_object_new_object();
7344 json_peer
= json_object_new_object();
7345 json_nexthop_global
= json_object_new_object();
7348 #if defined(HAVE_CUMULUS)
7349 if (!json_paths
&& safi
== SAFI_EVPN
) {
7352 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7353 vty_out(vty
, " Route %s", buf2
);
7356 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7358 vty_out(vty
, " VNI %s", tag_buf
);
7361 if (binfo
->extra
&& binfo
->extra
->parent
) {
7362 struct bgp_info
*parent_ri
;
7363 struct bgp_node
*rn
, *prn
;
7365 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7366 rn
= parent_ri
->net
;
7367 if (rn
&& rn
->prn
) {
7369 vty_out(vty
, " Imported from %s:%s\n",
7371 (struct prefix_rd
*)&prn
->p
,
7372 buf1
, RD_ADDRSTRLEN
),
7382 /* Line1 display AS-path, Aggregator */
7385 json_object_lock(attr
->aspath
->json
);
7386 json_object_object_add(json_path
, "aspath",
7387 attr
->aspath
->json
);
7389 if (attr
->aspath
->segments
)
7390 aspath_print_vty(vty
, " %s",
7393 vty_out(vty
, " Local");
7397 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7399 json_object_boolean_true_add(json_path
,
7402 vty_out(vty
, ", (removed)");
7405 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7407 json_object_boolean_true_add(json_path
,
7410 vty_out(vty
, ", (stale)");
7413 if (CHECK_FLAG(attr
->flag
,
7414 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7416 json_object_int_add(json_path
, "aggregatorAs",
7417 attr
->aggregator_as
);
7418 json_object_string_add(
7419 json_path
, "aggregatorId",
7420 inet_ntoa(attr
->aggregator_addr
));
7422 vty_out(vty
, ", (aggregated by %u %s)",
7423 attr
->aggregator_as
,
7424 inet_ntoa(attr
->aggregator_addr
));
7428 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7429 PEER_FLAG_REFLECTOR_CLIENT
)) {
7431 json_object_boolean_true_add(
7432 json_path
, "rxedFromRrClient");
7434 vty_out(vty
, ", (Received from a RR-client)");
7437 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7438 PEER_FLAG_RSERVER_CLIENT
)) {
7440 json_object_boolean_true_add(
7441 json_path
, "rxedFromRsClient");
7443 vty_out(vty
, ", (Received from a RS-client)");
7446 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7448 json_object_boolean_true_add(
7449 json_path
, "dampeningHistoryEntry");
7451 vty_out(vty
, ", (history entry)");
7452 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7454 json_object_boolean_true_add(
7455 json_path
, "dampeningSuppressed");
7457 vty_out(vty
, ", (suppressed due to dampening)");
7463 /* Line2 display Next-hop, Neighbor, Router-id */
7464 /* Display the nexthop */
7465 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
7466 p
->family
== AF_EVPN
)
7467 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7468 || safi
== SAFI_EVPN
7469 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7470 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7471 || safi
== SAFI_EVPN
) {
7473 json_object_string_add(
7474 json_nexthop_global
, "ip",
7476 attr
->mp_nexthop_global_in
));
7480 attr
->mp_nexthop_global_in
));
7483 json_object_string_add(
7484 json_nexthop_global
, "ip",
7485 inet_ntoa(attr
->nexthop
));
7488 inet_ntoa(attr
->nexthop
));
7492 json_object_string_add(json_nexthop_global
,
7496 json_object_string_add(
7497 json_nexthop_global
, "ip",
7499 &attr
->mp_nexthop_global
, buf
,
7501 json_object_string_add(json_nexthop_global
,
7503 json_object_string_add(json_nexthop_global
,
7508 &attr
->mp_nexthop_global
, buf
,
7513 /* Display the IGP cost or 'inaccessible' */
7514 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7516 json_object_boolean_false_add(
7517 json_nexthop_global
, "accessible");
7519 vty_out(vty
, " (inaccessible)");
7521 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7523 json_object_int_add(
7524 json_nexthop_global
, "metric",
7525 binfo
->extra
->igpmetric
);
7527 vty_out(vty
, " (metric %u)",
7528 binfo
->extra
->igpmetric
);
7531 /* IGP cost is 0, display this only for json */
7534 json_object_int_add(json_nexthop_global
,
7539 json_object_boolean_true_add(
7540 json_nexthop_global
, "accessible");
7543 /* Display peer "from" output */
7544 /* This path was originated locally */
7545 if (binfo
->peer
== bgp
->peer_self
) {
7547 if (safi
== SAFI_EVPN
7548 || (p
->family
== AF_INET
7549 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7551 json_object_string_add(
7552 json_peer
, "peerId", "0.0.0.0");
7554 vty_out(vty
, " from 0.0.0.0 ");
7557 json_object_string_add(json_peer
,
7560 vty_out(vty
, " from :: ");
7564 json_object_string_add(
7565 json_peer
, "routerId",
7566 inet_ntoa(bgp
->router_id
));
7568 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7571 /* We RXed this path from one of our peers */
7575 json_object_string_add(
7576 json_peer
, "peerId",
7577 sockunion2str(&binfo
->peer
->su
, buf
,
7579 json_object_string_add(
7580 json_peer
, "routerId",
7582 &binfo
->peer
->remote_id
, buf1
,
7585 if (binfo
->peer
->hostname
)
7586 json_object_string_add(
7587 json_peer
, "hostname",
7588 binfo
->peer
->hostname
);
7590 if (binfo
->peer
->domainname
)
7591 json_object_string_add(
7592 json_peer
, "domainname",
7593 binfo
->peer
->domainname
);
7595 if (binfo
->peer
->conf_if
)
7596 json_object_string_add(
7597 json_peer
, "interface",
7598 binfo
->peer
->conf_if
);
7600 if (binfo
->peer
->conf_if
) {
7601 if (binfo
->peer
->hostname
7604 BGP_FLAG_SHOW_HOSTNAME
))
7605 vty_out(vty
, " from %s(%s)",
7606 binfo
->peer
->hostname
,
7607 binfo
->peer
->conf_if
);
7609 vty_out(vty
, " from %s",
7610 binfo
->peer
->conf_if
);
7612 if (binfo
->peer
->hostname
7615 BGP_FLAG_SHOW_HOSTNAME
))
7616 vty_out(vty
, " from %s(%s)",
7617 binfo
->peer
->hostname
,
7620 vty_out(vty
, " from %s",
7629 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7630 vty_out(vty
, " (%s)",
7631 inet_ntoa(attr
->originator_id
));
7633 vty_out(vty
, " (%s)",
7636 &binfo
->peer
->remote_id
,
7644 /* display the link-local nexthop */
7645 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7647 json_nexthop_ll
= json_object_new_object();
7648 json_object_string_add(
7649 json_nexthop_ll
, "ip",
7651 &attr
->mp_nexthop_local
, buf
,
7653 json_object_string_add(json_nexthop_ll
, "afi",
7655 json_object_string_add(json_nexthop_ll
, "scope",
7658 json_object_boolean_true_add(json_nexthop_ll
,
7661 if (!attr
->mp_nexthop_prefer_global
)
7662 json_object_boolean_true_add(
7663 json_nexthop_ll
, "used");
7665 json_object_boolean_true_add(
7666 json_nexthop_global
, "used");
7668 vty_out(vty
, " (%s) %s\n",
7670 &attr
->mp_nexthop_local
, buf
,
7672 attr
->mp_nexthop_prefer_global
7677 /* If we do not have a link-local nexthop then we must flag the
7681 json_object_boolean_true_add(
7682 json_nexthop_global
, "used");
7685 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7686 * Int/Ext/Local, Atomic, best */
7688 json_object_string_add(
7689 json_path
, "origin",
7690 bgp_origin_long_str
[attr
->origin
]);
7692 vty_out(vty
, " Origin %s",
7693 bgp_origin_long_str
[attr
->origin
]);
7695 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7697 json_object_int_add(json_path
, "med",
7700 vty_out(vty
, ", metric %u", attr
->med
);
7703 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7705 json_object_int_add(json_path
, "localpref",
7708 vty_out(vty
, ", localpref %u",
7712 json_object_int_add(json_path
, "localpref",
7713 bgp
->default_local_pref
);
7715 vty_out(vty
, ", localpref %u",
7716 bgp
->default_local_pref
);
7719 if (attr
->weight
!= 0) {
7721 json_object_int_add(json_path
, "weight",
7724 vty_out(vty
, ", weight %u", attr
->weight
);
7727 if (attr
->tag
!= 0) {
7729 json_object_int_add(json_path
, "tag",
7732 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7736 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7738 json_object_boolean_false_add(json_path
,
7741 vty_out(vty
, ", invalid");
7742 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7744 json_object_boolean_true_add(json_path
,
7747 vty_out(vty
, ", valid");
7750 if (binfo
->peer
!= bgp
->peer_self
) {
7751 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7752 if (CHECK_FLAG(bgp
->config
,
7753 BGP_CONFIG_CONFEDERATION
)) {
7755 json_object_string_add(
7760 ", confed-internal");
7763 json_object_string_add(
7767 vty_out(vty
, ", internal");
7770 if (bgp_confederation_peers_check(
7771 bgp
, binfo
->peer
->as
)) {
7773 json_object_string_add(
7778 ", confed-external");
7781 json_object_string_add(
7785 vty_out(vty
, ", external");
7788 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7790 json_object_boolean_true_add(json_path
,
7792 json_object_boolean_true_add(json_path
,
7795 vty_out(vty
, ", aggregated, local");
7797 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7799 json_object_boolean_true_add(json_path
,
7802 vty_out(vty
, ", sourced");
7805 json_object_boolean_true_add(json_path
,
7807 json_object_boolean_true_add(json_path
,
7810 vty_out(vty
, ", sourced, local");
7814 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7816 json_object_boolean_true_add(json_path
,
7819 vty_out(vty
, ", atomic-aggregate");
7822 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7823 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7824 && bgp_info_mpath_count(binfo
))) {
7826 json_object_boolean_true_add(json_path
,
7829 vty_out(vty
, ", multipath");
7832 // Mark the bestpath(s)
7833 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7834 first_as
= aspath_get_first_as(attr
->aspath
);
7839 json_object_new_object();
7840 json_object_int_add(json_bestpath
,
7841 "bestpathFromAs", first_as
);
7844 vty_out(vty
, ", bestpath-from-AS %d",
7848 ", bestpath-from-AS Local");
7852 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7856 json_object_new_object();
7857 json_object_boolean_true_add(json_bestpath
,
7860 vty_out(vty
, ", best");
7864 json_object_object_add(json_path
, "bestpath",
7870 /* Line 4 display Community */
7871 if (attr
->community
) {
7873 json_object_lock(attr
->community
->json
);
7874 json_object_object_add(json_path
, "community",
7875 attr
->community
->json
);
7877 vty_out(vty
, " Community: %s\n",
7878 attr
->community
->str
);
7882 /* Line 5 display Extended-community */
7883 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7885 json_ext_community
= json_object_new_object();
7886 json_object_string_add(json_ext_community
,
7888 attr
->ecommunity
->str
);
7889 json_object_object_add(json_path
,
7890 "extendedCommunity",
7891 json_ext_community
);
7893 vty_out(vty
, " Extended Community: %s\n",
7894 attr
->ecommunity
->str
);
7898 /* Line 6 display Large community */
7899 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7901 json_lcommunity
= json_object_new_object();
7902 json_object_string_add(json_lcommunity
,
7904 attr
->lcommunity
->str
);
7905 json_object_object_add(json_path
,
7909 vty_out(vty
, " Large Community: %s\n",
7910 attr
->lcommunity
->str
);
7914 /* Line 7 display Originator, Cluster-id */
7915 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7916 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7918 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7920 json_object_string_add(
7921 json_path
, "originatorId",
7922 inet_ntoa(attr
->originator_id
));
7924 vty_out(vty
, " Originator: %s",
7925 inet_ntoa(attr
->originator_id
));
7928 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7933 json_object_new_object();
7934 json_cluster_list_list
=
7935 json_object_new_array();
7938 i
< attr
->cluster
->length
/ 4;
7940 json_string
= json_object_new_string(
7944 json_object_array_add(
7945 json_cluster_list_list
,
7949 /* struct cluster_list does not have
7951 * aspath and community do. Add this
7954 json_object_string_add(json_cluster_list,
7955 "string", attr->cluster->str);
7957 json_object_object_add(
7958 json_cluster_list
, "list",
7959 json_cluster_list_list
);
7960 json_object_object_add(
7961 json_path
, "clusterList",
7964 vty_out(vty
, ", Cluster list: ");
7967 i
< attr
->cluster
->length
/ 4;
7981 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7982 bgp_damp_info_vty(vty
, binfo
, json_path
);
7985 #if defined(HAVE_CUMULUS)
7986 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7987 && safi
!= SAFI_EVPN
)
7989 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
7992 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
7994 json_object_int_add(json_path
, "remoteLabel",
7997 vty_out(vty
, " Remote label: %d\n", label
);
8001 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8003 json_object_int_add(json_path
, "labelIndex",
8006 vty_out(vty
, " Label Index: %d\n",
8010 /* Line 8 display Addpath IDs */
8011 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8013 json_object_int_add(json_path
, "addpathRxId",
8014 binfo
->addpath_rx_id
);
8015 json_object_int_add(json_path
, "addpathTxId",
8016 binfo
->addpath_tx_id
);
8018 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8019 binfo
->addpath_rx_id
,
8020 binfo
->addpath_tx_id
);
8024 /* If we used addpath to TX a non-bestpath we need to display
8025 * "Advertised to" on a path-by-path basis */
8026 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8029 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8031 bgp_addpath_encode_tx(peer
, afi
, safi
);
8032 has_adj
= bgp_adj_out_lookup(
8033 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8035 if ((addpath_capable
&& has_adj
)
8036 || (!addpath_capable
&& has_adj
8037 && CHECK_FLAG(binfo
->flags
,
8038 BGP_INFO_SELECTED
))) {
8039 if (json_path
&& !json_adv_to
)
8041 json_object_new_object();
8043 route_vty_out_advertised_to(
8052 json_object_object_add(json_path
,
8063 /* Line 9 display Uptime */
8064 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8066 json_last_update
= json_object_new_object();
8067 json_object_int_add(json_last_update
, "epoch", tbuf
);
8068 json_object_string_add(json_last_update
, "string",
8070 json_object_object_add(json_path
, "lastUpdate",
8073 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8076 /* We've constructed the json object for this path, add it to the json
8080 if (json_nexthop_global
|| json_nexthop_ll
) {
8081 json_nexthops
= json_object_new_array();
8083 if (json_nexthop_global
)
8084 json_object_array_add(json_nexthops
,
8085 json_nexthop_global
);
8087 if (json_nexthop_ll
)
8088 json_object_array_add(json_nexthops
,
8091 json_object_object_add(json_path
, "nexthops",
8095 json_object_object_add(json_path
, "peer", json_peer
);
8096 json_object_array_add(json_paths
, json_path
);
8101 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8102 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8103 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8105 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8106 const char *prefix_list_str
, afi_t afi
,
8107 safi_t safi
, enum bgp_show_type type
);
8108 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8109 const char *filter
, afi_t afi
, safi_t safi
,
8110 enum bgp_show_type type
);
8111 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8112 const char *rmap_str
, afi_t afi
, safi_t safi
,
8113 enum bgp_show_type type
);
8114 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8115 const char *com
, int exact
, afi_t afi
,
8117 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8118 const char *prefix
, afi_t afi
, safi_t safi
,
8119 enum bgp_show_type type
);
8120 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
8121 const char *regstr
, afi_t afi
,
8122 safi_t safi
, enum bgp_show_type type
);
8123 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8124 const char *comstr
, int exact
, afi_t afi
,
8127 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
,
8128 struct bgp_table
*table
, enum bgp_show_type type
,
8129 void *output_arg
, u_char use_json
)
8131 struct bgp_info
*ri
;
8132 struct bgp_node
*rn
;
8135 unsigned long output_count
;
8136 unsigned long total_count
;
8140 json_object
*json_paths
= NULL
;
8145 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
8146 ", \"routerId\": \"%s\", \"routes\": { ",
8147 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
8148 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8150 table
->version
, inet_ntoa(bgp
->router_id
));
8151 json_paths
= json_object_new_object();
8154 /* This is first entry point, so reset total line. */
8158 /* Start processing of routes. */
8159 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
8160 if (rn
->info
!= NULL
) {
8162 if (!first
&& use_json
) {
8166 json_paths
= json_object_new_array();
8170 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8172 if (type
== bgp_show_type_flap_statistics
8173 || type
== bgp_show_type_flap_neighbor
8174 || type
== bgp_show_type_dampend_paths
8175 || type
== bgp_show_type_damp_neighbor
) {
8177 && ri
->extra
->damp_info
))
8180 if (type
== bgp_show_type_regexp
) {
8181 regex_t
*regex
= output_arg
;
8183 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8187 if (type
== bgp_show_type_prefix_list
) {
8188 struct prefix_list
*plist
= output_arg
;
8190 if (prefix_list_apply(plist
, &rn
->p
)
8194 if (type
== bgp_show_type_filter_list
) {
8195 struct as_list
*as_list
= output_arg
;
8197 if (as_list_apply(as_list
,
8199 != AS_FILTER_PERMIT
)
8202 if (type
== bgp_show_type_route_map
) {
8203 struct route_map
*rmap
= output_arg
;
8204 struct bgp_info binfo
;
8205 struct attr dummy_attr
;
8208 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8210 binfo
.peer
= ri
->peer
;
8211 binfo
.attr
= &dummy_attr
;
8213 ret
= route_map_apply(rmap
, &rn
->p
,
8215 if (ret
== RMAP_DENYMATCH
)
8218 if (type
== bgp_show_type_neighbor
8219 || type
== bgp_show_type_flap_neighbor
8220 || type
== bgp_show_type_damp_neighbor
) {
8221 union sockunion
*su
= output_arg
;
8223 if (ri
->peer
== NULL
8224 || ri
->peer
->su_remote
== NULL
8226 ri
->peer
->su_remote
, su
))
8229 if (type
== bgp_show_type_cidr_only
) {
8230 u_int32_t destination
;
8233 ntohl(rn
->p
.u
.prefix4
.s_addr
);
8234 if (IN_CLASSC(destination
)
8235 && rn
->p
.prefixlen
== 24)
8237 if (IN_CLASSB(destination
)
8238 && rn
->p
.prefixlen
== 16)
8240 if (IN_CLASSA(destination
)
8241 && rn
->p
.prefixlen
== 8)
8244 if (type
== bgp_show_type_prefix_longer
) {
8245 struct prefix
*p
= output_arg
;
8247 if (!prefix_match(p
, &rn
->p
))
8250 if (type
== bgp_show_type_community_all
) {
8251 if (!ri
->attr
->community
)
8254 if (type
== bgp_show_type_community
) {
8255 struct community
*com
= output_arg
;
8257 if (!ri
->attr
->community
8258 || !community_match(
8259 ri
->attr
->community
,
8263 if (type
== bgp_show_type_community_exact
) {
8264 struct community
*com
= output_arg
;
8266 if (!ri
->attr
->community
8268 ri
->attr
->community
,
8272 if (type
== bgp_show_type_community_list
) {
8273 struct community_list
*list
=
8276 if (!community_list_match(
8277 ri
->attr
->community
, list
))
8281 == bgp_show_type_community_list_exact
) {
8282 struct community_list
*list
=
8285 if (!community_list_exact_match(
8286 ri
->attr
->community
, list
))
8289 if (type
== bgp_show_type_lcommunity
) {
8290 struct lcommunity
*lcom
= output_arg
;
8292 if (!ri
->attr
->lcommunity
8293 || !lcommunity_match(
8294 ri
->attr
->lcommunity
,
8298 if (type
== bgp_show_type_lcommunity_list
) {
8299 struct community_list
*list
=
8302 if (!lcommunity_list_match(
8303 ri
->attr
->lcommunity
, list
))
8306 if (type
== bgp_show_type_lcommunity_all
) {
8307 if (!ri
->attr
->lcommunity
)
8310 if (type
== bgp_show_type_dampend_paths
8311 || type
== bgp_show_type_damp_neighbor
) {
8312 if (!CHECK_FLAG(ri
->flags
,
8314 || CHECK_FLAG(ri
->flags
,
8319 if (!use_json
&& header
) {
8321 "BGP table version is %" PRIu64
8322 ", local router ID is %s\n",
8324 inet_ntoa(bgp
->router_id
));
8325 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8326 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8327 if (type
== bgp_show_type_dampend_paths
8328 || type
== bgp_show_type_damp_neighbor
)
8330 BGP_SHOW_DAMP_HEADER
);
8332 type
== bgp_show_type_flap_statistics
8333 || type
== bgp_show_type_flap_neighbor
)
8335 BGP_SHOW_FLAP_HEADER
);
8337 vty_out(vty
, BGP_SHOW_HEADER
);
8341 if (type
== bgp_show_type_dampend_paths
8342 || type
== bgp_show_type_damp_neighbor
)
8344 vty
, &rn
->p
, ri
, display
,
8345 SAFI_UNICAST
, use_json
,
8347 else if (type
== bgp_show_type_flap_statistics
8348 || type
== bgp_show_type_flap_neighbor
)
8350 vty
, &rn
->p
, ri
, display
,
8351 SAFI_UNICAST
, use_json
,
8354 route_vty_out(vty
, &rn
->p
, ri
, display
,
8355 SAFI_UNICAST
, json_paths
);
8363 sprintf(buf2
, "%s/%d",
8364 inet_ntop(p
->family
,
8368 vty_out(vty
, "\"%s\": ", buf2
);
8370 json_object_to_json_string(
8372 json_object_free(json_paths
);
8379 json_object_free(json_paths
);
8380 vty_out(vty
, " } }\n");
8382 /* No route is displayed */
8383 if (output_count
== 0) {
8384 if (type
== bgp_show_type_normal
)
8386 "No BGP prefixes displayed, %ld exist\n",
8390 "\nDisplayed %ld routes and %ld total paths\n",
8391 output_count
, total_count
);
8397 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8398 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8400 struct bgp_table
*table
;
8403 bgp
= bgp_get_default();
8408 vty_out(vty
, "No BGP process is configured\n");
8410 vty_out(vty
, "{}\n");
8414 /* use MPLS and ENCAP specific shows until they are merged */
8415 if (safi
== SAFI_MPLS_VPN
) {
8416 return bgp_show_mpls_vpn(vty
, afi
, NULL
, type
, output_arg
, 0,
8419 /* labeled-unicast routes live in the unicast table */
8420 else if (safi
== SAFI_LABELED_UNICAST
)
8421 safi
= SAFI_UNICAST
;
8423 table
= bgp
->rib
[afi
][safi
];
8425 return bgp_show_table(vty
, bgp
, table
, type
, output_arg
, use_json
);
8428 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8429 safi_t safi
, u_char use_json
)
8431 struct listnode
*node
, *nnode
;
8436 vty_out(vty
, "{\n");
8438 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8441 vty_out(vty
, ",\n");
8445 vty_out(vty
, "\"%s\":",
8446 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8450 vty_out(vty
, "\nInstance %s:\n",
8451 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8455 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8460 vty_out(vty
, "}\n");
8463 /* Header of detailed BGP route information */
8464 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8465 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8466 afi_t afi
, safi_t safi
, json_object
*json
)
8468 struct bgp_info
*ri
;
8471 struct listnode
*node
, *nnode
;
8472 char buf1
[INET6_ADDRSTRLEN
];
8473 char buf2
[INET6_ADDRSTRLEN
];
8474 #if defined(HAVE_CUMULUS)
8475 char buf3
[EVPN_ROUTE_STRLEN
];
8477 char prefix_str
[BUFSIZ
];
8482 int no_advertise
= 0;
8485 int has_valid_label
= 0;
8486 mpls_label_t label
= 0;
8487 json_object
*json_adv_to
= NULL
;
8490 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8492 if (has_valid_label
)
8493 label
= label_pton(&rn
->local_label
);
8496 if (has_valid_label
)
8497 json_object_int_add(json
, "localLabel", label
);
8499 json_object_string_add(
8501 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8503 #if defined(HAVE_CUMULUS)
8504 if (safi
== SAFI_EVPN
)
8505 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8506 prd
? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8509 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8510 buf3
, sizeof(buf3
)));
8512 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8513 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8514 ? prefix_rd2str(prd
, buf1
,
8517 safi
== SAFI_MPLS_VPN
? ":" : "",
8518 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8522 if (p
->family
== AF_ETHERNET
)
8523 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8525 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8527 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8528 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8529 || safi
== SAFI_EVPN
)
8530 ? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8532 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8534 buf2
, p
->prefixlen
);
8537 if (has_valid_label
)
8538 vty_out(vty
, "Local label: %d\n", label
);
8539 #if defined(HAVE_CUMULUS)
8540 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8542 if (bgp_labeled_safi(safi
))
8544 vty_out(vty
, "not allocated\n");
8547 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8549 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8551 if (ri
->extra
&& ri
->extra
->suppress
)
8553 if (ri
->attr
->community
!= NULL
) {
8554 if (community_include(ri
->attr
->community
,
8555 COMMUNITY_NO_ADVERTISE
))
8557 if (community_include(ri
->attr
->community
,
8558 COMMUNITY_NO_EXPORT
))
8560 if (community_include(ri
->attr
->community
,
8561 COMMUNITY_LOCAL_AS
))
8568 vty_out(vty
, "Paths: (%d available", count
);
8570 vty_out(vty
, ", best #%d", best
);
8571 if (safi
== SAFI_UNICAST
)
8572 vty_out(vty
, ", table %s",
8574 == BGP_INSTANCE_TYPE_DEFAULT
)
8575 ? "Default-IP-Routing-Table"
8578 vty_out(vty
, ", no best path");
8581 vty_out(vty
, ", not advertised to any peer");
8583 vty_out(vty
, ", not advertised to EBGP peer");
8585 vty_out(vty
, ", not advertised outside local AS");
8589 ", Advertisements suppressed by an aggregate.");
8590 vty_out(vty
, ")\n");
8593 /* If we are not using addpath then we can display Advertised to and
8595 * show what peers we advertised the bestpath to. If we are using
8597 * though then we must display Advertised to on a path-by-path basis. */
8598 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8599 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8600 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8601 if (json
&& !json_adv_to
)
8602 json_adv_to
= json_object_new_object();
8604 route_vty_out_advertised_to(
8606 " Advertised to non peer-group peers:\n ",
8613 json_object_object_add(json
, "advertisedTo",
8618 vty_out(vty
, " Not advertised to any peer");
8624 /* Display specified route of BGP table. */
8625 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8626 struct bgp_table
*rib
, const char *ip_str
,
8627 afi_t afi
, safi_t safi
,
8628 struct prefix_rd
*prd
, int prefix_check
,
8629 enum bgp_path_type pathtype
, u_char use_json
)
8634 struct prefix match
;
8635 struct bgp_node
*rn
;
8636 struct bgp_node
*rm
;
8637 struct bgp_info
*ri
;
8638 struct bgp_table
*table
;
8639 json_object
*json
= NULL
;
8640 json_object
*json_paths
= NULL
;
8642 /* Check IP address argument. */
8643 ret
= str2prefix(ip_str
, &match
);
8645 vty_out(vty
, "address is malformed\n");
8649 match
.family
= afi2family(afi
);
8652 json
= json_object_new_object();
8653 json_paths
= json_object_new_array();
8656 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8657 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8658 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8661 if ((table
= rn
->info
) == NULL
)
8666 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8670 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8671 bgp_unlock_node(rm
);
8675 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8677 route_vty_out_detail_header(
8679 (struct prefix_rd
*)&rn
->p
,
8680 AFI_IP
, safi
, json
);
8685 if (pathtype
== BGP_PATH_ALL
8686 || (pathtype
== BGP_PATH_BESTPATH
8687 && CHECK_FLAG(ri
->flags
,
8689 || (pathtype
== BGP_PATH_MULTIPATH
8690 && (CHECK_FLAG(ri
->flags
,
8692 || CHECK_FLAG(ri
->flags
,
8693 BGP_INFO_SELECTED
))))
8694 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8699 bgp_unlock_node(rm
);
8704 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8706 || rn
->p
.prefixlen
== match
.prefixlen
) {
8707 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8709 route_vty_out_detail_header(
8710 vty
, bgp
, rn
, NULL
, afi
,
8716 if (pathtype
== BGP_PATH_ALL
8717 || (pathtype
== BGP_PATH_BESTPATH
8721 || (pathtype
== BGP_PATH_MULTIPATH
8727 BGP_INFO_SELECTED
))))
8728 route_vty_out_detail(
8729 vty
, bgp
, &rn
->p
, ri
,
8730 afi
, safi
, json_paths
);
8734 bgp_unlock_node(rn
);
8740 json_object_object_add(json
, "paths", json_paths
);
8742 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8743 json
, JSON_C_TO_STRING_PRETTY
));
8744 json_object_free(json
);
8747 vty_out(vty
, "%% Network not in table\n");
8755 /* Display specified route of Main RIB */
8756 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8757 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8758 int prefix_check
, enum bgp_path_type pathtype
,
8762 bgp
= bgp_get_default();
8765 vty_out(vty
, "No BGP process is configured\n");
8767 vty_out(vty
, "{}\n");
8772 /* labeled-unicast routes live in the unicast table */
8773 if (safi
== SAFI_LABELED_UNICAST
)
8774 safi
= SAFI_UNICAST
;
8776 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8777 afi
, safi
, prd
, prefix_check
, pathtype
,
8781 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8782 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8785 struct lcommunity
*lcom
;
8791 b
= buffer_new(1024);
8792 for (i
= 0; i
< argc
; i
++) {
8794 buffer_putc(b
, ' ');
8796 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8798 buffer_putstr(b
, argv
[i
]->arg
);
8802 buffer_putc(b
, '\0');
8804 str
= buffer_getstr(b
);
8807 lcom
= lcommunity_str2com(str
);
8808 XFREE(MTYPE_TMP
, str
);
8810 vty_out(vty
, "%% Large-community malformed\n");
8814 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8818 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8819 const char *lcom
, afi_t afi
, safi_t safi
,
8822 struct community_list
*list
;
8824 list
= community_list_lookup(bgp_clist
, lcom
,
8825 LARGE_COMMUNITY_LIST_MASTER
);
8827 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8832 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8836 DEFUN (show_ip_bgp_large_community_list
,
8837 show_ip_bgp_large_community_list_cmd
,
8838 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8842 BGP_INSTANCE_HELP_STR
8844 BGP_SAFI_WITH_LABEL_HELP_STR
8845 "Display routes matching the large-community-list\n"
8846 "large-community-list number\n"
8847 "large-community-list name\n"
8851 afi_t afi
= AFI_IP6
;
8852 safi_t safi
= SAFI_UNICAST
;
8855 if (argv_find(argv
, argc
, "ip", &idx
))
8857 if (argv_find(argv
, argc
, "view", &idx
)
8858 || argv_find(argv
, argc
, "vrf", &idx
))
8859 vrf
= argv
[++idx
]->arg
;
8860 if (argv_find(argv
, argc
, "ipv4", &idx
)
8861 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8862 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8863 if (argv_find(argv
, argc
, "unicast", &idx
)
8864 || argv_find(argv
, argc
, "multicast", &idx
))
8865 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8868 int uj
= use_json(argc
, argv
);
8870 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8872 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8876 argv_find(argv
, argc
, "large-community-list", &idx
);
8877 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8880 DEFUN (show_ip_bgp_large_community
,
8881 show_ip_bgp_large_community_cmd
,
8882 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8886 BGP_INSTANCE_HELP_STR
8888 BGP_SAFI_WITH_LABEL_HELP_STR
8889 "Display routes matching the large-communities\n"
8890 "List of large-community numbers\n"
8894 afi_t afi
= AFI_IP6
;
8895 safi_t safi
= SAFI_UNICAST
;
8898 if (argv_find(argv
, argc
, "ip", &idx
))
8900 if (argv_find(argv
, argc
, "view", &idx
)
8901 || argv_find(argv
, argc
, "vrf", &idx
))
8902 vrf
= argv
[++idx
]->arg
;
8903 if (argv_find(argv
, argc
, "ipv4", &idx
)
8904 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8905 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8906 if (argv_find(argv
, argc
, "unicast", &idx
)
8907 || argv_find(argv
, argc
, "multicast", &idx
))
8908 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8911 int uj
= use_json(argc
, argv
);
8913 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8915 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8919 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8920 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8922 return bgp_show(vty
, bgp
, afi
, safi
,
8923 bgp_show_type_lcommunity_all
, NULL
, uj
);
8926 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8930 /* BGP route print out function without JSON */
8933 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8934 <dampening <parameters>\
8939 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
8940 |community-list <(1-500)|WORD> [exact-match]\
8941 |A.B.C.D/M longer-prefixes\
8942 |X:X::X:X/M longer-prefixes\
8947 BGP_INSTANCE_HELP_STR
8949 BGP_SAFI_WITH_LABEL_HELP_STR
8950 "Display detailed information about dampening\n"
8951 "Display detail of configured dampening parameters\n"
8952 "Display routes matching the route-map\n"
8953 "A route-map to match on\n"
8954 "Display routes conforming to the prefix-list\n"
8955 "Prefix-list name\n"
8956 "Display routes conforming to the filter-list\n"
8957 "Regular expression access list name\n"
8958 "BGP RIB advertisement statistics\n"
8959 "Display routes matching the communities\n"
8961 "Do not send outside local AS (well-known community)\n"
8962 "Do not advertise to any peer (well-known community)\n"
8963 "Do not export to next AS (well-known community)\n"
8964 "Graceful shutdown (well-known community)\n"
8965 "Exact match of the communities\n"
8966 "Display routes matching the community-list\n"
8967 "community-list number\n"
8968 "community-list name\n"
8969 "Exact match of the communities\n"
8971 "Display route and more specific routes\n"
8973 "Display route and more specific routes\n")
8975 afi_t afi
= AFI_IP6
;
8976 safi_t safi
= SAFI_UNICAST
;
8977 int exact_match
= 0;
8978 struct bgp
*bgp
= NULL
;
8980 int idx_community_type
= 0;
8982 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8987 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8988 if (argv_find(argv
, argc
, "parameters", &idx
))
8989 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8992 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8993 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8994 safi
, bgp_show_type_prefix_list
);
8996 if (argv_find(argv
, argc
, "filter-list", &idx
))
8997 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8998 safi
, bgp_show_type_filter_list
);
9000 if (argv_find(argv
, argc
, "statistics", &idx
))
9001 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9003 if (argv_find(argv
, argc
, "route-map", &idx
))
9004 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9005 safi
, bgp_show_type_route_map
);
9007 if (argv_find(argv
, argc
, "community", &idx
)) {
9008 /* show a specific community */
9009 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9010 || argv_find(argv
, argc
, "no-advertise", &idx_community_type
)
9011 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9012 || argv_find(argv
, argc
, "graceful-shutdown", &idx_community_type
)
9013 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9015 if (argv_find(argv
, argc
, "exact-match", &idx
))
9017 return bgp_show_community(vty
, bgp
, argv
[idx_community_type
]->arg
,
9018 exact_match
, afi
, safi
);
9022 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9023 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9024 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9026 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9027 exact_match
, afi
, safi
);
9030 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9031 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9032 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9034 bgp_show_type_prefix_longer
);
9039 /* BGP route print out function with JSON */
9040 DEFUN (show_ip_bgp_json
,
9041 show_ip_bgp_json_cmd
,
9042 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9045 |dampening <flap-statistics|dampened-paths>\
9051 BGP_INSTANCE_HELP_STR
9053 BGP_SAFI_WITH_LABEL_HELP_STR
9054 "Display only routes with non-natural netmasks\n"
9055 "Display detailed information about dampening\n"
9056 "Display flap statistics of routes\n"
9057 "Display paths suppressed due to dampening\n"
9058 "Display routes matching the communities\n"
9061 afi_t afi
= AFI_IP6
;
9062 safi_t safi
= SAFI_UNICAST
;
9063 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9064 struct bgp
*bgp
= NULL
;
9067 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9072 int uj
= use_json(argc
, argv
);
9076 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9077 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9080 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9081 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9082 return bgp_show(vty
, bgp
, afi
, safi
,
9083 bgp_show_type_dampend_paths
, NULL
, uj
);
9084 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9085 return bgp_show(vty
, bgp
, afi
, safi
,
9086 bgp_show_type_flap_statistics
, NULL
,
9090 if (argv_find(argv
, argc
, "community", &idx
)) {
9091 /* show all communities */
9092 return bgp_show(vty
, bgp
, afi
, safi
,
9093 bgp_show_type_community_all
, NULL
, uj
);
9096 if (safi
== SAFI_MPLS_VPN
)
9097 return bgp_show_mpls_vpn(vty
, afi
, NULL
, bgp_show_type_normal
,
9100 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9103 DEFUN (show_ip_bgp_route
,
9104 show_ip_bgp_route_cmd
,
9105 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9106 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9110 BGP_INSTANCE_HELP_STR
9112 BGP_SAFI_WITH_LABEL_HELP_STR
9113 "Network in the BGP routing table to display\n"
9115 "Network in the BGP routing table to display\n"
9117 "Display only the bestpath\n"
9118 "Display only multipaths\n"
9121 int prefix_check
= 0;
9123 afi_t afi
= AFI_IP6
;
9124 safi_t safi
= SAFI_UNICAST
;
9125 char *prefix
= NULL
;
9126 struct bgp
*bgp
= NULL
;
9127 enum bgp_path_type path_type
;
9128 u_char uj
= use_json(argc
, argv
);
9132 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9139 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9143 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9144 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9145 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9147 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9148 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9151 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9152 && afi
!= AFI_IP6
) {
9154 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9157 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9160 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9164 prefix
= argv
[idx
]->arg
;
9166 /* [<bestpath|multipath>] */
9167 if (argv_find(argv
, argc
, "bestpath", &idx
))
9168 path_type
= BGP_PATH_BESTPATH
;
9169 else if (argv_find(argv
, argc
, "multipath", &idx
))
9170 path_type
= BGP_PATH_MULTIPATH
;
9172 path_type
= BGP_PATH_ALL
;
9174 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9178 DEFUN (show_ip_bgp_regexp
,
9179 show_ip_bgp_regexp_cmd
,
9180 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9184 BGP_INSTANCE_HELP_STR
9186 BGP_SAFI_WITH_LABEL_HELP_STR
9187 "Display routes matching the AS path regular expression\n"
9188 "A regular-expression to match the BGP AS paths\n")
9190 afi_t afi
= AFI_IP6
;
9191 safi_t safi
= SAFI_UNICAST
;
9192 struct bgp
*bgp
= NULL
;
9195 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9200 // get index of regex
9201 argv_find(argv
, argc
, "regexp", &idx
);
9204 char *regstr
= argv_concat(argv
, argc
, idx
);
9205 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9206 bgp_show_type_regexp
);
9207 XFREE(MTYPE_TMP
, regstr
);
9211 DEFUN (show_ip_bgp_instance_all
,
9212 show_ip_bgp_instance_all_cmd
,
9213 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9217 BGP_INSTANCE_ALL_HELP_STR
9219 BGP_SAFI_WITH_LABEL_HELP_STR
9223 safi_t safi
= SAFI_UNICAST
;
9224 struct bgp
*bgp
= NULL
;
9227 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9232 int uj
= use_json(argc
, argv
);
9236 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9240 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
9241 const char *regstr
, afi_t afi
,
9242 safi_t safi
, enum bgp_show_type type
)
9247 regex
= bgp_regcomp(regstr
);
9249 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9253 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9254 bgp_regex_free(regex
);
9258 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9259 const char *prefix_list_str
, afi_t afi
,
9260 safi_t safi
, enum bgp_show_type type
)
9262 struct prefix_list
*plist
;
9264 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9265 if (plist
== NULL
) {
9266 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9271 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9274 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9275 const char *filter
, afi_t afi
, safi_t safi
,
9276 enum bgp_show_type type
)
9278 struct as_list
*as_list
;
9280 as_list
= as_list_lookup(filter
);
9281 if (as_list
== NULL
) {
9282 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9287 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9290 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9291 const char *rmap_str
, afi_t afi
, safi_t safi
,
9292 enum bgp_show_type type
)
9294 struct route_map
*rmap
;
9296 rmap
= route_map_lookup_by_name(rmap_str
);
9298 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9302 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9305 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9306 const char *comstr
, int exact
, afi_t afi
,
9309 struct community
*com
;
9312 com
= community_str2com(comstr
);
9314 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9318 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9319 (exact
? bgp_show_type_community_exact
9320 : bgp_show_type_community
),
9322 community_free(com
);
9327 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9328 const char *com
, int exact
, afi_t afi
,
9331 struct community_list
*list
;
9333 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9335 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9339 return bgp_show(vty
, bgp
, afi
, safi
,
9340 (exact
? bgp_show_type_community_list_exact
9341 : bgp_show_type_community_list
),
9345 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9346 const char *prefix
, afi_t afi
, safi_t safi
,
9347 enum bgp_show_type type
)
9354 ret
= str2prefix(prefix
, p
);
9356 vty_out(vty
, "%% Malformed Prefix\n");
9360 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9365 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9366 const char *ip_str
, u_char use_json
)
9372 /* Get peer sockunion. */
9373 ret
= str2sockunion(ip_str
, &su
);
9375 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9377 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9381 json_object
*json_no
= NULL
;
9382 json_no
= json_object_new_object();
9383 json_object_string_add(
9385 "malformedAddressOrName",
9387 vty_out(vty
, "%s\n",
9388 json_object_to_json_string(
9390 json_object_free(json_no
);
9393 "%% Malformed address or name: %s\n",
9401 /* Peer structure lookup. */
9402 peer
= peer_lookup(bgp
, &su
);
9405 json_object
*json_no
= NULL
;
9406 json_no
= json_object_new_object();
9407 json_object_string_add(json_no
, "warning",
9408 "No such neighbor");
9409 vty_out(vty
, "%s\n",
9410 json_object_to_json_string(json_no
));
9411 json_object_free(json_no
);
9413 vty_out(vty
, "No such neighbor\n");
9421 BGP_STATS_MAXBITLEN
= 0,
9425 BGP_STATS_UNAGGREGATEABLE
,
9426 BGP_STATS_MAX_AGGREGATEABLE
,
9427 BGP_STATS_AGGREGATES
,
9429 BGP_STATS_ASPATH_COUNT
,
9430 BGP_STATS_ASPATH_MAXHOPS
,
9431 BGP_STATS_ASPATH_TOTHOPS
,
9432 BGP_STATS_ASPATH_MAXSIZE
,
9433 BGP_STATS_ASPATH_TOTSIZE
,
9434 BGP_STATS_ASN_HIGHEST
,
9438 static const char *table_stats_strs
[] = {
9439 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9440 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9441 [BGP_STATS_RIB
] = "Total Advertisements",
9442 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9443 [BGP_STATS_MAX_AGGREGATEABLE
] =
9444 "Maximum aggregateable prefixes",
9445 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9446 [BGP_STATS_SPACE
] = "Address space advertised",
9447 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9448 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9449 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9450 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9451 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9452 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9453 [BGP_STATS_MAX
] = NULL
,
9456 struct bgp_table_stats
{
9457 struct bgp_table
*table
;
9458 unsigned long long counts
[BGP_STATS_MAX
];
9463 #define TALLY_SIGFIG 100000
9464 static unsigned long
9465 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9467 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9468 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9469 unsigned long ret
= newtot
/ count
;
9471 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9478 static int bgp_table_stats_walker(struct thread
*t
)
9480 struct bgp_node
*rn
;
9481 struct bgp_node
*top
;
9482 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9483 unsigned int space
= 0;
9485 if (!(top
= bgp_table_top(ts
->table
)))
9488 switch (top
->p
.family
) {
9490 space
= IPV4_MAX_BITLEN
;
9493 space
= IPV6_MAX_BITLEN
;
9497 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9499 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9500 struct bgp_info
*ri
;
9501 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9502 unsigned int rinum
= 0;
9510 ts
->counts
[BGP_STATS_PREFIXES
]++;
9511 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9514 ts
->counts
[BGP_STATS_AVGPLEN
]
9515 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9516 ts
->counts
[BGP_STATS_AVGPLEN
],
9520 /* check if the prefix is included by any other announcements */
9521 while (prn
&& !prn
->info
)
9522 prn
= bgp_node_parent_nolock(prn
);
9524 if (prn
== NULL
|| prn
== top
) {
9525 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9526 /* announced address space */
9528 ts
->total_space
+= pow(2.0,
9529 space
- rn
->p
.prefixlen
);
9530 } else if (prn
->info
)
9531 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9533 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9535 ts
->counts
[BGP_STATS_RIB
]++;
9538 && (CHECK_FLAG(ri
->attr
->flag
,
9540 BGP_ATTR_ATOMIC_AGGREGATE
))))
9541 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9544 if (ri
->attr
&& ri
->attr
->aspath
) {
9546 aspath_count_hops(ri
->attr
->aspath
);
9548 aspath_size(ri
->attr
->aspath
);
9549 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9551 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9553 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9554 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9557 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9558 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9561 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9562 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9564 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9565 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9566 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9568 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9569 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9570 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9573 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9574 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9582 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9585 struct bgp_table_stats ts
;
9588 if (!bgp
->rib
[afi
][safi
]) {
9589 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9594 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9596 /* labeled-unicast routes live in the unicast table */
9597 if (safi
== SAFI_LABELED_UNICAST
)
9598 safi
= SAFI_UNICAST
;
9600 memset(&ts
, 0, sizeof(ts
));
9601 ts
.table
= bgp
->rib
[afi
][safi
];
9602 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9604 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9605 if (!table_stats_strs
[i
])
9610 case BGP_STATS_ASPATH_AVGHOPS
:
9611 case BGP_STATS_ASPATH_AVGSIZE
:
9612 case BGP_STATS_AVGPLEN
:
9613 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9614 vty_out (vty
, "%12.2f",
9615 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9618 case BGP_STATS_ASPATH_TOTHOPS
:
9619 case BGP_STATS_ASPATH_TOTSIZE
:
9620 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9621 vty_out(vty
, "%12.2f",
9623 ? (float)ts
.counts
[i
]
9625 [BGP_STATS_ASPATH_COUNT
]
9628 case BGP_STATS_TOTPLEN
:
9629 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9630 vty_out(vty
, "%12.2f",
9632 ? (float)ts
.counts
[i
]
9634 [BGP_STATS_PREFIXES
]
9637 case BGP_STATS_SPACE
:
9638 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9639 vty_out(vty
, "%12g\n", ts
.total_space
);
9641 if (afi
== AFI_IP6
) {
9642 vty_out(vty
, "%30s: ", "/32 equivalent ");
9643 vty_out(vty
, "%12g\n",
9644 ts
.total_space
* pow(2.0, -128+32));
9645 vty_out(vty
, "%30s: ", "/48 equivalent ");
9646 vty_out(vty
, "%12g\n",
9647 ts
.total_space
* pow(2.0, -128+48));
9649 vty_out(vty
, "%30s: ", "% announced ");
9650 vty_out(vty
, "%12.2f\n",
9651 ts
.total_space
* 100. * pow(2.0, -32));
9652 vty_out(vty
, "%30s: ", "/8 equivalent ");
9653 vty_out(vty
, "%12.2f\n",
9654 ts
.total_space
* pow(2.0, -32+8));
9655 vty_out(vty
, "%30s: ", "/24 equivalent ");
9656 vty_out(vty
, "%12.2f\n",
9657 ts
.total_space
* pow(2.0, -32+24));
9661 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9662 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9679 PCOUNT_PFCNT
, /* the figure we display to users */
9683 static const char *pcount_strs
[] = {
9684 [PCOUNT_ADJ_IN
] = "Adj-in",
9685 [PCOUNT_DAMPED
] = "Damped",
9686 [PCOUNT_REMOVED
] = "Removed",
9687 [PCOUNT_HISTORY
] = "History",
9688 [PCOUNT_STALE
] = "Stale",
9689 [PCOUNT_VALID
] = "Valid",
9690 [PCOUNT_ALL
] = "All RIB",
9691 [PCOUNT_COUNTED
] = "PfxCt counted",
9692 [PCOUNT_PFCNT
] = "Useable",
9693 [PCOUNT_MAX
] = NULL
,
9696 struct peer_pcounts
{
9697 unsigned int count
[PCOUNT_MAX
];
9698 const struct peer
*peer
;
9699 const struct bgp_table
*table
;
9702 static int bgp_peer_count_walker(struct thread
*t
)
9704 struct bgp_node
*rn
;
9705 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9706 const struct peer
*peer
= pc
->peer
;
9708 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9709 struct bgp_adj_in
*ain
;
9710 struct bgp_info
*ri
;
9712 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9713 if (ain
->peer
== peer
)
9714 pc
->count
[PCOUNT_ADJ_IN
]++;
9716 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9717 char buf
[SU_ADDRSTRLEN
];
9719 if (ri
->peer
!= peer
)
9722 pc
->count
[PCOUNT_ALL
]++;
9724 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9725 pc
->count
[PCOUNT_DAMPED
]++;
9726 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9727 pc
->count
[PCOUNT_HISTORY
]++;
9728 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9729 pc
->count
[PCOUNT_REMOVED
]++;
9730 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9731 pc
->count
[PCOUNT_STALE
]++;
9732 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9733 pc
->count
[PCOUNT_VALID
]++;
9734 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9735 pc
->count
[PCOUNT_PFCNT
]++;
9737 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9738 pc
->count
[PCOUNT_COUNTED
]++;
9739 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9741 "%s [pcount] %s/%d is counted but flags 0x%x",
9743 inet_ntop(rn
->p
.family
,
9744 &rn
->p
.u
.prefix
, buf
,
9746 rn
->p
.prefixlen
, ri
->flags
);
9748 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9750 "%s [pcount] %s/%d not counted but flags 0x%x",
9752 inet_ntop(rn
->p
.family
,
9753 &rn
->p
.u
.prefix
, buf
,
9755 rn
->p
.prefixlen
, ri
->flags
);
9762 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9763 safi_t safi
, u_char use_json
)
9765 struct peer_pcounts pcounts
= {.peer
= peer
};
9767 json_object
*json
= NULL
;
9768 json_object
*json_loop
= NULL
;
9771 json
= json_object_new_object();
9772 json_loop
= json_object_new_object();
9775 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9776 || !peer
->bgp
->rib
[afi
][safi
]) {
9778 json_object_string_add(
9780 "No such neighbor or address family");
9781 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9782 json_object_free(json
);
9784 vty_out(vty
, "%% No such neighbor or address family\n");
9789 memset(&pcounts
, 0, sizeof(pcounts
));
9790 pcounts
.peer
= peer
;
9791 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9793 /* in-place call via thread subsystem so as to record execution time
9794 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9795 * * on just vty_read()).
9797 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9800 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9801 json_object_string_add(json
, "multiProtocol",
9802 afi_safi_print(afi
, safi
));
9803 json_object_int_add(json
, "pfxCounter",
9804 peer
->pcount
[afi
][safi
]);
9806 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9807 json_object_int_add(json_loop
, pcount_strs
[i
],
9810 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9812 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9813 json_object_string_add(json
, "pfxctDriftFor",
9815 json_object_string_add(
9816 json
, "recommended",
9817 "Please report this bug, with the above command output");
9819 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9820 json_object_free(json
);
9824 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9825 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9826 peer
->hostname
, peer
->host
,
9827 afi_safi_print(afi
, safi
));
9829 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9830 afi_safi_print(afi
, safi
));
9833 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9834 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9836 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9837 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9840 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9841 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9843 "Please report this bug, with the above command output\n");
9850 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9851 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9852 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9853 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9857 BGP_INSTANCE_HELP_STR
9860 "Detailed information on TCP and BGP neighbor connections\n"
9861 "Neighbor to display information about\n"
9862 "Neighbor to display information about\n"
9863 "Neighbor on BGP configured interface\n"
9864 "Display detailed prefix count information\n"
9867 afi_t afi
= AFI_IP6
;
9868 safi_t safi
= SAFI_UNICAST
;
9871 struct bgp
*bgp
= NULL
;
9873 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9878 int uj
= use_json(argc
, argv
);
9882 argv_find(argv
, argc
, "neighbors", &idx
);
9883 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9887 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9890 #ifdef KEEP_OLD_VPN_COMMANDS
9891 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9892 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9893 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9898 "Display information about all VPNv4 NLRIs\n"
9899 "Detailed information on TCP and BGP neighbor connections\n"
9900 "Neighbor to display information about\n"
9901 "Neighbor to display information about\n"
9902 "Neighbor on BGP configured interface\n"
9903 "Display detailed prefix count information\n"
9908 u_char uj
= use_json(argc
, argv
);
9910 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9914 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9917 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9918 show_ip_bgp_vpn_all_route_prefix_cmd
,
9919 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9924 "Display information about all VPNv4 NLRIs\n"
9925 "Network in the BGP routing table to display\n"
9926 "Network in the BGP routing table to display\n"
9930 char *network
= NULL
;
9931 struct bgp
*bgp
= bgp_get_default();
9933 vty_out(vty
, "Can't find default instance\n");
9937 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9938 network
= argv
[idx
]->arg
;
9939 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9940 network
= argv
[idx
]->arg
;
9942 vty_out(vty
, "Unable to figure out Network\n");
9946 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9947 BGP_PATH_ALL
, use_json(argc
, argv
));
9949 #endif /* KEEP_OLD_VPN_COMMANDS */
9951 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9952 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9953 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9959 "Display information about all EVPN NLRIs\n"
9960 "Network in the BGP routing table to display\n"
9961 "Network in the BGP routing table to display\n"
9965 char *network
= NULL
;
9967 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9968 network
= argv
[idx
]->arg
;
9969 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9970 network
= argv
[idx
]->arg
;
9972 vty_out(vty
, "Unable to figure out Network\n");
9975 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9976 BGP_PATH_ALL
, use_json(argc
, argv
));
9979 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9980 safi_t safi
, int in
, const char *rmap_name
,
9981 u_char use_json
, json_object
*json
)
9983 struct bgp_table
*table
;
9984 struct bgp_adj_in
*ain
;
9985 struct bgp_adj_out
*adj
;
9986 unsigned long output_count
;
9987 unsigned long filtered_count
;
9988 struct bgp_node
*rn
;
9994 struct update_subgroup
*subgrp
;
9995 json_object
*json_scode
= NULL
;
9996 json_object
*json_ocode
= NULL
;
9997 json_object
*json_ar
= NULL
;
9998 struct peer_af
*paf
;
10001 json_scode
= json_object_new_object();
10002 json_ocode
= json_object_new_object();
10003 json_ar
= json_object_new_object();
10005 json_object_string_add(json_scode
, "suppressed", "s");
10006 json_object_string_add(json_scode
, "damped", "d");
10007 json_object_string_add(json_scode
, "history", "h");
10008 json_object_string_add(json_scode
, "valid", "*");
10009 json_object_string_add(json_scode
, "best", ">");
10010 json_object_string_add(json_scode
, "multipath", "=");
10011 json_object_string_add(json_scode
, "internal", "i");
10012 json_object_string_add(json_scode
, "ribFailure", "r");
10013 json_object_string_add(json_scode
, "stale", "S");
10014 json_object_string_add(json_scode
, "removed", "R");
10016 json_object_string_add(json_ocode
, "igp", "i");
10017 json_object_string_add(json_ocode
, "egp", "e");
10018 json_object_string_add(json_ocode
, "incomplete", "?");
10025 json_object_string_add(json
, "alert", "no BGP");
10026 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10027 json_object_free(json
);
10029 vty_out(vty
, "%% No bgp\n");
10033 table
= bgp
->rib
[afi
][safi
];
10035 output_count
= filtered_count
= 0;
10036 subgrp
= peer_subgroup(peer
, afi
, safi
);
10039 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10041 json_object_int_add(json
, "bgpTableVersion",
10043 json_object_string_add(json
, "bgpLocalRouterId",
10044 inet_ntoa(bgp
->router_id
));
10045 json_object_object_add(json
, "bgpStatusCodes",
10047 json_object_object_add(json
, "bgpOriginCodes",
10049 json_object_string_add(json
,
10050 "bgpOriginatingDefaultNetwork",
10053 vty_out(vty
, "BGP table version is %" PRIu64
10054 ", local router ID is %s\n",
10055 table
->version
, inet_ntoa(bgp
->router_id
));
10056 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10057 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10059 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10064 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10066 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10067 if (ain
->peer
!= peer
)
10071 json_object_int_add(
10072 json
, "bgpTableVersion",
10074 json_object_string_add(
10076 "bgpLocalRouterId",
10079 json_object_object_add(
10080 json
, "bgpStatusCodes",
10082 json_object_object_add(
10083 json
, "bgpOriginCodes",
10087 "BGP table version is 0, local router ID is %s\n",
10091 BGP_SHOW_SCODE_HEADER
);
10093 BGP_SHOW_OCODE_HEADER
);
10099 vty_out(vty
, BGP_SHOW_HEADER
);
10103 bgp_attr_dup(&attr
, ain
->attr
);
10104 if (bgp_input_modifier(peer
, &rn
->p
,
10108 route_vty_out_tmp(vty
, &rn
->p
,
10118 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10119 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
)
10120 if (paf
->peer
== peer
) {
10123 json_object_int_add(
10127 json_object_string_add(
10129 "bgpLocalRouterId",
10132 json_object_object_add(
10136 json_object_object_add(
10142 "BGP table version is %" PRIu64
10143 ", local router ID is %s\n",
10148 BGP_SHOW_SCODE_HEADER
);
10150 BGP_SHOW_OCODE_HEADER
);
10163 bgp_attr_dup(&attr
,
10165 ret
= bgp_output_modifier(
10170 if (ret
!= RMAP_DENY
) {
10186 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10188 if (output_count
!= 0) {
10190 json_object_int_add(json
, "totalPrefixCounter",
10193 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10197 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10198 json_object_free(json
);
10202 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10203 safi_t safi
, int in
, const char *rmap_name
,
10206 json_object
*json
= NULL
;
10209 json
= json_object_new_object();
10211 /* labeled-unicast routes live in the unicast table */
10212 if (safi
== SAFI_LABELED_UNICAST
)
10213 safi
= SAFI_UNICAST
;
10215 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10217 json_object_string_add(
10219 "No such neighbor or address family");
10220 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10221 json_object_free(json
);
10223 vty_out(vty
, "%% No such neighbor or address family\n");
10225 return CMD_WARNING
;
10229 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10230 PEER_FLAG_SOFT_RECONFIG
)) {
10232 json_object_string_add(
10234 "Inbound soft reconfiguration not enabled");
10235 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10236 json_object_free(json
);
10239 "%% Inbound soft reconfiguration not enabled\n");
10241 return CMD_WARNING
;
10244 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10246 return CMD_SUCCESS
;
10249 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10250 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10251 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10252 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10256 BGP_INSTANCE_HELP_STR
10258 BGP_SAFI_WITH_LABEL_HELP_STR
10259 "Detailed information on TCP and BGP neighbor connections\n"
10260 "Neighbor to display information about\n"
10261 "Neighbor to display information about\n"
10262 "Neighbor on BGP configured interface\n"
10263 "Display the received routes from neighbor\n"
10264 "Display the routes advertised to a BGP neighbor\n"
10265 "Route-map to modify the attributes\n"
10266 "Name of the route map\n"
10269 afi_t afi
= AFI_IP6
;
10270 safi_t safi
= SAFI_UNICAST
;
10271 char *rmap_name
= NULL
;
10272 char *peerstr
= NULL
;
10274 struct bgp
*bgp
= NULL
;
10279 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10282 return CMD_WARNING
;
10284 int uj
= use_json(argc
, argv
);
10288 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10289 argv_find(argv
, argc
, "neighbors", &idx
);
10290 peerstr
= argv
[++idx
]->arg
;
10292 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10294 return CMD_WARNING
;
10296 if (argv_find(argv
, argc
, "received-routes", &idx
))
10298 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10300 if (argv_find(argv
, argc
, "route-map", &idx
))
10301 rmap_name
= argv
[++idx
]->arg
;
10303 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10306 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10307 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10308 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10314 "Address Family modifier\n"
10315 "Detailed information on TCP and BGP neighbor connections\n"
10316 "Neighbor to display information about\n"
10317 "Neighbor to display information about\n"
10318 "Neighbor on BGP configured interface\n"
10319 "Display information received from a BGP neighbor\n"
10320 "Display the prefixlist filter\n"
10323 afi_t afi
= AFI_IP6
;
10324 safi_t safi
= SAFI_UNICAST
;
10325 char *peerstr
= NULL
;
10328 union sockunion su
;
10334 /* show [ip] bgp */
10335 if (argv_find(argv
, argc
, "ip", &idx
))
10337 /* [<ipv4|ipv6> [unicast]] */
10338 if (argv_find(argv
, argc
, "ipv4", &idx
))
10340 if (argv_find(argv
, argc
, "ipv6", &idx
))
10342 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10343 argv_find(argv
, argc
, "neighbors", &idx
);
10344 peerstr
= argv
[++idx
]->arg
;
10346 u_char uj
= use_json(argc
, argv
);
10348 ret
= str2sockunion(peerstr
, &su
);
10350 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10353 vty_out(vty
, "{}\n");
10356 "%% Malformed address or name: %s\n",
10358 return CMD_WARNING
;
10361 peer
= peer_lookup(NULL
, &su
);
10364 vty_out(vty
, "{}\n");
10366 vty_out(vty
, "No peer\n");
10367 return CMD_WARNING
;
10371 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10372 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10375 vty_out(vty
, "Address Family: %s\n",
10376 afi_safi_print(afi
, safi
));
10377 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10380 vty_out(vty
, "{}\n");
10382 vty_out(vty
, "No functional output\n");
10385 return CMD_SUCCESS
;
10388 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10389 afi_t afi
, safi_t safi
,
10390 enum bgp_show_type type
, u_char use_json
)
10392 /* labeled-unicast routes live in the unicast table */
10393 if (safi
== SAFI_LABELED_UNICAST
)
10394 safi
= SAFI_UNICAST
;
10396 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10398 json_object
*json_no
= NULL
;
10399 json_no
= json_object_new_object();
10400 json_object_string_add(
10401 json_no
, "warning",
10402 "No such neighbor or address family");
10403 vty_out(vty
, "%s\n",
10404 json_object_to_json_string(json_no
));
10405 json_object_free(json_no
);
10407 vty_out(vty
, "%% No such neighbor or address family\n");
10408 return CMD_WARNING
;
10411 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10414 DEFUN (show_ip_bgp_neighbor_routes
,
10415 show_ip_bgp_neighbor_routes_cmd
,
10416 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10417 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10421 BGP_INSTANCE_HELP_STR
10423 BGP_SAFI_WITH_LABEL_HELP_STR
10424 "Detailed information on TCP and BGP neighbor connections\n"
10425 "Neighbor to display information about\n"
10426 "Neighbor to display information about\n"
10427 "Neighbor on BGP configured interface\n"
10428 "Display flap statistics of the routes learned from neighbor\n"
10429 "Display the dampened routes received from neighbor\n"
10430 "Display routes learned from neighbor\n"
10433 char *peerstr
= NULL
;
10434 struct bgp
*bgp
= NULL
;
10435 afi_t afi
= AFI_IP6
;
10436 safi_t safi
= SAFI_UNICAST
;
10438 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10442 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10445 return CMD_WARNING
;
10447 int uj
= use_json(argc
, argv
);
10451 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10452 argv_find(argv
, argc
, "neighbors", &idx
);
10453 peerstr
= argv
[++idx
]->arg
;
10455 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10457 vty_out(vty
, "No such neighbor\n");
10458 return CMD_WARNING
;
10461 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10462 sh_type
= bgp_show_type_flap_neighbor
;
10463 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10464 sh_type
= bgp_show_type_damp_neighbor
;
10465 else if (argv_find(argv
, argc
, "routes", &idx
))
10466 sh_type
= bgp_show_type_neighbor
;
10468 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10471 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10473 struct bgp_distance
{
10474 /* Distance value for the IP source prefix. */
10477 /* Name of the access-list to be matched. */
10481 DEFUN (show_bgp_afi_vpn_rd_route
,
10482 show_bgp_afi_vpn_rd_route_cmd
,
10483 "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]",
10487 "Address Family modifier\n"
10488 "Display information for a route distinguisher\n"
10489 "Route Distinguisher\n"
10490 "Network in the BGP routing table to display\n"
10491 "Network in the BGP routing table to display\n"
10495 struct prefix_rd prd
;
10496 afi_t afi
= AFI_MAX
;
10499 argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
);
10500 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10502 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10503 return CMD_WARNING
;
10505 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10506 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10509 static struct bgp_distance
*bgp_distance_new(void)
10511 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10514 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10516 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10519 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10520 const char *ip_str
, const char *access_list_str
)
10527 struct bgp_node
*rn
;
10528 struct bgp_distance
*bdistance
;
10530 afi
= bgp_node_afi(vty
);
10531 safi
= bgp_node_safi(vty
);
10533 ret
= str2prefix(ip_str
, &p
);
10535 vty_out(vty
, "Malformed prefix\n");
10536 return CMD_WARNING_CONFIG_FAILED
;
10539 distance
= atoi(distance_str
);
10541 /* Get BGP distance node. */
10542 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10544 bdistance
= rn
->info
;
10545 bgp_unlock_node(rn
);
10547 bdistance
= bgp_distance_new();
10548 rn
->info
= bdistance
;
10551 /* Set distance value. */
10552 bdistance
->distance
= distance
;
10554 /* Reset access-list configuration. */
10555 if (bdistance
->access_list
) {
10556 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10557 bdistance
->access_list
= NULL
;
10559 if (access_list_str
)
10560 bdistance
->access_list
=
10561 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10563 return CMD_SUCCESS
;
10566 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10567 const char *ip_str
, const char *access_list_str
)
10574 struct bgp_node
*rn
;
10575 struct bgp_distance
*bdistance
;
10577 afi
= bgp_node_afi(vty
);
10578 safi
= bgp_node_safi(vty
);
10580 ret
= str2prefix(ip_str
, &p
);
10582 vty_out(vty
, "Malformed prefix\n");
10583 return CMD_WARNING_CONFIG_FAILED
;
10586 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10587 (struct prefix
*)&p
);
10589 vty_out(vty
, "Can't find specified prefix\n");
10590 return CMD_WARNING_CONFIG_FAILED
;
10593 bdistance
= rn
->info
;
10594 distance
= atoi(distance_str
);
10596 if (bdistance
->distance
!= distance
) {
10597 vty_out(vty
, "Distance does not match configured\n");
10598 return CMD_WARNING_CONFIG_FAILED
;
10601 if (bdistance
->access_list
)
10602 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10603 bgp_distance_free(bdistance
);
10606 bgp_unlock_node(rn
);
10607 bgp_unlock_node(rn
);
10609 return CMD_SUCCESS
;
10612 /* Apply BGP information to distance method. */
10613 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10614 safi_t safi
, struct bgp
*bgp
)
10616 struct bgp_node
*rn
;
10619 struct bgp_distance
*bdistance
;
10620 struct access_list
*alist
;
10621 struct bgp_static
*bgp_static
;
10626 peer
= rinfo
->peer
;
10628 /* Check source address. */
10629 sockunion2hostprefix(&peer
->su
, &q
);
10630 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10632 bdistance
= rn
->info
;
10633 bgp_unlock_node(rn
);
10635 if (bdistance
->access_list
) {
10636 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10638 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10639 return bdistance
->distance
;
10641 return bdistance
->distance
;
10644 /* Backdoor check. */
10645 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10647 bgp_static
= rn
->info
;
10648 bgp_unlock_node(rn
);
10650 if (bgp_static
->backdoor
) {
10651 if (bgp
->distance_local
[afi
][safi
])
10652 return bgp
->distance_local
[afi
][safi
];
10654 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10658 if (peer
->sort
== BGP_PEER_EBGP
) {
10659 if (bgp
->distance_ebgp
[afi
][safi
])
10660 return bgp
->distance_ebgp
[afi
][safi
];
10661 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10663 if (bgp
->distance_ibgp
[afi
][safi
])
10664 return bgp
->distance_ibgp
[afi
][safi
];
10665 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10669 DEFUN (bgp_distance
,
10671 "distance bgp (1-255) (1-255) (1-255)",
10672 "Define an administrative distance\n"
10674 "Distance for routes external to the AS\n"
10675 "Distance for routes internal to the AS\n"
10676 "Distance for local routes\n")
10678 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10679 int idx_number
= 2;
10680 int idx_number_2
= 3;
10681 int idx_number_3
= 4;
10685 afi
= bgp_node_afi(vty
);
10686 safi
= bgp_node_safi(vty
);
10688 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10689 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10690 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10691 return CMD_SUCCESS
;
10694 DEFUN (no_bgp_distance
,
10695 no_bgp_distance_cmd
,
10696 "no distance bgp [(1-255) (1-255) (1-255)]",
10698 "Define an administrative distance\n"
10700 "Distance for routes external to the AS\n"
10701 "Distance for routes internal to the AS\n"
10702 "Distance for local routes\n")
10704 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10708 afi
= bgp_node_afi(vty
);
10709 safi
= bgp_node_safi(vty
);
10711 bgp
->distance_ebgp
[afi
][safi
] = 0;
10712 bgp
->distance_ibgp
[afi
][safi
] = 0;
10713 bgp
->distance_local
[afi
][safi
] = 0;
10714 return CMD_SUCCESS
;
10718 DEFUN (bgp_distance_source
,
10719 bgp_distance_source_cmd
,
10720 "distance (1-255) A.B.C.D/M",
10721 "Define an administrative distance\n"
10722 "Administrative distance\n"
10723 "IP source prefix\n")
10725 int idx_number
= 1;
10726 int idx_ipv4_prefixlen
= 2;
10727 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10728 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10729 return CMD_SUCCESS
;
10732 DEFUN (no_bgp_distance_source
,
10733 no_bgp_distance_source_cmd
,
10734 "no distance (1-255) A.B.C.D/M",
10736 "Define an administrative distance\n"
10737 "Administrative distance\n"
10738 "IP source prefix\n")
10740 int idx_number
= 2;
10741 int idx_ipv4_prefixlen
= 3;
10742 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10743 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10744 return CMD_SUCCESS
;
10747 DEFUN (bgp_distance_source_access_list
,
10748 bgp_distance_source_access_list_cmd
,
10749 "distance (1-255) A.B.C.D/M WORD",
10750 "Define an administrative distance\n"
10751 "Administrative distance\n"
10752 "IP source prefix\n"
10753 "Access list name\n")
10755 int idx_number
= 1;
10756 int idx_ipv4_prefixlen
= 2;
10758 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10759 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10760 return CMD_SUCCESS
;
10763 DEFUN (no_bgp_distance_source_access_list
,
10764 no_bgp_distance_source_access_list_cmd
,
10765 "no distance (1-255) A.B.C.D/M WORD",
10767 "Define an administrative distance\n"
10768 "Administrative distance\n"
10769 "IP source prefix\n"
10770 "Access list name\n")
10772 int idx_number
= 2;
10773 int idx_ipv4_prefixlen
= 3;
10775 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10776 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10777 return CMD_SUCCESS
;
10780 DEFUN (ipv6_bgp_distance_source
,
10781 ipv6_bgp_distance_source_cmd
,
10782 "distance (1-255) X:X::X:X/M",
10783 "Define an administrative distance\n"
10784 "Administrative distance\n"
10785 "IP source prefix\n")
10787 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10788 return CMD_SUCCESS
;
10791 DEFUN (no_ipv6_bgp_distance_source
,
10792 no_ipv6_bgp_distance_source_cmd
,
10793 "no distance (1-255) X:X::X:X/M",
10795 "Define an administrative distance\n"
10796 "Administrative distance\n"
10797 "IP source prefix\n")
10799 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10800 return CMD_SUCCESS
;
10803 DEFUN (ipv6_bgp_distance_source_access_list
,
10804 ipv6_bgp_distance_source_access_list_cmd
,
10805 "distance (1-255) X:X::X:X/M WORD",
10806 "Define an administrative distance\n"
10807 "Administrative distance\n"
10808 "IP source prefix\n"
10809 "Access list name\n")
10811 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10812 return CMD_SUCCESS
;
10815 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10816 no_ipv6_bgp_distance_source_access_list_cmd
,
10817 "no distance (1-255) X:X::X:X/M WORD",
10819 "Define an administrative distance\n"
10820 "Administrative distance\n"
10821 "IP source prefix\n"
10822 "Access list name\n")
10824 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10825 return CMD_SUCCESS
;
10828 DEFUN (bgp_damp_set
,
10830 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10831 "BGP Specific commands\n"
10832 "Enable route-flap dampening\n"
10833 "Half-life time for the penalty\n"
10834 "Value to start reusing a route\n"
10835 "Value to start suppressing a route\n"
10836 "Maximum duration to suppress a stable route\n")
10838 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10839 int idx_half_life
= 2;
10841 int idx_suppress
= 4;
10842 int idx_max_suppress
= 5;
10843 int half
= DEFAULT_HALF_LIFE
* 60;
10844 int reuse
= DEFAULT_REUSE
;
10845 int suppress
= DEFAULT_SUPPRESS
;
10846 int max
= 4 * half
;
10849 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10850 reuse
= atoi(argv
[idx_reuse
]->arg
);
10851 suppress
= atoi(argv
[idx_suppress
]->arg
);
10852 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10853 } else if (argc
== 3) {
10854 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10858 if (suppress
< reuse
) {
10860 "Suppress value cannot be less than reuse value \n");
10864 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10865 reuse
, suppress
, max
);
10868 DEFUN (bgp_damp_unset
,
10869 bgp_damp_unset_cmd
,
10870 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10872 "BGP Specific commands\n"
10873 "Enable route-flap dampening\n"
10874 "Half-life time for the penalty\n"
10875 "Value to start reusing a route\n"
10876 "Value to start suppressing a route\n"
10877 "Maximum duration to suppress a stable route\n")
10879 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10880 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10883 /* Display specified route of BGP table. */
10884 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10885 const char *ip_str
, afi_t afi
, safi_t safi
,
10886 struct prefix_rd
*prd
, int prefix_check
)
10889 struct prefix match
;
10890 struct bgp_node
*rn
;
10891 struct bgp_node
*rm
;
10892 struct bgp_info
*ri
;
10893 struct bgp_info
*ri_temp
;
10895 struct bgp_table
*table
;
10897 /* BGP structure lookup. */
10899 bgp
= bgp_lookup_by_name(view_name
);
10901 vty_out(vty
, "%% Can't find BGP instance %s\n",
10903 return CMD_WARNING
;
10906 bgp
= bgp_get_default();
10908 vty_out(vty
, "%% No BGP process is configured\n");
10909 return CMD_WARNING
;
10913 /* Check IP address argument. */
10914 ret
= str2prefix(ip_str
, &match
);
10916 vty_out(vty
, "%% address is malformed\n");
10917 return CMD_WARNING
;
10920 match
.family
= afi2family(afi
);
10922 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10923 || (safi
== SAFI_EVPN
)) {
10924 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10925 rn
= bgp_route_next(rn
)) {
10926 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10928 if ((table
= rn
->info
) == NULL
)
10930 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10934 || rm
->p
.prefixlen
== match
.prefixlen
) {
10937 if (ri
->extra
&& ri
->extra
->damp_info
) {
10938 ri_temp
= ri
->next
;
10939 bgp_damp_info_free(
10940 ri
->extra
->damp_info
,
10948 bgp_unlock_node(rm
);
10951 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10954 || rn
->p
.prefixlen
== match
.prefixlen
) {
10957 if (ri
->extra
&& ri
->extra
->damp_info
) {
10958 ri_temp
= ri
->next
;
10959 bgp_damp_info_free(
10960 ri
->extra
->damp_info
,
10968 bgp_unlock_node(rn
);
10972 return CMD_SUCCESS
;
10975 DEFUN (clear_ip_bgp_dampening
,
10976 clear_ip_bgp_dampening_cmd
,
10977 "clear ip bgp dampening",
10981 "Clear route flap dampening information\n")
10983 bgp_damp_info_clean();
10984 return CMD_SUCCESS
;
10987 DEFUN (clear_ip_bgp_dampening_prefix
,
10988 clear_ip_bgp_dampening_prefix_cmd
,
10989 "clear ip bgp dampening A.B.C.D/M",
10993 "Clear route flap dampening information\n"
10996 int idx_ipv4_prefixlen
= 4;
10997 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10998 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11001 DEFUN (clear_ip_bgp_dampening_address
,
11002 clear_ip_bgp_dampening_address_cmd
,
11003 "clear ip bgp dampening A.B.C.D",
11007 "Clear route flap dampening information\n"
11008 "Network to clear damping information\n")
11011 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11012 SAFI_UNICAST
, NULL
, 0);
11015 DEFUN (clear_ip_bgp_dampening_address_mask
,
11016 clear_ip_bgp_dampening_address_mask_cmd
,
11017 "clear ip bgp dampening A.B.C.D A.B.C.D",
11021 "Clear route flap dampening information\n"
11022 "Network to clear damping information\n"
11026 int idx_ipv4_2
= 5;
11028 char prefix_str
[BUFSIZ
];
11030 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11033 vty_out(vty
, "%% Inconsistent address and mask\n");
11034 return CMD_WARNING
;
11037 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11041 /* also used for encap safi */
11042 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11043 afi_t afi
, safi_t safi
)
11045 struct bgp_node
*prn
;
11046 struct bgp_node
*rn
;
11047 struct bgp_table
*table
;
11049 struct prefix_rd
*prd
;
11050 struct bgp_static
*bgp_static
;
11051 mpls_label_t label
;
11052 char buf
[SU_ADDRSTRLEN
];
11053 char rdbuf
[RD_ADDRSTRLEN
];
11055 /* Network configuration. */
11056 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11057 prn
= bgp_route_next(prn
)) {
11058 if ((table
= prn
->info
) == NULL
)
11061 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11062 if ((bgp_static
= rn
->info
) == NULL
)
11066 prd
= (struct prefix_rd
*)&prn
->p
;
11068 /* "network" configuration display. */
11069 prefix_rd2str(prd
, rdbuf
, RD_ADDRSTRLEN
);
11070 label
= decode_label(&bgp_static
->label
);
11072 vty_out(vty
, " network %s/%d rd %s",
11073 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11075 p
->prefixlen
, rdbuf
);
11076 if (safi
== SAFI_MPLS_VPN
)
11077 vty_out(vty
, " label %u", label
);
11079 if (bgp_static
->rmap
.name
)
11080 vty_out(vty
, " route-map %s",
11081 bgp_static
->rmap
.name
);
11083 if (bgp_static
->backdoor
)
11084 vty_out(vty
, " backdoor");
11086 vty_out(vty
, "\n");
11091 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11092 afi_t afi
, safi_t safi
)
11094 struct bgp_node
*prn
;
11095 struct bgp_node
*rn
;
11096 struct bgp_table
*table
;
11098 struct prefix_rd
*prd
;
11099 struct bgp_static
*bgp_static
;
11100 char buf
[PREFIX_STRLEN
];
11101 char buf2
[SU_ADDRSTRLEN
];
11102 char rdbuf
[RD_ADDRSTRLEN
];
11104 /* Network configuration. */
11105 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11106 prn
= bgp_route_next(prn
)) {
11107 if ((table
= prn
->info
) == NULL
)
11110 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11111 if ((bgp_static
= rn
->info
) == NULL
)
11114 char *macrouter
= NULL
;
11117 if (bgp_static
->router_mac
)
11118 macrouter
= prefix_mac2str(
11119 bgp_static
->router_mac
, NULL
, 0);
11120 if (bgp_static
->eth_s_id
)
11121 esi
= esi2str(bgp_static
->eth_s_id
);
11123 prd
= (struct prefix_rd
*)&prn
->p
;
11125 /* "network" configuration display. */
11126 prefix_rd2str(prd
, rdbuf
, RD_ADDRSTRLEN
);
11127 if (p
->u
.prefix_evpn
.route_type
== 5) {
11128 char local_buf
[PREFIX_STRLEN
];
11129 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)
11132 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
, local_buf
,
11134 sprintf(buf
, "%s/%u", local_buf
,p
->u
.prefix_evpn
.ip_prefix_length
);
11136 prefix2str(p
, buf
, sizeof(buf
));
11139 if (bgp_static
->gatewayIp
.family
== AF_INET
||
11140 bgp_static
->gatewayIp
.family
== AF_INET6
)
11141 inet_ntop(bgp_static
->gatewayIp
.family
,
11142 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11145 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
11146 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11147 decode_label(&bgp_static
->label
), esi
, buf2
,
11151 XFREE(MTYPE_TMP
, macrouter
);
11153 XFREE(MTYPE_TMP
, esi
);
11158 /* Configuration of static route announcement and aggregate
11160 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11163 struct bgp_node
*rn
;
11165 struct bgp_static
*bgp_static
;
11166 struct bgp_aggregate
*bgp_aggregate
;
11167 char buf
[SU_ADDRSTRLEN
];
11169 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11170 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11174 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11175 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11179 /* Network configuration. */
11180 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11181 rn
= bgp_route_next(rn
)) {
11182 if ((bgp_static
= rn
->info
) == NULL
)
11187 /* "network" configuration display. */
11188 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11189 u_int32_t destination
;
11190 struct in_addr netmask
;
11192 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11193 masklen2ip(p
->prefixlen
, &netmask
);
11194 vty_out(vty
, " network %s",
11195 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11198 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11199 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11200 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11201 || p
->u
.prefix4
.s_addr
== 0) {
11202 /* Natural mask is not display. */
11204 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11206 vty_out(vty
, " network %s/%d",
11207 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11212 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11213 vty_out(vty
, " label-index %u",
11214 bgp_static
->label_index
);
11216 if (bgp_static
->rmap
.name
)
11217 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11219 if (bgp_static
->backdoor
)
11220 vty_out(vty
, " backdoor");
11223 vty_out(vty
, "\n");
11226 /* Aggregate-address configuration. */
11227 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11228 rn
= bgp_route_next(rn
)) {
11229 if ((bgp_aggregate
= rn
->info
) == NULL
)
11234 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11235 struct in_addr netmask
;
11237 masklen2ip(p
->prefixlen
, &netmask
);
11238 vty_out(vty
, " aggregate-address %s %s",
11239 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11241 inet_ntoa(netmask
));
11243 vty_out(vty
, " aggregate-address %s/%d",
11244 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11249 if (bgp_aggregate
->as_set
)
11250 vty_out(vty
, " as-set");
11252 if (bgp_aggregate
->summary_only
)
11253 vty_out(vty
, " summary-only");
11255 vty_out(vty
, "\n");
11259 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11262 struct bgp_node
*rn
;
11263 struct bgp_distance
*bdistance
;
11265 /* Distance configuration. */
11266 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11267 && bgp
->distance_local
[afi
][safi
]
11268 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11269 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11270 || bgp
->distance_local
[afi
][safi
]
11271 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11272 vty_out(vty
, " distance bgp %d %d %d\n",
11273 bgp
->distance_ebgp
[afi
][safi
],
11274 bgp
->distance_ibgp
[afi
][safi
],
11275 bgp
->distance_local
[afi
][safi
]);
11278 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11279 rn
= bgp_route_next(rn
))
11280 if ((bdistance
= rn
->info
) != NULL
) {
11281 char buf
[PREFIX_STRLEN
];
11283 vty_out(vty
, " distance %d %s %s\n",
11284 bdistance
->distance
,
11285 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11286 bdistance
->access_list
? bdistance
->access_list
11291 /* Allocate routing table structure and install commands. */
11292 void bgp_route_init(void)
11297 /* Init BGP distance table. */
11298 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11299 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
11300 bgp_distance_table
[afi
][safi
] =
11301 bgp_table_init(afi
, safi
);
11303 /* IPv4 BGP commands. */
11304 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11305 install_element(BGP_NODE
, &bgp_network_cmd
);
11306 install_element(BGP_NODE
, &bgp_network_mask_cmd
);
11307 install_element(BGP_NODE
, &bgp_network_mask_natural_cmd
);
11308 install_element(BGP_NODE
, &bgp_network_route_map_cmd
);
11309 install_element(BGP_NODE
, &bgp_network_mask_route_map_cmd
);
11310 install_element(BGP_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11311 install_element(BGP_NODE
, &bgp_network_backdoor_cmd
);
11312 install_element(BGP_NODE
, &bgp_network_mask_backdoor_cmd
);
11313 install_element(BGP_NODE
, &bgp_network_mask_natural_backdoor_cmd
);
11314 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11315 install_element(BGP_NODE
, &no_bgp_network_cmd
);
11316 install_element(BGP_NODE
, &no_bgp_network_mask_cmd
);
11317 install_element(BGP_NODE
, &no_bgp_network_mask_natural_cmd
);
11319 install_element(BGP_NODE
, &aggregate_address_cmd
);
11320 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11321 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11322 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11324 /* IPv4 unicast configuration. */
11325 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11326 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11327 install_element(BGP_IPV4_NODE
, &bgp_network_mask_cmd
);
11328 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_cmd
);
11329 install_element(BGP_IPV4_NODE
, &bgp_network_route_map_cmd
);
11330 install_element(BGP_IPV4_NODE
, &bgp_network_mask_route_map_cmd
);
11331 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11332 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_cmd
);
11333 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_route_map_cmd
);
11334 install_element(BGP_IPV4_NODE
, &no_bgp_network_label_index_cmd
);
11335 install_element(BGP_IPV4_NODE
,
11336 &no_bgp_network_label_index_route_map_cmd
);
11337 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11338 install_element(BGP_IPV4_NODE
, &no_bgp_network_cmd
);
11339 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_cmd
);
11340 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_natural_cmd
);
11342 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11343 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11344 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11345 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11347 /* IPv4 multicast configuration. */
11348 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11349 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11350 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_cmd
);
11351 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_natural_cmd
);
11352 install_element(BGP_IPV4M_NODE
, &bgp_network_route_map_cmd
);
11353 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_route_map_cmd
);
11354 install_element(BGP_IPV4M_NODE
,
11355 &bgp_network_mask_natural_route_map_cmd
);
11356 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11357 install_element(BGP_IPV4M_NODE
, &no_bgp_network_cmd
);
11358 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_cmd
);
11359 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_natural_cmd
);
11360 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11361 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11362 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11363 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11365 /* IPv4 labeled-unicast configuration. */
11366 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11367 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11368 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11369 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11370 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11372 install_element(VIEW_NODE
,
11373 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11374 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11375 install_element(VIEW_NODE
,
11376 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11377 #ifdef KEEP_OLD_VPN_COMMANDS
11378 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11379 #endif /* KEEP_OLD_VPN_COMMANDS */
11380 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11381 install_element(VIEW_NODE
,
11382 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11384 /* BGP dampening clear commands */
11385 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11386 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11388 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11389 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11392 install_element(ENABLE_NODE
,
11393 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11394 #ifdef KEEP_OLD_VPN_COMMANDS
11395 install_element(ENABLE_NODE
,
11396 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11397 #endif /* KEEP_OLD_VPN_COMMANDS */
11399 /* New config IPv6 BGP commands. */
11400 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11401 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11402 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_route_map_cmd
);
11403 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11404 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_cmd
);
11405 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_label_index_cmd
);
11406 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_label_index_cmd
);
11407 install_element(BGP_IPV6_NODE
,
11408 &ipv6_bgp_network_label_index_route_map_cmd
);
11409 install_element(BGP_IPV6_NODE
,
11410 &no_ipv6_bgp_network_label_index_route_map_cmd
);
11412 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11413 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11415 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11416 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_network_cmd
);
11418 install_element(BGP_IPV6L_NODE
, &bgp_table_map_cmd
);
11419 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_cmd
);
11420 install_element(BGP_IPV6L_NODE
, &ipv6_bgp_network_route_map_cmd
);
11421 install_element(BGP_IPV6L_NODE
, &no_bgp_table_map_cmd
);
11422 install_element(BGP_IPV6L_NODE
, &no_ipv6_bgp_network_cmd
);
11424 install_element(BGP_NODE
, &bgp_distance_cmd
);
11425 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11426 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11427 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11428 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11429 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11430 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11431 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11432 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11433 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11434 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11435 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11436 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11437 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11438 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11439 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11440 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11441 install_element(BGP_IPV4M_NODE
,
11442 &no_bgp_distance_source_access_list_cmd
);
11443 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11444 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11445 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11446 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11447 install_element(BGP_IPV6_NODE
,
11448 &ipv6_bgp_distance_source_access_list_cmd
);
11449 install_element(BGP_IPV6_NODE
,
11450 &no_ipv6_bgp_distance_source_access_list_cmd
);
11451 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11452 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11453 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11454 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11455 install_element(BGP_IPV6M_NODE
,
11456 &ipv6_bgp_distance_source_access_list_cmd
);
11457 install_element(BGP_IPV6M_NODE
,
11458 &no_ipv6_bgp_distance_source_access_list_cmd
);
11460 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11461 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11462 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11463 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11465 /* IPv4 Multicast Mode */
11466 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11467 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11469 /* Large Communities */
11470 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11471 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11474 void bgp_route_finish(void)
11479 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11480 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
11481 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11482 bgp_distance_table
[afi
][safi
] = NULL
;