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
= newattr
->weight
;
492 exist_weight
= existattr
->weight
;
494 if (new_weight
> exist_weight
) {
496 zlog_debug("%s: %s wins over %s due to weight %d > %d",
497 pfx_buf
, new_buf
, exist_buf
, new_weight
,
502 if (new_weight
< exist_weight
) {
504 zlog_debug("%s: %s loses to %s due to weight %d < %d",
505 pfx_buf
, new_buf
, exist_buf
, new_weight
,
510 /* 2. Local preference check. */
511 new_pref
= exist_pref
= bgp
->default_local_pref
;
513 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
514 new_pref
= newattr
->local_pref
;
515 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
516 exist_pref
= existattr
->local_pref
;
518 if (new_pref
> exist_pref
) {
521 "%s: %s wins over %s due to localpref %d > %d",
522 pfx_buf
, new_buf
, exist_buf
, new_pref
,
527 if (new_pref
< exist_pref
) {
530 "%s: %s loses to %s due to localpref %d < %d",
531 pfx_buf
, new_buf
, exist_buf
, new_pref
,
536 /* 3. Local route check. We prefer:
538 * - BGP_ROUTE_AGGREGATE
539 * - BGP_ROUTE_REDISTRIBUTE
541 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
544 "%s: %s wins over %s due to preferred BGP_ROUTE type",
545 pfx_buf
, new_buf
, exist_buf
);
549 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
552 "%s: %s loses to %s due to preferred BGP_ROUTE type",
553 pfx_buf
, new_buf
, exist_buf
);
557 /* 4. AS path length check. */
558 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
559 int exist_hops
= aspath_count_hops(existattr
->aspath
);
560 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
562 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
565 aspath_hops
= aspath_count_hops(newattr
->aspath
);
566 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
568 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
571 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
572 pfx_buf
, new_buf
, exist_buf
,
574 (exist_hops
+ exist_confeds
));
578 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
581 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
582 pfx_buf
, new_buf
, exist_buf
,
584 (exist_hops
+ exist_confeds
));
588 int newhops
= aspath_count_hops(newattr
->aspath
);
590 if (newhops
< exist_hops
) {
593 "%s: %s wins over %s due to aspath hopcount %d < %d",
594 pfx_buf
, new_buf
, exist_buf
,
595 newhops
, exist_hops
);
599 if (newhops
> exist_hops
) {
602 "%s: %s loses to %s due to aspath hopcount %d > %d",
603 pfx_buf
, new_buf
, exist_buf
,
604 newhops
, exist_hops
);
610 /* 5. Origin check. */
611 if (newattr
->origin
< existattr
->origin
) {
613 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
614 pfx_buf
, new_buf
, exist_buf
,
615 bgp_origin_long_str
[newattr
->origin
],
616 bgp_origin_long_str
[existattr
->origin
]);
620 if (newattr
->origin
> existattr
->origin
) {
622 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
623 pfx_buf
, new_buf
, exist_buf
,
624 bgp_origin_long_str
[newattr
->origin
],
625 bgp_origin_long_str
[existattr
->origin
]);
630 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
631 && aspath_count_hops(existattr
->aspath
) == 0);
632 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
633 && aspath_count_confeds(existattr
->aspath
) > 0
634 && aspath_count_hops(newattr
->aspath
) == 0
635 && aspath_count_hops(existattr
->aspath
) == 0);
637 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
638 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
639 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
640 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
641 || internal_as_route
) {
642 new_med
= bgp_med_value(new->attr
, bgp
);
643 exist_med
= bgp_med_value(exist
->attr
, bgp
);
645 if (new_med
< exist_med
) {
648 "%s: %s wins over %s due to MED %d < %d",
649 pfx_buf
, new_buf
, exist_buf
, new_med
,
654 if (new_med
> exist_med
) {
657 "%s: %s loses to %s due to MED %d > %d",
658 pfx_buf
, new_buf
, exist_buf
, new_med
,
664 /* 7. Peer type check. */
665 new_sort
= new->peer
->sort
;
666 exist_sort
= exist
->peer
->sort
;
668 if (new_sort
== BGP_PEER_EBGP
669 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
672 "%s: %s wins over %s due to eBGP peer > iBGP peer",
673 pfx_buf
, new_buf
, exist_buf
);
677 if (exist_sort
== BGP_PEER_EBGP
678 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
681 "%s: %s loses to %s due to iBGP peer < eBGP peer",
682 pfx_buf
, new_buf
, exist_buf
);
686 /* 8. IGP metric check. */
690 newm
= new->extra
->igpmetric
;
692 existm
= exist
->extra
->igpmetric
;
697 "%s: %s wins over %s due to IGP metric %d < %d",
698 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
705 "%s: %s loses to %s due to IGP metric %d > %d",
706 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
710 /* 9. Same IGP metric. Compare the cluster list length as
711 representative of IGP hops metric. Rewrite the metric value
712 pair (newm, existm) with the cluster list length. Prefer the
713 path with smaller cluster list length. */
714 if (newm
== existm
) {
715 if (peer_sort(new->peer
) == BGP_PEER_IBGP
716 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
717 && (mpath_cfg
== NULL
719 mpath_cfg
->ibgp_flags
,
720 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
721 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
722 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
727 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
728 pfx_buf
, new_buf
, exist_buf
,
736 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
737 pfx_buf
, new_buf
, exist_buf
,
744 /* 10. confed-external vs. confed-internal */
745 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
746 if (new_sort
== BGP_PEER_CONFED
747 && exist_sort
== BGP_PEER_IBGP
) {
750 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
751 pfx_buf
, new_buf
, exist_buf
);
755 if (exist_sort
== BGP_PEER_CONFED
756 && new_sort
== BGP_PEER_IBGP
) {
759 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
760 pfx_buf
, new_buf
, exist_buf
);
765 /* 11. Maximum path check. */
766 if (newm
== existm
) {
767 /* If one path has a label but the other does not, do not treat
768 * them as equals for multipath
770 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
))
772 && bgp_is_valid_label(&exist
->extra
->label
))) {
775 "%s: %s and %s cannot be multipath, one has a label while the other does not",
776 pfx_buf
, new_buf
, exist_buf
);
777 } else if (bgp_flag_check(bgp
,
778 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
781 * For the two paths, all comparison steps till IGP
783 * have succeeded - including AS_PATH hop count. Since
785 * bestpath as-path multipath-relax' knob is on, we
787 * an exact match of AS_PATH. Thus, mark the paths are
789 * That will trigger both these paths to get into the
797 "%s: %s and %s are equal via multipath-relax",
798 pfx_buf
, new_buf
, exist_buf
);
799 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
800 if (aspath_cmp(new->attr
->aspath
,
801 exist
->attr
->aspath
)) {
806 "%s: %s and %s are equal via matching aspaths",
807 pfx_buf
, new_buf
, exist_buf
);
809 } else if (new->peer
->as
== exist
->peer
->as
) {
814 "%s: %s and %s are equal via same remote-as",
815 pfx_buf
, new_buf
, exist_buf
);
819 * TODO: If unequal cost ibgp multipath is enabled we can
820 * mark the paths as equal here instead of returning
825 "%s: %s wins over %s after IGP metric comparison",
826 pfx_buf
, new_buf
, exist_buf
);
829 "%s: %s loses to %s after IGP metric comparison",
830 pfx_buf
, new_buf
, exist_buf
);
835 /* 12. If both paths are external, prefer the path that was received
836 first (the oldest one). This step minimizes route-flap, since a
837 newer path won't displace an older one, even if it was the
838 preferred route based on the additional decision criteria below. */
839 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
840 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
841 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
844 "%s: %s wins over %s due to oldest external",
845 pfx_buf
, new_buf
, exist_buf
);
849 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
852 "%s: %s loses to %s due to oldest external",
853 pfx_buf
, new_buf
, exist_buf
);
858 /* 13. Router-ID comparision. */
859 /* If one of the paths is "stale", the corresponding peer router-id will
860 * be 0 and would always win over the other path. If originator id is
861 * used for the comparision, it will decide which path is better.
863 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
864 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
866 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
867 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
868 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
870 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
872 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
875 "%s: %s wins over %s due to Router-ID comparison",
876 pfx_buf
, new_buf
, exist_buf
);
880 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
883 "%s: %s loses to %s due to Router-ID comparison",
884 pfx_buf
, new_buf
, exist_buf
);
888 /* 14. Cluster length comparision. */
889 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
890 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
892 if (new_cluster
< exist_cluster
) {
895 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
896 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
901 if (new_cluster
> exist_cluster
) {
904 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
905 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
910 /* 15. Neighbor address comparision. */
911 /* Do this only if neither path is "stale" as stale paths do not have
912 * valid peer information (as the connection may or may not be up).
914 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
917 "%s: %s wins over %s due to latter path being STALE",
918 pfx_buf
, new_buf
, exist_buf
);
922 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
925 "%s: %s loses to %s due to former path being STALE",
926 pfx_buf
, new_buf
, exist_buf
);
930 /* locally configured routes to advertise do not have su_remote */
931 if (new->peer
->su_remote
== NULL
)
933 if (exist
->peer
->su_remote
== NULL
)
936 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
941 "%s: %s loses to %s due to Neighor IP comparison",
942 pfx_buf
, new_buf
, exist_buf
);
949 "%s: %s wins over %s due to Neighor IP comparison",
950 pfx_buf
, new_buf
, exist_buf
);
955 zlog_debug("%s: %s wins over %s due to nothing left to compare",
956 pfx_buf
, new_buf
, exist_buf
);
961 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
962 * is preferred, or 0 if they are the same (usually will only occur if
963 * multipath is enabled
964 * This version is compatible with */
965 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
966 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
971 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
985 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
986 struct attr
*attr
, afi_t afi
,
989 struct bgp_filter
*filter
;
991 filter
= &peer
->filter
[afi
][safi
];
993 #define FILTER_EXIST_WARN(F, f, filter) \
994 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
995 zlog_warn("%s: Could not find configured input %s-list %s!", \
996 peer->host, #f, F##_IN_NAME(filter));
998 if (DISTRIBUTE_IN_NAME(filter
)) {
999 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1001 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1005 if (PREFIX_LIST_IN_NAME(filter
)) {
1006 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1008 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1012 if (FILTER_LIST_IN_NAME(filter
)) {
1013 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1015 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1020 return FILTER_PERMIT
;
1021 #undef FILTER_EXIST_WARN
1024 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1025 struct attr
*attr
, afi_t afi
,
1028 struct bgp_filter
*filter
;
1030 filter
= &peer
->filter
[afi
][safi
];
1032 #define FILTER_EXIST_WARN(F, f, filter) \
1033 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1034 zlog_warn("%s: Could not find configured output %s-list %s!", \
1035 peer->host, #f, F##_OUT_NAME(filter));
1037 if (DISTRIBUTE_OUT_NAME(filter
)) {
1038 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1040 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1044 if (PREFIX_LIST_OUT_NAME(filter
)) {
1045 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1047 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1052 if (FILTER_LIST_OUT_NAME(filter
)) {
1053 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1055 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1060 return FILTER_PERMIT
;
1061 #undef FILTER_EXIST_WARN
1064 /* If community attribute includes no_export then return 1. */
1065 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1067 if (attr
->community
) {
1068 /* NO_ADVERTISE check. */
1069 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1072 /* NO_EXPORT check. */
1073 if (peer
->sort
== BGP_PEER_EBGP
1074 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1077 /* NO_EXPORT_SUBCONFED check. */
1078 if (peer
->sort
== BGP_PEER_EBGP
1079 || peer
->sort
== BGP_PEER_CONFED
)
1080 if (community_include(attr
->community
,
1081 COMMUNITY_NO_EXPORT_SUBCONFED
))
1087 /* Route reflection loop check. */
1088 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1090 struct in_addr cluster_id
;
1092 if (attr
->cluster
) {
1093 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1094 cluster_id
= peer
->bgp
->cluster_id
;
1096 cluster_id
= peer
->bgp
->router_id
;
1098 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1104 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1105 struct attr
*attr
, afi_t afi
, safi_t safi
,
1106 const char *rmap_name
)
1108 struct bgp_filter
*filter
;
1109 struct bgp_info info
;
1110 route_map_result_t ret
;
1111 struct route_map
*rmap
= NULL
;
1113 filter
= &peer
->filter
[afi
][safi
];
1115 /* Apply default weight value. */
1116 if (peer
->weight
[afi
][safi
])
1117 attr
->weight
= peer
->weight
[afi
][safi
];
1120 rmap
= route_map_lookup_by_name(rmap_name
);
1125 if (ROUTE_MAP_IN_NAME(filter
)) {
1126 rmap
= ROUTE_MAP_IN(filter
);
1133 /* Route map apply. */
1135 /* Duplicate current value to new strucutre for modification. */
1139 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1141 /* Apply BGP route map to the attribute. */
1142 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1144 peer
->rmap_type
= 0;
1146 if (ret
== RMAP_DENYMATCH
) {
1147 /* Free newly generated AS path and community by
1149 bgp_attr_flush(attr
);
1156 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1157 struct attr
*attr
, afi_t afi
, safi_t safi
,
1158 const char *rmap_name
)
1160 struct bgp_filter
*filter
;
1161 struct bgp_info info
;
1162 route_map_result_t ret
;
1163 struct route_map
*rmap
= NULL
;
1165 filter
= &peer
->filter
[afi
][safi
];
1167 /* Apply default weight value. */
1168 if (peer
->weight
[afi
][safi
])
1169 attr
->weight
= peer
->weight
[afi
][safi
];
1172 rmap
= route_map_lookup_by_name(rmap_name
);
1177 if (ROUTE_MAP_OUT_NAME(filter
)) {
1178 rmap
= ROUTE_MAP_OUT(filter
);
1185 /* Route map apply. */
1187 /* Duplicate current value to new strucutre for modification. */
1191 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1193 /* Apply BGP route map to the attribute. */
1194 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1196 peer
->rmap_type
= 0;
1198 if (ret
== RMAP_DENYMATCH
)
1199 /* caller has multiple error paths with bgp_attr_flush()
1206 /* If this is an EBGP peer with remove-private-AS */
1207 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1208 struct peer
*peer
, struct attr
*attr
)
1210 if (peer
->sort
== BGP_PEER_EBGP
1211 && (peer_af_flag_check(peer
, afi
, safi
,
1212 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1213 || peer_af_flag_check(peer
, afi
, safi
,
1214 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1215 || peer_af_flag_check(peer
, afi
, safi
,
1216 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1217 || peer_af_flag_check(peer
, afi
, safi
,
1218 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1219 // Take action on the entire aspath
1220 if (peer_af_flag_check(peer
, afi
, safi
,
1221 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1222 || peer_af_flag_check(peer
, afi
, safi
,
1223 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1224 if (peer_af_flag_check(
1226 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1227 attr
->aspath
= aspath_replace_private_asns(
1228 attr
->aspath
, bgp
->as
);
1230 // The entire aspath consists of private ASNs so create
1232 else if (aspath_private_as_check(attr
->aspath
))
1233 attr
->aspath
= aspath_empty_get();
1235 // There are some public and some private ASNs, remove
1238 attr
->aspath
= aspath_remove_private_asns(
1242 // 'all' was not specified so the entire aspath must be private
1244 // for us to do anything
1245 else if (aspath_private_as_check(attr
->aspath
)) {
1246 if (peer_af_flag_check(
1248 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1249 attr
->aspath
= aspath_replace_private_asns(
1250 attr
->aspath
, bgp
->as
);
1252 attr
->aspath
= aspath_empty_get();
1257 /* If this is an EBGP peer with as-override */
1258 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1259 struct peer
*peer
, struct attr
*attr
)
1261 if (peer
->sort
== BGP_PEER_EBGP
1262 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1263 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1264 attr
->aspath
= aspath_replace_specific_asn(
1265 attr
->aspath
, peer
->as
, bgp
->as
);
1269 void bgp_attr_add_gshut_community(struct attr
*attr
)
1271 struct community
*old
;
1272 struct community
*new;
1273 struct community
*merge
;
1274 struct community
*gshut
;
1276 old
= attr
->community
;
1277 gshut
= community_str2com("graceful-shutdown");
1280 merge
= community_merge(community_dup(old
), gshut
);
1282 if (old
->refcnt
== 0)
1283 community_free(old
);
1285 new = community_uniq_sort(merge
);
1286 community_free(merge
);
1288 new = community_dup(gshut
);
1291 community_free(gshut
);
1292 attr
->community
= new;
1293 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1295 /* When we add the graceful-shutdown community we must also
1296 * lower the local-preference */
1297 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1298 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1302 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1304 if (family
== AF_INET
)
1305 attr
->nexthop
.s_addr
= 0;
1306 if (family
== AF_INET6
)
1307 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1310 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1311 struct update_subgroup
*subgrp
, struct prefix
*p
,
1314 struct bgp_filter
*filter
;
1317 struct peer
*onlypeer
;
1319 struct attr
*riattr
;
1320 char buf
[PREFIX_STRLEN
];
1326 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1328 if (DISABLE_BGP_ANNOUNCE
)
1331 afi
= SUBGRP_AFI(subgrp
);
1332 safi
= SUBGRP_SAFI(subgrp
);
1333 peer
= SUBGRP_PEER(subgrp
);
1335 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1336 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1339 filter
= &peer
->filter
[afi
][safi
];
1340 bgp
= SUBGRP_INST(subgrp
);
1341 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1344 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1345 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1346 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1349 * direct and direct_ext type routes originate internally even
1350 * though they can have peer pointers that reference other
1353 prefix2str(p
, buf
, PREFIX_STRLEN
);
1354 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1360 /* With addpath we may be asked to TX all kinds of paths so make sure
1362 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1363 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1364 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1368 /* If this is not the bestpath then check to see if there is an enabled
1370 * feature that requires us to advertise it */
1371 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1372 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1377 /* Aggregate-address suppress check. */
1378 if (ri
->extra
&& ri
->extra
->suppress
)
1379 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1383 /* If it's labeled safi, make sure the route has a valid label. */
1384 if (safi
== SAFI_LABELED_UNICAST
) {
1385 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1386 if (!bgp_is_valid_label(&label
)) {
1387 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1388 zlog_debug("u%" PRIu64
":s%" PRIu64
1389 " %s/%d is filtered - no label (%p)",
1390 subgrp
->update_group
->id
, subgrp
->id
,
1391 inet_ntop(p
->family
, &p
->u
.prefix
,
1392 buf
, SU_ADDRSTRLEN
),
1393 p
->prefixlen
, &label
);
1398 /* Do not send back route to sender. */
1399 if (onlypeer
&& from
== onlypeer
) {
1403 /* Do not send the default route in the BGP table if the neighbor is
1404 * configured for default-originate */
1405 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1406 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1407 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1409 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1413 /* Transparency check. */
1414 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1415 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1420 /* If community is not disabled check the no-export and local. */
1421 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1422 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1424 "subgrpannouncecheck: community filter check fail");
1428 /* If the attribute has originator-id and it is same as remote
1430 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1431 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1432 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1434 "%s [Update:SEND] %s originator-id is same as "
1437 prefix2str(p
, buf
, sizeof(buf
)));
1441 /* ORF prefix-list filter check */
1442 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1443 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1444 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1445 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1446 if (peer
->orf_plist
[afi
][safi
]) {
1447 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1449 if (bgp_debug_update(NULL
, p
,
1450 subgrp
->update_group
, 0))
1452 "%s [Update:SEND] %s is filtered via ORF",
1460 /* Output filter check. */
1461 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1462 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1463 zlog_debug("%s [Update:SEND] %s is filtered",
1464 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1468 #ifdef BGP_SEND_ASPATH_CHECK
1469 /* AS path loop check. */
1470 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1471 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1473 "%s [Update:SEND] suppress announcement to peer AS %u "
1474 "that is part of AS path.",
1475 onlypeer
->host
, onlypeer
->as
);
1478 #endif /* BGP_SEND_ASPATH_CHECK */
1480 /* If we're a CONFED we need to loop check the CONFED ID too */
1481 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1482 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1483 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1485 "%s [Update:SEND] suppress announcement to peer AS %u"
1487 peer
->host
, bgp
->confed_id
);
1492 /* Route-Reflect check. */
1493 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1498 /* IBGP reflection check. */
1499 if (reflect
&& !samepeer_safe
) {
1500 /* A route from a Client peer. */
1501 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1502 PEER_FLAG_REFLECTOR_CLIENT
)) {
1503 /* Reflect to all the Non-Client peers and also to the
1504 Client peers other than the originator. Originator
1506 is already done. So there is noting to do. */
1507 /* no bgp client-to-client reflection check. */
1508 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1509 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1510 PEER_FLAG_REFLECTOR_CLIENT
))
1513 /* A route from a Non-client peer. Reflect to all other
1515 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1516 PEER_FLAG_REFLECTOR_CLIENT
))
1521 /* For modify attribute, copy it to temporary structure. */
1522 bgp_attr_dup(attr
, riattr
);
1524 /* If local-preference is not set. */
1525 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1526 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1527 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1528 attr
->local_pref
= bgp
->default_local_pref
;
1531 /* If originator-id is not set and the route is to be reflected,
1532 set the originator id */
1534 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1535 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1536 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1539 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1541 if (peer
->sort
== BGP_PEER_EBGP
1542 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1543 if (from
!= bgp
->peer_self
&& !transparent
1544 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1545 PEER_FLAG_MED_UNCHANGED
))
1547 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1550 /* Since the nexthop attribute can vary per peer, it is not explicitly
1552 * in announce check, only certain flags and length (or number of
1554 * -- for IPv6/MP_REACH) are set here in order to guide the update
1556 * code in setting the nexthop(s) on a per peer basis in
1558 * Typically, the source nexthop in the attribute is preserved but in
1560 * scenarios where we know it will always be overwritten, we reset the
1561 * nexthop to "0" in an attempt to achieve better Update packing. An
1562 * example of this is when a prefix from each of 2 IBGP peers needs to
1564 * announced to an EBGP peer (and they have the same attributes barring
1568 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1570 #define NEXTHOP_IS_V6 \
1571 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1572 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1573 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1574 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1576 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1578 * the peer (group) is configured to receive link-local nexthop
1580 * and it is available in the prefix OR we're not reflecting the route
1582 * the peer (group) to whom we're going to announce is on a shared
1584 * and this is either a self-originated route or the peer is EBGP.
1586 if (NEXTHOP_IS_V6
) {
1587 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1588 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1589 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1590 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1591 || (!reflect
&& peer
->shared_network
1592 && (from
== bgp
->peer_self
1593 || peer
->sort
== BGP_PEER_EBGP
))) {
1594 attr
->mp_nexthop_len
=
1595 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1598 /* Clear off link-local nexthop in source, whenever it is not
1600 * ensure more prefixes share the same attribute for
1603 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1604 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1605 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1608 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1609 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1611 /* Route map & unsuppress-map apply. */
1612 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1613 struct bgp_info info
;
1614 struct bgp_info_extra dummy_info_extra
;
1615 struct attr dummy_attr
;
1621 memcpy(&dummy_info_extra
, ri
->extra
,
1622 sizeof(struct bgp_info_extra
));
1623 info
.extra
= &dummy_info_extra
;
1626 /* don't confuse inbound and outbound setting */
1627 RESET_FLAG(attr
->rmap_change_flags
);
1630 * The route reflector is not allowed to modify the attributes
1631 * of the reflected IBGP routes unless explicitly allowed.
1633 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1634 && !bgp_flag_check(bgp
,
1635 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1636 bgp_attr_dup(&dummy_attr
, attr
);
1637 info
.attr
= &dummy_attr
;
1640 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1642 if (ri
->extra
&& ri
->extra
->suppress
)
1643 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1646 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1649 peer
->rmap_type
= 0;
1651 if (ret
== RMAP_DENYMATCH
) {
1652 bgp_attr_flush(attr
);
1657 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1658 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
1659 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1660 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1662 bgp_attr_add_gshut_community(attr
);
1666 /* After route-map has been applied, we check to see if the nexthop to
1667 * be carried in the attribute (that is used for the announcement) can
1668 * be cleared off or not. We do this in all cases where we would be
1669 * setting the nexthop to "ourselves". For IPv6, we only need to
1671 * the global nexthop here; the link-local nexthop would have been
1673 * already, and if not, it is required by the update formation code.
1674 * Also see earlier comments in this function.
1677 * If route-map has performed some operation on the nexthop or the peer
1678 * configuration says to pass it unchanged, we cannot reset the nexthop
1679 * here, so only attempt to do it if these aren't true. Note that the
1680 * route-map handler itself might have cleared the nexthop, if for
1682 * it is configured as 'peer-address'.
1684 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1685 riattr
->rmap_change_flags
)
1687 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1688 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1689 /* We can reset the nexthop, if setting (or forcing) it to
1691 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1692 PEER_FLAG_NEXTHOP_SELF
)
1693 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1694 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1696 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1697 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1698 subgroup_announce_reset_nhop(
1699 (peer_cap_enhe(peer
, afi
, safi
)
1703 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1704 /* Can also reset the nexthop if announcing to EBGP, but
1706 * no peer in the subgroup is on a shared subnet.
1707 * Note: 3rd party nexthop currently implemented for
1710 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1712 subgroup_announce_reset_nhop(
1713 (peer_cap_enhe(peer
, afi
, safi
)
1718 /* If IPv6/MP and nexthop does not have any override and happens
1720 * be a link-local address, reset it so that we don't pass along
1722 * source's link-local IPv6 address to recipients who may not be
1724 * the same interface.
1726 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1727 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1728 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1735 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1736 struct bgp_maxpaths_cfg
*mpath_cfg
,
1737 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1739 struct bgp_info
*new_select
;
1740 struct bgp_info
*old_select
;
1741 struct bgp_info
*ri
;
1742 struct bgp_info
*ri1
;
1743 struct bgp_info
*ri2
;
1744 struct bgp_info
*nextri
= NULL
;
1745 int paths_eq
, do_mpath
, debug
;
1746 struct list mp_list
;
1747 char pfx_buf
[PREFIX2STR_BUFFER
];
1748 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1750 bgp_mp_list_init(&mp_list
);
1752 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1754 debug
= bgp_debug_bestpath(&rn
->p
);
1757 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1759 /* bgp deterministic-med */
1761 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1763 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1764 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1765 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1767 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1768 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1770 if (BGP_INFO_HOLDDOWN(ri1
))
1772 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1773 if (ri1
->peer
->status
!= Established
)
1778 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1779 if (CHECK_FLAG(ri2
->flags
,
1780 BGP_INFO_DMED_CHECK
))
1782 if (BGP_INFO_HOLDDOWN(ri2
))
1785 && ri2
->peer
!= bgp
->peer_self
1788 PEER_STATUS_NSF_WAIT
))
1789 if (ri2
->peer
->status
1793 if (aspath_cmp_left(ri1
->attr
->aspath
,
1795 || aspath_cmp_left_confed(
1797 ri2
->attr
->aspath
)) {
1798 if (bgp_info_cmp(bgp
, ri2
,
1804 bgp_info_unset_flag(
1806 BGP_INFO_DMED_SELECTED
);
1812 BGP_INFO_DMED_CHECK
);
1816 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1817 bgp_info_set_flag(rn
, new_select
,
1818 BGP_INFO_DMED_SELECTED
);
1821 bgp_info_path_with_addpath_rx_str(new_select
,
1823 zlog_debug("%s: %s is the bestpath from AS %d",
1825 aspath_get_first_as(
1826 new_select
->attr
->aspath
));
1831 /* Check old selected route and new selected route. */
1834 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1836 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1839 if (BGP_INFO_HOLDDOWN(ri
)) {
1840 /* reap REMOVED routes, if needs be
1841 * selected route must stay for a while longer though
1843 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1844 && (ri
!= old_select
))
1845 bgp_info_reap(rn
, ri
);
1850 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1851 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1852 if (ri
->peer
->status
!= Established
)
1855 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1856 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1857 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1861 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1863 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1864 debug
, pfx_buf
, afi
, safi
)) {
1869 /* Now that we know which path is the bestpath see if any of the other
1871 * qualify as multipaths
1875 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1877 sprintf(path_buf
, "NONE");
1879 "%s: After path selection, newbest is %s oldbest was %s",
1881 old_select
? old_select
->peer
->host
: "NONE");
1884 if (do_mpath
&& new_select
) {
1885 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1889 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1891 if (ri
== new_select
) {
1894 "%s: %s is the bestpath, add to the multipath list",
1896 bgp_mp_list_add(&mp_list
, ri
);
1900 if (BGP_INFO_HOLDDOWN(ri
))
1903 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1904 && !CHECK_FLAG(ri
->peer
->sflags
,
1905 PEER_STATUS_NSF_WAIT
))
1906 if (ri
->peer
->status
!= Established
)
1909 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1912 "%s: %s has the same nexthop as the bestpath, skip it",
1917 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1918 debug
, pfx_buf
, afi
, safi
);
1923 "%s: %s is equivalent to the bestpath, add to the multipath list",
1925 bgp_mp_list_add(&mp_list
, ri
);
1930 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1931 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1932 bgp_mp_list_clear(&mp_list
);
1934 result
->old
= old_select
;
1935 result
->new = new_select
;
1941 * A new route/change in bestpath of an existing route. Evaluate the path
1942 * for advertisement to the subgroup.
1944 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1945 struct bgp_info
*selected
,
1946 struct bgp_node
*rn
,
1947 u_int32_t addpath_tx_id
)
1950 struct peer
*onlypeer
;
1956 afi
= SUBGRP_AFI(subgrp
);
1957 safi
= SUBGRP_SAFI(subgrp
);
1958 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1961 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1962 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1963 PEER_STATUS_ORF_WAIT_REFRESH
))
1966 memset(&attr
, 0, sizeof(struct attr
));
1967 /* It's initialized in bgp_announce_check() */
1969 /* Announcement to the subgroup. If the route is filtered withdraw it.
1972 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1973 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1975 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1976 selected
->addpath_tx_id
);
1979 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1981 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1988 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1989 * This is called at the end of route processing.
1991 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1993 struct bgp_info
*ri
;
1995 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1996 if (BGP_INFO_HOLDDOWN(ri
))
1998 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
1999 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2004 * Has the route changed from the RIB's perspective? This is invoked only
2005 * if the route selection returns the same best route as earlier - to
2006 * determine if we need to update zebra or not.
2008 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2010 struct bgp_info
*mpinfo
;
2012 /* If this is multipath, check all selected paths for any nexthop change
2014 * attribute change. Some attribute changes (e.g., community) aren't of
2015 * relevance to the RIB, but we'll update zebra to ensure we handle the
2016 * case of BGP nexthop change. This is the behavior when the best path
2018 * an attribute change anyway.
2020 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2021 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2024 /* If this is multipath, check all selected paths for any nexthop change
2026 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2027 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2028 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2029 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2033 /* Nothing has changed from the RIB's perspective. */
2037 struct bgp_process_queue
{
2039 STAILQ_HEAD(, bgp_node
)pqueue
;
2040 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2042 unsigned int queued
;
2045 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2046 afi_t afi
, safi_t safi
)
2048 struct prefix
*p
= &rn
->p
;
2049 struct bgp_info
*new_select
;
2050 struct bgp_info
*old_select
;
2051 struct bgp_info_pair old_and_new
;
2053 /* Is it end of initial update? (after startup) */
2055 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2056 sizeof(bgp
->update_delay_zebra_resume_time
));
2058 bgp
->main_zebra_update_hold
= 0;
2059 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
2060 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
2061 if (bgp_fibupd_safi(safi
))
2062 bgp_zebra_announce_table(bgp
, afi
,
2065 bgp
->main_peers_update_hold
= 0;
2067 bgp_start_routeadv(bgp
);
2071 /* Best path selection. */
2072 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2074 old_select
= old_and_new
.old
;
2075 new_select
= old_and_new
.new;
2077 /* Do we need to allocate or free labels?
2078 * Right now, since we only deal with per-prefix labels, it is not
2079 * necessary to do this upon changes to best path except if the label
2082 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2085 || bgp_label_index_differs(new_select
, old_select
)
2086 || new_select
->sub_type
!= old_select
->sub_type
) {
2087 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2088 && new_select
->attr
->flag
2090 BGP_ATTR_PREFIX_SID
)
2091 && new_select
->attr
->label_index
2092 != BGP_INVALID_LABEL_INDEX
) {
2095 BGP_NODE_REGISTERED_FOR_LABEL
))
2096 bgp_unregister_for_label(rn
);
2097 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2099 bgp_set_valid_label(&rn
->local_label
);
2101 bgp_register_for_label(rn
, new_select
);
2103 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2104 bgp_unregister_for_label(rn
);
2106 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2107 bgp_unregister_for_label(rn
);
2110 /* If best route remains the same and this is not due to user-initiated
2111 * clear, see exactly what needs to be done.
2114 if (old_select
&& old_select
== new_select
2115 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2116 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2117 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2118 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2120 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2121 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2123 if (bgp_fibupd_safi(safi
)
2124 && !bgp_option_check(BGP_OPT_NO_FIB
)
2125 && new_select
->type
== ZEBRA_ROUTE_BGP
2126 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2127 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2130 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2131 bgp_zebra_clear_route_change_flags(rn
);
2133 /* If there is a change of interest to peers, reannounce the
2135 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2136 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2137 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2139 /* unicast routes must also be annouced to
2140 * labeled-unicast update-groups */
2141 if (safi
== SAFI_UNICAST
)
2142 group_announce_route(bgp
, afi
,
2143 SAFI_LABELED_UNICAST
, rn
,
2146 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2147 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2150 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2154 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2156 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2158 /* bestpath has changed; bump version */
2159 if (old_select
|| new_select
) {
2160 bgp_bump_version(rn
);
2162 if (!bgp
->t_rmap_def_originate_eval
) {
2166 update_group_refresh_default_originate_route_map
,
2167 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2168 &bgp
->t_rmap_def_originate_eval
);
2173 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2175 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2176 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2177 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2181 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2182 if (old_select
!= new_select
) {
2184 vnc_import_bgp_exterior_del_route(bgp
, p
,
2186 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2189 vnc_import_bgp_exterior_add_route(bgp
, p
,
2191 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2197 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2199 /* unicast routes must also be annouced to labeled-unicast update-groups
2201 if (safi
== SAFI_UNICAST
)
2202 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2206 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2207 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2208 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2209 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2210 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2211 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2213 /* Withdraw the route from the kernel. */
2214 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2215 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2216 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2217 bgp_zebra_withdraw(p
, old_select
, safi
);
2221 /* Clear any route change flags. */
2222 bgp_zebra_clear_route_change_flags(rn
);
2224 /* Reap old select bgp_info, if it has been removed */
2225 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2226 bgp_info_reap(rn
, old_select
);
2228 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2232 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2234 struct bgp_process_queue
*pqnode
= data
;
2235 struct bgp
*bgp
= pqnode
->bgp
;
2236 struct bgp_table
*table
;
2237 struct bgp_node
*rn
;
2240 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2241 bgp_process_main_one(bgp
, NULL
, 0, 0);
2242 /* should always have dedicated wq call */
2243 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2247 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2248 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2249 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2250 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2251 table
= bgp_node_table(rn
);
2252 /* note, new RNs may be added as part of processing */
2253 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2255 bgp_unlock_node(rn
);
2256 bgp_table_unlock(table
);
2262 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2264 struct bgp_process_queue
*pqnode
= data
;
2266 bgp_unlock(pqnode
->bgp
);
2268 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2271 void bgp_process_queue_init(void)
2273 if (!bm
->process_main_queue
) {
2274 bm
->process_main_queue
=
2275 work_queue_new(bm
->master
, "process_main_queue");
2277 if (!bm
->process_main_queue
) {
2278 zlog_err("%s: Failed to allocate work queue", __func__
);
2283 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2284 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2285 bm
->process_main_queue
->spec
.max_retries
= 0;
2286 bm
->process_main_queue
->spec
.hold
= 50;
2287 /* Use a higher yield value of 50ms for main queue processing */
2288 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2291 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2293 struct bgp_process_queue
*pqnode
;
2295 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
, sizeof(struct bgp_process_queue
));
2297 /* unlocked in bgp_processq_del */
2298 pqnode
->bgp
= bgp_lock(bgp
);
2299 STAILQ_INIT(&pqnode
->pqueue
);
2304 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2306 #define ARBITRARY_PROCESS_QLEN 10000
2307 struct work_queue
*wq
= bm
->process_main_queue
;
2308 struct bgp_process_queue
*pqnode
;
2309 int pqnode_reuse
= 0;
2311 /* already scheduled for processing? */
2312 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2318 /* Add route nodes to an existing work queue item until reaching the
2319 limit only if is from the same BGP view and it's not an EOIU marker */
2320 if (work_queue_item_count(wq
)) {
2321 struct work_queue_item
*item
= work_queue_last_item(wq
);
2322 pqnode
= item
->data
;
2324 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
) ||
2325 pqnode
->bgp
!= bgp
|| pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2326 pqnode
= bgp_processq_alloc(bgp
);
2330 pqnode
= bgp_processq_alloc(bgp
);
2331 /* all unlocked in bgp_process_wq */
2332 bgp_table_lock(bgp_node_table(rn
));
2334 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2337 /* can't be enqueued twice */
2338 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2339 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2343 work_queue_add(wq
, pqnode
);
2348 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2350 struct bgp_process_queue
*pqnode
;
2352 if (bm
->process_main_queue
== NULL
)
2355 pqnode
= bgp_processq_alloc(bgp
);
2357 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2358 work_queue_add(bm
->process_main_queue
, pqnode
);
2361 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2365 peer
= THREAD_ARG(thread
);
2366 peer
->t_pmax_restart
= NULL
;
2368 if (bgp_debug_neighbor_events(peer
))
2370 "%s Maximum-prefix restart timer expired, restore peering",
2373 peer_clear(peer
, NULL
);
2378 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2382 iana_safi_t pkt_safi
;
2384 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2387 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2388 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2389 PEER_STATUS_PREFIX_LIMIT
)
2394 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2396 afi_safi_print(afi
, safi
), peer
->host
,
2397 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2398 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2400 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2401 PEER_FLAG_MAX_PREFIX_WARNING
))
2404 /* Convert AFI, SAFI to values for packet. */
2405 pkt_afi
= afi_int2iana(afi
);
2406 pkt_safi
= safi_int2iana(safi
);
2410 ndata
[0] = (pkt_afi
>> 8);
2412 ndata
[2] = pkt_safi
;
2413 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2414 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2415 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2416 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2418 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2419 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2420 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2424 /* Dynamic peers will just close their connection. */
2425 if (peer_dynamic_neighbor(peer
))
2428 /* restart timer start */
2429 if (peer
->pmax_restart
[afi
][safi
]) {
2430 peer
->v_pmax_restart
=
2431 peer
->pmax_restart
[afi
][safi
] * 60;
2433 if (bgp_debug_neighbor_events(peer
))
2435 "%s Maximum-prefix restart timer started for %d secs",
2436 peer
->host
, peer
->v_pmax_restart
);
2438 BGP_TIMER_ON(peer
->t_pmax_restart
,
2439 bgp_maximum_prefix_restart_timer
,
2440 peer
->v_pmax_restart
);
2445 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2446 PEER_STATUS_PREFIX_LIMIT
);
2448 if (peer
->pcount
[afi
][safi
]
2449 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2450 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2451 PEER_STATUS_PREFIX_THRESHOLD
)
2456 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2457 afi_safi_print(afi
, safi
), peer
->host
,
2458 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2459 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2460 PEER_STATUS_PREFIX_THRESHOLD
);
2462 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2463 PEER_STATUS_PREFIX_THRESHOLD
);
2467 /* Unconditionally remove the route from the RIB, without taking
2468 * damping into consideration (eg, because the session went down)
2470 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2471 afi_t afi
, safi_t safi
)
2473 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2475 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2476 bgp_info_delete(rn
, ri
); /* keep historical info */
2478 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2481 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2482 struct peer
*peer
, afi_t afi
, safi_t safi
,
2483 struct prefix_rd
*prd
)
2485 int status
= BGP_DAMP_NONE
;
2487 /* apply dampening, if result is suppressed, we'll be retaining
2488 * the bgp_info in the RIB for historical reference.
2490 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2491 && peer
->sort
== BGP_PEER_EBGP
)
2492 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2493 == BGP_DAMP_SUPPRESSED
) {
2494 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2500 if (safi
== SAFI_MPLS_VPN
) {
2501 struct bgp_node
*prn
= NULL
;
2502 struct bgp_table
*table
= NULL
;
2504 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2505 (struct prefix
*)prd
);
2507 table
= (struct bgp_table
*)(prn
->info
);
2509 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2510 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2512 bgp_unlock_node(prn
);
2514 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2515 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2517 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2518 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2524 /* If this is an EVPN route, process for un-import. */
2525 if (safi
== SAFI_EVPN
)
2526 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2528 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2531 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2532 struct peer
*peer
, struct attr
*attr
,
2533 struct bgp_node
*rn
)
2535 struct bgp_info
*new;
2537 /* Make new BGP info. */
2538 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2540 new->instance
= instance
;
2541 new->sub_type
= sub_type
;
2544 new->uptime
= bgp_clock();
2546 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2550 static void overlay_index_update(struct attr
*attr
,
2551 struct eth_segment_id
*eth_s_id
,
2552 union gw_addr
*gw_ip
)
2557 if (eth_s_id
== NULL
) {
2558 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2559 sizeof(struct eth_segment_id
));
2561 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2562 sizeof(struct eth_segment_id
));
2564 if (gw_ip
== NULL
) {
2565 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2567 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2568 sizeof(union gw_addr
));
2572 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2573 struct eth_segment_id
*eth_s_id
,
2574 union gw_addr
*gw_ip
)
2576 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2577 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2580 if (afi
!= AFI_L2VPN
)
2583 memset(&temp
, 0, 16);
2584 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2585 info_gw_ip
= (union gw_addr
*)&temp
;
2586 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2589 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2590 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2593 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2595 info_gw_ip_remote
= gw_ip
;
2596 if (eth_s_id
== NULL
)
2597 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2599 info_eth_s_id_remote
= eth_s_id
;
2600 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2602 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2603 sizeof(struct eth_segment_id
));
2606 /* Check if received nexthop is valid or not. */
2607 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2612 /* Only validated for unicast and multicast currently. */
2613 /* Also valid for EVPN where the nexthop is an IP address. */
2614 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2617 /* If NEXT_HOP is present, validate it. */
2618 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2619 if (attr
->nexthop
.s_addr
== 0
2620 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2621 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2625 /* If MP_NEXTHOP is present, validate it. */
2626 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2627 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2628 * it is not an IPv6 link-local address.
2630 if (attr
->mp_nexthop_len
) {
2631 switch (attr
->mp_nexthop_len
) {
2632 case BGP_ATTR_NHLEN_IPV4
:
2633 case BGP_ATTR_NHLEN_VPNV4
:
2634 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2635 || IPV4_CLASS_DE(ntohl(
2636 attr
->mp_nexthop_global_in
.s_addr
))
2637 || bgp_nexthop_self(bgp
,
2638 attr
->mp_nexthop_global_in
));
2641 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2642 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2643 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2644 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2645 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2646 || IN6_IS_ADDR_MULTICAST(
2647 &attr
->mp_nexthop_global
));
2659 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2660 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2661 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2662 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2665 int aspath_loop_count
= 0;
2666 struct bgp_node
*rn
;
2668 struct attr new_attr
;
2669 struct attr
*attr_new
;
2670 struct bgp_info
*ri
;
2671 struct bgp_info
*new;
2673 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2676 int do_loop_check
= 1;
2677 int has_valid_label
= 0;
2679 int vnc_implicit_withdraw
= 0;
2683 memset(&new_attr
, 0, sizeof(struct attr
));
2684 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2685 new_attr
.label
= MPLS_INVALID_LABEL
;
2688 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2689 has_valid_label
= bgp_is_valid_label(label
);
2691 if (has_valid_label
)
2692 sprintf(label_buf
, "label %u", label_pton(label
));
2694 /* When peer's soft reconfiguration enabled. Record input packet in
2697 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2698 && peer
!= bgp
->peer_self
)
2699 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2701 /* Check previously received route. */
2702 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2703 if (ri
->peer
== peer
&& ri
->type
== type
2704 && ri
->sub_type
== sub_type
2705 && ri
->addpath_rx_id
== addpath_id
)
2708 /* AS path local-as loop check. */
2709 if (peer
->change_local_as
) {
2710 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2711 aspath_loop_count
= 1;
2713 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2714 > aspath_loop_count
) {
2715 reason
= "as-path contains our own AS;";
2720 /* If the peer is configured for "allowas-in origin" and the last ASN in
2722 * as-path is our ASN then we do not need to call aspath_loop_check
2724 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2725 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2728 /* AS path loop check. */
2729 if (do_loop_check
) {
2730 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2731 > peer
->allowas_in
[afi
][safi
]
2732 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2733 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2734 > peer
->allowas_in
[afi
][safi
])) {
2735 reason
= "as-path contains our own AS;";
2740 /* Route reflector originator ID check. */
2741 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2742 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2743 reason
= "originator is us;";
2747 /* Route reflector cluster ID check. */
2748 if (bgp_cluster_filter(peer
, attr
)) {
2749 reason
= "reflected from the same cluster;";
2753 /* Apply incoming filter. */
2754 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2759 bgp_attr_dup(&new_attr
, attr
);
2761 /* Apply incoming route-map.
2762 * NB: new_attr may now contain newly allocated values from route-map
2764 * commands, so we need bgp_attr_flush in the error paths, until we
2766 * the attr (which takes over the memory references) */
2767 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2769 reason
= "route-map;";
2770 bgp_attr_flush(&new_attr
);
2774 if (peer
->sort
== BGP_PEER_EBGP
) {
2776 /* If we receive the graceful-shutdown community from an eBGP peer we
2777 * must lower local-preference */
2778 if (new_attr
.community
&&
2779 community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2780 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2781 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2783 /* If graceful-shutdown is configured then add the GSHUT community to
2784 * all paths received from eBGP peers */
2785 } else if (bgp_flag_check(peer
->bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2786 bgp_attr_add_gshut_community(&new_attr
);
2790 /* next hop check. */
2791 if (bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2792 reason
= "martian or self next-hop;";
2793 bgp_attr_flush(&new_attr
);
2797 attr_new
= bgp_attr_intern(&new_attr
);
2799 /* If the update is implicit withdraw. */
2801 ri
->uptime
= bgp_clock();
2802 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2804 /* Same attribute comes in. */
2805 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2806 && attrhash_cmp(ri
->attr
, attr_new
)
2807 && (!has_valid_label
2808 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2811 && (overlay_index_equal(
2812 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2813 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2814 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2815 BGP_CONFIG_DAMPENING
)
2816 && peer
->sort
== BGP_PEER_EBGP
2817 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2818 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2819 bgp_debug_rdpfxpath2str(
2820 afi
, safi
, prd
, p
, label
,
2821 addpath_id
? 1 : 0, addpath_id
,
2822 pfx_buf
, sizeof(pfx_buf
));
2823 zlog_debug("%s rcvd %s", peer
->host
,
2827 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2828 != BGP_DAMP_SUPPRESSED
) {
2829 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2831 bgp_process(bgp
, rn
, afi
, safi
);
2833 } else /* Duplicate - odd */
2835 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2836 if (!peer
->rcvd_attr_printed
) {
2838 "%s rcvd UPDATE w/ attr: %s",
2840 peer
->rcvd_attr_str
);
2841 peer
->rcvd_attr_printed
= 1;
2844 bgp_debug_rdpfxpath2str(
2845 afi
, safi
, prd
, p
, label
,
2846 addpath_id
? 1 : 0, addpath_id
,
2847 pfx_buf
, sizeof(pfx_buf
));
2849 "%s rcvd %s...duplicate ignored",
2850 peer
->host
, pfx_buf
);
2853 /* graceful restart STALE flag unset. */
2854 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2855 bgp_info_unset_flag(rn
, ri
,
2857 bgp_process(bgp
, rn
, afi
, safi
);
2861 bgp_unlock_node(rn
);
2862 bgp_attr_unintern(&attr_new
);
2867 /* Withdraw/Announce before we fully processed the withdraw */
2868 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2869 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2870 bgp_debug_rdpfxpath2str(
2871 afi
, safi
, prd
, p
, label
,
2872 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2875 "%s rcvd %s, flapped quicker than processing",
2876 peer
->host
, pfx_buf
);
2879 bgp_info_restore(rn
, ri
);
2882 /* Received Logging. */
2883 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2884 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2885 addpath_id
? 1 : 0, addpath_id
,
2886 pfx_buf
, sizeof(pfx_buf
));
2887 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2890 /* graceful restart STALE flag unset. */
2891 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2892 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2894 /* The attribute is changed. */
2895 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2897 /* implicit withdraw, decrement aggregate and pcount here.
2898 * only if update is accepted, they'll increment below.
2900 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2902 /* Update bgp route dampening information. */
2903 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2904 && peer
->sort
== BGP_PEER_EBGP
) {
2905 /* This is implicit withdraw so we should update
2908 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2909 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2912 if (safi
== SAFI_MPLS_VPN
) {
2913 struct bgp_node
*prn
= NULL
;
2914 struct bgp_table
*table
= NULL
;
2916 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2917 (struct prefix
*)prd
);
2919 table
= (struct bgp_table
*)(prn
->info
);
2921 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2922 bgp
, prd
, table
, p
, ri
);
2924 bgp_unlock_node(prn
);
2926 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2927 && (safi
== SAFI_UNICAST
)) {
2928 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2930 * Implicit withdraw case.
2932 ++vnc_implicit_withdraw
;
2933 vnc_import_bgp_del_route(bgp
, p
, ri
);
2934 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2939 /* Special handling for EVPN update of an existing route. If the
2940 * extended community attribute has changed, we need to
2942 * the route using its existing extended community. It will be
2943 * subsequently processed for import with the new extended
2946 if (safi
== SAFI_EVPN
&& !same_attr
) {
2948 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2950 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2953 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2954 attr_new
->ecommunity
);
2956 if (bgp_debug_update(peer
, p
, NULL
, 1))
2958 "Change in EXT-COMM, existing %s new %s",
2960 ri
->attr
->ecommunity
),
2962 attr_new
->ecommunity
));
2963 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2969 /* Update to new attribute. */
2970 bgp_attr_unintern(&ri
->attr
);
2971 ri
->attr
= attr_new
;
2973 /* Update MPLS label */
2974 if (has_valid_label
) {
2975 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2977 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2981 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2982 && (safi
== SAFI_UNICAST
)) {
2983 if (vnc_implicit_withdraw
) {
2985 * Add back the route with its new attributes
2987 * The route is still selected, until the route
2989 * queued by bgp_process actually runs. We have
2991 * update to the VNC side immediately to avoid
2993 * configuration changes (e.g., route-map
2995 * trigger re-importation of the entire RIB.
2997 vnc_import_bgp_add_route(bgp
, p
, ri
);
2998 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3002 /* Update Overlay Index */
3003 if (afi
== AFI_L2VPN
) {
3004 overlay_index_update(
3005 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3006 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3009 /* Update bgp route dampening information. */
3010 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3011 && peer
->sort
== BGP_PEER_EBGP
) {
3012 /* Now we do normal update dampening. */
3013 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3014 if (ret
== BGP_DAMP_SUPPRESSED
) {
3015 bgp_unlock_node(rn
);
3020 /* Nexthop reachability check - for unicast and
3021 * labeled-unicast.. */
3022 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3023 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3024 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3025 && !CHECK_FLAG(peer
->flags
,
3026 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3028 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3033 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
3035 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3037 if (BGP_DEBUG(nht
, NHT
)) {
3038 char buf1
[INET6_ADDRSTRLEN
];
3040 (const void *)&attr_new
3042 buf1
, INET6_ADDRSTRLEN
);
3043 zlog_debug("%s(%s): NH unresolved",
3044 __FUNCTION__
, buf1
);
3046 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3049 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3052 if (safi
== SAFI_MPLS_VPN
) {
3053 struct bgp_node
*prn
= NULL
;
3054 struct bgp_table
*table
= NULL
;
3056 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3057 (struct prefix
*)prd
);
3059 table
= (struct bgp_table
*)(prn
->info
);
3061 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3062 bgp
, prd
, table
, p
, ri
);
3064 bgp_unlock_node(prn
);
3068 /* If this is an EVPN route and some attribute has changed,
3070 * route for import. If the extended community has changed, we
3072 * have done the un-import earlier and the import would result
3074 * route getting injected into appropriate L2 VNIs. If it is
3076 * some other attribute change, the import will result in
3078 * the attributes for the route in the VNI(s).
3080 if (safi
== SAFI_EVPN
&& !same_attr
)
3081 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3083 /* Process change. */
3084 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3086 bgp_process(bgp
, rn
, afi
, safi
);
3087 bgp_unlock_node(rn
);
3090 if (SAFI_MPLS_VPN
== safi
) {
3091 mpls_label_t label_decoded
= decode_label(label
);
3093 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3094 type
, sub_type
, &label_decoded
);
3096 if (SAFI_ENCAP
== safi
) {
3097 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3098 type
, sub_type
, NULL
);
3103 } // End of implicit withdraw
3105 /* Received Logging. */
3106 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3107 if (!peer
->rcvd_attr_printed
) {
3108 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3109 peer
->rcvd_attr_str
);
3110 peer
->rcvd_attr_printed
= 1;
3113 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3114 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3116 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3119 /* Make new BGP info. */
3120 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3122 /* Update MPLS label */
3123 if (has_valid_label
) {
3124 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3126 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3129 /* Update Overlay Index */
3130 if (afi
== AFI_L2VPN
) {
3131 overlay_index_update(new->attr
,
3132 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3133 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3135 /* Nexthop reachability check. */
3136 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3137 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3138 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3139 && !CHECK_FLAG(peer
->flags
,
3140 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3141 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3146 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
))
3147 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3149 if (BGP_DEBUG(nht
, NHT
)) {
3150 char buf1
[INET6_ADDRSTRLEN
];
3152 (const void *)&attr_new
->nexthop
,
3153 buf1
, INET6_ADDRSTRLEN
);
3154 zlog_debug("%s(%s): NH unresolved",
3155 __FUNCTION__
, buf1
);
3157 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3160 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3163 new->addpath_rx_id
= addpath_id
;
3165 /* Increment prefix */
3166 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3168 /* Register new BGP information. */
3169 bgp_info_add(rn
, new);
3171 /* route_node_get lock */
3172 bgp_unlock_node(rn
);
3175 if (safi
== SAFI_MPLS_VPN
) {
3176 struct bgp_node
*prn
= NULL
;
3177 struct bgp_table
*table
= NULL
;
3179 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3181 table
= (struct bgp_table
*)(prn
->info
);
3183 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3184 bgp
, prd
, table
, p
, new);
3186 bgp_unlock_node(prn
);
3190 /* If maximum prefix count is configured and current prefix
3192 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3195 /* If this is an EVPN route, process for import. */
3196 if (safi
== SAFI_EVPN
)
3197 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3199 /* Process change. */
3200 bgp_process(bgp
, rn
, afi
, safi
);
3203 if (SAFI_MPLS_VPN
== safi
) {
3204 mpls_label_t label_decoded
= decode_label(label
);
3206 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3207 sub_type
, &label_decoded
);
3209 if (SAFI_ENCAP
== safi
) {
3210 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3217 /* This BGP update is filtered. Log the reason then update BGP
3220 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3221 if (!peer
->rcvd_attr_printed
) {
3222 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3223 peer
->rcvd_attr_str
);
3224 peer
->rcvd_attr_printed
= 1;
3227 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3228 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3230 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3231 peer
->host
, pfx_buf
, reason
);
3235 /* If this is an EVPN route, un-import it as it is now filtered.
3237 if (safi
== SAFI_EVPN
)
3238 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3240 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3243 bgp_unlock_node(rn
);
3247 * Filtered update is treated as an implicit withdrawal (see
3249 * a few lines above)
3251 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3252 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3260 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3261 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3262 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3263 struct bgp_route_evpn
*evpn
)
3266 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3267 struct bgp_node
*rn
;
3268 struct bgp_info
*ri
;
3271 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3272 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3280 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3282 /* If peer is soft reconfiguration enabled. Record input packet for
3283 * further calculation.
3285 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3286 * routes that are filtered. This tanks out Quagga RS pretty badly due
3288 * the iteration over all RS clients.
3289 * Since we need to remove the entry from adj_in anyway, do that first
3291 * if there was no entry, we don't need to do anything more.
3293 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3294 && peer
!= bgp
->peer_self
)
3295 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3296 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3297 bgp_debug_rdpfxpath2str(
3298 afi
, safi
, prd
, p
, label
,
3299 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3302 "%s withdrawing route %s not in adj-in",
3303 peer
->host
, pfx_buf
);
3305 bgp_unlock_node(rn
);
3309 /* Lookup withdrawn route. */
3310 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3311 if (ri
->peer
== peer
&& ri
->type
== type
3312 && ri
->sub_type
== sub_type
3313 && ri
->addpath_rx_id
== addpath_id
)
3317 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3318 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3319 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3321 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3325 /* Withdraw specified route from routing table. */
3326 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3327 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3328 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3329 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3330 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3332 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3335 /* Unlock bgp_node_get() lock. */
3336 bgp_unlock_node(rn
);
3341 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3344 struct update_subgroup
*subgrp
;
3345 subgrp
= peer_subgroup(peer
, afi
, safi
);
3346 subgroup_default_originate(subgrp
, withdraw
);
3351 * bgp_stop_announce_route_timer
3353 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3355 if (!paf
->t_announce_route
)
3358 THREAD_TIMER_OFF(paf
->t_announce_route
);
3362 * bgp_announce_route_timer_expired
3364 * Callback that is invoked when the route announcement timer for a
3367 static int bgp_announce_route_timer_expired(struct thread
*t
)
3369 struct peer_af
*paf
;
3372 paf
= THREAD_ARG(t
);
3375 if (peer
->status
!= Established
)
3378 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3381 peer_af_announce_route(paf
, 1);
3386 * bgp_announce_route
3388 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3390 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3392 struct peer_af
*paf
;
3393 struct update_subgroup
*subgrp
;
3395 paf
= peer_af_find(peer
, afi
, safi
);
3398 subgrp
= PAF_SUBGRP(paf
);
3401 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3402 * or a refresh has already been triggered.
3404 if (!subgrp
|| paf
->t_announce_route
)
3408 * Start a timer to stagger/delay the announce. This serves
3409 * two purposes - announcement can potentially be combined for
3410 * multiple peers and the announcement doesn't happen in the
3413 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3414 (subgrp
->peer_count
== 1)
3415 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3416 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3417 &paf
->t_announce_route
);
3421 * Announce routes from all AF tables to a peer.
3423 * This should ONLY be called when there is a need to refresh the
3424 * routes to the peer based on a policy change for this peer alone
3425 * or a route refresh request received from the peer.
3426 * The operation will result in splitting the peer from its existing
3427 * subgroups and putting it in new subgroups.
3429 void bgp_announce_route_all(struct peer
*peer
)
3434 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3435 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3436 bgp_announce_route(peer
, afi
, safi
);
3439 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3440 struct bgp_table
*table
,
3441 struct prefix_rd
*prd
)
3444 struct bgp_node
*rn
;
3445 struct bgp_adj_in
*ain
;
3448 table
= peer
->bgp
->rib
[afi
][safi
];
3450 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3451 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3452 if (ain
->peer
!= peer
)
3455 struct bgp_info
*ri
= rn
->info
;
3456 mpls_label_t label
= (ri
&& ri
->extra
)
3458 : MPLS_INVALID_LABEL
;
3460 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3461 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3462 BGP_ROUTE_NORMAL
, prd
, &label
, 1,
3466 bgp_unlock_node(rn
);
3472 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3474 struct bgp_node
*rn
;
3475 struct bgp_table
*table
;
3477 if (peer
->status
!= Established
)
3480 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3481 && (safi
!= SAFI_EVPN
))
3482 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3484 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3485 rn
= bgp_route_next(rn
))
3486 if ((table
= rn
->info
) != NULL
) {
3487 struct prefix_rd prd
;
3488 prd
.family
= AF_UNSPEC
;
3490 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3492 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3498 struct bgp_clear_node_queue
{
3499 struct bgp_node
*rn
;
3502 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3504 struct bgp_clear_node_queue
*cnq
= data
;
3505 struct bgp_node
*rn
= cnq
->rn
;
3506 struct peer
*peer
= wq
->spec
.data
;
3507 struct bgp_info
*ri
;
3508 afi_t afi
= bgp_node_table(rn
)->afi
;
3509 safi_t safi
= bgp_node_table(rn
)->safi
;
3513 /* It is possible that we have multiple paths for a prefix from a peer
3514 * if that peer is using AddPath.
3516 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3517 if (ri
->peer
!= peer
)
3520 /* graceful restart STALE flag set. */
3521 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3522 && peer
->nsf
[afi
][safi
]
3523 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3524 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3525 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3527 /* If this is an EVPN route, process for
3529 if (safi
== SAFI_EVPN
)
3530 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
,
3532 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3538 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3540 struct bgp_clear_node_queue
*cnq
= data
;
3541 struct bgp_node
*rn
= cnq
->rn
;
3542 struct bgp_table
*table
= bgp_node_table(rn
);
3544 bgp_unlock_node(rn
);
3545 bgp_table_unlock(table
);
3546 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3549 static void bgp_clear_node_complete(struct work_queue
*wq
)
3551 struct peer
*peer
= wq
->spec
.data
;
3553 /* Tickle FSM to start moving again */
3554 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3556 peer_unlock(peer
); /* bgp_clear_route */
3559 static void bgp_clear_node_queue_init(struct peer
*peer
)
3561 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3563 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3564 #undef CLEAR_QUEUE_NAME_LEN
3566 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3568 zlog_err("%s: Failed to allocate work queue", __func__
);
3571 peer
->clear_node_queue
->spec
.hold
= 10;
3572 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3573 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3574 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3575 peer
->clear_node_queue
->spec
.max_retries
= 0;
3577 /* we only 'lock' this peer reference when the queue is actually active
3579 peer
->clear_node_queue
->spec
.data
= peer
;
3582 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3583 struct bgp_table
*table
)
3585 struct bgp_node
*rn
;
3586 int force
= bm
->process_main_queue
? 0 : 1;
3589 table
= peer
->bgp
->rib
[afi
][safi
];
3591 /* If still no table => afi/safi isn't configured at all or smth. */
3595 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3596 struct bgp_info
*ri
, *next
;
3597 struct bgp_adj_in
*ain
;
3598 struct bgp_adj_in
*ain_next
;
3600 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3601 * queued for every clearing peer, regardless of whether it is
3602 * relevant to the peer at hand.
3604 * Overview: There are 3 different indices which need to be
3605 * scrubbed, potentially, when a peer is removed:
3607 * 1 peer's routes visible via the RIB (ie accepted routes)
3608 * 2 peer's routes visible by the (optional) peer's adj-in index
3609 * 3 other routes visible by the peer's adj-out index
3611 * 3 there is no hurry in scrubbing, once the struct peer is
3612 * removed from bgp->peer, we could just GC such deleted peer's
3613 * adj-outs at our leisure.
3615 * 1 and 2 must be 'scrubbed' in some way, at least made
3616 * invisible via RIB index before peer session is allowed to be
3617 * brought back up. So one needs to know when such a 'search' is
3622 * - there'd be a single global queue or a single RIB walker
3623 * - rather than tracking which route_nodes still need to be
3624 * examined on a peer basis, we'd track which peers still
3627 * Given that our per-peer prefix-counts now should be reliable,
3628 * this may actually be achievable. It doesn't seem to be a huge
3629 * problem at this time,
3631 * It is possible that we have multiple paths for a prefix from
3633 * if that peer is using AddPath.
3637 ain_next
= ain
->next
;
3639 if (ain
->peer
== peer
) {
3640 bgp_adj_in_remove(rn
, ain
);
3641 bgp_unlock_node(rn
);
3647 for (ri
= rn
->info
; ri
; ri
= next
) {
3649 if (ri
->peer
!= peer
)
3653 bgp_info_reap(rn
, ri
);
3655 struct bgp_clear_node_queue
*cnq
;
3657 /* both unlocked in bgp_clear_node_queue_del */
3658 bgp_table_lock(bgp_node_table(rn
));
3661 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3662 sizeof(struct bgp_clear_node_queue
));
3664 work_queue_add(peer
->clear_node_queue
, cnq
);
3672 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3674 struct bgp_node
*rn
;
3675 struct bgp_table
*table
;
3677 if (peer
->clear_node_queue
== NULL
)
3678 bgp_clear_node_queue_init(peer
);
3680 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3681 * Idle until it receives a Clearing_Completed event. This protects
3682 * against peers which flap faster than we can we clear, which could
3685 * a) race with routes from the new session being installed before
3686 * clear_route_node visits the node (to delete the route of that
3688 * b) resource exhaustion, clear_route_node likely leads to an entry
3689 * on the process_main queue. Fast-flapping could cause that queue
3693 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3694 * the unlock will happen upon work-queue completion; other wise, the
3695 * unlock happens at the end of this function.
3697 if (!peer
->clear_node_queue
->thread
)
3700 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3701 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3703 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3704 rn
= bgp_route_next(rn
))
3705 if ((table
= rn
->info
) != NULL
)
3706 bgp_clear_route_table(peer
, afi
, safi
, table
);
3708 /* unlock if no nodes got added to the clear-node-queue. */
3709 if (!peer
->clear_node_queue
->thread
)
3713 void bgp_clear_route_all(struct peer
*peer
)
3718 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
3719 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
3720 bgp_clear_route(peer
, afi
, safi
);
3723 rfapiProcessPeerDown(peer
);
3727 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3729 struct bgp_table
*table
;
3730 struct bgp_node
*rn
;
3731 struct bgp_adj_in
*ain
;
3732 struct bgp_adj_in
*ain_next
;
3734 table
= peer
->bgp
->rib
[afi
][safi
];
3736 /* It is possible that we have multiple paths for a prefix from a peer
3737 * if that peer is using AddPath.
3739 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3743 ain_next
= ain
->next
;
3745 if (ain
->peer
== peer
) {
3746 bgp_adj_in_remove(rn
, ain
);
3747 bgp_unlock_node(rn
);
3755 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3757 struct bgp_node
*rn
;
3758 struct bgp_info
*ri
;
3759 struct bgp_table
*table
;
3761 if (safi
== SAFI_MPLS_VPN
) {
3762 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3763 rn
= bgp_route_next(rn
)) {
3764 struct bgp_node
*rm
;
3765 struct bgp_info
*ri
;
3767 /* look for neighbor in tables */
3768 if ((table
= rn
->info
) == NULL
)
3771 for (rm
= bgp_table_top(table
); rm
;
3772 rm
= bgp_route_next(rm
))
3773 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3774 if (ri
->peer
!= peer
)
3776 if (!CHECK_FLAG(ri
->flags
,
3780 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
3785 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3786 rn
= bgp_route_next(rn
))
3787 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3788 if (ri
->peer
!= peer
)
3790 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3792 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3798 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3800 struct bgp_node
*rn
;
3801 struct bgp_info
*ri
;
3802 struct bgp_info
*next
;
3804 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3805 for (ri
= rn
->info
; ri
; ri
= next
) {
3807 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3808 && ri
->type
== ZEBRA_ROUTE_BGP
3809 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3810 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3811 if (bgp_fibupd_safi(safi
))
3812 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3813 bgp_info_reap(rn
, ri
);
3818 /* Delete all kernel routes. */
3819 void bgp_cleanup_routes(struct bgp
*bgp
)
3822 struct bgp_node
*rn
;
3824 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3825 if (afi
== AFI_L2VPN
)
3827 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3829 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3831 if (afi
!= AFI_L2VPN
) {
3833 safi
= SAFI_MPLS_VPN
;
3834 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3835 rn
= bgp_route_next(rn
)) {
3838 (struct bgp_table
*)(rn
->info
),
3840 bgp_table_finish((struct bgp_table
**)&(
3843 bgp_unlock_node(rn
);
3847 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3848 rn
= bgp_route_next(rn
)) {
3851 (struct bgp_table
*)(rn
->info
),
3853 bgp_table_finish((struct bgp_table
**)&(
3856 bgp_unlock_node(rn
);
3861 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3862 rn
= bgp_route_next(rn
)) {
3864 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3866 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3868 bgp_unlock_node(rn
);
3873 void bgp_reset(void)
3876 bgp_zclient_reset();
3877 access_list_reset();
3878 prefix_list_reset();
3881 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3883 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3884 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3885 PEER_CAP_ADDPATH_AF_TX_RCV
));
3888 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3890 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3891 struct bgp_nlri
*packet
)
3900 int addpath_encoded
;
3901 u_int32_t addpath_id
;
3903 /* Check peer status. */
3904 if (peer
->status
!= Established
)
3908 lim
= pnt
+ packet
->length
;
3910 safi
= packet
->safi
;
3912 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3914 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3915 syntactic validity. If the field is syntactically incorrect,
3916 then the Error Subcode is set to Invalid Network Field. */
3917 for (; pnt
< lim
; pnt
+= psize
) {
3918 /* Clear prefix structure. */
3919 memset(&p
, 0, sizeof(struct prefix
));
3921 if (addpath_encoded
) {
3923 /* When packet overflow occurs return immediately. */
3924 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3927 addpath_id
= ntohl(*((uint32_t *)pnt
));
3928 pnt
+= BGP_ADDPATH_ID_LEN
;
3931 /* Fetch prefix length. */
3932 p
.prefixlen
= *pnt
++;
3933 /* afi/safi validity already verified by caller,
3934 * bgp_update_receive */
3935 p
.family
= afi2family(afi
);
3937 /* Prefix length check. */
3938 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3940 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3941 peer
->host
, p
.prefixlen
, packet
->afi
);
3945 /* Packet size overflow check. */
3946 psize
= PSIZE(p
.prefixlen
);
3948 /* When packet overflow occur return immediately. */
3949 if (pnt
+ psize
> lim
) {
3951 "%s [Error] Update packet error (prefix length %d overflows packet)",
3952 peer
->host
, p
.prefixlen
);
3956 /* Defensive coding, double-check the psize fits in a struct
3958 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3960 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3961 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3965 /* Fetch prefix from NLRI packet. */
3966 memcpy(&p
.u
.prefix
, pnt
, psize
);
3968 /* Check address. */
3969 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3970 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3971 /* From RFC4271 Section 6.3:
3973 * If a prefix in the NLRI field is semantically
3975 * (e.g., an unexpected multicast IP address),
3977 * be logged locally, and the prefix SHOULD be
3981 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3982 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3987 /* Check address. */
3988 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3989 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3993 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
3995 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4000 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4004 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4006 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4013 /* Normal process. */
4015 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4016 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4017 NULL
, NULL
, 0, NULL
);
4019 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4020 safi
, ZEBRA_ROUTE_BGP
,
4021 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
4023 /* Address family configuration mismatch or maximum-prefix count
4029 /* Packet length consistency check. */
4032 "%s [Error] Update packet error (prefix length mismatch with total length)",
4040 static struct bgp_static
*bgp_static_new(void)
4042 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4045 static void bgp_static_free(struct bgp_static
*bgp_static
)
4047 if (bgp_static
->rmap
.name
)
4048 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4049 if (bgp_static
->eth_s_id
)
4050 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4051 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4054 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4055 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4057 struct bgp_node
*rn
;
4058 struct bgp_info
*ri
;
4059 struct bgp_info
*new;
4060 struct bgp_info info
;
4062 struct attr
*attr_new
;
4065 int vnc_implicit_withdraw
= 0;
4072 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4074 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4076 attr
.nexthop
= bgp_static
->igpnexthop
;
4077 attr
.med
= bgp_static
->igpmetric
;
4078 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4080 if (bgp_static
->atomic
)
4081 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4083 /* Store label index, if required. */
4084 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4085 attr
.label_index
= bgp_static
->label_index
;
4086 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4089 /* Apply route-map. */
4090 if (bgp_static
->rmap
.name
) {
4091 struct attr attr_tmp
= attr
;
4092 info
.peer
= bgp
->peer_self
;
4093 info
.attr
= &attr_tmp
;
4095 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4097 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4099 bgp
->peer_self
->rmap_type
= 0;
4101 if (ret
== RMAP_DENYMATCH
) {
4102 /* Free uninterned attribute. */
4103 bgp_attr_flush(&attr_tmp
);
4105 /* Unintern original. */
4106 aspath_unintern(&attr
.aspath
);
4107 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4111 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4112 bgp_attr_add_gshut_community(&attr_tmp
);
4114 attr_new
= bgp_attr_intern(&attr_tmp
);
4117 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4118 bgp_attr_add_gshut_community(&attr
);
4120 attr_new
= bgp_attr_intern(&attr
);
4123 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4124 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4125 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4129 if (attrhash_cmp(ri
->attr
, attr_new
)
4130 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4131 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4132 bgp_unlock_node(rn
);
4133 bgp_attr_unintern(&attr_new
);
4134 aspath_unintern(&attr
.aspath
);
4137 /* The attribute is changed. */
4138 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4140 /* Rewrite BGP route information. */
4141 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4142 bgp_info_restore(rn
, ri
);
4144 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4146 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4147 && (safi
== SAFI_UNICAST
)) {
4148 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4150 * Implicit withdraw case.
4151 * We have to do this before ri is
4154 ++vnc_implicit_withdraw
;
4155 vnc_import_bgp_del_route(bgp
, p
, ri
);
4156 vnc_import_bgp_exterior_del_route(
4161 bgp_attr_unintern(&ri
->attr
);
4162 ri
->attr
= attr_new
;
4163 ri
->uptime
= bgp_clock();
4165 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4166 && (safi
== SAFI_UNICAST
)) {
4167 if (vnc_implicit_withdraw
) {
4168 vnc_import_bgp_add_route(bgp
, p
, ri
);
4169 vnc_import_bgp_exterior_add_route(
4175 /* Nexthop reachability check. */
4176 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4177 && (safi
== SAFI_UNICAST
4178 || safi
== SAFI_LABELED_UNICAST
)) {
4179 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4181 bgp_info_set_flag(rn
, ri
,
4184 if (BGP_DEBUG(nht
, NHT
)) {
4185 char buf1
[INET6_ADDRSTRLEN
];
4186 inet_ntop(p
->family
,
4190 "%s(%s): Route not in table, not advertising",
4191 __FUNCTION__
, buf1
);
4193 bgp_info_unset_flag(rn
, ri
,
4197 /* Delete the NHT structure if any, if we're
4199 * enabling/disabling import check. We
4200 * deregister the route
4201 * from NHT to avoid overloading NHT and the
4202 * process interaction
4204 bgp_unlink_nexthop(ri
);
4205 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4207 /* Process change. */
4208 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4209 bgp_process(bgp
, rn
, afi
, safi
);
4210 bgp_unlock_node(rn
);
4211 aspath_unintern(&attr
.aspath
);
4216 /* Make new BGP info. */
4217 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4219 /* Nexthop reachability check. */
4220 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4221 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4222 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4223 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4225 if (BGP_DEBUG(nht
, NHT
)) {
4226 char buf1
[INET6_ADDRSTRLEN
];
4227 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4230 "%s(%s): Route not in table, not advertising",
4231 __FUNCTION__
, buf1
);
4233 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4236 /* Delete the NHT structure if any, if we're toggling between
4237 * enabling/disabling import check. We deregister the route
4238 * from NHT to avoid overloading NHT and the process interaction
4240 bgp_unlink_nexthop(new);
4242 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4245 /* Aggregate address increment. */
4246 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4248 /* Register new BGP information. */
4249 bgp_info_add(rn
, new);
4251 /* route_node_get lock */
4252 bgp_unlock_node(rn
);
4254 /* Process change. */
4255 bgp_process(bgp
, rn
, afi
, safi
);
4257 /* Unintern original. */
4258 aspath_unintern(&attr
.aspath
);
4261 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4264 struct bgp_node
*rn
;
4265 struct bgp_info
*ri
;
4267 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4269 /* Check selected route and self inserted route. */
4270 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4271 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4272 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4275 /* Withdraw static BGP route from routing table. */
4277 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4278 bgp_unlink_nexthop(ri
);
4279 bgp_info_delete(rn
, ri
);
4280 bgp_process(bgp
, rn
, afi
, safi
);
4283 /* Unlock bgp_node_lookup. */
4284 bgp_unlock_node(rn
);
4288 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4290 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4291 afi_t afi
, safi_t safi
,
4292 struct prefix_rd
*prd
)
4294 struct bgp_node
*rn
;
4295 struct bgp_info
*ri
;
4297 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4299 /* Check selected route and self inserted route. */
4300 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4301 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4302 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4305 /* Withdraw static BGP route from routing table. */
4308 rfapiProcessWithdraw(
4309 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4310 1); /* Kill, since it is an administrative change */
4312 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4313 bgp_info_delete(rn
, ri
);
4314 bgp_process(bgp
, rn
, afi
, safi
);
4317 /* Unlock bgp_node_lookup. */
4318 bgp_unlock_node(rn
);
4321 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4322 struct bgp_static
*bgp_static
, afi_t afi
,
4325 struct bgp_node
*rn
;
4326 struct bgp_info
*new;
4327 struct attr
*attr_new
;
4328 struct attr attr
= {0};
4329 struct bgp_info
*ri
;
4331 mpls_label_t label
= 0;
4337 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4340 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4342 attr
.nexthop
= bgp_static
->igpnexthop
;
4343 attr
.med
= bgp_static
->igpmetric
;
4344 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4346 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4347 || (safi
== SAFI_ENCAP
)) {
4348 if (afi
== AFI_IP
) {
4349 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4350 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4353 if (afi
== AFI_L2VPN
) {
4354 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4356 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4357 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4358 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4359 sizeof(struct in6_addr
));
4360 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4361 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4362 struct bgp_encap_type_vxlan bet
;
4363 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4364 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4365 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4367 if (bgp_static
->router_mac
) {
4368 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4371 /* Apply route-map. */
4372 if (bgp_static
->rmap
.name
) {
4373 struct attr attr_tmp
= attr
;
4374 struct bgp_info info
;
4377 info
.peer
= bgp
->peer_self
;
4378 info
.attr
= &attr_tmp
;
4380 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4382 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4384 bgp
->peer_self
->rmap_type
= 0;
4386 if (ret
== RMAP_DENYMATCH
) {
4387 /* Free uninterned attribute. */
4388 bgp_attr_flush(&attr_tmp
);
4390 /* Unintern original. */
4391 aspath_unintern(&attr
.aspath
);
4392 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4397 attr_new
= bgp_attr_intern(&attr_tmp
);
4399 attr_new
= bgp_attr_intern(&attr
);
4402 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4403 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4404 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4409 memset(&add
, 0, sizeof(union gw_addr
));
4410 if (attrhash_cmp(ri
->attr
, attr_new
)
4411 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4412 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4413 bgp_unlock_node(rn
);
4414 bgp_attr_unintern(&attr_new
);
4415 aspath_unintern(&attr
.aspath
);
4418 /* The attribute is changed. */
4419 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4421 /* Rewrite BGP route information. */
4422 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4423 bgp_info_restore(rn
, ri
);
4425 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4426 bgp_attr_unintern(&ri
->attr
);
4427 ri
->attr
= attr_new
;
4428 ri
->uptime
= bgp_clock();
4431 label
= decode_label(&ri
->extra
->label
);
4434 /* Process change. */
4435 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4436 bgp_process(bgp
, rn
, afi
, safi
);
4438 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4439 ri
->attr
, afi
, safi
, ri
->type
,
4440 ri
->sub_type
, &label
);
4442 bgp_unlock_node(rn
);
4443 aspath_unintern(&attr
.aspath
);
4449 /* Make new BGP info. */
4450 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4452 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4453 new->extra
= bgp_info_extra_new();
4454 new->extra
->label
= bgp_static
->label
;
4456 label
= decode_label(&bgp_static
->label
);
4459 /* Aggregate address increment. */
4460 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4462 /* Register new BGP information. */
4463 bgp_info_add(rn
, new);
4464 /* route_node_get lock */
4465 bgp_unlock_node(rn
);
4467 /* Process change. */
4468 bgp_process(bgp
, rn
, afi
, safi
);
4471 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4472 safi
, new->type
, new->sub_type
, &label
);
4475 /* Unintern original. */
4476 aspath_unintern(&attr
.aspath
);
4479 /* Configure static BGP network. When user don't run zebra, static
4480 route should be installed as valid. */
4481 static int bgp_static_set(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4482 safi_t safi
, const char *rmap
, int backdoor
,
4483 u_int32_t label_index
)
4485 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4488 struct bgp_static
*bgp_static
;
4489 struct bgp_node
*rn
;
4490 u_char need_update
= 0;
4492 /* Convert IP prefix string to struct prefix. */
4493 ret
= str2prefix(ip_str
, &p
);
4495 vty_out(vty
, "%% Malformed prefix\n");
4496 return CMD_WARNING_CONFIG_FAILED
;
4498 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4499 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4500 return CMD_WARNING_CONFIG_FAILED
;
4505 /* Set BGP static route configuration. */
4506 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4509 /* Configuration change. */
4510 bgp_static
= rn
->info
;
4512 /* Label index cannot be changed. */
4513 if (bgp_static
->label_index
!= label_index
) {
4514 vty_out(vty
, "%% Label index cannot be changed\n");
4515 return CMD_WARNING_CONFIG_FAILED
;
4518 /* Check previous routes are installed into BGP. */
4519 if (bgp_static
->valid
&& bgp_static
->backdoor
!= backdoor
)
4522 bgp_static
->backdoor
= backdoor
;
4525 if (bgp_static
->rmap
.name
)
4526 XFREE(MTYPE_ROUTE_MAP_NAME
,
4527 bgp_static
->rmap
.name
);
4528 bgp_static
->rmap
.name
=
4529 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4530 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4532 if (bgp_static
->rmap
.name
)
4533 XFREE(MTYPE_ROUTE_MAP_NAME
,
4534 bgp_static
->rmap
.name
);
4535 bgp_static
->rmap
.name
= NULL
;
4536 bgp_static
->rmap
.map
= NULL
;
4537 bgp_static
->valid
= 0;
4539 bgp_unlock_node(rn
);
4541 /* New configuration. */
4542 bgp_static
= bgp_static_new();
4543 bgp_static
->backdoor
= backdoor
;
4544 bgp_static
->valid
= 0;
4545 bgp_static
->igpmetric
= 0;
4546 bgp_static
->igpnexthop
.s_addr
= 0;
4547 bgp_static
->label_index
= label_index
;
4550 if (bgp_static
->rmap
.name
)
4551 XFREE(MTYPE_ROUTE_MAP_NAME
,
4552 bgp_static
->rmap
.name
);
4553 bgp_static
->rmap
.name
=
4554 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4555 bgp_static
->rmap
.map
= route_map_lookup_by_name(rmap
);
4557 rn
->info
= bgp_static
;
4560 bgp_static
->valid
= 1;
4562 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4564 if (!bgp_static
->backdoor
)
4565 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4570 /* Configure static BGP network. */
4571 static int bgp_static_unset(struct vty
*vty
, const char *ip_str
, afi_t afi
,
4574 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4577 struct bgp_static
*bgp_static
;
4578 struct bgp_node
*rn
;
4580 /* Convert IP prefix string to struct prefix. */
4581 ret
= str2prefix(ip_str
, &p
);
4583 vty_out(vty
, "%% Malformed prefix\n");
4584 return CMD_WARNING_CONFIG_FAILED
;
4586 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4587 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4588 return CMD_WARNING_CONFIG_FAILED
;
4593 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4596 "%% Can't find specified static route configuration.\n");
4597 return CMD_WARNING_CONFIG_FAILED
;
4600 bgp_static
= rn
->info
;
4602 /* Update BGP RIB. */
4603 if (!bgp_static
->backdoor
)
4604 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4606 /* Clear configuration. */
4607 bgp_static_free(bgp_static
);
4609 bgp_unlock_node(rn
);
4610 bgp_unlock_node(rn
);
4615 void bgp_static_add(struct bgp
*bgp
)
4619 struct bgp_node
*rn
;
4620 struct bgp_node
*rm
;
4621 struct bgp_table
*table
;
4622 struct bgp_static
*bgp_static
;
4624 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4625 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4626 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4627 rn
= bgp_route_next(rn
)) {
4628 if (rn
->info
== NULL
)
4631 if ((safi
== SAFI_MPLS_VPN
)
4632 || (safi
== SAFI_ENCAP
)
4633 || (safi
== SAFI_EVPN
)) {
4636 for (rm
= bgp_table_top(table
); rm
;
4637 rm
= bgp_route_next(rm
)) {
4638 bgp_static
= rm
->info
;
4639 bgp_static_update_safi(
4640 bgp
, &rm
->p
, bgp_static
,
4644 bgp_static_update(bgp
, &rn
->p
, rn
->info
,
4650 /* Called from bgp_delete(). Delete all static routes from the BGP
4652 void bgp_static_delete(struct bgp
*bgp
)
4656 struct bgp_node
*rn
;
4657 struct bgp_node
*rm
;
4658 struct bgp_table
*table
;
4659 struct bgp_static
*bgp_static
;
4661 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4662 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4663 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4664 rn
= bgp_route_next(rn
)) {
4665 if (rn
->info
== NULL
)
4668 if ((safi
== SAFI_MPLS_VPN
)
4669 || (safi
== SAFI_ENCAP
)
4670 || (safi
== SAFI_EVPN
)) {
4673 for (rm
= bgp_table_top(table
); rm
;
4674 rm
= bgp_route_next(rm
)) {
4675 bgp_static
= rm
->info
;
4676 bgp_static_withdraw_safi(
4677 bgp
, &rm
->p
, AFI_IP
,
4679 (struct prefix_rd
*)&rn
4681 bgp_static_free(bgp_static
);
4683 bgp_unlock_node(rn
);
4686 bgp_static
= rn
->info
;
4687 bgp_static_withdraw(bgp
, &rn
->p
, afi
,
4689 bgp_static_free(bgp_static
);
4691 bgp_unlock_node(rn
);
4696 void bgp_static_redo_import_check(struct bgp
*bgp
)
4700 struct bgp_node
*rn
;
4701 struct bgp_node
*rm
;
4702 struct bgp_table
*table
;
4703 struct bgp_static
*bgp_static
;
4705 /* Use this flag to force reprocessing of the route */
4706 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4707 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4708 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4709 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4710 rn
= bgp_route_next(rn
)) {
4711 if (rn
->info
== NULL
)
4714 if ((safi
== SAFI_MPLS_VPN
)
4715 || (safi
== SAFI_ENCAP
)
4716 || (safi
== SAFI_EVPN
)) {
4719 for (rm
= bgp_table_top(table
); rm
;
4720 rm
= bgp_route_next(rm
)) {
4721 bgp_static
= rm
->info
;
4722 bgp_static_update_safi(
4723 bgp
, &rm
->p
, bgp_static
,
4727 bgp_static
= rn
->info
;
4728 bgp_static_update(bgp
, &rn
->p
,
4733 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4736 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4739 struct bgp_table
*table
;
4740 struct bgp_node
*rn
;
4741 struct bgp_info
*ri
;
4743 table
= bgp
->rib
[afi
][safi
];
4744 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4745 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4746 if (ri
->peer
== bgp
->peer_self
4747 && ((ri
->type
== ZEBRA_ROUTE_BGP
4748 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4749 || (ri
->type
!= ZEBRA_ROUTE_BGP
4751 == BGP_ROUTE_REDISTRIBUTE
))) {
4752 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4754 bgp_unlink_nexthop(ri
);
4755 bgp_info_delete(rn
, ri
);
4756 bgp_process(bgp
, rn
, afi
, safi
);
4763 * Purge all networks and redistributed routes from routing table.
4764 * Invoked upon the instance going down.
4766 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4771 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
4772 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
4773 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4778 * Currently this is used to set static routes for VPN and ENCAP.
4779 * I think it can probably be factored with bgp_static_set.
4781 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4782 const char *ip_str
, const char *rd_str
,
4783 const char *label_str
, const char *rmap_str
,
4784 int evpn_type
, const char *esi
, const char *gwip
,
4785 const char *ethtag
, const char *routermac
)
4787 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4790 struct prefix_rd prd
;
4791 struct bgp_node
*prn
;
4792 struct bgp_node
*rn
;
4793 struct bgp_table
*table
;
4794 struct bgp_static
*bgp_static
;
4795 mpls_label_t label
= MPLS_INVALID_LABEL
;
4796 struct prefix gw_ip
;
4798 /* validate ip prefix */
4799 ret
= str2prefix(ip_str
, &p
);
4801 vty_out(vty
, "%% Malformed prefix\n");
4802 return CMD_WARNING_CONFIG_FAILED
;
4805 if ((afi
== AFI_L2VPN
)
4806 && (bgp_build_evpn_prefix(evpn_type
,
4807 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4808 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4809 return CMD_WARNING_CONFIG_FAILED
;
4812 ret
= str2prefix_rd(rd_str
, &prd
);
4814 vty_out(vty
, "%% Malformed rd\n");
4815 return CMD_WARNING_CONFIG_FAILED
;
4819 unsigned long label_val
;
4820 label_val
= strtoul(label_str
, NULL
, 10);
4821 encode_label(label_val
, &label
);
4824 if (safi
== SAFI_EVPN
) {
4825 if (esi
&& str2esi(esi
, NULL
) == 0) {
4826 vty_out(vty
, "%% Malformed ESI\n");
4827 return CMD_WARNING_CONFIG_FAILED
;
4829 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4830 vty_out(vty
, "%% Malformed Router MAC\n");
4831 return CMD_WARNING_CONFIG_FAILED
;
4834 memset(&gw_ip
, 0, sizeof(struct prefix
));
4835 ret
= str2prefix(gwip
, &gw_ip
);
4837 vty_out(vty
, "%% Malformed GatewayIp\n");
4838 return CMD_WARNING_CONFIG_FAILED
;
4840 if ((gw_ip
.family
== AF_INET
4841 && IS_EVPN_PREFIX_IPADDR_V6(
4842 (struct prefix_evpn
*)&p
))
4843 || (gw_ip
.family
== AF_INET6
4844 && IS_EVPN_PREFIX_IPADDR_V4(
4845 (struct prefix_evpn
*)&p
))) {
4847 "%% GatewayIp family differs with IP prefix\n");
4848 return CMD_WARNING_CONFIG_FAILED
;
4852 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4853 if (prn
->info
== NULL
)
4854 prn
->info
= bgp_table_init(afi
, safi
);
4856 bgp_unlock_node(prn
);
4859 rn
= bgp_node_get(table
, &p
);
4862 vty_out(vty
, "%% Same network configuration exists\n");
4863 bgp_unlock_node(rn
);
4865 /* New configuration. */
4866 bgp_static
= bgp_static_new();
4867 bgp_static
->backdoor
= 0;
4868 bgp_static
->valid
= 0;
4869 bgp_static
->igpmetric
= 0;
4870 bgp_static
->igpnexthop
.s_addr
= 0;
4871 bgp_static
->label
= label
;
4872 bgp_static
->prd
= prd
;
4875 if (bgp_static
->rmap
.name
)
4876 XFREE(MTYPE_ROUTE_MAP_NAME
,
4877 bgp_static
->rmap
.name
);
4878 bgp_static
->rmap
.name
=
4879 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4880 bgp_static
->rmap
.map
=
4881 route_map_lookup_by_name(rmap_str
);
4884 if (safi
== SAFI_EVPN
) {
4886 bgp_static
->eth_s_id
=
4888 sizeof(struct eth_segment_id
));
4889 str2esi(esi
, bgp_static
->eth_s_id
);
4892 bgp_static
->router_mac
=
4893 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
4894 prefix_str2mac(routermac
,
4895 bgp_static
->router_mac
);
4898 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4900 rn
->info
= bgp_static
;
4902 bgp_static
->valid
= 1;
4903 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4909 /* Configure static BGP network. */
4910 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4911 const char *ip_str
, const char *rd_str
,
4912 const char *label_str
, int evpn_type
, const char *esi
,
4913 const char *gwip
, const char *ethtag
)
4915 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4918 struct prefix_rd prd
;
4919 struct bgp_node
*prn
;
4920 struct bgp_node
*rn
;
4921 struct bgp_table
*table
;
4922 struct bgp_static
*bgp_static
;
4923 mpls_label_t label
= MPLS_INVALID_LABEL
;
4925 /* Convert IP prefix string to struct prefix. */
4926 ret
= str2prefix(ip_str
, &p
);
4928 vty_out(vty
, "%% Malformed prefix\n");
4929 return CMD_WARNING_CONFIG_FAILED
;
4932 if ((afi
== AFI_L2VPN
)
4933 && (bgp_build_evpn_prefix(evpn_type
,
4934 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4935 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4936 return CMD_WARNING_CONFIG_FAILED
;
4938 ret
= str2prefix_rd(rd_str
, &prd
);
4940 vty_out(vty
, "%% Malformed rd\n");
4941 return CMD_WARNING_CONFIG_FAILED
;
4945 unsigned long label_val
;
4946 label_val
= strtoul(label_str
, NULL
, 10);
4947 encode_label(label_val
, &label
);
4950 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4951 if (prn
->info
== NULL
)
4952 prn
->info
= bgp_table_init(afi
, safi
);
4954 bgp_unlock_node(prn
);
4957 rn
= bgp_node_lookup(table
, &p
);
4960 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4962 bgp_static
= rn
->info
;
4963 bgp_static_free(bgp_static
);
4965 bgp_unlock_node(rn
);
4966 bgp_unlock_node(rn
);
4968 vty_out(vty
, "%% Can't find the route\n");
4973 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4974 const char *rmap_name
)
4976 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4977 struct bgp_rmap
*rmap
;
4979 rmap
= &bgp
->table_map
[afi
][safi
];
4982 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4983 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4984 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4987 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4992 if (bgp_fibupd_safi(safi
))
4993 bgp_zebra_announce_table(bgp
, afi
, safi
);
4998 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
4999 const char *rmap_name
)
5001 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5002 struct bgp_rmap
*rmap
;
5004 rmap
= &bgp
->table_map
[afi
][safi
];
5006 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5010 if (bgp_fibupd_safi(safi
))
5011 bgp_zebra_announce_table(bgp
, afi
, safi
);
5016 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5019 if (bgp
->table_map
[afi
][safi
].name
) {
5020 vty_out(vty
, " table-map %s\n",
5021 bgp
->table_map
[afi
][safi
].name
);
5025 DEFUN (bgp_table_map
,
5028 "BGP table to RIB route download filter\n"
5029 "Name of the route map\n")
5032 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5033 argv
[idx_word
]->arg
);
5035 DEFUN (no_bgp_table_map
,
5036 no_bgp_table_map_cmd
,
5037 "no table-map WORD",
5039 "BGP table to RIB route download filter\n"
5040 "Name of the route map\n")
5043 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5044 argv
[idx_word
]->arg
);
5049 "network A.B.C.D/M",
5050 "Specify a network to announce via BGP\n"
5053 int idx_ipv4_prefixlen
= 1;
5054 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5055 bgp_node_safi(vty
), NULL
, 0,
5056 BGP_INVALID_LABEL_INDEX
);
5059 DEFUN (bgp_network_route_map
,
5060 bgp_network_route_map_cmd
,
5061 "network A.B.C.D/M route-map WORD",
5062 "Specify a network to announce via BGP\n"
5064 "Route-map to modify the attributes\n"
5065 "Name of the route map\n")
5067 int idx_ipv4_prefixlen
= 1;
5069 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5070 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5071 BGP_INVALID_LABEL_INDEX
);
5074 DEFUN (bgp_network_backdoor
,
5075 bgp_network_backdoor_cmd
,
5076 "network A.B.C.D/M backdoor",
5077 "Specify a network to announce via BGP\n"
5079 "Specify a BGP backdoor route\n")
5081 int idx_ipv4_prefixlen
= 1;
5082 return bgp_static_set(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5083 SAFI_UNICAST
, NULL
, 1, BGP_INVALID_LABEL_INDEX
);
5086 DEFUN (bgp_network_mask
,
5087 bgp_network_mask_cmd
,
5088 "network A.B.C.D mask A.B.C.D",
5089 "Specify a network to announce via BGP\n"
5097 char prefix_str
[BUFSIZ
];
5099 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5102 vty_out(vty
, "%% Inconsistent address and mask\n");
5103 return CMD_WARNING_CONFIG_FAILED
;
5106 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5107 0, BGP_INVALID_LABEL_INDEX
);
5110 DEFUN (bgp_network_mask_route_map
,
5111 bgp_network_mask_route_map_cmd
,
5112 "network A.B.C.D mask A.B.C.D route-map WORD",
5113 "Specify a network to announce via BGP\n"
5117 "Route-map to modify the attributes\n"
5118 "Name of the route map\n")
5124 char prefix_str
[BUFSIZ
];
5126 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5129 vty_out(vty
, "%% Inconsistent address and mask\n");
5130 return CMD_WARNING_CONFIG_FAILED
;
5133 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5134 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5137 DEFUN (bgp_network_mask_backdoor
,
5138 bgp_network_mask_backdoor_cmd
,
5139 "network A.B.C.D mask A.B.C.D backdoor",
5140 "Specify a network to announce via BGP\n"
5144 "Specify a BGP backdoor route\n")
5149 char prefix_str
[BUFSIZ
];
5151 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5154 vty_out(vty
, "%% Inconsistent address and mask\n");
5155 return CMD_WARNING_CONFIG_FAILED
;
5158 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5159 BGP_INVALID_LABEL_INDEX
);
5162 DEFUN (bgp_network_mask_natural
,
5163 bgp_network_mask_natural_cmd
,
5165 "Specify a network to announce via BGP\n"
5170 char prefix_str
[BUFSIZ
];
5172 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5174 vty_out(vty
, "%% Inconsistent address and mask\n");
5175 return CMD_WARNING_CONFIG_FAILED
;
5178 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
), NULL
,
5179 0, BGP_INVALID_LABEL_INDEX
);
5182 DEFUN (bgp_network_mask_natural_route_map
,
5183 bgp_network_mask_natural_route_map_cmd
,
5184 "network A.B.C.D route-map WORD",
5185 "Specify a network to announce via BGP\n"
5187 "Route-map to modify the attributes\n"
5188 "Name of the route map\n")
5193 char prefix_str
[BUFSIZ
];
5195 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5197 vty_out(vty
, "%% Inconsistent address and mask\n");
5198 return CMD_WARNING_CONFIG_FAILED
;
5201 return bgp_static_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5202 argv
[idx_word
]->arg
, 0, BGP_INVALID_LABEL_INDEX
);
5205 DEFUN (bgp_network_mask_natural_backdoor
,
5206 bgp_network_mask_natural_backdoor_cmd
,
5207 "network A.B.C.D backdoor",
5208 "Specify a network to announce via BGP\n"
5210 "Specify a BGP backdoor route\n")
5214 char prefix_str
[BUFSIZ
];
5216 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5218 vty_out(vty
, "%% Inconsistent address and mask\n");
5219 return CMD_WARNING_CONFIG_FAILED
;
5222 return bgp_static_set(vty
, prefix_str
, AFI_IP
, SAFI_UNICAST
, NULL
, 1,
5223 BGP_INVALID_LABEL_INDEX
);
5226 DEFUN (bgp_network_label_index
,
5227 bgp_network_label_index_cmd
,
5228 "network A.B.C.D/M label-index (0-1048560)",
5229 "Specify a network to announce via BGP\n"
5230 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5231 "Label index to associate with the prefix\n"
5232 "Label index value\n")
5234 u_int32_t label_index
;
5236 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5237 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5238 NULL
, 0, label_index
);
5241 DEFUN (bgp_network_label_index_route_map
,
5242 bgp_network_label_index_route_map_cmd
,
5243 "network A.B.C.D/M label-index (0-1048560) route-map WORD",
5244 "Specify a network to announce via BGP\n"
5246 "Label index to associate with the prefix\n"
5247 "Label index value\n"
5248 "Route-map to modify the attributes\n"
5249 "Name of the route map\n")
5251 u_int32_t label_index
;
5253 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5254 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP
, bgp_node_safi(vty
),
5255 argv
[5]->arg
, 0, label_index
);
5258 DEFUN (no_bgp_network
,
5260 "no network A.B.C.D/M [<backdoor|route-map WORD>]",
5262 "Specify a network to announce via BGP\n"
5264 "Specify a BGP backdoor route\n"
5265 "Route-map to modify the attributes\n"
5266 "Name of the route map\n")
5268 int idx_ipv4_prefixlen
= 2;
5269 return bgp_static_unset(vty
, argv
[idx_ipv4_prefixlen
]->arg
, AFI_IP
,
5270 bgp_node_safi(vty
));
5273 DEFUN (no_bgp_network_mask
,
5274 no_bgp_network_mask_cmd
,
5275 "no network A.B.C.D mask A.B.C.D [<backdoor|route-map WORD>]",
5277 "Specify a network to announce via BGP\n"
5281 "Specify a BGP backdoor route\n"
5282 "Route-map to modify the attributes\n"
5283 "Name of the route map\n")
5288 char prefix_str
[BUFSIZ
];
5290 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
5293 vty_out(vty
, "%% Inconsistent address and mask\n");
5294 return CMD_WARNING_CONFIG_FAILED
;
5297 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5300 DEFUN (no_bgp_network_mask_natural
,
5301 no_bgp_network_mask_natural_cmd
,
5302 "no network A.B.C.D [<backdoor|route-map WORD>]",
5304 "Specify a network to announce via BGP\n"
5306 "Specify a BGP backdoor route\n"
5307 "Route-map to modify the attributes\n"
5308 "Name of the route map\n")
5312 char prefix_str
[BUFSIZ
];
5314 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, NULL
, prefix_str
);
5316 vty_out(vty
, "%% Inconsistent address and mask\n");
5317 return CMD_WARNING_CONFIG_FAILED
;
5320 return bgp_static_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5323 ALIAS(no_bgp_network
, no_bgp_network_label_index_cmd
,
5324 "no network A.B.C.D/M label-index (0-1048560)", NO_STR
5325 "Specify a network to announce via BGP\n"
5326 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
5327 "Label index to associate with the prefix\n"
5328 "Label index value\n")
5330 ALIAS(no_bgp_network
, no_bgp_network_label_index_route_map_cmd
,
5331 "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR
5332 "Specify a network to announce via BGP\n"
5334 "Label index to associate with the prefix\n"
5335 "Label index value\n"
5336 "Route-map to modify the attributes\n"
5337 "Name of the route map\n")
5339 DEFUN (ipv6_bgp_network
,
5340 ipv6_bgp_network_cmd
,
5341 "network X:X::X:X/M",
5342 "Specify a network to announce via BGP\n"
5345 int idx_ipv6_prefixlen
= 1;
5346 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5347 bgp_node_safi(vty
), NULL
, 0,
5348 BGP_INVALID_LABEL_INDEX
);
5351 DEFUN (ipv6_bgp_network_route_map
,
5352 ipv6_bgp_network_route_map_cmd
,
5353 "network X:X::X:X/M route-map WORD",
5354 "Specify a network to announce via BGP\n"
5356 "Route-map to modify the attributes\n"
5357 "Name of the route map\n")
5359 int idx_ipv6_prefixlen
= 1;
5361 return bgp_static_set(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5362 bgp_node_safi(vty
), argv
[idx_word
]->arg
, 0,
5363 BGP_INVALID_LABEL_INDEX
);
5366 DEFUN (ipv6_bgp_network_label_index
,
5367 ipv6_bgp_network_label_index_cmd
,
5368 "network X:X::X:X/M label-index (0-1048560)",
5369 "Specify a network to announce via BGP\n"
5370 "IPv6 prefix <network>/<length>\n"
5371 "Label index to associate with the prefix\n"
5372 "Label index value\n")
5374 u_int32_t label_index
;
5376 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5377 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5378 NULL
, 0, label_index
);
5381 DEFUN (ipv6_bgp_network_label_index_route_map
,
5382 ipv6_bgp_network_label_index_route_map_cmd
,
5383 "network X:X::X:X/M label-index (0-1048560) route-map WORD",
5384 "Specify a network to announce via BGP\n"
5386 "Label index to associate with the prefix\n"
5387 "Label index value\n"
5388 "Route-map to modify the attributes\n"
5389 "Name of the route map\n")
5391 u_int32_t label_index
;
5393 label_index
= strtoul(argv
[3]->arg
, NULL
, 10);
5394 return bgp_static_set(vty
, argv
[1]->arg
, AFI_IP6
, bgp_node_safi(vty
),
5395 argv
[5]->arg
, 0, label_index
);
5398 DEFUN (no_ipv6_bgp_network
,
5399 no_ipv6_bgp_network_cmd
,
5400 "no network X:X::X:X/M [route-map WORD]",
5402 "Specify a network to announce via BGP\n"
5404 "Route-map to modify the attributes\n"
5405 "Name of the route map\n")
5407 int idx_ipv6_prefixlen
= 2;
5408 return bgp_static_unset(vty
, argv
[idx_ipv6_prefixlen
]->arg
, AFI_IP6
,
5409 bgp_node_safi(vty
));
5412 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_cmd
,
5413 "no network X:X::X:X/M label-index (0-1048560)", NO_STR
5414 "Specify a network to announce via BGP\n"
5415 "IPv6 prefix <network>/<length>\n"
5416 "Label index to associate with the prefix\n"
5417 "Label index value\n")
5419 ALIAS(no_ipv6_bgp_network
, no_ipv6_bgp_network_label_index_route_map_cmd
,
5420 "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR
5421 "Specify a network to announce via BGP\n"
5423 "Label index to associate with the prefix\n"
5424 "Label index value\n"
5425 "Route-map to modify the attributes\n"
5426 "Name of the route map\n")
5428 /* Aggreagete address:
5430 advertise-map Set condition to advertise attribute
5431 as-set Generate AS set path information
5432 attribute-map Set attributes of aggregate
5433 route-map Set parameters of aggregate
5434 summary-only Filter more specific routes from updates
5435 suppress-map Conditionally filter more specific routes from updates
5438 struct bgp_aggregate
{
5439 /* Summary-only flag. */
5440 u_char summary_only
;
5442 /* AS set generation. */
5445 /* Route-map for aggregated route. */
5446 struct route_map
*map
;
5448 /* Suppress-count. */
5449 unsigned long count
;
5451 /* SAFI configuration. */
5455 static struct bgp_aggregate
*bgp_aggregate_new(void)
5457 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5460 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5462 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5465 /* Update an aggregate as routes are added/removed from the BGP table */
5466 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5467 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5468 struct bgp_info
*del
,
5469 struct bgp_aggregate
*aggregate
)
5471 struct bgp_table
*table
;
5472 struct bgp_node
*top
;
5473 struct bgp_node
*rn
;
5475 struct aspath
*aspath
= NULL
;
5476 struct aspath
*asmerge
= NULL
;
5477 struct community
*community
= NULL
;
5478 struct community
*commerge
= NULL
;
5479 #if defined(AGGREGATE_NEXTHOP_CHECK)
5480 struct in_addr nexthop
;
5483 struct bgp_info
*ri
;
5484 struct bgp_info
*new;
5486 unsigned long match
= 0;
5487 u_char atomic_aggregate
= 0;
5489 /* Record adding route's nexthop and med. */
5491 #if defined(AGGREGATE_NEXTHOP_CHECK)
5492 nexthop
= rinew
->attr
->nexthop
;
5493 med
= rinew
->attr
->med
;
5497 /* ORIGIN attribute: If at least one route among routes that are
5498 aggregated has ORIGIN with the value INCOMPLETE, then the
5499 aggregated route must have the ORIGIN attribute with the value
5500 INCOMPLETE. Otherwise, if at least one route among routes that
5501 are aggregated has ORIGIN with the value EGP, then the aggregated
5502 route must have the origin attribute with the value EGP. In all
5503 other case the value of the ORIGIN attribute of the aggregated
5504 route is INTERNAL. */
5505 origin
= BGP_ORIGIN_IGP
;
5507 table
= bgp
->rib
[afi
][safi
];
5509 top
= bgp_node_get(table
, p
);
5510 for (rn
= bgp_node_get(table
, p
); rn
;
5511 rn
= bgp_route_next_until(rn
, top
))
5512 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5515 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5516 if (BGP_INFO_HOLDDOWN(ri
))
5519 if (del
&& ri
== del
)
5522 if (!rinew
&& first
) {
5523 #if defined(AGGREGATE_NEXTHOP_CHECK)
5524 nexthop
= ri
->attr
->nexthop
;
5525 med
= ri
->attr
->med
;
5530 #ifdef AGGREGATE_NEXTHOP_CHECK
5531 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5533 || ri
->attr
->med
!= med
) {
5535 aspath_free(aspath
);
5537 community_free(community
);
5538 bgp_unlock_node(rn
);
5539 bgp_unlock_node(top
);
5542 #endif /* AGGREGATE_NEXTHOP_CHECK */
5545 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5546 atomic_aggregate
= 1;
5548 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5549 if (aggregate
->summary_only
) {
5550 (bgp_info_extra_get(ri
))
5554 BGP_INFO_ATTR_CHANGED
);
5560 if (origin
< ri
->attr
->origin
)
5561 origin
= ri
->attr
->origin
;
5563 if (aggregate
->as_set
) {
5565 asmerge
= aspath_aggregate(
5568 aspath_free(aspath
);
5571 aspath
= aspath_dup(
5574 if (ri
->attr
->community
) {
5576 commerge
= community_merge(
5578 ri
->attr
->community
);
5579 community
= community_uniq_sort(
5584 community
= community_dup(
5585 ri
->attr
->community
);
5591 bgp_process(bgp
, rn
, afi
, safi
);
5593 bgp_unlock_node(top
);
5598 if (aggregate
->summary_only
)
5599 (bgp_info_extra_get(rinew
))->suppress
++;
5601 if (origin
< rinew
->attr
->origin
)
5602 origin
= rinew
->attr
->origin
;
5604 if (aggregate
->as_set
) {
5606 asmerge
= aspath_aggregate(aspath
,
5607 rinew
->attr
->aspath
);
5608 aspath_free(aspath
);
5611 aspath
= aspath_dup(rinew
->attr
->aspath
);
5613 if (rinew
->attr
->community
) {
5615 commerge
= community_merge(
5617 rinew
->attr
->community
);
5619 community_uniq_sort(commerge
);
5620 community_free(commerge
);
5622 community
= community_dup(
5623 rinew
->attr
->community
);
5628 if (aggregate
->count
> 0) {
5629 rn
= bgp_node_get(table
, p
);
5631 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5632 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5633 community
, aggregate
->as_set
,
5636 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5638 bgp_info_add(rn
, new);
5639 bgp_unlock_node(rn
);
5640 bgp_process(bgp
, rn
, afi
, safi
);
5643 aspath_free(aspath
);
5645 community_free(community
);
5649 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5650 struct bgp_aggregate
*);
5652 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5653 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5655 struct bgp_node
*child
;
5656 struct bgp_node
*rn
;
5657 struct bgp_aggregate
*aggregate
;
5658 struct bgp_table
*table
;
5660 /* MPLS-VPN aggregation is not yet supported. */
5661 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5662 || (safi
== SAFI_EVPN
))
5665 table
= bgp
->aggregate
[afi
][safi
];
5667 /* No aggregates configured. */
5668 if (bgp_table_top_nolock(table
) == NULL
)
5671 if (p
->prefixlen
== 0)
5674 if (BGP_INFO_HOLDDOWN(ri
))
5677 child
= bgp_node_get(table
, p
);
5679 /* Aggregate address configuration check. */
5680 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5681 if ((aggregate
= rn
->info
) != NULL
5682 && rn
->p
.prefixlen
< p
->prefixlen
) {
5683 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5684 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5687 bgp_unlock_node(child
);
5690 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5691 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5693 struct bgp_node
*child
;
5694 struct bgp_node
*rn
;
5695 struct bgp_aggregate
*aggregate
;
5696 struct bgp_table
*table
;
5698 /* MPLS-VPN aggregation is not yet supported. */
5699 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5700 || (safi
== SAFI_EVPN
))
5703 table
= bgp
->aggregate
[afi
][safi
];
5705 /* No aggregates configured. */
5706 if (bgp_table_top_nolock(table
) == NULL
)
5709 if (p
->prefixlen
== 0)
5712 child
= bgp_node_get(table
, p
);
5714 /* Aggregate address configuration check. */
5715 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5716 if ((aggregate
= rn
->info
) != NULL
5717 && rn
->p
.prefixlen
< p
->prefixlen
) {
5718 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5719 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5722 bgp_unlock_node(child
);
5725 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5726 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5727 safi_t safi
, struct bgp_aggregate
*aggregate
)
5729 struct bgp_table
*table
;
5730 struct bgp_node
*top
;
5731 struct bgp_node
*rn
;
5732 struct bgp_info
*new;
5733 struct bgp_info
*ri
;
5734 unsigned long match
;
5735 u_char origin
= BGP_ORIGIN_IGP
;
5736 struct aspath
*aspath
= NULL
;
5737 struct aspath
*asmerge
= NULL
;
5738 struct community
*community
= NULL
;
5739 struct community
*commerge
= NULL
;
5740 u_char atomic_aggregate
= 0;
5742 table
= bgp
->rib
[afi
][safi
];
5745 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5747 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5750 /* If routes exists below this node, generate aggregate routes. */
5751 top
= bgp_node_get(table
, p
);
5752 for (rn
= bgp_node_get(table
, p
); rn
;
5753 rn
= bgp_route_next_until(rn
, top
)) {
5754 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5759 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5760 if (BGP_INFO_HOLDDOWN(ri
))
5764 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5765 atomic_aggregate
= 1;
5767 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5770 /* summary-only aggregate route suppress
5771 * aggregated route announcement. */
5772 if (aggregate
->summary_only
) {
5773 (bgp_info_extra_get(ri
))->suppress
++;
5774 bgp_info_set_flag(rn
, ri
,
5775 BGP_INFO_ATTR_CHANGED
);
5779 /* If at least one route among routes that are
5780 * aggregated has ORIGIN with the value INCOMPLETE,
5781 * then the aggregated route MUST have the ORIGIN
5782 * attribute with the value INCOMPLETE. Otherwise, if
5783 * at least one route among routes that are aggregated
5784 * has ORIGIN with the value EGP, then the aggregated
5785 * route MUST have the ORIGIN attribute with the value
5788 if (origin
< ri
->attr
->origin
)
5789 origin
= ri
->attr
->origin
;
5791 /* as-set aggregate route generate origin, as path,
5792 * community aggregation. */
5793 if (aggregate
->as_set
) {
5795 asmerge
= aspath_aggregate(
5796 aspath
, ri
->attr
->aspath
);
5797 aspath_free(aspath
);
5800 aspath
= aspath_dup(ri
->attr
->aspath
);
5802 if (ri
->attr
->community
) {
5804 commerge
= community_merge(
5806 ri
->attr
->community
);
5807 community
= community_uniq_sort(
5809 community_free(commerge
);
5811 community
= community_dup(
5812 ri
->attr
->community
);
5818 /* If this node is suppressed, process the change. */
5820 bgp_process(bgp
, rn
, afi
, safi
);
5822 bgp_unlock_node(top
);
5824 /* Add aggregate route to BGP table. */
5825 if (aggregate
->count
) {
5826 rn
= bgp_node_get(table
, p
);
5828 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5829 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5830 community
, aggregate
->as_set
,
5833 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5835 bgp_info_add(rn
, new);
5836 bgp_unlock_node(rn
);
5838 /* Process change. */
5839 bgp_process(bgp
, rn
, afi
, safi
);
5842 aspath_free(aspath
);
5844 community_free(community
);
5848 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5849 safi_t safi
, struct bgp_aggregate
*aggregate
)
5851 struct bgp_table
*table
;
5852 struct bgp_node
*top
;
5853 struct bgp_node
*rn
;
5854 struct bgp_info
*ri
;
5855 unsigned long match
;
5857 table
= bgp
->rib
[afi
][safi
];
5859 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5861 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5864 /* If routes exists below this node, generate aggregate routes. */
5865 top
= bgp_node_get(table
, p
);
5866 for (rn
= bgp_node_get(table
, p
); rn
;
5867 rn
= bgp_route_next_until(rn
, top
)) {
5868 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5872 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5873 if (BGP_INFO_HOLDDOWN(ri
))
5876 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5879 if (aggregate
->summary_only
&& ri
->extra
) {
5880 ri
->extra
->suppress
--;
5882 if (ri
->extra
->suppress
== 0) {
5884 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5891 /* If this node was suppressed, process the change. */
5893 bgp_process(bgp
, rn
, afi
, safi
);
5895 bgp_unlock_node(top
);
5897 /* Delete aggregate route from BGP table. */
5898 rn
= bgp_node_get(table
, p
);
5900 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5901 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5902 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5905 /* Withdraw static BGP route from routing table. */
5907 bgp_info_delete(rn
, ri
);
5908 bgp_process(bgp
, rn
, afi
, safi
);
5911 /* Unlock bgp_node_lookup. */
5912 bgp_unlock_node(rn
);
5915 /* Aggregate route attribute. */
5916 #define AGGREGATE_SUMMARY_ONLY 1
5917 #define AGGREGATE_AS_SET 1
5919 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5920 afi_t afi
, safi_t safi
)
5922 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5925 struct bgp_node
*rn
;
5926 struct bgp_aggregate
*aggregate
;
5928 /* Convert string to prefix structure. */
5929 ret
= str2prefix(prefix_str
, &p
);
5931 vty_out(vty
, "Malformed prefix\n");
5932 return CMD_WARNING_CONFIG_FAILED
;
5936 /* Old configuration check. */
5937 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5940 "%% There is no aggregate-address configuration.\n");
5941 return CMD_WARNING_CONFIG_FAILED
;
5944 aggregate
= rn
->info
;
5945 if (aggregate
->safi
== SAFI_UNICAST
)
5946 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5947 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5948 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5950 if (aggregate
->safi
== SAFI_MULTICAST
)
5951 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5953 /* Unlock aggregate address configuration. */
5955 bgp_aggregate_free(aggregate
);
5956 bgp_unlock_node(rn
);
5957 bgp_unlock_node(rn
);
5962 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5963 safi_t safi
, u_char summary_only
, u_char as_set
)
5965 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5968 struct bgp_node
*rn
;
5969 struct bgp_aggregate
*aggregate
;
5971 /* Convert string to prefix structure. */
5972 ret
= str2prefix(prefix_str
, &p
);
5974 vty_out(vty
, "Malformed prefix\n");
5975 return CMD_WARNING_CONFIG_FAILED
;
5979 /* Old configuration check. */
5980 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5983 vty_out(vty
, "There is already same aggregate network.\n");
5984 /* try to remove the old entry */
5985 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5987 vty_out(vty
, "Error deleting aggregate.\n");
5988 bgp_unlock_node(rn
);
5989 return CMD_WARNING_CONFIG_FAILED
;
5993 /* Make aggregate address structure. */
5994 aggregate
= bgp_aggregate_new();
5995 aggregate
->summary_only
= summary_only
;
5996 aggregate
->as_set
= as_set
;
5997 aggregate
->safi
= safi
;
5998 rn
->info
= aggregate
;
6000 /* Aggregate address insert into BGP routing table. */
6001 if (safi
== SAFI_UNICAST
)
6002 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
6003 if (safi
== SAFI_LABELED_UNICAST
)
6004 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
6006 if (safi
== SAFI_MULTICAST
)
6007 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
6012 DEFUN (aggregate_address
,
6013 aggregate_address_cmd
,
6014 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6015 "Configure BGP aggregate entries\n"
6016 "Aggregate prefix\n"
6017 "Generate AS set path information\n"
6018 "Filter more specific routes from updates\n"
6019 "Filter more specific routes from updates\n"
6020 "Generate AS set path information\n")
6023 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6024 char *prefix
= argv
[idx
]->arg
;
6026 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6028 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6029 ? AGGREGATE_SUMMARY_ONLY
6032 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6033 summary_only
, as_set
);
6036 DEFUN (aggregate_address_mask
,
6037 aggregate_address_mask_cmd
,
6038 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6039 "Configure BGP aggregate entries\n"
6040 "Aggregate address\n"
6042 "Generate AS set path information\n"
6043 "Filter more specific routes from updates\n"
6044 "Filter more specific routes from updates\n"
6045 "Generate AS set path information\n")
6048 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6049 char *prefix
= argv
[idx
]->arg
;
6050 char *mask
= argv
[idx
+ 1]->arg
;
6052 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6054 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6055 ? AGGREGATE_SUMMARY_ONLY
6058 char prefix_str
[BUFSIZ
];
6059 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6062 vty_out(vty
, "%% Inconsistent address and mask\n");
6063 return CMD_WARNING_CONFIG_FAILED
;
6066 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6067 summary_only
, as_set
);
6070 DEFUN (no_aggregate_address
,
6071 no_aggregate_address_cmd
,
6072 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6074 "Configure BGP aggregate entries\n"
6075 "Aggregate prefix\n"
6076 "Generate AS set path information\n"
6077 "Filter more specific routes from updates\n"
6078 "Filter more specific routes from updates\n"
6079 "Generate AS set path information\n")
6082 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6083 char *prefix
= argv
[idx
]->arg
;
6084 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6087 DEFUN (no_aggregate_address_mask
,
6088 no_aggregate_address_mask_cmd
,
6089 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6091 "Configure BGP aggregate entries\n"
6092 "Aggregate address\n"
6094 "Generate AS set path information\n"
6095 "Filter more specific routes from updates\n"
6096 "Filter more specific routes from updates\n"
6097 "Generate AS set path information\n")
6100 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6101 char *prefix
= argv
[idx
]->arg
;
6102 char *mask
= argv
[idx
+ 1]->arg
;
6104 char prefix_str
[BUFSIZ
];
6105 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6108 vty_out(vty
, "%% Inconsistent address and mask\n");
6109 return CMD_WARNING_CONFIG_FAILED
;
6112 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6115 DEFUN (ipv6_aggregate_address
,
6116 ipv6_aggregate_address_cmd
,
6117 "aggregate-address X:X::X:X/M [summary-only]",
6118 "Configure BGP aggregate entries\n"
6119 "Aggregate prefix\n"
6120 "Filter more specific routes from updates\n")
6123 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6124 char *prefix
= argv
[idx
]->arg
;
6125 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6126 ? AGGREGATE_SUMMARY_ONLY
6128 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6132 DEFUN (no_ipv6_aggregate_address
,
6133 no_ipv6_aggregate_address_cmd
,
6134 "no aggregate-address X:X::X:X/M [summary-only]",
6136 "Configure BGP aggregate entries\n"
6137 "Aggregate prefix\n"
6138 "Filter more specific routes from updates\n")
6141 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6142 char *prefix
= argv
[idx
]->arg
;
6143 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6146 /* Redistribute route treatment. */
6147 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6148 const union g_addr
*nexthop
, unsigned int ifindex
,
6149 u_int32_t metric
, u_char type
, u_short instance
,
6152 struct bgp_info
*new;
6153 struct bgp_info
*bi
;
6154 struct bgp_info info
;
6155 struct bgp_node
*bn
;
6157 struct attr
*new_attr
;
6160 struct bgp_redist
*red
;
6162 /* Make default attribute. */
6163 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6165 switch (p
->family
) {
6167 attr
.nexthop
= nexthop
->ipv4
;
6170 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6171 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6174 attr
.nh_ifindex
= ifindex
;
6177 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6180 afi
= family2afi(p
->family
);
6182 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6184 struct attr attr_new
;
6186 /* Copy attribute for modification. */
6187 bgp_attr_dup(&attr_new
, &attr
);
6189 if (red
->redist_metric_flag
)
6190 attr_new
.med
= red
->redist_metric
;
6192 /* Apply route-map. */
6193 if (red
->rmap
.name
) {
6194 info
.peer
= bgp
->peer_self
;
6195 info
.attr
= &attr_new
;
6197 SET_FLAG(bgp
->peer_self
->rmap_type
,
6198 PEER_RMAP_TYPE_REDISTRIBUTE
);
6200 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6203 bgp
->peer_self
->rmap_type
= 0;
6205 if (ret
== RMAP_DENYMATCH
) {
6206 /* Free uninterned attribute. */
6207 bgp_attr_flush(&attr_new
);
6209 /* Unintern original. */
6210 aspath_unintern(&attr
.aspath
);
6211 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6216 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6217 bgp_attr_add_gshut_community(&attr_new
);
6219 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6220 SAFI_UNICAST
, p
, NULL
);
6222 new_attr
= bgp_attr_intern(&attr_new
);
6224 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
6225 if (bi
->peer
== bgp
->peer_self
6226 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6230 /* Ensure the (source route) type is updated. */
6232 if (attrhash_cmp(bi
->attr
, new_attr
)
6233 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
6234 bgp_attr_unintern(&new_attr
);
6235 aspath_unintern(&attr
.aspath
);
6236 bgp_unlock_node(bn
);
6239 /* The attribute is changed. */
6240 bgp_info_set_flag(bn
, bi
,
6241 BGP_INFO_ATTR_CHANGED
);
6243 /* Rewrite BGP route information. */
6244 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
6245 bgp_info_restore(bn
, bi
);
6247 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
6249 bgp_attr_unintern(&bi
->attr
);
6250 bi
->attr
= new_attr
;
6251 bi
->uptime
= bgp_clock();
6253 /* Process change. */
6254 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
6256 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6257 bgp_unlock_node(bn
);
6258 aspath_unintern(&attr
.aspath
);
6263 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6264 bgp
->peer_self
, new_attr
, bn
);
6265 SET_FLAG(new->flags
, BGP_INFO_VALID
);
6267 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6268 bgp_info_add(bn
, new);
6269 bgp_unlock_node(bn
);
6270 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6273 /* Unintern original. */
6274 aspath_unintern(&attr
.aspath
);
6277 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6281 struct bgp_node
*rn
;
6282 struct bgp_info
*ri
;
6283 struct bgp_redist
*red
;
6285 afi
= family2afi(p
->family
);
6287 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6289 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6290 SAFI_UNICAST
, p
, NULL
);
6292 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6293 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6297 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6298 bgp_info_delete(rn
, ri
);
6299 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6301 bgp_unlock_node(rn
);
6305 /* Withdraw specified route type's route. */
6306 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6309 struct bgp_node
*rn
;
6310 struct bgp_info
*ri
;
6311 struct bgp_table
*table
;
6313 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6315 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6316 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6317 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6318 && ri
->instance
== instance
)
6322 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6324 bgp_info_delete(rn
, ri
);
6325 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6330 /* Static function to display route. */
6331 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6335 u_int32_t destination
;
6338 if (p
->family
== AF_INET
) {
6340 len
= vty_out(vty
, "%s",
6341 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6343 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6345 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6346 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6347 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6348 || p
->u
.prefix4
.s_addr
== 0) {
6349 /* When mask is natural,
6350 mask is not displayed. */
6352 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6354 json_object_string_add(json
, "prefix",
6355 inet_ntop(p
->family
,
6358 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6360 } else if (p
->family
== AF_ETHERNET
) {
6361 prefix2str(p
, buf
, PREFIX_STRLEN
);
6362 len
= vty_out(vty
, "%s", buf
);
6363 } else if (p
->family
== AF_EVPN
) {
6364 #if defined(HAVE_CUMULUS)
6368 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6371 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6373 prefix2str(p
, buf
, PREFIX_STRLEN
);
6374 len
= vty_out(vty
, "%s", buf
);
6380 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6387 vty_out(vty
, "\n%*s", 20, " ");
6389 vty_out(vty
, "%*s", len
, " ");
6393 enum bgp_display_type
{
6397 /* Print the short form route status for a bgp_info */
6398 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6399 json_object
*json_path
)
6403 /* Route status display. */
6404 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6405 json_object_boolean_true_add(json_path
, "removed");
6407 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6408 json_object_boolean_true_add(json_path
, "stale");
6410 if (binfo
->extra
&& binfo
->extra
->suppress
)
6411 json_object_boolean_true_add(json_path
, "suppressed");
6413 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6414 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6415 json_object_boolean_true_add(json_path
, "valid");
6418 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6419 json_object_boolean_true_add(json_path
, "history");
6421 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6422 json_object_boolean_true_add(json_path
, "damped");
6424 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6425 json_object_boolean_true_add(json_path
, "bestpath");
6427 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6428 json_object_boolean_true_add(json_path
, "multipath");
6430 /* Internal route. */
6431 if ((binfo
->peer
->as
)
6432 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6433 json_object_string_add(json_path
, "pathFrom",
6436 json_object_string_add(json_path
, "pathFrom",
6442 /* Route status display. */
6443 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6445 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6447 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6449 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6450 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6456 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6458 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6460 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6462 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6467 /* Internal route. */
6468 if (binfo
->peer
&& (binfo
->peer
->as
)
6469 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6475 /* called from terminal list command */
6476 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6477 int display
, safi_t safi
, json_object
*json_paths
)
6480 json_object
*json_path
= NULL
;
6481 json_object
*json_nexthops
= NULL
;
6482 json_object
*json_nexthop_global
= NULL
;
6483 json_object
*json_nexthop_ll
= NULL
;
6486 json_path
= json_object_new_object();
6488 /* short status lead text */
6489 route_vty_short_status_out(vty
, binfo
, json_path
);
6492 /* print prefix and mask */
6494 route_vty_out_route(p
, vty
, json_path
);
6496 vty_out(vty
, "%*s", 17, " ");
6498 route_vty_out_route(p
, vty
, json_path
);
6501 /* Print attribute */
6505 json_object_array_add(json_paths
, json_path
);
6513 * For ENCAP and EVPN routes, nexthop address family is not
6514 * neccessarily the same as the prefix address family.
6515 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6516 * EVPN routes are also exchanged with a MP nexthop. Currently,
6518 * is only IPv4, the value will be present in either
6520 * attr->mp_nexthop_global_in
6522 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6525 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6529 sprintf(nexthop
, "%s",
6530 inet_ntop(af
, &attr
->mp_nexthop_global_in
,
6534 sprintf(nexthop
, "%s",
6535 inet_ntop(af
, &attr
->mp_nexthop_global
,
6539 sprintf(nexthop
, "?");
6544 json_nexthop_global
= json_object_new_object();
6546 json_object_string_add(json_nexthop_global
,
6550 json_object_string_add(json_nexthop_global
,
6554 json_object_boolean_true_add(json_nexthop_global
,
6557 vty_out(vty
, "%s", nexthop
);
6558 } else if (safi
== SAFI_EVPN
) {
6560 json_nexthop_global
= json_object_new_object();
6562 json_object_string_add(json_nexthop_global
, "ip",
6563 inet_ntoa(attr
->nexthop
));
6564 json_object_string_add(json_nexthop_global
,
6566 json_object_boolean_true_add(json_nexthop_global
,
6569 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6572 else if (p
->family
== AF_INET
6573 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6575 json_nexthop_global
= json_object_new_object();
6577 if ((safi
== SAFI_MPLS_VPN
)
6578 || (safi
== SAFI_EVPN
))
6579 json_object_string_add(json_nexthop_global
,
6581 inet_ntoa(attr
->mp_nexthop_global_in
));
6583 json_object_string_add(json_nexthop_global
,
6585 inet_ntoa(attr
->nexthop
));
6587 json_object_string_add(json_nexthop_global
,
6589 json_object_boolean_true_add(json_nexthop_global
,
6592 if ((safi
== SAFI_MPLS_VPN
)
6593 || (safi
== SAFI_EVPN
))
6594 vty_out(vty
, "%-16s",
6596 attr
->mp_nexthop_global_in
));
6598 vty_out(vty
, "%-16s",
6599 inet_ntoa(attr
->nexthop
));
6604 else if (p
->family
== AF_INET6
6605 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6610 json_nexthop_global
= json_object_new_object();
6611 json_object_string_add(json_nexthop_global
, "ip",
6613 &attr
->mp_nexthop_global
, buf
,
6615 json_object_string_add(json_nexthop_global
,
6617 json_object_string_add(json_nexthop_global
,
6620 /* We display both LL & GL if both have been
6622 if ((attr
->mp_nexthop_len
== 32)
6623 || (binfo
->peer
->conf_if
)) {
6625 json_object_new_object();
6626 json_object_string_add(
6627 json_nexthop_ll
, "ip",
6630 &attr
->mp_nexthop_local
,
6632 json_object_string_add(json_nexthop_ll
,
6634 json_object_string_add(json_nexthop_ll
,
6639 &attr
->mp_nexthop_global
,
6640 &attr
->mp_nexthop_local
)
6642 && !attr
->mp_nexthop_prefer_global
)
6643 json_object_boolean_true_add(
6647 json_object_boolean_true_add(
6648 json_nexthop_global
,
6651 json_object_boolean_true_add(
6652 json_nexthop_global
, "used");
6654 /* Display LL if LL/Global both in table unless
6655 * prefer-global is set */
6656 if (((attr
->mp_nexthop_len
== 32)
6657 && !attr
->mp_nexthop_prefer_global
)
6658 || (binfo
->peer
->conf_if
)) {
6659 if (binfo
->peer
->conf_if
) {
6662 binfo
->peer
->conf_if
);
6663 len
= 16 - len
; /* len of IPv6
6669 vty_out(vty
, "\n%*s",
6672 vty_out(vty
, "%*s", len
,
6679 &attr
->mp_nexthop_local
,
6684 vty_out(vty
, "\n%*s",
6687 vty_out(vty
, "%*s", len
,
6691 len
= vty_out(vty
, "%s",
6693 &attr
->mp_nexthop_global
,
6698 vty_out(vty
, "\n%*s", 36, " ");
6700 vty_out(vty
, "%*s", len
, " ");
6706 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6708 json_object_int_add(json_path
, "med",
6711 vty_out(vty
, "%10u", attr
->med
);
6712 else if (!json_paths
)
6716 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6718 json_object_int_add(json_path
, "localpref",
6721 vty_out(vty
, "%7u", attr
->local_pref
);
6722 else if (!json_paths
)
6726 json_object_int_add(json_path
, "weight", attr
->weight
);
6728 vty_out(vty
, "%7u ", attr
->weight
);
6732 json_object_string_add(json_path
, "peerId",
6733 sockunion2str(&binfo
->peer
->su
,
6741 json_object_string_add(json_path
, "aspath",
6744 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6749 json_object_string_add(
6750 json_path
, "origin",
6751 bgp_origin_long_str
[attr
->origin
]);
6753 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6756 if (json_nexthop_global
|| json_nexthop_ll
) {
6757 json_nexthops
= json_object_new_array();
6759 if (json_nexthop_global
)
6760 json_object_array_add(json_nexthops
,
6761 json_nexthop_global
);
6763 if (json_nexthop_ll
)
6764 json_object_array_add(json_nexthops
,
6767 json_object_object_add(json_path
, "nexthops",
6771 json_object_array_add(json_paths
, json_path
);
6775 /* prints an additional line, indented, with VNC info, if
6777 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6778 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6783 /* called from terminal list command */
6784 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6785 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6787 json_object
*json_status
= NULL
;
6788 json_object
*json_net
= NULL
;
6790 /* Route status display. */
6792 json_status
= json_object_new_object();
6793 json_net
= json_object_new_object();
6800 /* print prefix and mask */
6802 json_object_string_add(
6803 json_net
, "addrPrefix",
6804 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6806 route_vty_out_route(p
, vty
, NULL
);
6808 /* Print attribute */
6811 if (p
->family
== AF_INET
6812 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6813 || safi
== SAFI_EVPN
6814 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6815 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6816 || safi
== SAFI_EVPN
)
6817 json_object_string_add(
6818 json_net
, "nextHop",
6820 attr
->mp_nexthop_global_in
));
6822 json_object_string_add(
6823 json_net
, "nextHop",
6824 inet_ntoa(attr
->nexthop
));
6825 } else if (p
->family
== AF_INET6
6826 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6829 json_object_string_add(
6830 json_net
, "netHopGloabal",
6832 &attr
->mp_nexthop_global
, buf
,
6837 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6838 json_object_int_add(json_net
, "metric",
6841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6842 json_object_int_add(json_net
, "localPref",
6845 json_object_int_add(json_net
, "weight", attr
->weight
);
6849 json_object_string_add(json_net
, "asPath",
6853 json_object_string_add(json_net
, "bgpOriginCode",
6854 bgp_origin_str
[attr
->origin
]);
6856 if (p
->family
== AF_INET
6857 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6858 || safi
== SAFI_EVPN
6859 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6860 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6861 || safi
== SAFI_EVPN
)
6862 vty_out(vty
, "%-16s",
6864 attr
->mp_nexthop_global_in
));
6866 vty_out(vty
, "%-16s",
6867 inet_ntoa(attr
->nexthop
));
6868 } else if (p
->family
== AF_INET6
6869 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6876 &attr
->mp_nexthop_global
, buf
,
6880 vty_out(vty
, "\n%*s", 36, " ");
6882 vty_out(vty
, "%*s", len
, " ");
6885 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6886 vty_out(vty
, "%10u", attr
->med
);
6890 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6891 vty_out(vty
, "%7u", attr
->local_pref
);
6895 vty_out(vty
, "%7u ", attr
->weight
);
6899 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6902 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6906 json_object_boolean_true_add(json_status
, "*");
6907 json_object_boolean_true_add(json_status
, ">");
6908 json_object_object_add(json_net
, "appliedStatusSymbols",
6910 char buf_cut
[BUFSIZ
];
6911 json_object_object_add(
6913 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6919 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6920 struct bgp_info
*binfo
, int display
, safi_t safi
,
6923 json_object
*json_out
= NULL
;
6925 mpls_label_t label
= MPLS_INVALID_LABEL
;
6931 json_out
= json_object_new_object();
6933 /* short status lead text */
6934 route_vty_short_status_out(vty
, binfo
, json_out
);
6936 /* print prefix and mask */
6939 route_vty_out_route(p
, vty
, NULL
);
6941 vty_out(vty
, "%*s", 17, " ");
6944 /* Print attribute */
6947 if (((p
->family
== AF_INET
)
6948 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6949 || (safi
== SAFI_EVPN
6950 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6951 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6952 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6953 || safi
== SAFI_EVPN
) {
6955 json_object_string_add(
6956 json_out
, "mpNexthopGlobalIn",
6958 attr
->mp_nexthop_global_in
));
6960 vty_out(vty
, "%-16s",
6962 attr
->mp_nexthop_global_in
));
6965 json_object_string_add(
6966 json_out
, "nexthop",
6967 inet_ntoa(attr
->nexthop
));
6969 vty_out(vty
, "%-16s",
6970 inet_ntoa(attr
->nexthop
));
6972 } else if (((p
->family
== AF_INET6
)
6973 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6974 || (safi
== SAFI_EVPN
6975 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6976 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6980 if (attr
->mp_nexthop_len
6981 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6983 json_object_string_add(
6984 json_out
, "mpNexthopGlobalIn",
6987 &attr
->mp_nexthop_global
,
6993 &attr
->mp_nexthop_global
,
6995 } else if (attr
->mp_nexthop_len
6996 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6999 &attr
->mp_nexthop_global
,
7002 &attr
->mp_nexthop_local
,
7004 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7005 json_object_string_add(
7007 "mpNexthopGlobalLocal", buf_c
);
7009 vty_out(vty
, "%s(%s)",
7012 &attr
->mp_nexthop_global
,
7016 &attr
->mp_nexthop_local
,
7022 label
= decode_label(&binfo
->extra
->label
);
7024 if (bgp_is_valid_label(&label
)) {
7026 json_object_int_add(json_out
, "notag", label
);
7027 json_object_array_add(json
, json_out
);
7029 vty_out(vty
, "notag/%d", label
);
7035 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7036 struct bgp_info
*binfo
, int display
,
7037 json_object
*json_paths
)
7041 json_object
*json_path
= NULL
;
7044 json_path
= json_object_new_object();
7049 /* short status lead text */
7050 route_vty_short_status_out(vty
, binfo
, json_path
);
7052 /* print prefix and mask */
7054 route_vty_out_route(p
, vty
, NULL
);
7056 vty_out(vty
, "%*s", 17, " ");
7058 /* Print attribute */
7062 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7066 vty_out(vty
, "%-16s",
7067 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7071 vty_out(vty
, "%s(%s)",
7072 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7074 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7082 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
7083 char *str
= esi2str(id
);
7084 vty_out(vty
, "%s", str
);
7085 XFREE(MTYPE_TMP
, str
);
7086 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
7087 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7088 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
7090 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
7093 if (attr
->ecommunity
) {
7095 struct ecommunity_val
*routermac
= ecommunity_lookup(
7096 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7097 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7099 mac
= ecom_mac2str((char *)routermac
->val
);
7101 vty_out(vty
, "/%s", (char *)mac
);
7102 XFREE(MTYPE_TMP
, mac
);
7108 /* dampening route */
7109 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7110 struct bgp_info
*binfo
, int display
, safi_t safi
,
7111 u_char use_json
, json_object
*json
)
7115 char timebuf
[BGP_UPTIME_LEN
];
7117 /* short status lead text */
7118 route_vty_short_status_out(vty
, binfo
, json
);
7120 /* print prefix and mask */
7123 route_vty_out_route(p
, vty
, NULL
);
7125 vty_out(vty
, "%*s", 17, " ");
7128 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7132 vty_out(vty
, "\n%*s", 34, " ");
7135 json_object_int_add(json
, "peerHost", len
);
7137 vty_out(vty
, "%*s", len
, " ");
7141 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
7144 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7148 /* Print attribute */
7154 json_object_string_add(json
, "asPath",
7157 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7162 json_object_string_add(json
, "origin",
7163 bgp_origin_str
[attr
->origin
]);
7165 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7172 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7173 struct bgp_info
*binfo
, int display
, safi_t safi
,
7174 u_char use_json
, json_object
*json
)
7177 struct bgp_damp_info
*bdi
;
7178 char timebuf
[BGP_UPTIME_LEN
];
7184 bdi
= binfo
->extra
->damp_info
;
7186 /* short status lead text */
7187 route_vty_short_status_out(vty
, binfo
, json
);
7189 /* print prefix and mask */
7192 route_vty_out_route(p
, vty
, NULL
);
7194 vty_out(vty
, "%*s", 17, " ");
7197 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
7201 vty_out(vty
, "\n%*s", 33, " ");
7204 json_object_int_add(json
, "peerHost", len
);
7206 vty_out(vty
, "%*s", len
, " ");
7209 len
= vty_out(vty
, "%d", bdi
->flap
);
7216 json_object_int_add(json
, "bdiFlap", len
);
7218 vty_out(vty
, "%*s", len
, " ");
7222 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7225 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7226 BGP_UPTIME_LEN
, 0, NULL
));
7228 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
7229 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7231 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7232 BGP_UPTIME_LEN
, use_json
, json
);
7235 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
7240 vty_out(vty
, "%*s ", 8, " ");
7243 /* Print attribute */
7249 json_object_string_add(json
, "asPath",
7252 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7257 json_object_string_add(json
, "origin",
7258 bgp_origin_str
[attr
->origin
]);
7260 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7266 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7267 int *first
, const char *header
,
7268 json_object
*json_adv_to
)
7270 char buf1
[INET6_ADDRSTRLEN
];
7271 json_object
*json_peer
= NULL
;
7274 /* 'advertised-to' is a dictionary of peers we have advertised
7276 * prefix too. The key is the peer's IP or swpX, the value is
7278 * hostname if we know it and "" if not.
7280 json_peer
= json_object_new_object();
7283 json_object_string_add(json_peer
, "hostname",
7287 json_object_object_add(json_adv_to
, peer
->conf_if
,
7290 json_object_object_add(
7292 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7296 vty_out(vty
, "%s", header
);
7301 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7303 vty_out(vty
, " %s(%s)", peer
->hostname
,
7306 vty_out(vty
, " %s(%s)", peer
->hostname
,
7307 sockunion2str(&peer
->su
, buf1
,
7311 vty_out(vty
, " %s", peer
->conf_if
);
7314 sockunion2str(&peer
->su
, buf1
,
7320 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7321 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7322 json_object
*json_paths
)
7324 char buf
[INET6_ADDRSTRLEN
];
7326 #if defined(HAVE_CUMULUS)
7327 char buf2
[EVPN_ROUTE_STRLEN
];
7330 int sockunion_vty_out(struct vty
*, union sockunion
*);
7332 json_object
*json_bestpath
= NULL
;
7333 json_object
*json_cluster_list
= NULL
;
7334 json_object
*json_cluster_list_list
= NULL
;
7335 json_object
*json_ext_community
= NULL
;
7336 json_object
*json_lcommunity
= NULL
;
7337 json_object
*json_last_update
= NULL
;
7338 json_object
*json_nexthop_global
= NULL
;
7339 json_object
*json_nexthop_ll
= NULL
;
7340 json_object
*json_nexthops
= NULL
;
7341 json_object
*json_path
= NULL
;
7342 json_object
*json_peer
= NULL
;
7343 json_object
*json_string
= NULL
;
7344 json_object
*json_adv_to
= NULL
;
7346 struct listnode
*node
, *nnode
;
7348 int addpath_capable
;
7350 unsigned int first_as
;
7353 json_path
= json_object_new_object();
7354 json_peer
= json_object_new_object();
7355 json_nexthop_global
= json_object_new_object();
7358 #if defined(HAVE_CUMULUS)
7359 if (!json_paths
&& safi
== SAFI_EVPN
) {
7362 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7363 vty_out(vty
, " Route %s", buf2
);
7366 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7368 vty_out(vty
, " VNI %s", tag_buf
);
7371 if (binfo
->extra
&& binfo
->extra
->parent
) {
7372 struct bgp_info
*parent_ri
;
7373 struct bgp_node
*rn
, *prn
;
7375 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7376 rn
= parent_ri
->net
;
7377 if (rn
&& rn
->prn
) {
7379 vty_out(vty
, " Imported from %s:%s\n",
7381 (struct prefix_rd
*)&prn
->p
,
7382 buf1
, RD_ADDRSTRLEN
),
7392 /* Line1 display AS-path, Aggregator */
7395 json_object_lock(attr
->aspath
->json
);
7396 json_object_object_add(json_path
, "aspath",
7397 attr
->aspath
->json
);
7399 if (attr
->aspath
->segments
)
7400 aspath_print_vty(vty
, " %s",
7403 vty_out(vty
, " Local");
7407 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7409 json_object_boolean_true_add(json_path
,
7412 vty_out(vty
, ", (removed)");
7415 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7417 json_object_boolean_true_add(json_path
,
7420 vty_out(vty
, ", (stale)");
7423 if (CHECK_FLAG(attr
->flag
,
7424 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7426 json_object_int_add(json_path
, "aggregatorAs",
7427 attr
->aggregator_as
);
7428 json_object_string_add(
7429 json_path
, "aggregatorId",
7430 inet_ntoa(attr
->aggregator_addr
));
7432 vty_out(vty
, ", (aggregated by %u %s)",
7433 attr
->aggregator_as
,
7434 inet_ntoa(attr
->aggregator_addr
));
7438 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7439 PEER_FLAG_REFLECTOR_CLIENT
)) {
7441 json_object_boolean_true_add(
7442 json_path
, "rxedFromRrClient");
7444 vty_out(vty
, ", (Received from a RR-client)");
7447 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7448 PEER_FLAG_RSERVER_CLIENT
)) {
7450 json_object_boolean_true_add(
7451 json_path
, "rxedFromRsClient");
7453 vty_out(vty
, ", (Received from a RS-client)");
7456 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7458 json_object_boolean_true_add(
7459 json_path
, "dampeningHistoryEntry");
7461 vty_out(vty
, ", (history entry)");
7462 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7464 json_object_boolean_true_add(
7465 json_path
, "dampeningSuppressed");
7467 vty_out(vty
, ", (suppressed due to dampening)");
7473 /* Line2 display Next-hop, Neighbor, Router-id */
7474 /* Display the nexthop */
7475 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
7476 p
->family
== AF_EVPN
)
7477 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7478 || safi
== SAFI_EVPN
7479 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7480 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7481 || safi
== SAFI_EVPN
) {
7483 json_object_string_add(
7484 json_nexthop_global
, "ip",
7486 attr
->mp_nexthop_global_in
));
7490 attr
->mp_nexthop_global_in
));
7493 json_object_string_add(
7494 json_nexthop_global
, "ip",
7495 inet_ntoa(attr
->nexthop
));
7498 inet_ntoa(attr
->nexthop
));
7502 json_object_string_add(json_nexthop_global
,
7506 json_object_string_add(
7507 json_nexthop_global
, "ip",
7509 &attr
->mp_nexthop_global
, buf
,
7511 json_object_string_add(json_nexthop_global
,
7513 json_object_string_add(json_nexthop_global
,
7518 &attr
->mp_nexthop_global
, buf
,
7523 /* Display the IGP cost or 'inaccessible' */
7524 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7526 json_object_boolean_false_add(
7527 json_nexthop_global
, "accessible");
7529 vty_out(vty
, " (inaccessible)");
7531 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7533 json_object_int_add(
7534 json_nexthop_global
, "metric",
7535 binfo
->extra
->igpmetric
);
7537 vty_out(vty
, " (metric %u)",
7538 binfo
->extra
->igpmetric
);
7541 /* IGP cost is 0, display this only for json */
7544 json_object_int_add(json_nexthop_global
,
7549 json_object_boolean_true_add(
7550 json_nexthop_global
, "accessible");
7553 /* Display peer "from" output */
7554 /* This path was originated locally */
7555 if (binfo
->peer
== bgp
->peer_self
) {
7557 if (safi
== SAFI_EVPN
7558 || (p
->family
== AF_INET
7559 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7561 json_object_string_add(
7562 json_peer
, "peerId", "0.0.0.0");
7564 vty_out(vty
, " from 0.0.0.0 ");
7567 json_object_string_add(json_peer
,
7570 vty_out(vty
, " from :: ");
7574 json_object_string_add(
7575 json_peer
, "routerId",
7576 inet_ntoa(bgp
->router_id
));
7578 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7581 /* We RXed this path from one of our peers */
7585 json_object_string_add(
7586 json_peer
, "peerId",
7587 sockunion2str(&binfo
->peer
->su
, buf
,
7589 json_object_string_add(
7590 json_peer
, "routerId",
7592 &binfo
->peer
->remote_id
, buf1
,
7595 if (binfo
->peer
->hostname
)
7596 json_object_string_add(
7597 json_peer
, "hostname",
7598 binfo
->peer
->hostname
);
7600 if (binfo
->peer
->domainname
)
7601 json_object_string_add(
7602 json_peer
, "domainname",
7603 binfo
->peer
->domainname
);
7605 if (binfo
->peer
->conf_if
)
7606 json_object_string_add(
7607 json_peer
, "interface",
7608 binfo
->peer
->conf_if
);
7610 if (binfo
->peer
->conf_if
) {
7611 if (binfo
->peer
->hostname
7614 BGP_FLAG_SHOW_HOSTNAME
))
7615 vty_out(vty
, " from %s(%s)",
7616 binfo
->peer
->hostname
,
7617 binfo
->peer
->conf_if
);
7619 vty_out(vty
, " from %s",
7620 binfo
->peer
->conf_if
);
7622 if (binfo
->peer
->hostname
7625 BGP_FLAG_SHOW_HOSTNAME
))
7626 vty_out(vty
, " from %s(%s)",
7627 binfo
->peer
->hostname
,
7630 vty_out(vty
, " from %s",
7639 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7640 vty_out(vty
, " (%s)",
7641 inet_ntoa(attr
->originator_id
));
7643 vty_out(vty
, " (%s)",
7646 &binfo
->peer
->remote_id
,
7654 /* display the link-local nexthop */
7655 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7657 json_nexthop_ll
= json_object_new_object();
7658 json_object_string_add(
7659 json_nexthop_ll
, "ip",
7661 &attr
->mp_nexthop_local
, buf
,
7663 json_object_string_add(json_nexthop_ll
, "afi",
7665 json_object_string_add(json_nexthop_ll
, "scope",
7668 json_object_boolean_true_add(json_nexthop_ll
,
7671 if (!attr
->mp_nexthop_prefer_global
)
7672 json_object_boolean_true_add(
7673 json_nexthop_ll
, "used");
7675 json_object_boolean_true_add(
7676 json_nexthop_global
, "used");
7678 vty_out(vty
, " (%s) %s\n",
7680 &attr
->mp_nexthop_local
, buf
,
7682 attr
->mp_nexthop_prefer_global
7687 /* If we do not have a link-local nexthop then we must flag the
7691 json_object_boolean_true_add(
7692 json_nexthop_global
, "used");
7695 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7696 * Int/Ext/Local, Atomic, best */
7698 json_object_string_add(
7699 json_path
, "origin",
7700 bgp_origin_long_str
[attr
->origin
]);
7702 vty_out(vty
, " Origin %s",
7703 bgp_origin_long_str
[attr
->origin
]);
7705 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7707 json_object_int_add(json_path
, "med",
7710 vty_out(vty
, ", metric %u", attr
->med
);
7713 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7715 json_object_int_add(json_path
, "localpref",
7718 vty_out(vty
, ", localpref %u",
7722 json_object_int_add(json_path
, "localpref",
7723 bgp
->default_local_pref
);
7725 vty_out(vty
, ", localpref %u",
7726 bgp
->default_local_pref
);
7729 if (attr
->weight
!= 0) {
7731 json_object_int_add(json_path
, "weight",
7734 vty_out(vty
, ", weight %u", attr
->weight
);
7737 if (attr
->tag
!= 0) {
7739 json_object_int_add(json_path
, "tag",
7742 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7746 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7748 json_object_boolean_false_add(json_path
,
7751 vty_out(vty
, ", invalid");
7752 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7754 json_object_boolean_true_add(json_path
,
7757 vty_out(vty
, ", valid");
7760 if (binfo
->peer
!= bgp
->peer_self
) {
7761 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7762 if (CHECK_FLAG(bgp
->config
,
7763 BGP_CONFIG_CONFEDERATION
)) {
7765 json_object_string_add(
7770 ", confed-internal");
7773 json_object_string_add(
7777 vty_out(vty
, ", internal");
7780 if (bgp_confederation_peers_check(
7781 bgp
, binfo
->peer
->as
)) {
7783 json_object_string_add(
7788 ", confed-external");
7791 json_object_string_add(
7795 vty_out(vty
, ", external");
7798 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7800 json_object_boolean_true_add(json_path
,
7802 json_object_boolean_true_add(json_path
,
7805 vty_out(vty
, ", aggregated, local");
7807 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7809 json_object_boolean_true_add(json_path
,
7812 vty_out(vty
, ", sourced");
7815 json_object_boolean_true_add(json_path
,
7817 json_object_boolean_true_add(json_path
,
7820 vty_out(vty
, ", sourced, local");
7824 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7826 json_object_boolean_true_add(json_path
,
7829 vty_out(vty
, ", atomic-aggregate");
7832 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7833 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7834 && bgp_info_mpath_count(binfo
))) {
7836 json_object_boolean_true_add(json_path
,
7839 vty_out(vty
, ", multipath");
7842 // Mark the bestpath(s)
7843 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7844 first_as
= aspath_get_first_as(attr
->aspath
);
7849 json_object_new_object();
7850 json_object_int_add(json_bestpath
,
7851 "bestpathFromAs", first_as
);
7854 vty_out(vty
, ", bestpath-from-AS %u",
7858 ", bestpath-from-AS Local");
7862 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7866 json_object_new_object();
7867 json_object_boolean_true_add(json_bestpath
,
7870 vty_out(vty
, ", best");
7874 json_object_object_add(json_path
, "bestpath",
7880 /* Line 4 display Community */
7881 if (attr
->community
) {
7883 json_object_lock(attr
->community
->json
);
7884 json_object_object_add(json_path
, "community",
7885 attr
->community
->json
);
7887 vty_out(vty
, " Community: %s\n",
7888 attr
->community
->str
);
7892 /* Line 5 display Extended-community */
7893 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7895 json_ext_community
= json_object_new_object();
7896 json_object_string_add(json_ext_community
,
7898 attr
->ecommunity
->str
);
7899 json_object_object_add(json_path
,
7900 "extendedCommunity",
7901 json_ext_community
);
7903 vty_out(vty
, " Extended Community: %s\n",
7904 attr
->ecommunity
->str
);
7908 /* Line 6 display Large community */
7909 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7911 json_lcommunity
= json_object_new_object();
7912 json_object_string_add(json_lcommunity
,
7914 attr
->lcommunity
->str
);
7915 json_object_object_add(json_path
,
7919 vty_out(vty
, " Large Community: %s\n",
7920 attr
->lcommunity
->str
);
7924 /* Line 7 display Originator, Cluster-id */
7925 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7926 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7928 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7930 json_object_string_add(
7931 json_path
, "originatorId",
7932 inet_ntoa(attr
->originator_id
));
7934 vty_out(vty
, " Originator: %s",
7935 inet_ntoa(attr
->originator_id
));
7938 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7943 json_object_new_object();
7944 json_cluster_list_list
=
7945 json_object_new_array();
7948 i
< attr
->cluster
->length
/ 4;
7950 json_string
= json_object_new_string(
7954 json_object_array_add(
7955 json_cluster_list_list
,
7959 /* struct cluster_list does not have
7961 * aspath and community do. Add this
7964 json_object_string_add(json_cluster_list,
7965 "string", attr->cluster->str);
7967 json_object_object_add(
7968 json_cluster_list
, "list",
7969 json_cluster_list_list
);
7970 json_object_object_add(
7971 json_path
, "clusterList",
7974 vty_out(vty
, ", Cluster list: ");
7977 i
< attr
->cluster
->length
/ 4;
7991 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7992 bgp_damp_info_vty(vty
, binfo
, json_path
);
7995 #if defined(HAVE_CUMULUS)
7996 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7997 && safi
!= SAFI_EVPN
)
7999 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
8002 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
8004 json_object_int_add(json_path
, "remoteLabel",
8007 vty_out(vty
, " Remote label: %d\n", label
);
8011 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8013 json_object_int_add(json_path
, "labelIndex",
8016 vty_out(vty
, " Label Index: %d\n",
8020 /* Line 8 display Addpath IDs */
8021 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
8023 json_object_int_add(json_path
, "addpathRxId",
8024 binfo
->addpath_rx_id
);
8025 json_object_int_add(json_path
, "addpathTxId",
8026 binfo
->addpath_tx_id
);
8028 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8029 binfo
->addpath_rx_id
,
8030 binfo
->addpath_tx_id
);
8034 /* If we used addpath to TX a non-bestpath we need to display
8035 * "Advertised to" on a path-by-path basis */
8036 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8039 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8041 bgp_addpath_encode_tx(peer
, afi
, safi
);
8042 has_adj
= bgp_adj_out_lookup(
8043 peer
, binfo
->net
, binfo
->addpath_tx_id
);
8045 if ((addpath_capable
&& has_adj
)
8046 || (!addpath_capable
&& has_adj
8047 && CHECK_FLAG(binfo
->flags
,
8048 BGP_INFO_SELECTED
))) {
8049 if (json_path
&& !json_adv_to
)
8051 json_object_new_object();
8053 route_vty_out_advertised_to(
8062 json_object_object_add(json_path
,
8073 /* Line 9 display Uptime */
8074 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
8076 json_last_update
= json_object_new_object();
8077 json_object_int_add(json_last_update
, "epoch", tbuf
);
8078 json_object_string_add(json_last_update
, "string",
8080 json_object_object_add(json_path
, "lastUpdate",
8083 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8086 /* We've constructed the json object for this path, add it to the json
8090 if (json_nexthop_global
|| json_nexthop_ll
) {
8091 json_nexthops
= json_object_new_array();
8093 if (json_nexthop_global
)
8094 json_object_array_add(json_nexthops
,
8095 json_nexthop_global
);
8097 if (json_nexthop_ll
)
8098 json_object_array_add(json_nexthops
,
8101 json_object_object_add(json_path
, "nexthops",
8105 json_object_object_add(json_path
, "peer", json_peer
);
8106 json_object_array_add(json_paths
, json_path
);
8111 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8112 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8113 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8115 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8116 const char *prefix_list_str
, afi_t afi
,
8117 safi_t safi
, enum bgp_show_type type
);
8118 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8119 const char *filter
, afi_t afi
, safi_t safi
,
8120 enum bgp_show_type type
);
8121 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8122 const char *rmap_str
, afi_t afi
, safi_t safi
,
8123 enum bgp_show_type type
);
8124 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8125 const char *com
, int exact
, afi_t afi
,
8127 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8128 const char *prefix
, afi_t afi
, safi_t safi
,
8129 enum bgp_show_type type
);
8130 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
8131 const char *regstr
, afi_t afi
,
8132 safi_t safi
, enum bgp_show_type type
);
8133 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8134 const char *comstr
, int exact
, afi_t afi
,
8138 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8139 struct bgp_table
*table
, enum bgp_show_type type
,
8140 void *output_arg
, u_char use_json
,
8141 char *rd
, int is_last
,
8142 unsigned long *output_cum
, unsigned long *total_cum
)
8144 struct bgp_info
*ri
;
8145 struct bgp_node
*rn
;
8148 unsigned long output_count
= 0;
8149 unsigned long total_count
= 0;
8153 json_object
*json_paths
= NULL
;
8156 if (output_cum
&& *output_cum
!= 0)
8159 if (use_json
&& header
) {
8161 "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64
8162 ", \"routerId\": \"%s\", \"routes\": { ",
8163 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
8164 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
8166 table
->version
, inet_ntoa(bgp
->router_id
));
8168 vty_out(vty
, " \"routeDistinguishers\" : {");
8169 json_paths
= json_object_new_object();
8172 if (use_json
&& rd
) {
8173 vty_out(vty
, " \"%s\" : { ", rd
);
8176 /* Start processing of routes. */
8177 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8178 if (rn
->info
== NULL
)
8182 if (!first
&& use_json
)
8185 json_paths
= json_object_new_array();
8189 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8191 if (type
== bgp_show_type_flap_statistics
8192 || type
== bgp_show_type_flap_neighbor
8193 || type
== bgp_show_type_dampend_paths
8194 || type
== bgp_show_type_damp_neighbor
) {
8196 && ri
->extra
->damp_info
))
8199 if (type
== bgp_show_type_regexp
) {
8200 regex_t
*regex
= output_arg
;
8202 if (bgp_regexec(regex
, ri
->attr
->aspath
)
8206 if (type
== bgp_show_type_prefix_list
) {
8207 struct prefix_list
*plist
= output_arg
;
8209 if (prefix_list_apply(plist
, &rn
->p
)
8213 if (type
== bgp_show_type_filter_list
) {
8214 struct as_list
*as_list
= output_arg
;
8216 if (as_list_apply(as_list
, ri
->attr
->aspath
)
8217 != AS_FILTER_PERMIT
)
8220 if (type
== bgp_show_type_route_map
) {
8221 struct route_map
*rmap
= output_arg
;
8222 struct bgp_info binfo
;
8223 struct attr dummy_attr
;
8226 bgp_attr_dup(&dummy_attr
, ri
->attr
);
8228 binfo
.peer
= ri
->peer
;
8229 binfo
.attr
= &dummy_attr
;
8231 ret
= route_map_apply(rmap
, &rn
->p
,
8233 if (ret
== RMAP_DENYMATCH
)
8236 if (type
== bgp_show_type_neighbor
8237 || type
== bgp_show_type_flap_neighbor
8238 || type
== bgp_show_type_damp_neighbor
) {
8239 union sockunion
*su
= output_arg
;
8241 if (ri
->peer
== NULL
8242 || ri
->peer
->su_remote
== NULL
8243 || !sockunion_same(ri
->peer
->su_remote
,
8247 if (type
== bgp_show_type_cidr_only
) {
8248 u_int32_t destination
;
8250 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8251 if (IN_CLASSC(destination
)
8252 && rn
->p
.prefixlen
== 24)
8254 if (IN_CLASSB(destination
)
8255 && rn
->p
.prefixlen
== 16)
8257 if (IN_CLASSA(destination
)
8258 && rn
->p
.prefixlen
== 8)
8261 if (type
== bgp_show_type_prefix_longer
) {
8262 struct prefix
*p
= output_arg
;
8264 if (!prefix_match(p
, &rn
->p
))
8267 if (type
== bgp_show_type_community_all
) {
8268 if (!ri
->attr
->community
)
8271 if (type
== bgp_show_type_community
) {
8272 struct community
*com
= output_arg
;
8274 if (!ri
->attr
->community
8275 || !community_match(ri
->attr
->community
,
8279 if (type
== bgp_show_type_community_exact
) {
8280 struct community
*com
= output_arg
;
8282 if (!ri
->attr
->community
8283 || !community_cmp(ri
->attr
->community
,
8287 if (type
== bgp_show_type_community_list
) {
8288 struct community_list
*list
= output_arg
;
8290 if (!community_list_match(
8291 ri
->attr
->community
, list
))
8295 == bgp_show_type_community_list_exact
) {
8296 struct community_list
*list
= output_arg
;
8298 if (!community_list_exact_match(
8299 ri
->attr
->community
, list
))
8302 if (type
== bgp_show_type_lcommunity
) {
8303 struct lcommunity
*lcom
= output_arg
;
8305 if (!ri
->attr
->lcommunity
8306 || !lcommunity_match(ri
->attr
->lcommunity
,
8310 if (type
== bgp_show_type_lcommunity_list
) {
8311 struct community_list
*list
= output_arg
;
8313 if (!lcommunity_list_match(
8314 ri
->attr
->lcommunity
, list
))
8317 if (type
== bgp_show_type_lcommunity_all
) {
8318 if (!ri
->attr
->lcommunity
)
8321 if (type
== bgp_show_type_dampend_paths
8322 || type
== bgp_show_type_damp_neighbor
) {
8323 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8324 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8328 if (!use_json
&& header
) {
8330 "BGP table version is %" PRIu64
8331 ", local router ID is %s\n",
8333 inet_ntoa(bgp
->router_id
));
8334 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8335 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8336 if (type
== bgp_show_type_dampend_paths
8337 || type
== bgp_show_type_damp_neighbor
)
8338 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8340 type
== bgp_show_type_flap_statistics
8341 || type
== bgp_show_type_flap_neighbor
)
8342 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8344 vty_out(vty
, BGP_SHOW_HEADER
);
8347 if (rd
!= NULL
&& !display
&& !output_count
) {
8350 "Route Distinguisher: %s\n",
8353 if (type
== bgp_show_type_dampend_paths
8354 || type
== bgp_show_type_damp_neighbor
)
8355 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8358 else if (type
== bgp_show_type_flap_statistics
8359 || type
== bgp_show_type_flap_neighbor
)
8360 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8364 route_vty_out(vty
, &rn
->p
, ri
, display
,
8375 sprintf(buf2
, "%s/%d",
8376 inet_ntop(p
->family
, &p
->u
.prefix
,
8379 vty_out(vty
, "\"%s\": ", buf2
);
8381 json_object_to_json_string(json_paths
));
8382 json_object_free(json_paths
);
8388 output_count
+= *output_cum
;
8389 *output_cum
= output_count
;
8392 total_count
+= *total_cum
;
8393 *total_cum
= total_count
;
8396 json_object_free(json_paths
);
8398 vty_out(vty
, " } }\n");
8400 vty_out(vty
, " }, ");
8403 /* No route is displayed */
8404 if (output_count
== 0) {
8405 if (type
== bgp_show_type_normal
)
8407 "No BGP prefixes displayed, %ld exist\n",
8411 "\nDisplayed %ld routes and %ld total paths\n",
8412 output_count
, total_count
);
8419 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8420 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8421 enum bgp_show_type type
, void *output_arg
,
8424 struct bgp_node
*rn
, *next
;
8425 unsigned long output_cum
= 0;
8426 unsigned long total_cum
= 0;
8428 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8429 next
= bgp_route_next(rn
);
8430 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8432 if (rn
->info
!= NULL
) {
8433 struct prefix_rd prd
;
8436 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8437 if (prefix_rd2str(&prd
, rd
, BUFSIZ
) == NULL
)
8440 decode_rd_type(prd
.val
));
8441 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8442 output_arg
, use_json
,
8444 &output_cum
, &total_cum
);
8448 vty_out(vty
, " } }");
8451 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8452 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8454 struct bgp_table
*table
;
8457 bgp
= bgp_get_default();
8462 vty_out(vty
, "No BGP process is configured\n");
8464 vty_out(vty
, "{}\n");
8468 table
= bgp
->rib
[afi
][safi
];
8469 /* use MPLS and ENCAP specific shows until they are merged */
8470 if (safi
== SAFI_MPLS_VPN
) {
8471 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8472 output_arg
, use_json
);
8474 /* labeled-unicast routes live in the unicast table */
8475 else if (safi
== SAFI_LABELED_UNICAST
)
8476 safi
= SAFI_UNICAST
;
8478 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8479 NULL
, 1, NULL
, NULL
);
8482 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8483 safi_t safi
, u_char use_json
)
8485 struct listnode
*node
, *nnode
;
8490 vty_out(vty
, "{\n");
8492 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8495 vty_out(vty
, ",\n");
8499 vty_out(vty
, "\"%s\":",
8500 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8504 vty_out(vty
, "\nInstance %s:\n",
8505 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8509 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8514 vty_out(vty
, "}\n");
8517 /* Header of detailed BGP route information */
8518 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8519 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8520 afi_t afi
, safi_t safi
, json_object
*json
)
8522 struct bgp_info
*ri
;
8525 struct listnode
*node
, *nnode
;
8526 char buf1
[INET6_ADDRSTRLEN
];
8527 char buf2
[INET6_ADDRSTRLEN
];
8528 #if defined(HAVE_CUMULUS)
8529 char buf3
[EVPN_ROUTE_STRLEN
];
8531 char prefix_str
[BUFSIZ
];
8536 int no_advertise
= 0;
8539 int has_valid_label
= 0;
8540 mpls_label_t label
= 0;
8541 json_object
*json_adv_to
= NULL
;
8544 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8546 if (has_valid_label
)
8547 label
= label_pton(&rn
->local_label
);
8550 if (has_valid_label
)
8551 json_object_int_add(json
, "localLabel", label
);
8553 json_object_string_add(
8555 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8557 #if defined(HAVE_CUMULUS)
8558 if (safi
== SAFI_EVPN
)
8559 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8560 prd
? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8563 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8564 buf3
, sizeof(buf3
)));
8566 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8567 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8568 ? prefix_rd2str(prd
, buf1
,
8571 safi
== SAFI_MPLS_VPN
? ":" : "",
8572 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8576 if (p
->family
== AF_ETHERNET
)
8577 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8579 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8581 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8582 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8583 || safi
== SAFI_EVPN
)
8584 ? prefix_rd2str(prd
, buf1
, RD_ADDRSTRLEN
)
8586 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8588 buf2
, p
->prefixlen
);
8591 if (has_valid_label
)
8592 vty_out(vty
, "Local label: %d\n", label
);
8593 #if defined(HAVE_CUMULUS)
8594 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8596 if (bgp_labeled_safi(safi
))
8598 vty_out(vty
, "not allocated\n");
8601 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8603 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8605 if (ri
->extra
&& ri
->extra
->suppress
)
8607 if (ri
->attr
->community
!= NULL
) {
8608 if (community_include(ri
->attr
->community
,
8609 COMMUNITY_NO_ADVERTISE
))
8611 if (community_include(ri
->attr
->community
,
8612 COMMUNITY_NO_EXPORT
))
8614 if (community_include(ri
->attr
->community
,
8615 COMMUNITY_LOCAL_AS
))
8622 vty_out(vty
, "Paths: (%d available", count
);
8624 vty_out(vty
, ", best #%d", best
);
8625 if (safi
== SAFI_UNICAST
)
8626 vty_out(vty
, ", table %s",
8628 == BGP_INSTANCE_TYPE_DEFAULT
)
8629 ? "Default-IP-Routing-Table"
8632 vty_out(vty
, ", no best path");
8635 vty_out(vty
, ", not advertised to any peer");
8637 vty_out(vty
, ", not advertised to EBGP peer");
8639 vty_out(vty
, ", not advertised outside local AS");
8643 ", Advertisements suppressed by an aggregate.");
8644 vty_out(vty
, ")\n");
8647 /* If we are not using addpath then we can display Advertised to and
8649 * show what peers we advertised the bestpath to. If we are using
8651 * though then we must display Advertised to on a path-by-path basis. */
8652 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8653 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8654 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8655 if (json
&& !json_adv_to
)
8656 json_adv_to
= json_object_new_object();
8658 route_vty_out_advertised_to(
8660 " Advertised to non peer-group peers:\n ",
8667 json_object_object_add(json
, "advertisedTo",
8672 vty_out(vty
, " Not advertised to any peer");
8678 /* Display specified route of BGP table. */
8679 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8680 struct bgp_table
*rib
, const char *ip_str
,
8681 afi_t afi
, safi_t safi
,
8682 struct prefix_rd
*prd
, int prefix_check
,
8683 enum bgp_path_type pathtype
, u_char use_json
)
8688 struct prefix match
;
8689 struct bgp_node
*rn
;
8690 struct bgp_node
*rm
;
8691 struct bgp_info
*ri
;
8692 struct bgp_table
*table
;
8693 json_object
*json
= NULL
;
8694 json_object
*json_paths
= NULL
;
8696 /* Check IP address argument. */
8697 ret
= str2prefix(ip_str
, &match
);
8699 vty_out(vty
, "address is malformed\n");
8703 match
.family
= afi2family(afi
);
8706 json
= json_object_new_object();
8707 json_paths
= json_object_new_array();
8710 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8711 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8712 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8715 if ((table
= rn
->info
) == NULL
)
8720 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8724 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8725 bgp_unlock_node(rm
);
8729 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8731 route_vty_out_detail_header(
8733 (struct prefix_rd
*)&rn
->p
,
8734 AFI_IP
, safi
, json
);
8739 if (pathtype
== BGP_PATH_ALL
8740 || (pathtype
== BGP_PATH_BESTPATH
8741 && CHECK_FLAG(ri
->flags
,
8743 || (pathtype
== BGP_PATH_MULTIPATH
8744 && (CHECK_FLAG(ri
->flags
,
8746 || CHECK_FLAG(ri
->flags
,
8747 BGP_INFO_SELECTED
))))
8748 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8753 bgp_unlock_node(rm
);
8758 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8760 || rn
->p
.prefixlen
== match
.prefixlen
) {
8761 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8763 route_vty_out_detail_header(
8764 vty
, bgp
, rn
, NULL
, afi
,
8770 if (pathtype
== BGP_PATH_ALL
8771 || (pathtype
== BGP_PATH_BESTPATH
8775 || (pathtype
== BGP_PATH_MULTIPATH
8781 BGP_INFO_SELECTED
))))
8782 route_vty_out_detail(
8783 vty
, bgp
, &rn
->p
, ri
,
8784 afi
, safi
, json_paths
);
8788 bgp_unlock_node(rn
);
8794 json_object_object_add(json
, "paths", json_paths
);
8796 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8797 json
, JSON_C_TO_STRING_PRETTY
));
8798 json_object_free(json
);
8801 vty_out(vty
, "%% Network not in table\n");
8809 /* Display specified route of Main RIB */
8810 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8811 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8812 int prefix_check
, enum bgp_path_type pathtype
,
8816 bgp
= bgp_get_default();
8819 vty_out(vty
, "No BGP process is configured\n");
8821 vty_out(vty
, "{}\n");
8826 /* labeled-unicast routes live in the unicast table */
8827 if (safi
== SAFI_LABELED_UNICAST
)
8828 safi
= SAFI_UNICAST
;
8830 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8831 afi
, safi
, prd
, prefix_check
, pathtype
,
8835 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8836 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8839 struct lcommunity
*lcom
;
8845 b
= buffer_new(1024);
8846 for (i
= 0; i
< argc
; i
++) {
8848 buffer_putc(b
, ' ');
8850 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8852 buffer_putstr(b
, argv
[i
]->arg
);
8856 buffer_putc(b
, '\0');
8858 str
= buffer_getstr(b
);
8861 lcom
= lcommunity_str2com(str
);
8862 XFREE(MTYPE_TMP
, str
);
8864 vty_out(vty
, "%% Large-community malformed\n");
8868 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8872 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8873 const char *lcom
, afi_t afi
, safi_t safi
,
8876 struct community_list
*list
;
8878 list
= community_list_lookup(bgp_clist
, lcom
,
8879 LARGE_COMMUNITY_LIST_MASTER
);
8881 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8886 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8890 DEFUN (show_ip_bgp_large_community_list
,
8891 show_ip_bgp_large_community_list_cmd
,
8892 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8896 BGP_INSTANCE_HELP_STR
8898 BGP_SAFI_WITH_LABEL_HELP_STR
8899 "Display routes matching the large-community-list\n"
8900 "large-community-list number\n"
8901 "large-community-list name\n"
8905 afi_t afi
= AFI_IP6
;
8906 safi_t safi
= SAFI_UNICAST
;
8909 if (argv_find(argv
, argc
, "ip", &idx
))
8911 if (argv_find(argv
, argc
, "view", &idx
)
8912 || argv_find(argv
, argc
, "vrf", &idx
))
8913 vrf
= argv
[++idx
]->arg
;
8914 if (argv_find(argv
, argc
, "ipv4", &idx
)
8915 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8916 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8917 if (argv_find(argv
, argc
, "unicast", &idx
)
8918 || argv_find(argv
, argc
, "multicast", &idx
))
8919 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8922 int uj
= use_json(argc
, argv
);
8924 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8926 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8930 argv_find(argv
, argc
, "large-community-list", &idx
);
8931 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8934 DEFUN (show_ip_bgp_large_community
,
8935 show_ip_bgp_large_community_cmd
,
8936 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8940 BGP_INSTANCE_HELP_STR
8942 BGP_SAFI_WITH_LABEL_HELP_STR
8943 "Display routes matching the large-communities\n"
8944 "List of large-community numbers\n"
8948 afi_t afi
= AFI_IP6
;
8949 safi_t safi
= SAFI_UNICAST
;
8952 if (argv_find(argv
, argc
, "ip", &idx
))
8954 if (argv_find(argv
, argc
, "view", &idx
)
8955 || argv_find(argv
, argc
, "vrf", &idx
))
8956 vrf
= argv
[++idx
]->arg
;
8957 if (argv_find(argv
, argc
, "ipv4", &idx
)
8958 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8959 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8960 if (argv_find(argv
, argc
, "unicast", &idx
)
8961 || argv_find(argv
, argc
, "multicast", &idx
))
8962 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8965 int uj
= use_json(argc
, argv
);
8967 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8969 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8973 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8974 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8976 return bgp_show(vty
, bgp
, afi
, safi
,
8977 bgp_show_type_lcommunity_all
, NULL
, uj
);
8980 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8984 /* BGP route print out function without JSON */
8987 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8988 <dampening <parameters>\
8993 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
8994 |community-list <(1-500)|WORD> [exact-match]\
8995 |A.B.C.D/M longer-prefixes\
8996 |X:X::X:X/M longer-prefixes\
9001 BGP_INSTANCE_HELP_STR
9003 BGP_SAFI_WITH_LABEL_HELP_STR
9004 "Display detailed information about dampening\n"
9005 "Display detail of configured dampening parameters\n"
9006 "Display routes matching the route-map\n"
9007 "A route-map to match on\n"
9008 "Display routes conforming to the prefix-list\n"
9009 "Prefix-list name\n"
9010 "Display routes conforming to the filter-list\n"
9011 "Regular expression access list name\n"
9012 "BGP RIB advertisement statistics\n"
9013 "Display routes matching the communities\n"
9015 "Do not send outside local AS (well-known community)\n"
9016 "Do not advertise to any peer (well-known community)\n"
9017 "Do not export to next AS (well-known community)\n"
9018 "Graceful shutdown (well-known community)\n"
9019 "Exact match of the communities\n"
9020 "Display routes matching the community-list\n"
9021 "community-list number\n"
9022 "community-list name\n"
9023 "Exact match of the communities\n"
9025 "Display route and more specific routes\n"
9027 "Display route and more specific routes\n")
9029 afi_t afi
= AFI_IP6
;
9030 safi_t safi
= SAFI_UNICAST
;
9031 int exact_match
= 0;
9032 struct bgp
*bgp
= NULL
;
9034 int idx_community_type
= 0;
9036 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9041 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9042 if (argv_find(argv
, argc
, "parameters", &idx
))
9043 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9046 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9047 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9048 safi
, bgp_show_type_prefix_list
);
9050 if (argv_find(argv
, argc
, "filter-list", &idx
))
9051 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9052 safi
, bgp_show_type_filter_list
);
9054 if (argv_find(argv
, argc
, "statistics", &idx
))
9055 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9057 if (argv_find(argv
, argc
, "route-map", &idx
))
9058 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9059 safi
, bgp_show_type_route_map
);
9061 if (argv_find(argv
, argc
, "community", &idx
)) {
9062 /* show a specific community */
9063 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
9064 || argv_find(argv
, argc
, "no-advertise", &idx_community_type
)
9065 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
9066 || argv_find(argv
, argc
, "graceful-shutdown", &idx_community_type
)
9067 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
9069 if (argv_find(argv
, argc
, "exact-match", &idx
))
9071 return bgp_show_community(vty
, bgp
, argv
[idx_community_type
]->arg
,
9072 exact_match
, afi
, safi
);
9076 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9077 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9078 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9080 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9081 exact_match
, afi
, safi
);
9084 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9085 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9086 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9088 bgp_show_type_prefix_longer
);
9093 /* BGP route print out function with JSON */
9094 DEFUN (show_ip_bgp_json
,
9095 show_ip_bgp_json_cmd
,
9096 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9099 |dampening <flap-statistics|dampened-paths>\
9105 BGP_INSTANCE_HELP_STR
9107 BGP_SAFI_WITH_LABEL_HELP_STR
9108 "Display only routes with non-natural netmasks\n"
9109 "Display detailed information about dampening\n"
9110 "Display flap statistics of routes\n"
9111 "Display paths suppressed due to dampening\n"
9112 "Display routes matching the communities\n"
9115 afi_t afi
= AFI_IP6
;
9116 safi_t safi
= SAFI_UNICAST
;
9117 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9118 struct bgp
*bgp
= NULL
;
9121 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9126 int uj
= use_json(argc
, argv
);
9130 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9131 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9134 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9135 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9136 return bgp_show(vty
, bgp
, afi
, safi
,
9137 bgp_show_type_dampend_paths
, NULL
, uj
);
9138 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9139 return bgp_show(vty
, bgp
, afi
, safi
,
9140 bgp_show_type_flap_statistics
, NULL
,
9144 if (argv_find(argv
, argc
, "community", &idx
)) {
9145 /* show all communities */
9146 return bgp_show(vty
, bgp
, afi
, safi
,
9147 bgp_show_type_community_all
, NULL
, uj
);
9149 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9152 DEFUN (show_ip_bgp_route
,
9153 show_ip_bgp_route_cmd
,
9154 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9155 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9159 BGP_INSTANCE_HELP_STR
9161 BGP_SAFI_WITH_LABEL_HELP_STR
9162 "Network in the BGP routing table to display\n"
9164 "Network in the BGP routing table to display\n"
9166 "Display only the bestpath\n"
9167 "Display only multipaths\n"
9170 int prefix_check
= 0;
9172 afi_t afi
= AFI_IP6
;
9173 safi_t safi
= SAFI_UNICAST
;
9174 char *prefix
= NULL
;
9175 struct bgp
*bgp
= NULL
;
9176 enum bgp_path_type path_type
;
9177 u_char uj
= use_json(argc
, argv
);
9181 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9188 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9192 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9193 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9194 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9196 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9197 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9200 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9201 && afi
!= AFI_IP6
) {
9203 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9206 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9209 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9213 prefix
= argv
[idx
]->arg
;
9215 /* [<bestpath|multipath>] */
9216 if (argv_find(argv
, argc
, "bestpath", &idx
))
9217 path_type
= BGP_PATH_BESTPATH
;
9218 else if (argv_find(argv
, argc
, "multipath", &idx
))
9219 path_type
= BGP_PATH_MULTIPATH
;
9221 path_type
= BGP_PATH_ALL
;
9223 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9227 DEFUN (show_ip_bgp_regexp
,
9228 show_ip_bgp_regexp_cmd
,
9229 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9233 BGP_INSTANCE_HELP_STR
9235 BGP_SAFI_WITH_LABEL_HELP_STR
9236 "Display routes matching the AS path regular expression\n"
9237 "A regular-expression to match the BGP AS paths\n")
9239 afi_t afi
= AFI_IP6
;
9240 safi_t safi
= SAFI_UNICAST
;
9241 struct bgp
*bgp
= NULL
;
9244 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9249 // get index of regex
9250 argv_find(argv
, argc
, "regexp", &idx
);
9253 char *regstr
= argv_concat(argv
, argc
, idx
);
9254 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9255 bgp_show_type_regexp
);
9256 XFREE(MTYPE_TMP
, regstr
);
9260 DEFUN (show_ip_bgp_instance_all
,
9261 show_ip_bgp_instance_all_cmd
,
9262 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9266 BGP_INSTANCE_ALL_HELP_STR
9268 BGP_SAFI_WITH_LABEL_HELP_STR
9272 safi_t safi
= SAFI_UNICAST
;
9273 struct bgp
*bgp
= NULL
;
9276 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9281 int uj
= use_json(argc
, argv
);
9285 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9289 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
9290 const char *regstr
, afi_t afi
,
9291 safi_t safi
, enum bgp_show_type type
)
9296 regex
= bgp_regcomp(regstr
);
9298 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9302 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9303 bgp_regex_free(regex
);
9307 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9308 const char *prefix_list_str
, afi_t afi
,
9309 safi_t safi
, enum bgp_show_type type
)
9311 struct prefix_list
*plist
;
9313 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9314 if (plist
== NULL
) {
9315 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9320 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9323 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9324 const char *filter
, afi_t afi
, safi_t safi
,
9325 enum bgp_show_type type
)
9327 struct as_list
*as_list
;
9329 as_list
= as_list_lookup(filter
);
9330 if (as_list
== NULL
) {
9331 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9336 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9339 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9340 const char *rmap_str
, afi_t afi
, safi_t safi
,
9341 enum bgp_show_type type
)
9343 struct route_map
*rmap
;
9345 rmap
= route_map_lookup_by_name(rmap_str
);
9347 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9351 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9354 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9355 const char *comstr
, int exact
, afi_t afi
,
9358 struct community
*com
;
9361 com
= community_str2com(comstr
);
9363 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9367 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9368 (exact
? bgp_show_type_community_exact
9369 : bgp_show_type_community
),
9371 community_free(com
);
9376 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9377 const char *com
, int exact
, afi_t afi
,
9380 struct community_list
*list
;
9382 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9384 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9388 return bgp_show(vty
, bgp
, afi
, safi
,
9389 (exact
? bgp_show_type_community_list_exact
9390 : bgp_show_type_community_list
),
9394 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9395 const char *prefix
, afi_t afi
, safi_t safi
,
9396 enum bgp_show_type type
)
9403 ret
= str2prefix(prefix
, p
);
9405 vty_out(vty
, "%% Malformed Prefix\n");
9409 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9414 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9415 const char *ip_str
, u_char use_json
)
9421 /* Get peer sockunion. */
9422 ret
= str2sockunion(ip_str
, &su
);
9424 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9426 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9430 json_object
*json_no
= NULL
;
9431 json_no
= json_object_new_object();
9432 json_object_string_add(
9434 "malformedAddressOrName",
9436 vty_out(vty
, "%s\n",
9437 json_object_to_json_string(
9439 json_object_free(json_no
);
9442 "%% Malformed address or name: %s\n",
9450 /* Peer structure lookup. */
9451 peer
= peer_lookup(bgp
, &su
);
9454 json_object
*json_no
= NULL
;
9455 json_no
= json_object_new_object();
9456 json_object_string_add(json_no
, "warning",
9457 "No such neighbor");
9458 vty_out(vty
, "%s\n",
9459 json_object_to_json_string(json_no
));
9460 json_object_free(json_no
);
9462 vty_out(vty
, "No such neighbor\n");
9470 BGP_STATS_MAXBITLEN
= 0,
9474 BGP_STATS_UNAGGREGATEABLE
,
9475 BGP_STATS_MAX_AGGREGATEABLE
,
9476 BGP_STATS_AGGREGATES
,
9478 BGP_STATS_ASPATH_COUNT
,
9479 BGP_STATS_ASPATH_MAXHOPS
,
9480 BGP_STATS_ASPATH_TOTHOPS
,
9481 BGP_STATS_ASPATH_MAXSIZE
,
9482 BGP_STATS_ASPATH_TOTSIZE
,
9483 BGP_STATS_ASN_HIGHEST
,
9487 static const char *table_stats_strs
[] = {
9488 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9489 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9490 [BGP_STATS_RIB
] = "Total Advertisements",
9491 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9492 [BGP_STATS_MAX_AGGREGATEABLE
] =
9493 "Maximum aggregateable prefixes",
9494 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9495 [BGP_STATS_SPACE
] = "Address space advertised",
9496 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9497 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9498 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9499 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9500 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9501 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9502 [BGP_STATS_MAX
] = NULL
,
9505 struct bgp_table_stats
{
9506 struct bgp_table
*table
;
9507 unsigned long long counts
[BGP_STATS_MAX
];
9512 #define TALLY_SIGFIG 100000
9513 static unsigned long
9514 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9516 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9517 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9518 unsigned long ret
= newtot
/ count
;
9520 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9527 static int bgp_table_stats_walker(struct thread
*t
)
9529 struct bgp_node
*rn
;
9530 struct bgp_node
*top
;
9531 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9532 unsigned int space
= 0;
9534 if (!(top
= bgp_table_top(ts
->table
)))
9537 switch (top
->p
.family
) {
9539 space
= IPV4_MAX_BITLEN
;
9542 space
= IPV6_MAX_BITLEN
;
9546 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9548 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9549 struct bgp_info
*ri
;
9550 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9551 unsigned int rinum
= 0;
9559 ts
->counts
[BGP_STATS_PREFIXES
]++;
9560 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9563 ts
->counts
[BGP_STATS_AVGPLEN
]
9564 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9565 ts
->counts
[BGP_STATS_AVGPLEN
],
9569 /* check if the prefix is included by any other announcements */
9570 while (prn
&& !prn
->info
)
9571 prn
= bgp_node_parent_nolock(prn
);
9573 if (prn
== NULL
|| prn
== top
) {
9574 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9575 /* announced address space */
9577 ts
->total_space
+= pow(2.0,
9578 space
- rn
->p
.prefixlen
);
9579 } else if (prn
->info
)
9580 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9582 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9584 ts
->counts
[BGP_STATS_RIB
]++;
9587 && (CHECK_FLAG(ri
->attr
->flag
,
9589 BGP_ATTR_ATOMIC_AGGREGATE
))))
9590 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9593 if (ri
->attr
&& ri
->attr
->aspath
) {
9595 aspath_count_hops(ri
->attr
->aspath
);
9597 aspath_size(ri
->attr
->aspath
);
9598 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9600 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9602 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9603 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9606 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9607 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9610 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9611 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9613 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9614 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9615 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9617 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9618 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9619 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9622 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9623 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9631 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9634 struct bgp_table_stats ts
;
9637 if (!bgp
->rib
[afi
][safi
]) {
9638 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9643 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9645 /* labeled-unicast routes live in the unicast table */
9646 if (safi
== SAFI_LABELED_UNICAST
)
9647 safi
= SAFI_UNICAST
;
9649 memset(&ts
, 0, sizeof(ts
));
9650 ts
.table
= bgp
->rib
[afi
][safi
];
9651 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9653 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9654 if (!table_stats_strs
[i
])
9659 case BGP_STATS_ASPATH_AVGHOPS
:
9660 case BGP_STATS_ASPATH_AVGSIZE
:
9661 case BGP_STATS_AVGPLEN
:
9662 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9663 vty_out (vty
, "%12.2f",
9664 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9667 case BGP_STATS_ASPATH_TOTHOPS
:
9668 case BGP_STATS_ASPATH_TOTSIZE
:
9669 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9670 vty_out(vty
, "%12.2f",
9672 ? (float)ts
.counts
[i
]
9674 [BGP_STATS_ASPATH_COUNT
]
9677 case BGP_STATS_TOTPLEN
:
9678 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9679 vty_out(vty
, "%12.2f",
9681 ? (float)ts
.counts
[i
]
9683 [BGP_STATS_PREFIXES
]
9686 case BGP_STATS_SPACE
:
9687 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9688 vty_out(vty
, "%12g\n", ts
.total_space
);
9690 if (afi
== AFI_IP6
) {
9691 vty_out(vty
, "%30s: ", "/32 equivalent ");
9692 vty_out(vty
, "%12g\n",
9693 ts
.total_space
* pow(2.0, -128+32));
9694 vty_out(vty
, "%30s: ", "/48 equivalent ");
9695 vty_out(vty
, "%12g\n",
9696 ts
.total_space
* pow(2.0, -128+48));
9698 vty_out(vty
, "%30s: ", "% announced ");
9699 vty_out(vty
, "%12.2f\n",
9700 ts
.total_space
* 100. * pow(2.0, -32));
9701 vty_out(vty
, "%30s: ", "/8 equivalent ");
9702 vty_out(vty
, "%12.2f\n",
9703 ts
.total_space
* pow(2.0, -32+8));
9704 vty_out(vty
, "%30s: ", "/24 equivalent ");
9705 vty_out(vty
, "%12.2f\n",
9706 ts
.total_space
* pow(2.0, -32+24));
9710 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9711 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9728 PCOUNT_PFCNT
, /* the figure we display to users */
9732 static const char *pcount_strs
[] = {
9733 [PCOUNT_ADJ_IN
] = "Adj-in",
9734 [PCOUNT_DAMPED
] = "Damped",
9735 [PCOUNT_REMOVED
] = "Removed",
9736 [PCOUNT_HISTORY
] = "History",
9737 [PCOUNT_STALE
] = "Stale",
9738 [PCOUNT_VALID
] = "Valid",
9739 [PCOUNT_ALL
] = "All RIB",
9740 [PCOUNT_COUNTED
] = "PfxCt counted",
9741 [PCOUNT_PFCNT
] = "Useable",
9742 [PCOUNT_MAX
] = NULL
,
9745 struct peer_pcounts
{
9746 unsigned int count
[PCOUNT_MAX
];
9747 const struct peer
*peer
;
9748 const struct bgp_table
*table
;
9751 static int bgp_peer_count_walker(struct thread
*t
)
9753 struct bgp_node
*rn
;
9754 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9755 const struct peer
*peer
= pc
->peer
;
9757 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9758 struct bgp_adj_in
*ain
;
9759 struct bgp_info
*ri
;
9761 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9762 if (ain
->peer
== peer
)
9763 pc
->count
[PCOUNT_ADJ_IN
]++;
9765 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9766 char buf
[SU_ADDRSTRLEN
];
9768 if (ri
->peer
!= peer
)
9771 pc
->count
[PCOUNT_ALL
]++;
9773 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9774 pc
->count
[PCOUNT_DAMPED
]++;
9775 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9776 pc
->count
[PCOUNT_HISTORY
]++;
9777 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9778 pc
->count
[PCOUNT_REMOVED
]++;
9779 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9780 pc
->count
[PCOUNT_STALE
]++;
9781 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9782 pc
->count
[PCOUNT_VALID
]++;
9783 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9784 pc
->count
[PCOUNT_PFCNT
]++;
9786 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9787 pc
->count
[PCOUNT_COUNTED
]++;
9788 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9790 "%s [pcount] %s/%d is counted but flags 0x%x",
9792 inet_ntop(rn
->p
.family
,
9793 &rn
->p
.u
.prefix
, buf
,
9795 rn
->p
.prefixlen
, ri
->flags
);
9797 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9799 "%s [pcount] %s/%d not counted but flags 0x%x",
9801 inet_ntop(rn
->p
.family
,
9802 &rn
->p
.u
.prefix
, buf
,
9804 rn
->p
.prefixlen
, ri
->flags
);
9811 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9812 safi_t safi
, u_char use_json
)
9814 struct peer_pcounts pcounts
= {.peer
= peer
};
9816 json_object
*json
= NULL
;
9817 json_object
*json_loop
= NULL
;
9820 json
= json_object_new_object();
9821 json_loop
= json_object_new_object();
9824 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9825 || !peer
->bgp
->rib
[afi
][safi
]) {
9827 json_object_string_add(
9829 "No such neighbor or address family");
9830 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9831 json_object_free(json
);
9833 vty_out(vty
, "%% No such neighbor or address family\n");
9838 memset(&pcounts
, 0, sizeof(pcounts
));
9839 pcounts
.peer
= peer
;
9840 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9842 /* in-place call via thread subsystem so as to record execution time
9843 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9844 * * on just vty_read()).
9846 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9849 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9850 json_object_string_add(json
, "multiProtocol",
9851 afi_safi_print(afi
, safi
));
9852 json_object_int_add(json
, "pfxCounter",
9853 peer
->pcount
[afi
][safi
]);
9855 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9856 json_object_int_add(json_loop
, pcount_strs
[i
],
9859 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9861 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9862 json_object_string_add(json
, "pfxctDriftFor",
9864 json_object_string_add(
9865 json
, "recommended",
9866 "Please report this bug, with the above command output");
9868 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9869 json_object_free(json
);
9873 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9874 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9875 peer
->hostname
, peer
->host
,
9876 afi_safi_print(afi
, safi
));
9878 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9879 afi_safi_print(afi
, safi
));
9882 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9883 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9885 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9886 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9889 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9890 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9892 "Please report this bug, with the above command output\n");
9899 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9900 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9901 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9902 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9906 BGP_INSTANCE_HELP_STR
9909 "Detailed information on TCP and BGP neighbor connections\n"
9910 "Neighbor to display information about\n"
9911 "Neighbor to display information about\n"
9912 "Neighbor on BGP configured interface\n"
9913 "Display detailed prefix count information\n"
9916 afi_t afi
= AFI_IP6
;
9917 safi_t safi
= SAFI_UNICAST
;
9920 struct bgp
*bgp
= NULL
;
9922 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9927 int uj
= use_json(argc
, argv
);
9931 argv_find(argv
, argc
, "neighbors", &idx
);
9932 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9936 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9939 #ifdef KEEP_OLD_VPN_COMMANDS
9940 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9941 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9942 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9947 "Display information about all VPNv4 NLRIs\n"
9948 "Detailed information on TCP and BGP neighbor connections\n"
9949 "Neighbor to display information about\n"
9950 "Neighbor to display information about\n"
9951 "Neighbor on BGP configured interface\n"
9952 "Display detailed prefix count information\n"
9957 u_char uj
= use_json(argc
, argv
);
9959 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9963 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9966 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9967 show_ip_bgp_vpn_all_route_prefix_cmd
,
9968 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9973 "Display information about all VPNv4 NLRIs\n"
9974 "Network in the BGP routing table to display\n"
9975 "Network in the BGP routing table to display\n"
9979 char *network
= NULL
;
9980 struct bgp
*bgp
= bgp_get_default();
9982 vty_out(vty
, "Can't find default instance\n");
9986 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9987 network
= argv
[idx
]->arg
;
9988 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9989 network
= argv
[idx
]->arg
;
9991 vty_out(vty
, "Unable to figure out Network\n");
9995 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9996 BGP_PATH_ALL
, use_json(argc
, argv
));
9998 #endif /* KEEP_OLD_VPN_COMMANDS */
10000 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10001 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10002 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10008 "Display information about all EVPN NLRIs\n"
10009 "Network in the BGP routing table to display\n"
10010 "Network in the BGP routing table to display\n"
10014 char *network
= NULL
;
10016 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10017 network
= argv
[idx
]->arg
;
10018 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10019 network
= argv
[idx
]->arg
;
10021 vty_out(vty
, "Unable to figure out Network\n");
10022 return CMD_WARNING
;
10024 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10025 BGP_PATH_ALL
, use_json(argc
, argv
));
10028 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10029 safi_t safi
, int in
, const char *rmap_name
,
10030 u_char use_json
, json_object
*json
)
10032 struct bgp_table
*table
;
10033 struct bgp_adj_in
*ain
;
10034 struct bgp_adj_out
*adj
;
10035 unsigned long output_count
;
10036 unsigned long filtered_count
;
10037 struct bgp_node
*rn
;
10043 struct update_subgroup
*subgrp
;
10044 json_object
*json_scode
= NULL
;
10045 json_object
*json_ocode
= NULL
;
10046 json_object
*json_ar
= NULL
;
10047 struct peer_af
*paf
;
10050 json_scode
= json_object_new_object();
10051 json_ocode
= json_object_new_object();
10052 json_ar
= json_object_new_object();
10054 json_object_string_add(json_scode
, "suppressed", "s");
10055 json_object_string_add(json_scode
, "damped", "d");
10056 json_object_string_add(json_scode
, "history", "h");
10057 json_object_string_add(json_scode
, "valid", "*");
10058 json_object_string_add(json_scode
, "best", ">");
10059 json_object_string_add(json_scode
, "multipath", "=");
10060 json_object_string_add(json_scode
, "internal", "i");
10061 json_object_string_add(json_scode
, "ribFailure", "r");
10062 json_object_string_add(json_scode
, "stale", "S");
10063 json_object_string_add(json_scode
, "removed", "R");
10065 json_object_string_add(json_ocode
, "igp", "i");
10066 json_object_string_add(json_ocode
, "egp", "e");
10067 json_object_string_add(json_ocode
, "incomplete", "?");
10074 json_object_string_add(json
, "alert", "no BGP");
10075 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10076 json_object_free(json
);
10078 vty_out(vty
, "%% No bgp\n");
10082 table
= bgp
->rib
[afi
][safi
];
10084 output_count
= filtered_count
= 0;
10085 subgrp
= peer_subgroup(peer
, afi
, safi
);
10088 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10090 json_object_int_add(json
, "bgpTableVersion",
10092 json_object_string_add(json
, "bgpLocalRouterId",
10093 inet_ntoa(bgp
->router_id
));
10094 json_object_object_add(json
, "bgpStatusCodes",
10096 json_object_object_add(json
, "bgpOriginCodes",
10098 json_object_string_add(json
,
10099 "bgpOriginatingDefaultNetwork",
10102 vty_out(vty
, "BGP table version is %" PRIu64
10103 ", local router ID is %s\n",
10104 table
->version
, inet_ntoa(bgp
->router_id
));
10105 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10106 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10108 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
10113 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10115 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10116 if (ain
->peer
!= peer
)
10120 json_object_int_add(
10121 json
, "bgpTableVersion",
10123 json_object_string_add(
10125 "bgpLocalRouterId",
10128 json_object_object_add(
10129 json
, "bgpStatusCodes",
10131 json_object_object_add(
10132 json
, "bgpOriginCodes",
10136 "BGP table version is 0, local router ID is %s\n",
10140 BGP_SHOW_SCODE_HEADER
);
10142 BGP_SHOW_OCODE_HEADER
);
10148 vty_out(vty
, BGP_SHOW_HEADER
);
10152 bgp_attr_dup(&attr
, ain
->attr
);
10153 if (bgp_input_modifier(peer
, &rn
->p
,
10157 route_vty_out_tmp(vty
, &rn
->p
,
10167 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10168 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
)
10169 if (paf
->peer
== peer
) {
10172 json_object_int_add(
10176 json_object_string_add(
10178 "bgpLocalRouterId",
10181 json_object_object_add(
10185 json_object_object_add(
10191 "BGP table version is %" PRIu64
10192 ", local router ID is %s\n",
10197 BGP_SHOW_SCODE_HEADER
);
10199 BGP_SHOW_OCODE_HEADER
);
10212 bgp_attr_dup(&attr
,
10214 ret
= bgp_output_modifier(
10219 if (ret
!= RMAP_DENY
) {
10235 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10237 if (output_count
!= 0) {
10239 json_object_int_add(json
, "totalPrefixCounter",
10242 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10246 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10247 json_object_free(json
);
10251 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10252 safi_t safi
, int in
, const char *rmap_name
,
10255 json_object
*json
= NULL
;
10258 json
= json_object_new_object();
10260 /* labeled-unicast routes live in the unicast table */
10261 if (safi
== SAFI_LABELED_UNICAST
)
10262 safi
= SAFI_UNICAST
;
10264 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10266 json_object_string_add(
10268 "No such neighbor or address family");
10269 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10270 json_object_free(json
);
10272 vty_out(vty
, "%% No such neighbor or address family\n");
10274 return CMD_WARNING
;
10278 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10279 PEER_FLAG_SOFT_RECONFIG
)) {
10281 json_object_string_add(
10283 "Inbound soft reconfiguration not enabled");
10284 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10285 json_object_free(json
);
10288 "%% Inbound soft reconfiguration not enabled\n");
10290 return CMD_WARNING
;
10293 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10295 return CMD_SUCCESS
;
10298 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10299 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10300 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10301 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10305 BGP_INSTANCE_HELP_STR
10307 BGP_SAFI_WITH_LABEL_HELP_STR
10308 "Detailed information on TCP and BGP neighbor connections\n"
10309 "Neighbor to display information about\n"
10310 "Neighbor to display information about\n"
10311 "Neighbor on BGP configured interface\n"
10312 "Display the received routes from neighbor\n"
10313 "Display the routes advertised to a BGP neighbor\n"
10314 "Route-map to modify the attributes\n"
10315 "Name of the route map\n"
10318 afi_t afi
= AFI_IP6
;
10319 safi_t safi
= SAFI_UNICAST
;
10320 char *rmap_name
= NULL
;
10321 char *peerstr
= NULL
;
10323 struct bgp
*bgp
= NULL
;
10328 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10331 return CMD_WARNING
;
10333 int uj
= use_json(argc
, argv
);
10337 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10338 argv_find(argv
, argc
, "neighbors", &idx
);
10339 peerstr
= argv
[++idx
]->arg
;
10341 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10343 return CMD_WARNING
;
10345 if (argv_find(argv
, argc
, "received-routes", &idx
))
10347 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10349 if (argv_find(argv
, argc
, "route-map", &idx
))
10350 rmap_name
= argv
[++idx
]->arg
;
10352 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10355 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10356 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10357 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10363 "Address Family modifier\n"
10364 "Detailed information on TCP and BGP neighbor connections\n"
10365 "Neighbor to display information about\n"
10366 "Neighbor to display information about\n"
10367 "Neighbor on BGP configured interface\n"
10368 "Display information received from a BGP neighbor\n"
10369 "Display the prefixlist filter\n"
10372 afi_t afi
= AFI_IP6
;
10373 safi_t safi
= SAFI_UNICAST
;
10374 char *peerstr
= NULL
;
10377 union sockunion su
;
10383 /* show [ip] bgp */
10384 if (argv_find(argv
, argc
, "ip", &idx
))
10386 /* [<ipv4|ipv6> [unicast]] */
10387 if (argv_find(argv
, argc
, "ipv4", &idx
))
10389 if (argv_find(argv
, argc
, "ipv6", &idx
))
10391 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10392 argv_find(argv
, argc
, "neighbors", &idx
);
10393 peerstr
= argv
[++idx
]->arg
;
10395 u_char uj
= use_json(argc
, argv
);
10397 ret
= str2sockunion(peerstr
, &su
);
10399 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10402 vty_out(vty
, "{}\n");
10405 "%% Malformed address or name: %s\n",
10407 return CMD_WARNING
;
10410 peer
= peer_lookup(NULL
, &su
);
10413 vty_out(vty
, "{}\n");
10415 vty_out(vty
, "No peer\n");
10416 return CMD_WARNING
;
10420 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10421 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10424 vty_out(vty
, "Address Family: %s\n",
10425 afi_safi_print(afi
, safi
));
10426 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10429 vty_out(vty
, "{}\n");
10431 vty_out(vty
, "No functional output\n");
10434 return CMD_SUCCESS
;
10437 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10438 afi_t afi
, safi_t safi
,
10439 enum bgp_show_type type
, u_char use_json
)
10441 /* labeled-unicast routes live in the unicast table */
10442 if (safi
== SAFI_LABELED_UNICAST
)
10443 safi
= SAFI_UNICAST
;
10445 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10447 json_object
*json_no
= NULL
;
10448 json_no
= json_object_new_object();
10449 json_object_string_add(
10450 json_no
, "warning",
10451 "No such neighbor or address family");
10452 vty_out(vty
, "%s\n",
10453 json_object_to_json_string(json_no
));
10454 json_object_free(json_no
);
10456 vty_out(vty
, "%% No such neighbor or address family\n");
10457 return CMD_WARNING
;
10460 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10463 DEFUN (show_ip_bgp_neighbor_routes
,
10464 show_ip_bgp_neighbor_routes_cmd
,
10465 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10466 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10470 BGP_INSTANCE_HELP_STR
10472 BGP_SAFI_WITH_LABEL_HELP_STR
10473 "Detailed information on TCP and BGP neighbor connections\n"
10474 "Neighbor to display information about\n"
10475 "Neighbor to display information about\n"
10476 "Neighbor on BGP configured interface\n"
10477 "Display flap statistics of the routes learned from neighbor\n"
10478 "Display the dampened routes received from neighbor\n"
10479 "Display routes learned from neighbor\n"
10482 char *peerstr
= NULL
;
10483 struct bgp
*bgp
= NULL
;
10484 afi_t afi
= AFI_IP6
;
10485 safi_t safi
= SAFI_UNICAST
;
10487 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10491 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10494 return CMD_WARNING
;
10496 int uj
= use_json(argc
, argv
);
10500 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10501 argv_find(argv
, argc
, "neighbors", &idx
);
10502 peerstr
= argv
[++idx
]->arg
;
10504 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10506 vty_out(vty
, "No such neighbor\n");
10507 return CMD_WARNING
;
10510 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10511 sh_type
= bgp_show_type_flap_neighbor
;
10512 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10513 sh_type
= bgp_show_type_damp_neighbor
;
10514 else if (argv_find(argv
, argc
, "routes", &idx
))
10515 sh_type
= bgp_show_type_neighbor
;
10517 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10520 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10522 struct bgp_distance
{
10523 /* Distance value for the IP source prefix. */
10526 /* Name of the access-list to be matched. */
10530 DEFUN (show_bgp_afi_vpn_rd_route
,
10531 show_bgp_afi_vpn_rd_route_cmd
,
10532 "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]",
10536 "Address Family modifier\n"
10537 "Display information for a route distinguisher\n"
10538 "Route Distinguisher\n"
10539 "Network in the BGP routing table to display\n"
10540 "Network in the BGP routing table to display\n"
10544 struct prefix_rd prd
;
10545 afi_t afi
= AFI_MAX
;
10548 (void)argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
);
10549 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10551 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10552 return CMD_WARNING
;
10554 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10555 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10558 static struct bgp_distance
*bgp_distance_new(void)
10560 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10563 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10565 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10568 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10569 const char *ip_str
, const char *access_list_str
)
10576 struct bgp_node
*rn
;
10577 struct bgp_distance
*bdistance
;
10579 afi
= bgp_node_afi(vty
);
10580 safi
= bgp_node_safi(vty
);
10582 ret
= str2prefix(ip_str
, &p
);
10584 vty_out(vty
, "Malformed prefix\n");
10585 return CMD_WARNING_CONFIG_FAILED
;
10588 distance
= atoi(distance_str
);
10590 /* Get BGP distance node. */
10591 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10593 bdistance
= rn
->info
;
10594 bgp_unlock_node(rn
);
10596 bdistance
= bgp_distance_new();
10597 rn
->info
= bdistance
;
10600 /* Set distance value. */
10601 bdistance
->distance
= distance
;
10603 /* Reset access-list configuration. */
10604 if (bdistance
->access_list
) {
10605 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10606 bdistance
->access_list
= NULL
;
10608 if (access_list_str
)
10609 bdistance
->access_list
=
10610 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10612 return CMD_SUCCESS
;
10615 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10616 const char *ip_str
, const char *access_list_str
)
10623 struct bgp_node
*rn
;
10624 struct bgp_distance
*bdistance
;
10626 afi
= bgp_node_afi(vty
);
10627 safi
= bgp_node_safi(vty
);
10629 ret
= str2prefix(ip_str
, &p
);
10631 vty_out(vty
, "Malformed prefix\n");
10632 return CMD_WARNING_CONFIG_FAILED
;
10635 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10636 (struct prefix
*)&p
);
10638 vty_out(vty
, "Can't find specified prefix\n");
10639 return CMD_WARNING_CONFIG_FAILED
;
10642 bdistance
= rn
->info
;
10643 distance
= atoi(distance_str
);
10645 if (bdistance
->distance
!= distance
) {
10646 vty_out(vty
, "Distance does not match configured\n");
10647 return CMD_WARNING_CONFIG_FAILED
;
10650 if (bdistance
->access_list
)
10651 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10652 bgp_distance_free(bdistance
);
10655 bgp_unlock_node(rn
);
10656 bgp_unlock_node(rn
);
10658 return CMD_SUCCESS
;
10661 /* Apply BGP information to distance method. */
10662 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10663 safi_t safi
, struct bgp
*bgp
)
10665 struct bgp_node
*rn
;
10668 struct bgp_distance
*bdistance
;
10669 struct access_list
*alist
;
10670 struct bgp_static
*bgp_static
;
10675 peer
= rinfo
->peer
;
10677 /* Check source address. */
10678 sockunion2hostprefix(&peer
->su
, &q
);
10679 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10681 bdistance
= rn
->info
;
10682 bgp_unlock_node(rn
);
10684 if (bdistance
->access_list
) {
10685 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10687 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10688 return bdistance
->distance
;
10690 return bdistance
->distance
;
10693 /* Backdoor check. */
10694 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10696 bgp_static
= rn
->info
;
10697 bgp_unlock_node(rn
);
10699 if (bgp_static
->backdoor
) {
10700 if (bgp
->distance_local
[afi
][safi
])
10701 return bgp
->distance_local
[afi
][safi
];
10703 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10707 if (peer
->sort
== BGP_PEER_EBGP
) {
10708 if (bgp
->distance_ebgp
[afi
][safi
])
10709 return bgp
->distance_ebgp
[afi
][safi
];
10710 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10712 if (bgp
->distance_ibgp
[afi
][safi
])
10713 return bgp
->distance_ibgp
[afi
][safi
];
10714 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10718 DEFUN (bgp_distance
,
10720 "distance bgp (1-255) (1-255) (1-255)",
10721 "Define an administrative distance\n"
10723 "Distance for routes external to the AS\n"
10724 "Distance for routes internal to the AS\n"
10725 "Distance for local routes\n")
10727 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10728 int idx_number
= 2;
10729 int idx_number_2
= 3;
10730 int idx_number_3
= 4;
10734 afi
= bgp_node_afi(vty
);
10735 safi
= bgp_node_safi(vty
);
10737 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10738 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10739 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10740 return CMD_SUCCESS
;
10743 DEFUN (no_bgp_distance
,
10744 no_bgp_distance_cmd
,
10745 "no distance bgp [(1-255) (1-255) (1-255)]",
10747 "Define an administrative distance\n"
10749 "Distance for routes external to the AS\n"
10750 "Distance for routes internal to the AS\n"
10751 "Distance for local routes\n")
10753 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10757 afi
= bgp_node_afi(vty
);
10758 safi
= bgp_node_safi(vty
);
10760 bgp
->distance_ebgp
[afi
][safi
] = 0;
10761 bgp
->distance_ibgp
[afi
][safi
] = 0;
10762 bgp
->distance_local
[afi
][safi
] = 0;
10763 return CMD_SUCCESS
;
10767 DEFUN (bgp_distance_source
,
10768 bgp_distance_source_cmd
,
10769 "distance (1-255) A.B.C.D/M",
10770 "Define an administrative distance\n"
10771 "Administrative distance\n"
10772 "IP source prefix\n")
10774 int idx_number
= 1;
10775 int idx_ipv4_prefixlen
= 2;
10776 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10777 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10778 return CMD_SUCCESS
;
10781 DEFUN (no_bgp_distance_source
,
10782 no_bgp_distance_source_cmd
,
10783 "no distance (1-255) A.B.C.D/M",
10785 "Define an administrative distance\n"
10786 "Administrative distance\n"
10787 "IP source prefix\n")
10789 int idx_number
= 2;
10790 int idx_ipv4_prefixlen
= 3;
10791 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10792 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10793 return CMD_SUCCESS
;
10796 DEFUN (bgp_distance_source_access_list
,
10797 bgp_distance_source_access_list_cmd
,
10798 "distance (1-255) A.B.C.D/M WORD",
10799 "Define an administrative distance\n"
10800 "Administrative distance\n"
10801 "IP source prefix\n"
10802 "Access list name\n")
10804 int idx_number
= 1;
10805 int idx_ipv4_prefixlen
= 2;
10807 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10808 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10809 return CMD_SUCCESS
;
10812 DEFUN (no_bgp_distance_source_access_list
,
10813 no_bgp_distance_source_access_list_cmd
,
10814 "no distance (1-255) A.B.C.D/M WORD",
10816 "Define an administrative distance\n"
10817 "Administrative distance\n"
10818 "IP source prefix\n"
10819 "Access list name\n")
10821 int idx_number
= 2;
10822 int idx_ipv4_prefixlen
= 3;
10824 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10825 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10826 return CMD_SUCCESS
;
10829 DEFUN (ipv6_bgp_distance_source
,
10830 ipv6_bgp_distance_source_cmd
,
10831 "distance (1-255) X:X::X:X/M",
10832 "Define an administrative distance\n"
10833 "Administrative distance\n"
10834 "IP source prefix\n")
10836 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10837 return CMD_SUCCESS
;
10840 DEFUN (no_ipv6_bgp_distance_source
,
10841 no_ipv6_bgp_distance_source_cmd
,
10842 "no distance (1-255) X:X::X:X/M",
10844 "Define an administrative distance\n"
10845 "Administrative distance\n"
10846 "IP source prefix\n")
10848 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10849 return CMD_SUCCESS
;
10852 DEFUN (ipv6_bgp_distance_source_access_list
,
10853 ipv6_bgp_distance_source_access_list_cmd
,
10854 "distance (1-255) X:X::X:X/M WORD",
10855 "Define an administrative distance\n"
10856 "Administrative distance\n"
10857 "IP source prefix\n"
10858 "Access list name\n")
10860 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10861 return CMD_SUCCESS
;
10864 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10865 no_ipv6_bgp_distance_source_access_list_cmd
,
10866 "no distance (1-255) X:X::X:X/M WORD",
10868 "Define an administrative distance\n"
10869 "Administrative distance\n"
10870 "IP source prefix\n"
10871 "Access list name\n")
10873 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10874 return CMD_SUCCESS
;
10877 DEFUN (bgp_damp_set
,
10879 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10880 "BGP Specific commands\n"
10881 "Enable route-flap dampening\n"
10882 "Half-life time for the penalty\n"
10883 "Value to start reusing a route\n"
10884 "Value to start suppressing a route\n"
10885 "Maximum duration to suppress a stable route\n")
10887 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10888 int idx_half_life
= 2;
10890 int idx_suppress
= 4;
10891 int idx_max_suppress
= 5;
10892 int half
= DEFAULT_HALF_LIFE
* 60;
10893 int reuse
= DEFAULT_REUSE
;
10894 int suppress
= DEFAULT_SUPPRESS
;
10895 int max
= 4 * half
;
10898 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10899 reuse
= atoi(argv
[idx_reuse
]->arg
);
10900 suppress
= atoi(argv
[idx_suppress
]->arg
);
10901 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10902 } else if (argc
== 3) {
10903 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10907 if (suppress
< reuse
) {
10909 "Suppress value cannot be less than reuse value \n");
10913 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10914 reuse
, suppress
, max
);
10917 DEFUN (bgp_damp_unset
,
10918 bgp_damp_unset_cmd
,
10919 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10921 "BGP Specific commands\n"
10922 "Enable route-flap dampening\n"
10923 "Half-life time for the penalty\n"
10924 "Value to start reusing a route\n"
10925 "Value to start suppressing a route\n"
10926 "Maximum duration to suppress a stable route\n")
10928 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10929 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10932 /* Display specified route of BGP table. */
10933 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10934 const char *ip_str
, afi_t afi
, safi_t safi
,
10935 struct prefix_rd
*prd
, int prefix_check
)
10938 struct prefix match
;
10939 struct bgp_node
*rn
;
10940 struct bgp_node
*rm
;
10941 struct bgp_info
*ri
;
10942 struct bgp_info
*ri_temp
;
10944 struct bgp_table
*table
;
10946 /* BGP structure lookup. */
10948 bgp
= bgp_lookup_by_name(view_name
);
10950 vty_out(vty
, "%% Can't find BGP instance %s\n",
10952 return CMD_WARNING
;
10955 bgp
= bgp_get_default();
10957 vty_out(vty
, "%% No BGP process is configured\n");
10958 return CMD_WARNING
;
10962 /* Check IP address argument. */
10963 ret
= str2prefix(ip_str
, &match
);
10965 vty_out(vty
, "%% address is malformed\n");
10966 return CMD_WARNING
;
10969 match
.family
= afi2family(afi
);
10971 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10972 || (safi
== SAFI_EVPN
)) {
10973 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10974 rn
= bgp_route_next(rn
)) {
10975 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10977 if ((table
= rn
->info
) == NULL
)
10979 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10983 || rm
->p
.prefixlen
== match
.prefixlen
) {
10986 if (ri
->extra
&& ri
->extra
->damp_info
) {
10987 ri_temp
= ri
->next
;
10988 bgp_damp_info_free(
10989 ri
->extra
->damp_info
,
10997 bgp_unlock_node(rm
);
11000 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11003 || rn
->p
.prefixlen
== match
.prefixlen
) {
11006 if (ri
->extra
&& ri
->extra
->damp_info
) {
11007 ri_temp
= ri
->next
;
11008 bgp_damp_info_free(
11009 ri
->extra
->damp_info
,
11017 bgp_unlock_node(rn
);
11021 return CMD_SUCCESS
;
11024 DEFUN (clear_ip_bgp_dampening
,
11025 clear_ip_bgp_dampening_cmd
,
11026 "clear ip bgp dampening",
11030 "Clear route flap dampening information\n")
11032 bgp_damp_info_clean();
11033 return CMD_SUCCESS
;
11036 DEFUN (clear_ip_bgp_dampening_prefix
,
11037 clear_ip_bgp_dampening_prefix_cmd
,
11038 "clear ip bgp dampening A.B.C.D/M",
11042 "Clear route flap dampening information\n"
11045 int idx_ipv4_prefixlen
= 4;
11046 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11047 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11050 DEFUN (clear_ip_bgp_dampening_address
,
11051 clear_ip_bgp_dampening_address_cmd
,
11052 "clear ip bgp dampening A.B.C.D",
11056 "Clear route flap dampening information\n"
11057 "Network to clear damping information\n")
11060 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11061 SAFI_UNICAST
, NULL
, 0);
11064 DEFUN (clear_ip_bgp_dampening_address_mask
,
11065 clear_ip_bgp_dampening_address_mask_cmd
,
11066 "clear ip bgp dampening A.B.C.D A.B.C.D",
11070 "Clear route flap dampening information\n"
11071 "Network to clear damping information\n"
11075 int idx_ipv4_2
= 5;
11077 char prefix_str
[BUFSIZ
];
11079 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11082 vty_out(vty
, "%% Inconsistent address and mask\n");
11083 return CMD_WARNING
;
11086 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11090 /* also used for encap safi */
11091 static void bgp_config_write_network_vpn(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 mpls_label_t label
;
11101 char buf
[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
)
11115 prd
= (struct prefix_rd
*)&prn
->p
;
11117 /* "network" configuration display. */
11118 prefix_rd2str(prd
, rdbuf
, RD_ADDRSTRLEN
);
11119 label
= decode_label(&bgp_static
->label
);
11121 vty_out(vty
, " network %s/%d rd %s",
11122 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11124 p
->prefixlen
, rdbuf
);
11125 if (safi
== SAFI_MPLS_VPN
)
11126 vty_out(vty
, " label %u", label
);
11128 if (bgp_static
->rmap
.name
)
11129 vty_out(vty
, " route-map %s",
11130 bgp_static
->rmap
.name
);
11132 if (bgp_static
->backdoor
)
11133 vty_out(vty
, " backdoor");
11135 vty_out(vty
, "\n");
11140 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11141 afi_t afi
, safi_t safi
)
11143 struct bgp_node
*prn
;
11144 struct bgp_node
*rn
;
11145 struct bgp_table
*table
;
11147 struct prefix_rd
*prd
;
11148 struct bgp_static
*bgp_static
;
11149 char buf
[PREFIX_STRLEN
];
11150 char buf2
[SU_ADDRSTRLEN
];
11151 char rdbuf
[RD_ADDRSTRLEN
];
11153 /* Network configuration. */
11154 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11155 prn
= bgp_route_next(prn
)) {
11156 if ((table
= prn
->info
) == NULL
)
11159 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11160 if ((bgp_static
= rn
->info
) == NULL
)
11163 char *macrouter
= NULL
;
11166 if (bgp_static
->router_mac
)
11167 macrouter
= prefix_mac2str(
11168 bgp_static
->router_mac
, NULL
, 0);
11169 if (bgp_static
->eth_s_id
)
11170 esi
= esi2str(bgp_static
->eth_s_id
);
11172 prd
= (struct prefix_rd
*)&prn
->p
;
11174 /* "network" configuration display. */
11175 prefix_rd2str(prd
, rdbuf
, RD_ADDRSTRLEN
);
11176 if (p
->u
.prefix_evpn
.route_type
== 5) {
11177 char local_buf
[PREFIX_STRLEN
];
11178 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)
11181 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
, local_buf
,
11183 sprintf(buf
, "%s/%u", local_buf
,p
->u
.prefix_evpn
.ip_prefix_length
);
11185 prefix2str(p
, buf
, sizeof(buf
));
11188 if (bgp_static
->gatewayIp
.family
== AF_INET
||
11189 bgp_static
->gatewayIp
.family
== AF_INET6
)
11190 inet_ntop(bgp_static
->gatewayIp
.family
,
11191 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11194 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
11195 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
11196 decode_label(&bgp_static
->label
), esi
, buf2
,
11200 XFREE(MTYPE_TMP
, macrouter
);
11202 XFREE(MTYPE_TMP
, esi
);
11207 /* Configuration of static route announcement and aggregate
11209 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11212 struct bgp_node
*rn
;
11214 struct bgp_static
*bgp_static
;
11215 struct bgp_aggregate
*bgp_aggregate
;
11216 char buf
[SU_ADDRSTRLEN
];
11218 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11219 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11223 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11224 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11228 /* Network configuration. */
11229 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11230 rn
= bgp_route_next(rn
)) {
11231 if ((bgp_static
= rn
->info
) == NULL
)
11236 /* "network" configuration display. */
11237 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11238 u_int32_t destination
;
11239 struct in_addr netmask
;
11241 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11242 masklen2ip(p
->prefixlen
, &netmask
);
11243 vty_out(vty
, " network %s",
11244 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11247 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11248 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11249 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11250 || p
->u
.prefix4
.s_addr
== 0) {
11251 /* Natural mask is not display. */
11253 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11255 vty_out(vty
, " network %s/%d",
11256 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11261 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11262 vty_out(vty
, " label-index %u",
11263 bgp_static
->label_index
);
11265 if (bgp_static
->rmap
.name
)
11266 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11268 if (bgp_static
->backdoor
)
11269 vty_out(vty
, " backdoor");
11272 vty_out(vty
, "\n");
11275 /* Aggregate-address configuration. */
11276 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11277 rn
= bgp_route_next(rn
)) {
11278 if ((bgp_aggregate
= rn
->info
) == NULL
)
11283 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11284 struct in_addr netmask
;
11286 masklen2ip(p
->prefixlen
, &netmask
);
11287 vty_out(vty
, " aggregate-address %s %s",
11288 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11290 inet_ntoa(netmask
));
11292 vty_out(vty
, " aggregate-address %s/%d",
11293 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11298 if (bgp_aggregate
->as_set
)
11299 vty_out(vty
, " as-set");
11301 if (bgp_aggregate
->summary_only
)
11302 vty_out(vty
, " summary-only");
11304 vty_out(vty
, "\n");
11308 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11311 struct bgp_node
*rn
;
11312 struct bgp_distance
*bdistance
;
11314 /* Distance configuration. */
11315 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11316 && bgp
->distance_local
[afi
][safi
]
11317 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11318 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11319 || bgp
->distance_local
[afi
][safi
]
11320 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11321 vty_out(vty
, " distance bgp %d %d %d\n",
11322 bgp
->distance_ebgp
[afi
][safi
],
11323 bgp
->distance_ibgp
[afi
][safi
],
11324 bgp
->distance_local
[afi
][safi
]);
11327 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11328 rn
= bgp_route_next(rn
))
11329 if ((bdistance
= rn
->info
) != NULL
) {
11330 char buf
[PREFIX_STRLEN
];
11332 vty_out(vty
, " distance %d %s %s\n",
11333 bdistance
->distance
,
11334 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11335 bdistance
->access_list
? bdistance
->access_list
11340 /* Allocate routing table structure and install commands. */
11341 void bgp_route_init(void)
11346 /* Init BGP distance table. */
11347 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11348 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
11349 bgp_distance_table
[afi
][safi
] =
11350 bgp_table_init(afi
, safi
);
11352 /* IPv4 BGP commands. */
11353 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11354 install_element(BGP_NODE
, &bgp_network_cmd
);
11355 install_element(BGP_NODE
, &bgp_network_mask_cmd
);
11356 install_element(BGP_NODE
, &bgp_network_mask_natural_cmd
);
11357 install_element(BGP_NODE
, &bgp_network_route_map_cmd
);
11358 install_element(BGP_NODE
, &bgp_network_mask_route_map_cmd
);
11359 install_element(BGP_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11360 install_element(BGP_NODE
, &bgp_network_backdoor_cmd
);
11361 install_element(BGP_NODE
, &bgp_network_mask_backdoor_cmd
);
11362 install_element(BGP_NODE
, &bgp_network_mask_natural_backdoor_cmd
);
11363 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11364 install_element(BGP_NODE
, &no_bgp_network_cmd
);
11365 install_element(BGP_NODE
, &no_bgp_network_mask_cmd
);
11366 install_element(BGP_NODE
, &no_bgp_network_mask_natural_cmd
);
11368 install_element(BGP_NODE
, &aggregate_address_cmd
);
11369 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11370 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11371 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11373 /* IPv4 unicast configuration. */
11374 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11375 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11376 install_element(BGP_IPV4_NODE
, &bgp_network_mask_cmd
);
11377 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_cmd
);
11378 install_element(BGP_IPV4_NODE
, &bgp_network_route_map_cmd
);
11379 install_element(BGP_IPV4_NODE
, &bgp_network_mask_route_map_cmd
);
11380 install_element(BGP_IPV4_NODE
, &bgp_network_mask_natural_route_map_cmd
);
11381 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_cmd
);
11382 install_element(BGP_IPV4_NODE
, &bgp_network_label_index_route_map_cmd
);
11383 install_element(BGP_IPV4_NODE
, &no_bgp_network_label_index_cmd
);
11384 install_element(BGP_IPV4_NODE
,
11385 &no_bgp_network_label_index_route_map_cmd
);
11386 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11387 install_element(BGP_IPV4_NODE
, &no_bgp_network_cmd
);
11388 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_cmd
);
11389 install_element(BGP_IPV4_NODE
, &no_bgp_network_mask_natural_cmd
);
11391 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11392 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11393 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11394 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11396 /* IPv4 multicast configuration. */
11397 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11398 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11399 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_cmd
);
11400 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_natural_cmd
);
11401 install_element(BGP_IPV4M_NODE
, &bgp_network_route_map_cmd
);
11402 install_element(BGP_IPV4M_NODE
, &bgp_network_mask_route_map_cmd
);
11403 install_element(BGP_IPV4M_NODE
,
11404 &bgp_network_mask_natural_route_map_cmd
);
11405 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11406 install_element(BGP_IPV4M_NODE
, &no_bgp_network_cmd
);
11407 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_cmd
);
11408 install_element(BGP_IPV4M_NODE
, &no_bgp_network_mask_natural_cmd
);
11409 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11410 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11411 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11412 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11414 /* IPv4 labeled-unicast configuration. */
11415 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11416 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11417 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11418 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11419 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11421 install_element(VIEW_NODE
,
11422 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11423 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11424 install_element(VIEW_NODE
,
11425 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11426 #ifdef KEEP_OLD_VPN_COMMANDS
11427 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11428 #endif /* KEEP_OLD_VPN_COMMANDS */
11429 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11430 install_element(VIEW_NODE
,
11431 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11433 /* BGP dampening clear commands */
11434 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11435 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11437 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11438 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11441 install_element(ENABLE_NODE
,
11442 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11443 #ifdef KEEP_OLD_VPN_COMMANDS
11444 install_element(ENABLE_NODE
,
11445 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11446 #endif /* KEEP_OLD_VPN_COMMANDS */
11448 /* New config IPv6 BGP commands. */
11449 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11450 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11451 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_route_map_cmd
);
11452 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11453 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_cmd
);
11454 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_label_index_cmd
);
11455 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_network_label_index_cmd
);
11456 install_element(BGP_IPV6_NODE
,
11457 &ipv6_bgp_network_label_index_route_map_cmd
);
11458 install_element(BGP_IPV6_NODE
,
11459 &no_ipv6_bgp_network_label_index_route_map_cmd
);
11461 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11462 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11464 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11465 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_network_cmd
);
11467 install_element(BGP_NODE
, &bgp_distance_cmd
);
11468 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11469 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11470 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11471 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11472 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11473 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11474 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11475 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11476 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11477 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11478 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11479 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11480 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11481 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11482 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11483 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11484 install_element(BGP_IPV4M_NODE
,
11485 &no_bgp_distance_source_access_list_cmd
);
11486 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11487 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11488 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11489 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11490 install_element(BGP_IPV6_NODE
,
11491 &ipv6_bgp_distance_source_access_list_cmd
);
11492 install_element(BGP_IPV6_NODE
,
11493 &no_ipv6_bgp_distance_source_access_list_cmd
);
11494 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11495 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11496 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11497 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11498 install_element(BGP_IPV6M_NODE
,
11499 &ipv6_bgp_distance_source_access_list_cmd
);
11500 install_element(BGP_IPV6M_NODE
,
11501 &no_ipv6_bgp_distance_source_access_list_cmd
);
11503 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11504 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11505 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11506 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11508 /* IPv4 Multicast Mode */
11509 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11510 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11512 /* Large Communities */
11513 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11514 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11517 void bgp_route_finish(void)
11522 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
11523 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
11524 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11525 bgp_distance_table
[afi
][safi
] = NULL
;