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"
77 #ifndef VTYSH_EXTRACT_PL
78 #include "bgpd/bgp_route_clippy.c"
81 /* Extern from bgp_dump.c */
82 extern const char *bgp_origin_str
[];
83 extern const char *bgp_origin_long_str
[];
85 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
86 safi_t safi
, struct prefix
*p
,
87 struct prefix_rd
*prd
)
90 struct bgp_node
*prn
= NULL
;
96 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
97 || (safi
== SAFI_EVPN
)) {
98 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
100 if (prn
->info
== NULL
)
101 prn
->info
= bgp_table_init(afi
, safi
);
103 bgp_unlock_node(prn
);
107 rn
= bgp_node_get(table
, p
);
109 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
110 || (safi
== SAFI_EVPN
))
116 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
117 safi_t safi
, struct prefix
*p
,
118 struct prefix_rd
*prd
)
121 struct bgp_node
*prn
= NULL
;
126 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
127 || (safi
== SAFI_EVPN
)) {
128 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
132 if (prn
->info
== NULL
) {
133 bgp_unlock_node(prn
);
140 rn
= bgp_node_lookup(table
, p
);
145 /* Allocate bgp_info_extra */
146 static struct bgp_info_extra
*bgp_info_extra_new(void)
148 struct bgp_info_extra
*new;
149 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
, sizeof(struct bgp_info_extra
));
150 new->label
= MPLS_INVALID_LABEL
;
154 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
156 if (extra
&& *extra
) {
157 if ((*extra
)->damp_info
)
158 bgp_damp_info_free((*extra
)->damp_info
, 0);
160 (*extra
)->damp_info
= NULL
;
162 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
168 /* Get bgp_info extra information for the given bgp_info, lazy allocated
171 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
174 ri
->extra
= bgp_info_extra_new();
178 /* Allocate new bgp info structure. */
179 struct bgp_info
*bgp_info_new(void)
181 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
184 /* Free bgp route information. */
185 static void bgp_info_free(struct bgp_info
*binfo
)
188 bgp_attr_unintern(&binfo
->attr
);
190 bgp_unlink_nexthop(binfo
);
191 bgp_info_extra_free(&binfo
->extra
);
192 bgp_info_mpath_free(&binfo
->mpath
);
194 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
196 XFREE(MTYPE_BGP_ROUTE
, binfo
);
199 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
205 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
207 assert(binfo
&& binfo
->lock
> 0);
210 if (binfo
->lock
== 0) {
212 zlog_debug ("%s: unlocked and freeing", __func__
);
213 zlog_backtrace (LOG_DEBUG
);
215 bgp_info_free(binfo
);
220 if (binfo
->lock
== 1)
222 zlog_debug ("%s: unlocked to 1", __func__
);
223 zlog_backtrace (LOG_DEBUG
);
230 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
232 struct bgp_info
*top
;
244 peer_lock(ri
->peer
); /* bgp_info peer reference */
247 /* Do the actual removal of info from RIB, for use by bgp_process
248 completion callback *only* */
249 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
252 ri
->next
->prev
= ri
->prev
;
254 ri
->prev
->next
= ri
->next
;
258 bgp_info_mpath_dequeue(ri
);
263 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
265 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
266 /* set of previous already took care of pcount */
267 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
270 /* undo the effects of a previous call to bgp_info_delete; typically
271 called when a route is deleted and then quickly re-added before the
272 deletion has been processed */
273 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
275 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
276 /* unset of previous already took care of pcount */
277 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
280 /* Adjust pcount as required */
281 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
283 struct bgp_table
*table
;
285 assert(rn
&& bgp_node_table(rn
));
286 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
288 table
= bgp_node_table(rn
);
290 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
293 if (!BGP_INFO_COUNTABLE(ri
)
294 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
296 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
298 /* slight hack, but more robust against errors. */
299 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
300 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
303 "%s: Asked to decrement 0 prefix count for peer %s",
304 __func__
, ri
->peer
->host
);
305 zlog_backtrace(LOG_WARNING
);
306 zlog_warn("%s: Please report to Quagga bugzilla",
309 } else if (BGP_INFO_COUNTABLE(ri
)
310 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
311 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
312 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
316 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
318 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
321 /* Set/unset bgp_info flags, adjusting any other state as needed.
322 * This is here primarily to keep prefix-count in check.
324 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, u_int32_t flag
)
326 SET_FLAG(ri
->flags
, flag
);
328 /* early bath if we know it's not a flag that changes countability state
330 if (!CHECK_FLAG(flag
,
331 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
334 bgp_pcount_adjust(rn
, ri
);
337 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
340 UNSET_FLAG(ri
->flags
, flag
);
342 /* early bath if we know it's not a flag that changes countability state
344 if (!CHECK_FLAG(flag
,
345 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
348 bgp_pcount_adjust(rn
, ri
);
351 /* Get MED value. If MED value is missing and "bgp bestpath
352 missing-as-worst" is specified, treat it as the worst value. */
353 static u_int32_t
bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
355 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
358 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
365 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
367 if (ri
->addpath_rx_id
)
368 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
371 sprintf(buf
, "path %s", ri
->peer
->host
);
374 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
376 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
377 struct bgp_info
*exist
, int *paths_eq
,
378 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
379 char *pfx_buf
, afi_t afi
, safi_t safi
)
381 struct attr
*newattr
, *existattr
;
382 bgp_peer_sort_t new_sort
;
383 bgp_peer_sort_t exist_sort
;
385 u_int32_t exist_pref
;
388 u_int32_t new_weight
;
389 u_int32_t exist_weight
;
390 uint32_t newm
, existm
;
391 struct in_addr new_id
;
392 struct in_addr exist_id
;
395 int internal_as_route
;
398 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
399 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
400 u_int32_t new_mm_seq
;
401 u_int32_t exist_mm_seq
;
408 zlog_debug("%s: new is NULL", pfx_buf
);
413 bgp_info_path_with_addpath_rx_str(new, new_buf
);
417 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
423 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
424 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
425 pfx_buf
, new_buf
, new->flags
, exist_buf
,
430 existattr
= exist
->attr
;
432 /* For EVPN routes, we cannot just go by local vs remote, we have to
433 * look at the MAC mobility sequence number, if present.
435 if (safi
== SAFI_EVPN
) {
436 /* This is an error condition described in RFC 7432 Section
438 * states that in this scenario "the PE MUST alert the operator"
440 * does not state what other action to take. In order to provide
442 * consistency in this scenario we are going to prefer the path
446 if (newattr
->sticky
!= existattr
->sticky
) {
448 prefix2str(&new->net
->p
, pfx_buf
,
450 * PREFIX2STR_BUFFER
);
451 bgp_info_path_with_addpath_rx_str(new, new_buf
);
452 bgp_info_path_with_addpath_rx_str(exist
,
456 if (newattr
->sticky
&& !existattr
->sticky
) {
458 "%s: %s wins over %s due to sticky MAC flag",
459 pfx_buf
, new_buf
, exist_buf
);
463 if (!newattr
->sticky
&& existattr
->sticky
) {
465 "%s: %s loses to %s due to sticky MAC flag",
466 pfx_buf
, new_buf
, exist_buf
);
471 new_mm_seq
= mac_mobility_seqnum(newattr
);
472 exist_mm_seq
= mac_mobility_seqnum(existattr
);
474 if (new_mm_seq
> exist_mm_seq
) {
477 "%s: %s wins over %s due to MM seq %u > %u",
478 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
483 if (new_mm_seq
< exist_mm_seq
) {
486 "%s: %s loses to %s due to MM seq %u < %u",
487 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
493 /* 1. Weight check. */
494 new_weight
= newattr
->weight
;
495 exist_weight
= existattr
->weight
;
497 if (new_weight
> exist_weight
) {
499 zlog_debug("%s: %s wins over %s due to weight %d > %d",
500 pfx_buf
, new_buf
, exist_buf
, new_weight
,
505 if (new_weight
< exist_weight
) {
507 zlog_debug("%s: %s loses to %s due to weight %d < %d",
508 pfx_buf
, new_buf
, exist_buf
, new_weight
,
513 /* 2. Local preference check. */
514 new_pref
= exist_pref
= bgp
->default_local_pref
;
516 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
517 new_pref
= newattr
->local_pref
;
518 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
519 exist_pref
= existattr
->local_pref
;
521 if (new_pref
> exist_pref
) {
524 "%s: %s wins over %s due to localpref %d > %d",
525 pfx_buf
, new_buf
, exist_buf
, new_pref
,
530 if (new_pref
< exist_pref
) {
533 "%s: %s loses to %s due to localpref %d < %d",
534 pfx_buf
, new_buf
, exist_buf
, new_pref
,
539 /* 3. Local route check. We prefer:
541 * - BGP_ROUTE_AGGREGATE
542 * - BGP_ROUTE_REDISTRIBUTE
544 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
547 "%s: %s wins over %s due to preferred BGP_ROUTE type",
548 pfx_buf
, new_buf
, exist_buf
);
552 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
555 "%s: %s loses to %s due to preferred BGP_ROUTE type",
556 pfx_buf
, new_buf
, exist_buf
);
560 /* 4. AS path length check. */
561 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
562 int exist_hops
= aspath_count_hops(existattr
->aspath
);
563 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
565 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
568 aspath_hops
= aspath_count_hops(newattr
->aspath
);
569 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
571 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
574 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
575 pfx_buf
, new_buf
, exist_buf
,
577 (exist_hops
+ exist_confeds
));
581 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
584 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
585 pfx_buf
, new_buf
, exist_buf
,
587 (exist_hops
+ exist_confeds
));
591 int newhops
= aspath_count_hops(newattr
->aspath
);
593 if (newhops
< exist_hops
) {
596 "%s: %s wins over %s due to aspath hopcount %d < %d",
597 pfx_buf
, new_buf
, exist_buf
,
598 newhops
, exist_hops
);
602 if (newhops
> exist_hops
) {
605 "%s: %s loses to %s due to aspath hopcount %d > %d",
606 pfx_buf
, new_buf
, exist_buf
,
607 newhops
, exist_hops
);
613 /* 5. Origin check. */
614 if (newattr
->origin
< existattr
->origin
) {
616 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
617 pfx_buf
, new_buf
, exist_buf
,
618 bgp_origin_long_str
[newattr
->origin
],
619 bgp_origin_long_str
[existattr
->origin
]);
623 if (newattr
->origin
> existattr
->origin
) {
625 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
626 pfx_buf
, new_buf
, exist_buf
,
627 bgp_origin_long_str
[newattr
->origin
],
628 bgp_origin_long_str
[existattr
->origin
]);
633 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
634 && aspath_count_hops(existattr
->aspath
) == 0);
635 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
636 && aspath_count_confeds(existattr
->aspath
) > 0
637 && aspath_count_hops(newattr
->aspath
) == 0
638 && aspath_count_hops(existattr
->aspath
) == 0);
640 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
641 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
642 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
643 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
644 || internal_as_route
) {
645 new_med
= bgp_med_value(new->attr
, bgp
);
646 exist_med
= bgp_med_value(exist
->attr
, bgp
);
648 if (new_med
< exist_med
) {
651 "%s: %s wins over %s due to MED %d < %d",
652 pfx_buf
, new_buf
, exist_buf
, new_med
,
657 if (new_med
> exist_med
) {
660 "%s: %s loses to %s due to MED %d > %d",
661 pfx_buf
, new_buf
, exist_buf
, new_med
,
667 /* 7. Peer type check. */
668 new_sort
= new->peer
->sort
;
669 exist_sort
= exist
->peer
->sort
;
671 if (new_sort
== BGP_PEER_EBGP
672 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
675 "%s: %s wins over %s due to eBGP peer > iBGP peer",
676 pfx_buf
, new_buf
, exist_buf
);
680 if (exist_sort
== BGP_PEER_EBGP
681 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
684 "%s: %s loses to %s due to iBGP peer < eBGP peer",
685 pfx_buf
, new_buf
, exist_buf
);
689 /* 8. IGP metric check. */
693 newm
= new->extra
->igpmetric
;
695 existm
= exist
->extra
->igpmetric
;
700 "%s: %s wins over %s due to IGP metric %d < %d",
701 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
708 "%s: %s loses to %s due to IGP metric %d > %d",
709 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
713 /* 9. Same IGP metric. Compare the cluster list length as
714 representative of IGP hops metric. Rewrite the metric value
715 pair (newm, existm) with the cluster list length. Prefer the
716 path with smaller cluster list length. */
717 if (newm
== existm
) {
718 if (peer_sort(new->peer
) == BGP_PEER_IBGP
719 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
720 && (mpath_cfg
== NULL
722 mpath_cfg
->ibgp_flags
,
723 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
724 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
725 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
730 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
731 pfx_buf
, new_buf
, exist_buf
,
739 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
740 pfx_buf
, new_buf
, exist_buf
,
747 /* 10. confed-external vs. confed-internal */
748 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
749 if (new_sort
== BGP_PEER_CONFED
750 && exist_sort
== BGP_PEER_IBGP
) {
753 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
754 pfx_buf
, new_buf
, exist_buf
);
758 if (exist_sort
== BGP_PEER_CONFED
759 && new_sort
== BGP_PEER_IBGP
) {
762 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
763 pfx_buf
, new_buf
, exist_buf
);
768 /* 11. Maximum path check. */
769 if (newm
== existm
) {
770 /* If one path has a label but the other does not, do not treat
771 * them as equals for multipath
773 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
))
775 && bgp_is_valid_label(&exist
->extra
->label
))) {
778 "%s: %s and %s cannot be multipath, one has a label while the other does not",
779 pfx_buf
, new_buf
, exist_buf
);
780 } else if (bgp_flag_check(bgp
,
781 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
784 * For the two paths, all comparison steps till IGP
786 * have succeeded - including AS_PATH hop count. Since
788 * bestpath as-path multipath-relax' knob is on, we
790 * an exact match of AS_PATH. Thus, mark the paths are
792 * That will trigger both these paths to get into the
800 "%s: %s and %s are equal via multipath-relax",
801 pfx_buf
, new_buf
, exist_buf
);
802 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
803 if (aspath_cmp(new->attr
->aspath
,
804 exist
->attr
->aspath
)) {
809 "%s: %s and %s are equal via matching aspaths",
810 pfx_buf
, new_buf
, exist_buf
);
812 } else if (new->peer
->as
== exist
->peer
->as
) {
817 "%s: %s and %s are equal via same remote-as",
818 pfx_buf
, new_buf
, exist_buf
);
822 * TODO: If unequal cost ibgp multipath is enabled we can
823 * mark the paths as equal here instead of returning
828 "%s: %s wins over %s after IGP metric comparison",
829 pfx_buf
, new_buf
, exist_buf
);
832 "%s: %s loses to %s after IGP metric comparison",
833 pfx_buf
, new_buf
, exist_buf
);
838 /* 12. If both paths are external, prefer the path that was received
839 first (the oldest one). This step minimizes route-flap, since a
840 newer path won't displace an older one, even if it was the
841 preferred route based on the additional decision criteria below. */
842 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
843 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
844 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
847 "%s: %s wins over %s due to oldest external",
848 pfx_buf
, new_buf
, exist_buf
);
852 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
855 "%s: %s loses to %s due to oldest external",
856 pfx_buf
, new_buf
, exist_buf
);
861 /* 13. Router-ID comparision. */
862 /* If one of the paths is "stale", the corresponding peer router-id will
863 * be 0 and would always win over the other path. If originator id is
864 * used for the comparision, it will decide which path is better.
866 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
867 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
869 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
870 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
871 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
873 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
875 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
878 "%s: %s wins over %s due to Router-ID comparison",
879 pfx_buf
, new_buf
, exist_buf
);
883 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
886 "%s: %s loses to %s due to Router-ID comparison",
887 pfx_buf
, new_buf
, exist_buf
);
891 /* 14. Cluster length comparision. */
892 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
893 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
895 if (new_cluster
< exist_cluster
) {
898 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
899 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
904 if (new_cluster
> exist_cluster
) {
907 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
908 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
913 /* 15. Neighbor address comparision. */
914 /* Do this only if neither path is "stale" as stale paths do not have
915 * valid peer information (as the connection may or may not be up).
917 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
920 "%s: %s wins over %s due to latter path being STALE",
921 pfx_buf
, new_buf
, exist_buf
);
925 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
928 "%s: %s loses to %s due to former path being STALE",
929 pfx_buf
, new_buf
, exist_buf
);
933 /* locally configured routes to advertise do not have su_remote */
934 if (new->peer
->su_remote
== NULL
)
936 if (exist
->peer
->su_remote
== NULL
)
939 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
944 "%s: %s loses to %s due to Neighor IP comparison",
945 pfx_buf
, new_buf
, exist_buf
);
952 "%s: %s wins over %s due to Neighor IP comparison",
953 pfx_buf
, new_buf
, exist_buf
);
958 zlog_debug("%s: %s wins over %s due to nothing left to compare",
959 pfx_buf
, new_buf
, exist_buf
);
964 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
965 * is preferred, or 0 if they are the same (usually will only occur if
966 * multipath is enabled
967 * This version is compatible with */
968 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
969 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
974 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
988 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
989 struct attr
*attr
, afi_t afi
,
992 struct bgp_filter
*filter
;
994 filter
= &peer
->filter
[afi
][safi
];
996 #define FILTER_EXIST_WARN(F, f, filter) \
997 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
998 zlog_warn("%s: Could not find configured input %s-list %s!", \
999 peer->host, #f, F##_IN_NAME(filter));
1001 if (DISTRIBUTE_IN_NAME(filter
)) {
1002 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1004 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1008 if (PREFIX_LIST_IN_NAME(filter
)) {
1009 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1011 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1015 if (FILTER_LIST_IN_NAME(filter
)) {
1016 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1018 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1023 return FILTER_PERMIT
;
1024 #undef FILTER_EXIST_WARN
1027 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1028 struct attr
*attr
, afi_t afi
,
1031 struct bgp_filter
*filter
;
1033 filter
= &peer
->filter
[afi
][safi
];
1035 #define FILTER_EXIST_WARN(F, f, filter) \
1036 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1037 zlog_warn("%s: Could not find configured output %s-list %s!", \
1038 peer->host, #f, F##_OUT_NAME(filter));
1040 if (DISTRIBUTE_OUT_NAME(filter
)) {
1041 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1043 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1047 if (PREFIX_LIST_OUT_NAME(filter
)) {
1048 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1050 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1055 if (FILTER_LIST_OUT_NAME(filter
)) {
1056 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1058 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1063 return FILTER_PERMIT
;
1064 #undef FILTER_EXIST_WARN
1067 /* If community attribute includes no_export then return 1. */
1068 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1070 if (attr
->community
) {
1071 /* NO_ADVERTISE check. */
1072 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1075 /* NO_EXPORT check. */
1076 if (peer
->sort
== BGP_PEER_EBGP
1077 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1080 /* NO_EXPORT_SUBCONFED check. */
1081 if (peer
->sort
== BGP_PEER_EBGP
1082 || peer
->sort
== BGP_PEER_CONFED
)
1083 if (community_include(attr
->community
,
1084 COMMUNITY_NO_EXPORT_SUBCONFED
))
1090 /* Route reflection loop check. */
1091 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1093 struct in_addr cluster_id
;
1095 if (attr
->cluster
) {
1096 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1097 cluster_id
= peer
->bgp
->cluster_id
;
1099 cluster_id
= peer
->bgp
->router_id
;
1101 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1107 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1108 struct attr
*attr
, afi_t afi
, safi_t safi
,
1109 const char *rmap_name
)
1111 struct bgp_filter
*filter
;
1112 struct bgp_info info
;
1113 route_map_result_t ret
;
1114 struct route_map
*rmap
= NULL
;
1116 filter
= &peer
->filter
[afi
][safi
];
1118 /* Apply default weight value. */
1119 if (peer
->weight
[afi
][safi
])
1120 attr
->weight
= peer
->weight
[afi
][safi
];
1123 rmap
= route_map_lookup_by_name(rmap_name
);
1128 if (ROUTE_MAP_IN_NAME(filter
)) {
1129 rmap
= ROUTE_MAP_IN(filter
);
1136 /* Route map apply. */
1138 /* Duplicate current value to new strucutre for modification. */
1142 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1144 /* Apply BGP route map to the attribute. */
1145 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1147 peer
->rmap_type
= 0;
1149 if (ret
== RMAP_DENYMATCH
) {
1150 /* Free newly generated AS path and community by
1152 bgp_attr_flush(attr
);
1159 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1160 struct attr
*attr
, afi_t afi
, safi_t safi
,
1161 const char *rmap_name
)
1163 struct bgp_info info
;
1164 route_map_result_t ret
;
1165 struct route_map
*rmap
= NULL
;
1169 * So if we get to this point and have no rmap_name
1170 * we want to just show the output as it currently
1176 /* Apply default weight value. */
1177 if (peer
->weight
[afi
][safi
])
1178 attr
->weight
= peer
->weight
[afi
][safi
];
1180 rmap
= route_map_lookup_by_name(rmap_name
);
1183 * If we have a route map name and we do not find
1184 * the routemap that means we have an implicit
1190 /* Route map apply. */
1191 /* Duplicate current value to new strucutre for modification. */
1195 rmap_type
= peer
->rmap_type
;
1196 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1198 /* Apply BGP route map to the attribute. */
1199 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1201 peer
->rmap_type
= rmap_type
;
1203 if (ret
== RMAP_DENYMATCH
)
1205 * caller has multiple error paths with bgp_attr_flush()
1212 /* If this is an EBGP peer with remove-private-AS */
1213 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1214 struct peer
*peer
, struct attr
*attr
)
1216 if (peer
->sort
== BGP_PEER_EBGP
1217 && (peer_af_flag_check(peer
, afi
, safi
,
1218 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1219 || peer_af_flag_check(peer
, afi
, safi
,
1220 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1221 || peer_af_flag_check(peer
, afi
, safi
,
1222 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1223 || peer_af_flag_check(peer
, afi
, safi
,
1224 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1225 // Take action on the entire aspath
1226 if (peer_af_flag_check(peer
, afi
, safi
,
1227 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1228 || peer_af_flag_check(peer
, afi
, safi
,
1229 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1230 if (peer_af_flag_check(
1232 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1233 attr
->aspath
= aspath_replace_private_asns(
1234 attr
->aspath
, bgp
->as
);
1236 // The entire aspath consists of private ASNs so create
1238 else if (aspath_private_as_check(attr
->aspath
))
1239 attr
->aspath
= aspath_empty_get();
1241 // There are some public and some private ASNs, remove
1244 attr
->aspath
= aspath_remove_private_asns(
1248 // 'all' was not specified so the entire aspath must be private
1250 // for us to do anything
1251 else if (aspath_private_as_check(attr
->aspath
)) {
1252 if (peer_af_flag_check(
1254 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1255 attr
->aspath
= aspath_replace_private_asns(
1256 attr
->aspath
, bgp
->as
);
1258 attr
->aspath
= aspath_empty_get();
1263 /* If this is an EBGP peer with as-override */
1264 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1265 struct peer
*peer
, struct attr
*attr
)
1267 if (peer
->sort
== BGP_PEER_EBGP
1268 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1269 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1270 attr
->aspath
= aspath_replace_specific_asn(
1271 attr
->aspath
, peer
->as
, bgp
->as
);
1275 void bgp_attr_add_gshut_community(struct attr
*attr
)
1277 struct community
*old
;
1278 struct community
*new;
1279 struct community
*merge
;
1280 struct community
*gshut
;
1282 old
= attr
->community
;
1283 gshut
= community_str2com("graceful-shutdown");
1286 merge
= community_merge(community_dup(old
), gshut
);
1288 if (old
->refcnt
== 0)
1289 community_free(old
);
1291 new = community_uniq_sort(merge
);
1292 community_free(merge
);
1294 new = community_dup(gshut
);
1297 community_free(gshut
);
1298 attr
->community
= new;
1299 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1301 /* When we add the graceful-shutdown community we must also
1302 * lower the local-preference */
1303 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1304 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1308 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1310 if (family
== AF_INET
)
1311 attr
->nexthop
.s_addr
= 0;
1312 if (family
== AF_INET6
)
1313 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1316 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1317 struct update_subgroup
*subgrp
, struct prefix
*p
,
1320 struct bgp_filter
*filter
;
1323 struct peer
*onlypeer
;
1325 struct attr
*riattr
;
1326 char buf
[PREFIX_STRLEN
];
1332 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1334 if (DISABLE_BGP_ANNOUNCE
)
1337 afi
= SUBGRP_AFI(subgrp
);
1338 safi
= SUBGRP_SAFI(subgrp
);
1339 peer
= SUBGRP_PEER(subgrp
);
1341 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1342 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1345 filter
= &peer
->filter
[afi
][safi
];
1346 bgp
= SUBGRP_INST(subgrp
);
1347 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1350 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1351 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1352 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1355 * direct and direct_ext type routes originate internally even
1356 * though they can have peer pointers that reference other
1359 prefix2str(p
, buf
, PREFIX_STRLEN
);
1360 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1366 /* With addpath we may be asked to TX all kinds of paths so make sure
1368 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1369 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1370 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1374 /* If this is not the bestpath then check to see if there is an enabled
1376 * feature that requires us to advertise it */
1377 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1378 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1383 /* Aggregate-address suppress check. */
1384 if (ri
->extra
&& ri
->extra
->suppress
)
1385 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1389 /* If it's labeled safi, make sure the route has a valid label. */
1390 if (safi
== SAFI_LABELED_UNICAST
) {
1391 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1392 if (!bgp_is_valid_label(&label
)) {
1393 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1394 zlog_debug("u%" PRIu64
":s%" PRIu64
1395 " %s/%d is filtered - no label (%p)",
1396 subgrp
->update_group
->id
, subgrp
->id
,
1397 inet_ntop(p
->family
, &p
->u
.prefix
,
1398 buf
, SU_ADDRSTRLEN
),
1399 p
->prefixlen
, &label
);
1404 /* Do not send back route to sender. */
1405 if (onlypeer
&& from
== onlypeer
) {
1409 /* Do not send the default route in the BGP table if the neighbor is
1410 * configured for default-originate */
1411 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1412 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1413 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1415 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1419 /* Transparency check. */
1420 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1421 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1426 /* If community is not disabled check the no-export and local. */
1427 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1428 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1430 "subgrpannouncecheck: community filter check fail");
1434 /* If the attribute has originator-id and it is same as remote
1436 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1437 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1438 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1440 "%s [Update:SEND] %s originator-id is same as "
1443 prefix2str(p
, buf
, sizeof(buf
)));
1447 /* ORF prefix-list filter check */
1448 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1449 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1450 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1451 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1452 if (peer
->orf_plist
[afi
][safi
]) {
1453 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1455 if (bgp_debug_update(NULL
, p
,
1456 subgrp
->update_group
, 0))
1458 "%s [Update:SEND] %s is filtered via ORF",
1466 /* Output filter check. */
1467 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1468 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1469 zlog_debug("%s [Update:SEND] %s is filtered",
1470 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1474 #ifdef BGP_SEND_ASPATH_CHECK
1475 /* AS path loop check. */
1476 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1477 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1479 "%s [Update:SEND] suppress announcement to peer AS %u "
1480 "that is part of AS path.",
1481 onlypeer
->host
, onlypeer
->as
);
1484 #endif /* BGP_SEND_ASPATH_CHECK */
1486 /* If we're a CONFED we need to loop check the CONFED ID too */
1487 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1488 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1489 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1491 "%s [Update:SEND] suppress announcement to peer AS %u"
1493 peer
->host
, bgp
->confed_id
);
1498 /* Route-Reflect check. */
1499 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1504 /* IBGP reflection check. */
1505 if (reflect
&& !samepeer_safe
) {
1506 /* A route from a Client peer. */
1507 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1508 PEER_FLAG_REFLECTOR_CLIENT
)) {
1509 /* Reflect to all the Non-Client peers and also to the
1510 Client peers other than the originator. Originator
1512 is already done. So there is noting to do. */
1513 /* no bgp client-to-client reflection check. */
1514 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1515 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1516 PEER_FLAG_REFLECTOR_CLIENT
))
1519 /* A route from a Non-client peer. Reflect to all other
1521 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1522 PEER_FLAG_REFLECTOR_CLIENT
))
1527 /* For modify attribute, copy it to temporary structure. */
1528 bgp_attr_dup(attr
, riattr
);
1530 /* If local-preference is not set. */
1531 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1532 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1533 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1534 attr
->local_pref
= bgp
->default_local_pref
;
1537 /* If originator-id is not set and the route is to be reflected,
1538 set the originator id */
1540 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1541 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1542 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1545 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1547 if (peer
->sort
== BGP_PEER_EBGP
1548 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1549 if (from
!= bgp
->peer_self
&& !transparent
1550 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1551 PEER_FLAG_MED_UNCHANGED
))
1553 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1556 /* Since the nexthop attribute can vary per peer, it is not explicitly
1558 * in announce check, only certain flags and length (or number of
1560 * -- for IPv6/MP_REACH) are set here in order to guide the update
1562 * code in setting the nexthop(s) on a per peer basis in
1564 * Typically, the source nexthop in the attribute is preserved but in
1566 * scenarios where we know it will always be overwritten, we reset the
1567 * nexthop to "0" in an attempt to achieve better Update packing. An
1568 * example of this is when a prefix from each of 2 IBGP peers needs to
1570 * announced to an EBGP peer (and they have the same attributes barring
1574 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1576 #define NEXTHOP_IS_V6 \
1577 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1578 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1579 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1580 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1582 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1584 * the peer (group) is configured to receive link-local nexthop
1586 * and it is available in the prefix OR we're not reflecting the route
1588 * the peer (group) to whom we're going to announce is on a shared
1590 * and this is either a self-originated route or the peer is EBGP.
1592 if (NEXTHOP_IS_V6
) {
1593 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1594 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1595 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1596 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1597 || (!reflect
&& peer
->shared_network
1598 && (from
== bgp
->peer_self
1599 || peer
->sort
== BGP_PEER_EBGP
))) {
1600 attr
->mp_nexthop_len
=
1601 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1604 /* Clear off link-local nexthop in source, whenever it is not
1606 * ensure more prefixes share the same attribute for
1609 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1610 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1611 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1614 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1615 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1617 /* Route map & unsuppress-map apply. */
1618 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1619 struct bgp_info info
;
1620 struct bgp_info_extra dummy_info_extra
;
1621 struct attr dummy_attr
;
1627 memcpy(&dummy_info_extra
, ri
->extra
,
1628 sizeof(struct bgp_info_extra
));
1629 info
.extra
= &dummy_info_extra
;
1632 /* don't confuse inbound and outbound setting */
1633 RESET_FLAG(attr
->rmap_change_flags
);
1636 * The route reflector is not allowed to modify the attributes
1637 * of the reflected IBGP routes unless explicitly allowed.
1639 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1640 && !bgp_flag_check(bgp
,
1641 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1642 bgp_attr_dup(&dummy_attr
, attr
);
1643 info
.attr
= &dummy_attr
;
1646 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1648 if (ri
->extra
&& ri
->extra
->suppress
)
1649 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1652 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1655 peer
->rmap_type
= 0;
1657 if (ret
== RMAP_DENYMATCH
) {
1658 bgp_attr_flush(attr
);
1663 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1664 if (peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
) {
1665 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1666 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1668 bgp_attr_add_gshut_community(attr
);
1672 /* After route-map has been applied, we check to see if the nexthop to
1673 * be carried in the attribute (that is used for the announcement) can
1674 * be cleared off or not. We do this in all cases where we would be
1675 * setting the nexthop to "ourselves". For IPv6, we only need to
1677 * the global nexthop here; the link-local nexthop would have been
1679 * already, and if not, it is required by the update formation code.
1680 * Also see earlier comments in this function.
1683 * If route-map has performed some operation on the nexthop or the peer
1684 * configuration says to pass it unchanged, we cannot reset the nexthop
1685 * here, so only attempt to do it if these aren't true. Note that the
1686 * route-map handler itself might have cleared the nexthop, if for
1688 * it is configured as 'peer-address'.
1690 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1691 riattr
->rmap_change_flags
)
1693 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1694 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1695 /* We can reset the nexthop, if setting (or forcing) it to
1697 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1698 PEER_FLAG_NEXTHOP_SELF
)
1699 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1700 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1702 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1703 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1704 subgroup_announce_reset_nhop(
1705 (peer_cap_enhe(peer
, afi
, safi
)
1709 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1710 /* Can also reset the nexthop if announcing to EBGP, but
1712 * no peer in the subgroup is on a shared subnet.
1713 * Note: 3rd party nexthop currently implemented for
1716 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1718 subgroup_announce_reset_nhop(
1719 (peer_cap_enhe(peer
, afi
, safi
)
1724 /* If IPv6/MP and nexthop does not have any override and happens
1726 * be a link-local address, reset it so that we don't pass along
1728 * source's link-local IPv6 address to recipients who may not be
1730 * the same interface.
1732 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1733 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1734 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1741 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1742 struct bgp_maxpaths_cfg
*mpath_cfg
,
1743 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1745 struct bgp_info
*new_select
;
1746 struct bgp_info
*old_select
;
1747 struct bgp_info
*ri
;
1748 struct bgp_info
*ri1
;
1749 struct bgp_info
*ri2
;
1750 struct bgp_info
*nextri
= NULL
;
1751 int paths_eq
, do_mpath
, debug
;
1752 struct list mp_list
;
1753 char pfx_buf
[PREFIX2STR_BUFFER
];
1754 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1756 bgp_mp_list_init(&mp_list
);
1758 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1760 debug
= bgp_debug_bestpath(&rn
->p
);
1763 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1765 /* bgp deterministic-med */
1767 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1769 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1770 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1771 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1773 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1774 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1776 if (BGP_INFO_HOLDDOWN(ri1
))
1778 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1779 if (ri1
->peer
->status
!= Established
)
1784 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1785 if (CHECK_FLAG(ri2
->flags
,
1786 BGP_INFO_DMED_CHECK
))
1788 if (BGP_INFO_HOLDDOWN(ri2
))
1791 && ri2
->peer
!= bgp
->peer_self
1794 PEER_STATUS_NSF_WAIT
))
1795 if (ri2
->peer
->status
1799 if (aspath_cmp_left(ri1
->attr
->aspath
,
1801 || aspath_cmp_left_confed(
1803 ri2
->attr
->aspath
)) {
1804 if (bgp_info_cmp(bgp
, ri2
,
1810 bgp_info_unset_flag(
1812 BGP_INFO_DMED_SELECTED
);
1818 BGP_INFO_DMED_CHECK
);
1822 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1823 bgp_info_set_flag(rn
, new_select
,
1824 BGP_INFO_DMED_SELECTED
);
1827 bgp_info_path_with_addpath_rx_str(new_select
,
1829 zlog_debug("%s: %s is the bestpath from AS %d",
1831 aspath_get_first_as(
1832 new_select
->attr
->aspath
));
1837 /* Check old selected route and new selected route. */
1840 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1842 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1845 if (BGP_INFO_HOLDDOWN(ri
)) {
1846 /* reap REMOVED routes, if needs be
1847 * selected route must stay for a while longer though
1849 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1850 && (ri
!= old_select
))
1851 bgp_info_reap(rn
, ri
);
1856 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1857 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1858 if (ri
->peer
->status
!= Established
)
1861 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1862 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1863 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1867 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1869 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1870 debug
, pfx_buf
, afi
, safi
)) {
1875 /* Now that we know which path is the bestpath see if any of the other
1877 * qualify as multipaths
1881 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1883 sprintf(path_buf
, "NONE");
1885 "%s: After path selection, newbest is %s oldbest was %s",
1887 old_select
? old_select
->peer
->host
: "NONE");
1890 if (do_mpath
&& new_select
) {
1891 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1895 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1897 if (ri
== new_select
) {
1900 "%s: %s is the bestpath, add to the multipath list",
1902 bgp_mp_list_add(&mp_list
, ri
);
1906 if (BGP_INFO_HOLDDOWN(ri
))
1909 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1910 && !CHECK_FLAG(ri
->peer
->sflags
,
1911 PEER_STATUS_NSF_WAIT
))
1912 if (ri
->peer
->status
!= Established
)
1915 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1918 "%s: %s has the same nexthop as the bestpath, skip it",
1923 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1924 debug
, pfx_buf
, afi
, safi
);
1929 "%s: %s is equivalent to the bestpath, add to the multipath list",
1931 bgp_mp_list_add(&mp_list
, ri
);
1936 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1937 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1938 bgp_mp_list_clear(&mp_list
);
1940 result
->old
= old_select
;
1941 result
->new = new_select
;
1947 * A new route/change in bestpath of an existing route. Evaluate the path
1948 * for advertisement to the subgroup.
1950 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1951 struct bgp_info
*selected
,
1952 struct bgp_node
*rn
,
1953 u_int32_t addpath_tx_id
)
1956 struct peer
*onlypeer
;
1962 afi
= SUBGRP_AFI(subgrp
);
1963 safi
= SUBGRP_SAFI(subgrp
);
1964 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1967 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1968 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1969 PEER_STATUS_ORF_WAIT_REFRESH
))
1972 memset(&attr
, 0, sizeof(struct attr
));
1973 /* It's initialized in bgp_announce_check() */
1975 /* Announcement to the subgroup. If the route is filtered withdraw it.
1978 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1979 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1981 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1982 selected
->addpath_tx_id
);
1985 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1987 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1994 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1995 * This is called at the end of route processing.
1997 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
1999 struct bgp_info
*ri
;
2001 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2002 if (BGP_INFO_HOLDDOWN(ri
))
2004 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2005 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2010 * Has the route changed from the RIB's perspective? This is invoked only
2011 * if the route selection returns the same best route as earlier - to
2012 * determine if we need to update zebra or not.
2014 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2016 struct bgp_info
*mpinfo
;
2018 /* If this is multipath, check all selected paths for any nexthop change
2020 * attribute change. Some attribute changes (e.g., community) aren't of
2021 * relevance to the RIB, but we'll update zebra to ensure we handle the
2022 * case of BGP nexthop change. This is the behavior when the best path
2024 * an attribute change anyway.
2026 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2027 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2030 /* If this is multipath, check all selected paths for any nexthop change
2032 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2033 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2034 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2035 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2039 /* Nothing has changed from the RIB's perspective. */
2043 struct bgp_process_queue
{
2045 STAILQ_HEAD(, bgp_node
)pqueue
;
2046 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2048 unsigned int queued
;
2051 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2052 afi_t afi
, safi_t safi
)
2054 struct prefix
*p
= &rn
->p
;
2055 struct bgp_info
*new_select
;
2056 struct bgp_info
*old_select
;
2057 struct bgp_info_pair old_and_new
;
2059 /* Is it end of initial update? (after startup) */
2061 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2062 sizeof(bgp
->update_delay_zebra_resume_time
));
2064 bgp
->main_zebra_update_hold
= 0;
2065 FOREACH_AFI_SAFI (afi
, safi
) {
2066 if (bgp_fibupd_safi(safi
))
2067 bgp_zebra_announce_table(bgp
, afi
, safi
);
2069 bgp
->main_peers_update_hold
= 0;
2071 bgp_start_routeadv(bgp
);
2075 /* Best path selection. */
2076 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2078 old_select
= old_and_new
.old
;
2079 new_select
= old_and_new
.new;
2081 /* Do we need to allocate or free labels?
2082 * Right now, since we only deal with per-prefix labels, it is not
2083 * necessary to do this upon changes to best path except if the label
2086 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2089 || bgp_label_index_differs(new_select
, old_select
)
2090 || new_select
->sub_type
!= old_select
->sub_type
) {
2091 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2092 && new_select
->attr
->flag
2094 BGP_ATTR_PREFIX_SID
)
2095 && new_select
->attr
->label_index
2096 != BGP_INVALID_LABEL_INDEX
) {
2099 BGP_NODE_REGISTERED_FOR_LABEL
))
2100 bgp_unregister_for_label(rn
);
2101 label_ntop(MPLS_IMP_NULL_LABEL
, 1,
2103 bgp_set_valid_label(&rn
->local_label
);
2105 bgp_register_for_label(rn
, new_select
);
2107 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2108 bgp_unregister_for_label(rn
);
2110 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2111 bgp_unregister_for_label(rn
);
2114 /* If best route remains the same and this is not due to user-initiated
2115 * clear, see exactly what needs to be done.
2118 if (old_select
&& old_select
== new_select
2119 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2120 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2121 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2122 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2124 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2125 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2127 if (bgp_fibupd_safi(safi
)
2128 && !bgp_option_check(BGP_OPT_NO_FIB
)
2129 && new_select
->type
== ZEBRA_ROUTE_BGP
2130 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2131 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2134 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2135 bgp_zebra_clear_route_change_flags(rn
);
2137 /* If there is a change of interest to peers, reannounce the
2139 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2140 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2141 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2143 /* unicast routes must also be annouced to
2144 * labeled-unicast update-groups */
2145 if (safi
== SAFI_UNICAST
)
2146 group_announce_route(bgp
, afi
,
2147 SAFI_LABELED_UNICAST
, rn
,
2150 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2151 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2154 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2158 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2160 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2162 /* bestpath has changed; bump version */
2163 if (old_select
|| new_select
) {
2164 bgp_bump_version(rn
);
2166 if (!bgp
->t_rmap_def_originate_eval
) {
2170 update_group_refresh_default_originate_route_map
,
2171 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2172 &bgp
->t_rmap_def_originate_eval
);
2177 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2179 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2180 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2181 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2185 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2186 if (old_select
!= new_select
) {
2188 vnc_import_bgp_exterior_del_route(bgp
, p
,
2190 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2193 vnc_import_bgp_exterior_add_route(bgp
, p
,
2195 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2201 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2203 /* unicast routes must also be annouced to labeled-unicast update-groups
2205 if (safi
== SAFI_UNICAST
)
2206 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2210 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2211 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2212 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2213 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2214 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2215 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2217 /* Withdraw the route from the kernel. */
2218 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2219 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2220 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2221 bgp_zebra_withdraw(p
, old_select
, safi
);
2225 /* Clear any route change flags. */
2226 bgp_zebra_clear_route_change_flags(rn
);
2228 /* Reap old select bgp_info, if it has been removed */
2229 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2230 bgp_info_reap(rn
, old_select
);
2232 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2236 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2238 struct bgp_process_queue
*pqnode
= data
;
2239 struct bgp
*bgp
= pqnode
->bgp
;
2240 struct bgp_table
*table
;
2241 struct bgp_node
*rn
;
2244 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2245 bgp_process_main_one(bgp
, NULL
, 0, 0);
2246 /* should always have dedicated wq call */
2247 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2251 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2252 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2253 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2254 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2255 table
= bgp_node_table(rn
);
2256 /* note, new RNs may be added as part of processing */
2257 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2259 bgp_unlock_node(rn
);
2260 bgp_table_unlock(table
);
2266 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2268 struct bgp_process_queue
*pqnode
= data
;
2270 bgp_unlock(pqnode
->bgp
);
2272 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2275 void bgp_process_queue_init(void)
2277 if (!bm
->process_main_queue
) {
2278 bm
->process_main_queue
=
2279 work_queue_new(bm
->master
, "process_main_queue");
2281 if (!bm
->process_main_queue
) {
2282 zlog_err("%s: Failed to allocate work queue", __func__
);
2287 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2288 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2289 bm
->process_main_queue
->spec
.max_retries
= 0;
2290 bm
->process_main_queue
->spec
.hold
= 50;
2291 /* Use a higher yield value of 50ms for main queue processing */
2292 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2295 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2297 struct bgp_process_queue
*pqnode
;
2299 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
, sizeof(struct bgp_process_queue
));
2301 /* unlocked in bgp_processq_del */
2302 pqnode
->bgp
= bgp_lock(bgp
);
2303 STAILQ_INIT(&pqnode
->pqueue
);
2308 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2310 #define ARBITRARY_PROCESS_QLEN 10000
2311 struct work_queue
*wq
= bm
->process_main_queue
;
2312 struct bgp_process_queue
*pqnode
;
2313 int pqnode_reuse
= 0;
2315 /* already scheduled for processing? */
2316 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2322 /* Add route nodes to an existing work queue item until reaching the
2323 limit only if is from the same BGP view and it's not an EOIU marker */
2324 if (work_queue_item_count(wq
)) {
2325 struct work_queue_item
*item
= work_queue_last_item(wq
);
2326 pqnode
= item
->data
;
2328 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
) ||
2329 pqnode
->bgp
!= bgp
|| pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2330 pqnode
= bgp_processq_alloc(bgp
);
2334 pqnode
= bgp_processq_alloc(bgp
);
2335 /* all unlocked in bgp_process_wq */
2336 bgp_table_lock(bgp_node_table(rn
));
2338 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2341 /* can't be enqueued twice */
2342 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2343 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2347 work_queue_add(wq
, pqnode
);
2352 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2354 struct bgp_process_queue
*pqnode
;
2356 if (bm
->process_main_queue
== NULL
)
2359 pqnode
= bgp_processq_alloc(bgp
);
2361 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2362 work_queue_add(bm
->process_main_queue
, pqnode
);
2365 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2369 peer
= THREAD_ARG(thread
);
2370 peer
->t_pmax_restart
= NULL
;
2372 if (bgp_debug_neighbor_events(peer
))
2374 "%s Maximum-prefix restart timer expired, restore peering",
2377 peer_clear(peer
, NULL
);
2382 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2386 iana_safi_t pkt_safi
;
2388 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2391 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2392 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2393 PEER_STATUS_PREFIX_LIMIT
)
2398 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2400 afi_safi_print(afi
, safi
), peer
->host
,
2401 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2402 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2404 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2405 PEER_FLAG_MAX_PREFIX_WARNING
))
2408 /* Convert AFI, SAFI to values for packet. */
2409 pkt_afi
= afi_int2iana(afi
);
2410 pkt_safi
= safi_int2iana(safi
);
2414 ndata
[0] = (pkt_afi
>> 8);
2416 ndata
[2] = pkt_safi
;
2417 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2418 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2419 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2420 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2422 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2423 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2424 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2428 /* Dynamic peers will just close their connection. */
2429 if (peer_dynamic_neighbor(peer
))
2432 /* restart timer start */
2433 if (peer
->pmax_restart
[afi
][safi
]) {
2434 peer
->v_pmax_restart
=
2435 peer
->pmax_restart
[afi
][safi
] * 60;
2437 if (bgp_debug_neighbor_events(peer
))
2439 "%s Maximum-prefix restart timer started for %d secs",
2440 peer
->host
, peer
->v_pmax_restart
);
2442 BGP_TIMER_ON(peer
->t_pmax_restart
,
2443 bgp_maximum_prefix_restart_timer
,
2444 peer
->v_pmax_restart
);
2449 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2450 PEER_STATUS_PREFIX_LIMIT
);
2452 if (peer
->pcount
[afi
][safi
]
2453 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2454 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2455 PEER_STATUS_PREFIX_THRESHOLD
)
2460 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2461 afi_safi_print(afi
, safi
), peer
->host
,
2462 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2463 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2464 PEER_STATUS_PREFIX_THRESHOLD
);
2466 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2467 PEER_STATUS_PREFIX_THRESHOLD
);
2471 /* Unconditionally remove the route from the RIB, without taking
2472 * damping into consideration (eg, because the session went down)
2474 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2475 afi_t afi
, safi_t safi
)
2477 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2479 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2480 bgp_info_delete(rn
, ri
); /* keep historical info */
2482 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2485 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2486 struct peer
*peer
, afi_t afi
, safi_t safi
,
2487 struct prefix_rd
*prd
)
2489 int status
= BGP_DAMP_NONE
;
2491 /* apply dampening, if result is suppressed, we'll be retaining
2492 * the bgp_info in the RIB for historical reference.
2494 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2495 && peer
->sort
== BGP_PEER_EBGP
)
2496 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2497 == BGP_DAMP_SUPPRESSED
) {
2498 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2504 if (safi
== SAFI_MPLS_VPN
) {
2505 struct bgp_node
*prn
= NULL
;
2506 struct bgp_table
*table
= NULL
;
2508 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2509 (struct prefix
*)prd
);
2511 table
= (struct bgp_table
*)(prn
->info
);
2513 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2514 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2516 bgp_unlock_node(prn
);
2518 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2519 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2521 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2522 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2528 /* If this is an EVPN route, process for un-import. */
2529 if (safi
== SAFI_EVPN
)
2530 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2532 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2535 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2536 struct peer
*peer
, struct attr
*attr
,
2537 struct bgp_node
*rn
)
2539 struct bgp_info
*new;
2541 /* Make new BGP info. */
2542 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2544 new->instance
= instance
;
2545 new->sub_type
= sub_type
;
2548 new->uptime
= bgp_clock();
2550 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2554 static void overlay_index_update(struct attr
*attr
,
2555 struct eth_segment_id
*eth_s_id
,
2556 union gw_addr
*gw_ip
)
2561 if (eth_s_id
== NULL
) {
2562 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2563 sizeof(struct eth_segment_id
));
2565 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2566 sizeof(struct eth_segment_id
));
2568 if (gw_ip
== NULL
) {
2569 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2571 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2572 sizeof(union gw_addr
));
2576 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2577 struct eth_segment_id
*eth_s_id
,
2578 union gw_addr
*gw_ip
)
2580 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2581 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2584 if (afi
!= AFI_L2VPN
)
2587 memset(&temp
, 0, 16);
2588 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2589 info_gw_ip
= (union gw_addr
*)&temp
;
2590 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2593 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2594 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2597 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2599 info_gw_ip_remote
= gw_ip
;
2600 if (eth_s_id
== NULL
)
2601 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2603 info_eth_s_id_remote
= eth_s_id
;
2604 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2606 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2607 sizeof(struct eth_segment_id
));
2610 /* Check if received nexthop is valid or not. */
2611 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2616 /* Only validated for unicast and multicast currently. */
2617 /* Also valid for EVPN where the nexthop is an IP address. */
2618 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2621 /* If NEXT_HOP is present, validate it. */
2622 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2623 if (attr
->nexthop
.s_addr
== 0
2624 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2625 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2629 /* If MP_NEXTHOP is present, validate it. */
2630 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2631 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2632 * it is not an IPv6 link-local address.
2634 if (attr
->mp_nexthop_len
) {
2635 switch (attr
->mp_nexthop_len
) {
2636 case BGP_ATTR_NHLEN_IPV4
:
2637 case BGP_ATTR_NHLEN_VPNV4
:
2638 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2639 || IPV4_CLASS_DE(ntohl(
2640 attr
->mp_nexthop_global_in
.s_addr
))
2641 || bgp_nexthop_self(bgp
,
2642 attr
->mp_nexthop_global_in
));
2645 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2646 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2647 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2648 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2649 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2650 || IN6_IS_ADDR_MULTICAST(
2651 &attr
->mp_nexthop_global
));
2663 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2664 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2665 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2666 int soft_reconfig
, struct bgp_route_evpn
*evpn
)
2669 int aspath_loop_count
= 0;
2670 struct bgp_node
*rn
;
2672 struct attr new_attr
;
2673 struct attr
*attr_new
;
2674 struct bgp_info
*ri
;
2675 struct bgp_info
*new;
2677 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2680 int do_loop_check
= 1;
2681 int has_valid_label
= 0;
2683 int vnc_implicit_withdraw
= 0;
2687 memset(&new_attr
, 0, sizeof(struct attr
));
2688 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2689 new_attr
.label
= MPLS_INVALID_LABEL
;
2692 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2693 has_valid_label
= bgp_is_valid_label(label
);
2695 if (has_valid_label
)
2696 sprintf(label_buf
, "label %u", label_pton(label
));
2698 /* When peer's soft reconfiguration enabled. Record input packet in
2701 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2702 && peer
!= bgp
->peer_self
)
2703 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2705 /* Check previously received route. */
2706 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2707 if (ri
->peer
== peer
&& ri
->type
== type
2708 && ri
->sub_type
== sub_type
2709 && ri
->addpath_rx_id
== addpath_id
)
2712 /* AS path local-as loop check. */
2713 if (peer
->change_local_as
) {
2714 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2715 aspath_loop_count
= 1;
2717 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2718 > aspath_loop_count
) {
2719 reason
= "as-path contains our own AS;";
2724 /* If the peer is configured for "allowas-in origin" and the last ASN in
2726 * as-path is our ASN then we do not need to call aspath_loop_check
2728 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2729 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2732 /* AS path loop check. */
2733 if (do_loop_check
) {
2734 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2735 > peer
->allowas_in
[afi
][safi
]
2736 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2737 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2738 > peer
->allowas_in
[afi
][safi
])) {
2739 reason
= "as-path contains our own AS;";
2744 /* Route reflector originator ID check. */
2745 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2746 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2747 reason
= "originator is us;";
2751 /* Route reflector cluster ID check. */
2752 if (bgp_cluster_filter(peer
, attr
)) {
2753 reason
= "reflected from the same cluster;";
2757 /* Apply incoming filter. */
2758 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2763 bgp_attr_dup(&new_attr
, attr
);
2765 /* Apply incoming route-map.
2766 * NB: new_attr may now contain newly allocated values from route-map
2768 * commands, so we need bgp_attr_flush in the error paths, until we
2770 * the attr (which takes over the memory references) */
2771 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2773 reason
= "route-map;";
2774 bgp_attr_flush(&new_attr
);
2778 if (peer
->sort
== BGP_PEER_EBGP
) {
2780 /* If we receive the graceful-shutdown community from an eBGP peer we
2781 * must lower local-preference */
2782 if (new_attr
.community
&&
2783 community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2784 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2785 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2787 /* If graceful-shutdown is configured then add the GSHUT community to
2788 * all paths received from eBGP peers */
2789 } else if (bgp_flag_check(peer
->bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2790 bgp_attr_add_gshut_community(&new_attr
);
2794 /* next hop check. */
2795 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
) &&
2796 bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2797 reason
= "martian or self next-hop;";
2798 bgp_attr_flush(&new_attr
);
2802 attr_new
= bgp_attr_intern(&new_attr
);
2804 /* If the update is implicit withdraw. */
2806 ri
->uptime
= bgp_clock();
2807 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2809 /* Same attribute comes in. */
2810 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2811 && attrhash_cmp(ri
->attr
, attr_new
)
2812 && (!has_valid_label
2813 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2816 && (overlay_index_equal(
2817 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2818 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2819 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2820 BGP_CONFIG_DAMPENING
)
2821 && peer
->sort
== BGP_PEER_EBGP
2822 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2823 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2824 bgp_debug_rdpfxpath2str(
2825 afi
, safi
, prd
, p
, label
,
2826 addpath_id
? 1 : 0, addpath_id
,
2827 pfx_buf
, sizeof(pfx_buf
));
2828 zlog_debug("%s rcvd %s", peer
->host
,
2832 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2833 != BGP_DAMP_SUPPRESSED
) {
2834 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2836 bgp_process(bgp
, rn
, afi
, safi
);
2838 } else /* Duplicate - odd */
2840 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2841 if (!peer
->rcvd_attr_printed
) {
2843 "%s rcvd UPDATE w/ attr: %s",
2845 peer
->rcvd_attr_str
);
2846 peer
->rcvd_attr_printed
= 1;
2849 bgp_debug_rdpfxpath2str(
2850 afi
, safi
, prd
, p
, label
,
2851 addpath_id
? 1 : 0, addpath_id
,
2852 pfx_buf
, sizeof(pfx_buf
));
2854 "%s rcvd %s...duplicate ignored",
2855 peer
->host
, pfx_buf
);
2858 /* graceful restart STALE flag unset. */
2859 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2860 bgp_info_unset_flag(rn
, ri
,
2862 bgp_process(bgp
, rn
, afi
, safi
);
2866 bgp_unlock_node(rn
);
2867 bgp_attr_unintern(&attr_new
);
2872 /* Withdraw/Announce before we fully processed the withdraw */
2873 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2874 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2875 bgp_debug_rdpfxpath2str(
2876 afi
, safi
, prd
, p
, label
,
2877 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2880 "%s rcvd %s, flapped quicker than processing",
2881 peer
->host
, pfx_buf
);
2884 bgp_info_restore(rn
, ri
);
2887 /* Received Logging. */
2888 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2889 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2890 addpath_id
? 1 : 0, addpath_id
,
2891 pfx_buf
, sizeof(pfx_buf
));
2892 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2895 /* graceful restart STALE flag unset. */
2896 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2897 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2899 /* The attribute is changed. */
2900 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2902 /* implicit withdraw, decrement aggregate and pcount here.
2903 * only if update is accepted, they'll increment below.
2905 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2907 /* Update bgp route dampening information. */
2908 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2909 && peer
->sort
== BGP_PEER_EBGP
) {
2910 /* This is implicit withdraw so we should update
2913 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2914 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2917 if (safi
== SAFI_MPLS_VPN
) {
2918 struct bgp_node
*prn
= NULL
;
2919 struct bgp_table
*table
= NULL
;
2921 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2922 (struct prefix
*)prd
);
2924 table
= (struct bgp_table
*)(prn
->info
);
2926 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2927 bgp
, prd
, table
, p
, ri
);
2929 bgp_unlock_node(prn
);
2931 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2932 && (safi
== SAFI_UNICAST
)) {
2933 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2935 * Implicit withdraw case.
2937 ++vnc_implicit_withdraw
;
2938 vnc_import_bgp_del_route(bgp
, p
, ri
);
2939 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2944 /* Special handling for EVPN update of an existing route. If the
2945 * extended community attribute has changed, we need to
2947 * the route using its existing extended community. It will be
2948 * subsequently processed for import with the new extended
2951 if (safi
== SAFI_EVPN
&& !same_attr
) {
2953 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2955 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2958 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2959 attr_new
->ecommunity
);
2961 if (bgp_debug_update(peer
, p
, NULL
, 1))
2963 "Change in EXT-COMM, existing %s new %s",
2965 ri
->attr
->ecommunity
),
2967 attr_new
->ecommunity
));
2968 bgp_evpn_unimport_route(bgp
, afi
, safi
,
2974 /* Update to new attribute. */
2975 bgp_attr_unintern(&ri
->attr
);
2976 ri
->attr
= attr_new
;
2978 /* Update MPLS label */
2979 if (has_valid_label
) {
2980 memcpy(&(bgp_info_extra_get(ri
))->label
, label
,
2982 bgp_set_valid_label(&(bgp_info_extra_get(ri
))->label
);
2986 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2987 && (safi
== SAFI_UNICAST
)) {
2988 if (vnc_implicit_withdraw
) {
2990 * Add back the route with its new attributes
2992 * The route is still selected, until the route
2994 * queued by bgp_process actually runs. We have
2996 * update to the VNC side immediately to avoid
2998 * configuration changes (e.g., route-map
3000 * trigger re-importation of the entire RIB.
3002 vnc_import_bgp_add_route(bgp
, p
, ri
);
3003 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3007 /* Update Overlay Index */
3008 if (afi
== AFI_L2VPN
) {
3009 overlay_index_update(
3010 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3011 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3014 /* Update bgp route dampening information. */
3015 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3016 && peer
->sort
== BGP_PEER_EBGP
) {
3017 /* Now we do normal update dampening. */
3018 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3019 if (ret
== BGP_DAMP_SUPPRESSED
) {
3020 bgp_unlock_node(rn
);
3025 /* Nexthop reachability check - for unicast and
3026 * labeled-unicast.. */
3027 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3028 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3029 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3030 && !CHECK_FLAG(peer
->flags
,
3031 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3033 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3038 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
3040 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3041 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3043 if (BGP_DEBUG(nht
, NHT
)) {
3044 char buf1
[INET6_ADDRSTRLEN
];
3046 (const void *)&attr_new
3048 buf1
, INET6_ADDRSTRLEN
);
3049 zlog_debug("%s(%s): NH unresolved",
3050 __FUNCTION__
, buf1
);
3052 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3055 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3058 if (safi
== SAFI_MPLS_VPN
) {
3059 struct bgp_node
*prn
= NULL
;
3060 struct bgp_table
*table
= NULL
;
3062 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3063 (struct prefix
*)prd
);
3065 table
= (struct bgp_table
*)(prn
->info
);
3067 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3068 bgp
, prd
, table
, p
, ri
);
3070 bgp_unlock_node(prn
);
3074 /* If this is an EVPN route and some attribute has changed,
3076 * route for import. If the extended community has changed, we
3078 * have done the un-import earlier and the import would result
3080 * route getting injected into appropriate L2 VNIs. If it is
3082 * some other attribute change, the import will result in
3084 * the attributes for the route in the VNI(s).
3086 if (safi
== SAFI_EVPN
&& !same_attr
)
3087 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3089 /* Process change. */
3090 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3092 bgp_process(bgp
, rn
, afi
, safi
);
3093 bgp_unlock_node(rn
);
3096 if (SAFI_MPLS_VPN
== safi
) {
3097 mpls_label_t label_decoded
= decode_label(label
);
3099 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3100 type
, sub_type
, &label_decoded
);
3102 if (SAFI_ENCAP
== safi
) {
3103 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3104 type
, sub_type
, NULL
);
3109 } // End of implicit withdraw
3111 /* Received Logging. */
3112 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3113 if (!peer
->rcvd_attr_printed
) {
3114 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3115 peer
->rcvd_attr_str
);
3116 peer
->rcvd_attr_printed
= 1;
3119 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3120 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3122 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3125 /* Make new BGP info. */
3126 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3128 /* Update MPLS label */
3129 if (has_valid_label
) {
3130 memcpy(&(bgp_info_extra_get(new))->label
, label
,
3132 bgp_set_valid_label(&(bgp_info_extra_get(new))->label
);
3135 /* Update Overlay Index */
3136 if (afi
== AFI_L2VPN
) {
3137 overlay_index_update(new->attr
,
3138 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3139 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3141 /* Nexthop reachability check. */
3142 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3143 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3144 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3145 && !CHECK_FLAG(peer
->flags
,
3146 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3147 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3152 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
) ||
3153 CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3154 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3156 if (BGP_DEBUG(nht
, NHT
)) {
3157 char buf1
[INET6_ADDRSTRLEN
];
3159 (const void *)&attr_new
->nexthop
,
3160 buf1
, INET6_ADDRSTRLEN
);
3161 zlog_debug("%s(%s): NH unresolved",
3162 __FUNCTION__
, buf1
);
3164 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3167 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3170 new->addpath_rx_id
= addpath_id
;
3172 /* Increment prefix */
3173 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3175 /* Register new BGP information. */
3176 bgp_info_add(rn
, new);
3178 /* route_node_get lock */
3179 bgp_unlock_node(rn
);
3182 if (safi
== SAFI_MPLS_VPN
) {
3183 struct bgp_node
*prn
= NULL
;
3184 struct bgp_table
*table
= NULL
;
3186 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3188 table
= (struct bgp_table
*)(prn
->info
);
3190 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3191 bgp
, prd
, table
, p
, new);
3193 bgp_unlock_node(prn
);
3197 /* If maximum prefix count is configured and current prefix
3199 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3202 /* If this is an EVPN route, process for import. */
3203 if (safi
== SAFI_EVPN
)
3204 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3206 /* Process change. */
3207 bgp_process(bgp
, rn
, afi
, safi
);
3210 if (SAFI_MPLS_VPN
== safi
) {
3211 mpls_label_t label_decoded
= decode_label(label
);
3213 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3214 sub_type
, &label_decoded
);
3216 if (SAFI_ENCAP
== safi
) {
3217 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3224 /* This BGP update is filtered. Log the reason then update BGP
3227 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3228 if (!peer
->rcvd_attr_printed
) {
3229 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3230 peer
->rcvd_attr_str
);
3231 peer
->rcvd_attr_printed
= 1;
3234 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3235 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3237 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3238 peer
->host
, pfx_buf
, reason
);
3242 /* If this is an EVPN route, un-import it as it is now filtered.
3244 if (safi
== SAFI_EVPN
)
3245 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3247 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3250 bgp_unlock_node(rn
);
3254 * Filtered update is treated as an implicit withdrawal (see
3256 * a few lines above)
3258 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3259 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3267 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3268 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3269 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3270 struct bgp_route_evpn
*evpn
)
3273 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3274 struct bgp_node
*rn
;
3275 struct bgp_info
*ri
;
3278 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3279 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3287 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3289 /* If peer is soft reconfiguration enabled. Record input packet for
3290 * further calculation.
3292 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3293 * routes that are filtered. This tanks out Quagga RS pretty badly due
3295 * the iteration over all RS clients.
3296 * Since we need to remove the entry from adj_in anyway, do that first
3298 * if there was no entry, we don't need to do anything more.
3300 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3301 && peer
!= bgp
->peer_self
)
3302 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3303 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3304 bgp_debug_rdpfxpath2str(
3305 afi
, safi
, prd
, p
, label
,
3306 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3309 "%s withdrawing route %s not in adj-in",
3310 peer
->host
, pfx_buf
);
3312 bgp_unlock_node(rn
);
3316 /* Lookup withdrawn route. */
3317 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3318 if (ri
->peer
== peer
&& ri
->type
== type
3319 && ri
->sub_type
== sub_type
3320 && ri
->addpath_rx_id
== addpath_id
)
3324 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3325 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3326 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3328 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3332 /* Withdraw specified route from routing table. */
3333 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3334 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3335 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3336 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3337 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3339 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3342 /* Unlock bgp_node_get() lock. */
3343 bgp_unlock_node(rn
);
3348 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3351 struct update_subgroup
*subgrp
;
3352 subgrp
= peer_subgroup(peer
, afi
, safi
);
3353 subgroup_default_originate(subgrp
, withdraw
);
3358 * bgp_stop_announce_route_timer
3360 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3362 if (!paf
->t_announce_route
)
3365 THREAD_TIMER_OFF(paf
->t_announce_route
);
3369 * bgp_announce_route_timer_expired
3371 * Callback that is invoked when the route announcement timer for a
3374 static int bgp_announce_route_timer_expired(struct thread
*t
)
3376 struct peer_af
*paf
;
3379 paf
= THREAD_ARG(t
);
3382 if (peer
->status
!= Established
)
3385 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3388 peer_af_announce_route(paf
, 1);
3393 * bgp_announce_route
3395 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3397 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3399 struct peer_af
*paf
;
3400 struct update_subgroup
*subgrp
;
3402 paf
= peer_af_find(peer
, afi
, safi
);
3405 subgrp
= PAF_SUBGRP(paf
);
3408 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3409 * or a refresh has already been triggered.
3411 if (!subgrp
|| paf
->t_announce_route
)
3415 * Start a timer to stagger/delay the announce. This serves
3416 * two purposes - announcement can potentially be combined for
3417 * multiple peers and the announcement doesn't happen in the
3420 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3421 (subgrp
->peer_count
== 1)
3422 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3423 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3424 &paf
->t_announce_route
);
3428 * Announce routes from all AF tables to a peer.
3430 * This should ONLY be called when there is a need to refresh the
3431 * routes to the peer based on a policy change for this peer alone
3432 * or a route refresh request received from the peer.
3433 * The operation will result in splitting the peer from its existing
3434 * subgroups and putting it in new subgroups.
3436 void bgp_announce_route_all(struct peer
*peer
)
3441 FOREACH_AFI_SAFI (afi
, safi
)
3442 bgp_announce_route(peer
, afi
, safi
);
3445 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3446 struct bgp_table
*table
,
3447 struct prefix_rd
*prd
)
3450 struct bgp_node
*rn
;
3451 struct bgp_adj_in
*ain
;
3454 table
= peer
->bgp
->rib
[afi
][safi
];
3456 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3457 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3458 if (ain
->peer
!= peer
)
3461 struct bgp_info
*ri
= rn
->info
;
3462 mpls_label_t label
= (ri
&& ri
->extra
)
3464 : MPLS_INVALID_LABEL
;
3466 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3467 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3468 BGP_ROUTE_NORMAL
, prd
, &label
, 1,
3472 bgp_unlock_node(rn
);
3478 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3480 struct bgp_node
*rn
;
3481 struct bgp_table
*table
;
3483 if (peer
->status
!= Established
)
3486 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3487 && (safi
!= SAFI_EVPN
))
3488 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3490 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3491 rn
= bgp_route_next(rn
))
3492 if ((table
= rn
->info
) != NULL
) {
3493 struct prefix_rd prd
;
3494 prd
.family
= AF_UNSPEC
;
3496 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3498 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3504 struct bgp_clear_node_queue
{
3505 struct bgp_node
*rn
;
3508 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3510 struct bgp_clear_node_queue
*cnq
= data
;
3511 struct bgp_node
*rn
= cnq
->rn
;
3512 struct peer
*peer
= wq
->spec
.data
;
3513 struct bgp_info
*ri
;
3514 afi_t afi
= bgp_node_table(rn
)->afi
;
3515 safi_t safi
= bgp_node_table(rn
)->safi
;
3519 /* It is possible that we have multiple paths for a prefix from a peer
3520 * if that peer is using AddPath.
3522 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3523 if (ri
->peer
!= peer
)
3526 /* graceful restart STALE flag set. */
3527 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3528 && peer
->nsf
[afi
][safi
]
3529 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3530 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3531 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3533 /* If this is an EVPN route, process for
3535 if (safi
== SAFI_EVPN
)
3536 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
,
3538 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3544 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3546 struct bgp_clear_node_queue
*cnq
= data
;
3547 struct bgp_node
*rn
= cnq
->rn
;
3548 struct bgp_table
*table
= bgp_node_table(rn
);
3550 bgp_unlock_node(rn
);
3551 bgp_table_unlock(table
);
3552 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3555 static void bgp_clear_node_complete(struct work_queue
*wq
)
3557 struct peer
*peer
= wq
->spec
.data
;
3559 /* Tickle FSM to start moving again */
3560 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3562 peer_unlock(peer
); /* bgp_clear_route */
3565 static void bgp_clear_node_queue_init(struct peer
*peer
)
3567 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3569 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3570 #undef CLEAR_QUEUE_NAME_LEN
3572 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3574 zlog_err("%s: Failed to allocate work queue", __func__
);
3577 peer
->clear_node_queue
->spec
.hold
= 10;
3578 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3579 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3580 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3581 peer
->clear_node_queue
->spec
.max_retries
= 0;
3583 /* we only 'lock' this peer reference when the queue is actually active
3585 peer
->clear_node_queue
->spec
.data
= peer
;
3588 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3589 struct bgp_table
*table
)
3591 struct bgp_node
*rn
;
3592 int force
= bm
->process_main_queue
? 0 : 1;
3595 table
= peer
->bgp
->rib
[afi
][safi
];
3597 /* If still no table => afi/safi isn't configured at all or smth. */
3601 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3602 struct bgp_info
*ri
, *next
;
3603 struct bgp_adj_in
*ain
;
3604 struct bgp_adj_in
*ain_next
;
3606 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3607 * queued for every clearing peer, regardless of whether it is
3608 * relevant to the peer at hand.
3610 * Overview: There are 3 different indices which need to be
3611 * scrubbed, potentially, when a peer is removed:
3613 * 1 peer's routes visible via the RIB (ie accepted routes)
3614 * 2 peer's routes visible by the (optional) peer's adj-in index
3615 * 3 other routes visible by the peer's adj-out index
3617 * 3 there is no hurry in scrubbing, once the struct peer is
3618 * removed from bgp->peer, we could just GC such deleted peer's
3619 * adj-outs at our leisure.
3621 * 1 and 2 must be 'scrubbed' in some way, at least made
3622 * invisible via RIB index before peer session is allowed to be
3623 * brought back up. So one needs to know when such a 'search' is
3628 * - there'd be a single global queue or a single RIB walker
3629 * - rather than tracking which route_nodes still need to be
3630 * examined on a peer basis, we'd track which peers still
3633 * Given that our per-peer prefix-counts now should be reliable,
3634 * this may actually be achievable. It doesn't seem to be a huge
3635 * problem at this time,
3637 * It is possible that we have multiple paths for a prefix from
3639 * if that peer is using AddPath.
3643 ain_next
= ain
->next
;
3645 if (ain
->peer
== peer
) {
3646 bgp_adj_in_remove(rn
, ain
);
3647 bgp_unlock_node(rn
);
3653 for (ri
= rn
->info
; ri
; ri
= next
) {
3655 if (ri
->peer
!= peer
)
3659 bgp_info_reap(rn
, ri
);
3661 struct bgp_clear_node_queue
*cnq
;
3663 /* both unlocked in bgp_clear_node_queue_del */
3664 bgp_table_lock(bgp_node_table(rn
));
3667 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3668 sizeof(struct bgp_clear_node_queue
));
3670 work_queue_add(peer
->clear_node_queue
, cnq
);
3678 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3680 struct bgp_node
*rn
;
3681 struct bgp_table
*table
;
3683 if (peer
->clear_node_queue
== NULL
)
3684 bgp_clear_node_queue_init(peer
);
3686 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3687 * Idle until it receives a Clearing_Completed event. This protects
3688 * against peers which flap faster than we can we clear, which could
3691 * a) race with routes from the new session being installed before
3692 * clear_route_node visits the node (to delete the route of that
3694 * b) resource exhaustion, clear_route_node likely leads to an entry
3695 * on the process_main queue. Fast-flapping could cause that queue
3699 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3700 * the unlock will happen upon work-queue completion; other wise, the
3701 * unlock happens at the end of this function.
3703 if (!peer
->clear_node_queue
->thread
)
3706 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3707 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3709 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3710 rn
= bgp_route_next(rn
))
3711 if ((table
= rn
->info
) != NULL
)
3712 bgp_clear_route_table(peer
, afi
, safi
, table
);
3714 /* unlock if no nodes got added to the clear-node-queue. */
3715 if (!peer
->clear_node_queue
->thread
)
3719 void bgp_clear_route_all(struct peer
*peer
)
3724 FOREACH_AFI_SAFI (afi
, safi
)
3725 bgp_clear_route(peer
, afi
, safi
);
3728 rfapiProcessPeerDown(peer
);
3732 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3734 struct bgp_table
*table
;
3735 struct bgp_node
*rn
;
3736 struct bgp_adj_in
*ain
;
3737 struct bgp_adj_in
*ain_next
;
3739 table
= peer
->bgp
->rib
[afi
][safi
];
3741 /* It is possible that we have multiple paths for a prefix from a peer
3742 * if that peer is using AddPath.
3744 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3748 ain_next
= ain
->next
;
3750 if (ain
->peer
== peer
) {
3751 bgp_adj_in_remove(rn
, ain
);
3752 bgp_unlock_node(rn
);
3760 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3762 struct bgp_node
*rn
;
3763 struct bgp_info
*ri
;
3764 struct bgp_table
*table
;
3766 if (safi
== SAFI_MPLS_VPN
) {
3767 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3768 rn
= bgp_route_next(rn
)) {
3769 struct bgp_node
*rm
;
3770 struct bgp_info
*ri
;
3772 /* look for neighbor in tables */
3773 if ((table
= rn
->info
) == NULL
)
3776 for (rm
= bgp_table_top(table
); rm
;
3777 rm
= bgp_route_next(rm
))
3778 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3779 if (ri
->peer
!= peer
)
3781 if (!CHECK_FLAG(ri
->flags
,
3785 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
3790 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3791 rn
= bgp_route_next(rn
))
3792 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3793 if (ri
->peer
!= peer
)
3795 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3797 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3803 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3805 struct bgp_node
*rn
;
3806 struct bgp_info
*ri
;
3807 struct bgp_info
*next
;
3809 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3810 for (ri
= rn
->info
; ri
; ri
= next
) {
3812 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3813 && ri
->type
== ZEBRA_ROUTE_BGP
3814 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3815 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3816 if (bgp_fibupd_safi(safi
))
3817 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3818 bgp_info_reap(rn
, ri
);
3823 /* Delete all kernel routes. */
3824 void bgp_cleanup_routes(struct bgp
*bgp
)
3827 struct bgp_node
*rn
;
3829 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3830 if (afi
== AFI_L2VPN
)
3832 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3834 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3836 if (afi
!= AFI_L2VPN
) {
3838 safi
= SAFI_MPLS_VPN
;
3839 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3840 rn
= bgp_route_next(rn
)) {
3843 (struct bgp_table
*)(rn
->info
),
3845 bgp_table_finish((struct bgp_table
**)&(
3848 bgp_unlock_node(rn
);
3852 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3853 rn
= bgp_route_next(rn
)) {
3856 (struct bgp_table
*)(rn
->info
),
3858 bgp_table_finish((struct bgp_table
**)&(
3861 bgp_unlock_node(rn
);
3866 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3867 rn
= bgp_route_next(rn
)) {
3869 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3871 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3873 bgp_unlock_node(rn
);
3878 void bgp_reset(void)
3881 bgp_zclient_reset();
3882 access_list_reset();
3883 prefix_list_reset();
3886 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3888 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3889 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3890 PEER_CAP_ADDPATH_AF_TX_RCV
));
3893 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3895 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3896 struct bgp_nlri
*packet
)
3905 int addpath_encoded
;
3906 u_int32_t addpath_id
;
3908 /* Check peer status. */
3909 if (peer
->status
!= Established
)
3913 lim
= pnt
+ packet
->length
;
3915 safi
= packet
->safi
;
3917 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3919 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3920 syntactic validity. If the field is syntactically incorrect,
3921 then the Error Subcode is set to Invalid Network Field. */
3922 for (; pnt
< lim
; pnt
+= psize
) {
3923 /* Clear prefix structure. */
3924 memset(&p
, 0, sizeof(struct prefix
));
3926 if (addpath_encoded
) {
3928 /* When packet overflow occurs return immediately. */
3929 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3932 addpath_id
= ntohl(*((uint32_t *)pnt
));
3933 pnt
+= BGP_ADDPATH_ID_LEN
;
3936 /* Fetch prefix length. */
3937 p
.prefixlen
= *pnt
++;
3938 /* afi/safi validity already verified by caller,
3939 * bgp_update_receive */
3940 p
.family
= afi2family(afi
);
3942 /* Prefix length check. */
3943 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3945 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3946 peer
->host
, p
.prefixlen
, packet
->afi
);
3950 /* Packet size overflow check. */
3951 psize
= PSIZE(p
.prefixlen
);
3953 /* When packet overflow occur return immediately. */
3954 if (pnt
+ psize
> lim
) {
3956 "%s [Error] Update packet error (prefix length %d overflows packet)",
3957 peer
->host
, p
.prefixlen
);
3961 /* Defensive coding, double-check the psize fits in a struct
3963 if (psize
> (ssize_t
)sizeof(p
.u
)) {
3965 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
3966 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
3970 /* Fetch prefix from NLRI packet. */
3971 memcpy(&p
.u
.prefix
, pnt
, psize
);
3973 /* Check address. */
3974 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
3975 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
3976 /* From RFC4271 Section 6.3:
3978 * If a prefix in the NLRI field is semantically
3980 * (e.g., an unexpected multicast IP address),
3982 * be logged locally, and the prefix SHOULD be
3986 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
3987 peer
->host
, inet_ntoa(p
.u
.prefix4
));
3992 /* Check address. */
3993 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
3994 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
3998 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4000 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4005 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4009 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4011 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4018 /* Normal process. */
4020 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4021 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4022 NULL
, NULL
, 0, NULL
);
4024 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4025 safi
, ZEBRA_ROUTE_BGP
,
4026 BGP_ROUTE_NORMAL
, NULL
, NULL
, NULL
);
4028 /* Address family configuration mismatch or maximum-prefix count
4034 /* Packet length consistency check. */
4037 "%s [Error] Update packet error (prefix length mismatch with total length)",
4045 static struct bgp_static
*bgp_static_new(void)
4047 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4050 static void bgp_static_free(struct bgp_static
*bgp_static
)
4052 if (bgp_static
->rmap
.name
)
4053 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4054 if (bgp_static
->eth_s_id
)
4055 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4056 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4059 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4060 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4062 struct bgp_node
*rn
;
4063 struct bgp_info
*ri
;
4064 struct bgp_info
*new;
4065 struct bgp_info info
;
4067 struct attr
*attr_new
;
4070 int vnc_implicit_withdraw
= 0;
4077 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4079 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4081 attr
.nexthop
= bgp_static
->igpnexthop
;
4082 attr
.med
= bgp_static
->igpmetric
;
4083 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4085 if (bgp_static
->atomic
)
4086 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4088 /* Store label index, if required. */
4089 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4090 attr
.label_index
= bgp_static
->label_index
;
4091 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4094 /* Apply route-map. */
4095 if (bgp_static
->rmap
.name
) {
4096 struct attr attr_tmp
= attr
;
4097 info
.peer
= bgp
->peer_self
;
4098 info
.attr
= &attr_tmp
;
4100 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4102 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4104 bgp
->peer_self
->rmap_type
= 0;
4106 if (ret
== RMAP_DENYMATCH
) {
4107 /* Free uninterned attribute. */
4108 bgp_attr_flush(&attr_tmp
);
4110 /* Unintern original. */
4111 aspath_unintern(&attr
.aspath
);
4112 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4116 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4117 bgp_attr_add_gshut_community(&attr_tmp
);
4119 attr_new
= bgp_attr_intern(&attr_tmp
);
4122 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4123 bgp_attr_add_gshut_community(&attr
);
4125 attr_new
= bgp_attr_intern(&attr
);
4128 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4129 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4130 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4134 if (attrhash_cmp(ri
->attr
, attr_new
)
4135 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4136 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4137 bgp_unlock_node(rn
);
4138 bgp_attr_unintern(&attr_new
);
4139 aspath_unintern(&attr
.aspath
);
4142 /* The attribute is changed. */
4143 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4145 /* Rewrite BGP route information. */
4146 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4147 bgp_info_restore(rn
, ri
);
4149 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4151 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4152 && (safi
== SAFI_UNICAST
)) {
4153 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4155 * Implicit withdraw case.
4156 * We have to do this before ri is
4159 ++vnc_implicit_withdraw
;
4160 vnc_import_bgp_del_route(bgp
, p
, ri
);
4161 vnc_import_bgp_exterior_del_route(
4166 bgp_attr_unintern(&ri
->attr
);
4167 ri
->attr
= attr_new
;
4168 ri
->uptime
= bgp_clock();
4170 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4171 && (safi
== SAFI_UNICAST
)) {
4172 if (vnc_implicit_withdraw
) {
4173 vnc_import_bgp_add_route(bgp
, p
, ri
);
4174 vnc_import_bgp_exterior_add_route(
4180 /* Nexthop reachability check. */
4181 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4182 && (safi
== SAFI_UNICAST
4183 || safi
== SAFI_LABELED_UNICAST
)) {
4184 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4186 bgp_info_set_flag(rn
, ri
,
4189 if (BGP_DEBUG(nht
, NHT
)) {
4190 char buf1
[INET6_ADDRSTRLEN
];
4191 inet_ntop(p
->family
,
4195 "%s(%s): Route not in table, not advertising",
4196 __FUNCTION__
, buf1
);
4198 bgp_info_unset_flag(rn
, ri
,
4202 /* Delete the NHT structure if any, if we're
4204 * enabling/disabling import check. We
4205 * deregister the route
4206 * from NHT to avoid overloading NHT and the
4207 * process interaction
4209 bgp_unlink_nexthop(ri
);
4210 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4212 /* Process change. */
4213 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4214 bgp_process(bgp
, rn
, afi
, safi
);
4215 bgp_unlock_node(rn
);
4216 aspath_unintern(&attr
.aspath
);
4221 /* Make new BGP info. */
4222 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4224 /* Nexthop reachability check. */
4225 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4226 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4227 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4228 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4230 if (BGP_DEBUG(nht
, NHT
)) {
4231 char buf1
[INET6_ADDRSTRLEN
];
4232 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4235 "%s(%s): Route not in table, not advertising",
4236 __FUNCTION__
, buf1
);
4238 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4241 /* Delete the NHT structure if any, if we're toggling between
4242 * enabling/disabling import check. We deregister the route
4243 * from NHT to avoid overloading NHT and the process interaction
4245 bgp_unlink_nexthop(new);
4247 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4250 /* Aggregate address increment. */
4251 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4253 /* Register new BGP information. */
4254 bgp_info_add(rn
, new);
4256 /* route_node_get lock */
4257 bgp_unlock_node(rn
);
4259 /* Process change. */
4260 bgp_process(bgp
, rn
, afi
, safi
);
4262 /* Unintern original. */
4263 aspath_unintern(&attr
.aspath
);
4266 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4269 struct bgp_node
*rn
;
4270 struct bgp_info
*ri
;
4272 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4274 /* Check selected route and self inserted route. */
4275 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4276 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4277 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4280 /* Withdraw static BGP route from routing table. */
4282 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4283 bgp_unlink_nexthop(ri
);
4284 bgp_info_delete(rn
, ri
);
4285 bgp_process(bgp
, rn
, afi
, safi
);
4288 /* Unlock bgp_node_lookup. */
4289 bgp_unlock_node(rn
);
4293 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4295 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4296 afi_t afi
, safi_t safi
,
4297 struct prefix_rd
*prd
)
4299 struct bgp_node
*rn
;
4300 struct bgp_info
*ri
;
4302 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4304 /* Check selected route and self inserted route. */
4305 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4306 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4307 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4310 /* Withdraw static BGP route from routing table. */
4313 rfapiProcessWithdraw(
4314 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4315 1); /* Kill, since it is an administrative change */
4317 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4318 bgp_info_delete(rn
, ri
);
4319 bgp_process(bgp
, rn
, afi
, safi
);
4322 /* Unlock bgp_node_lookup. */
4323 bgp_unlock_node(rn
);
4326 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4327 struct bgp_static
*bgp_static
, afi_t afi
,
4330 struct bgp_node
*rn
;
4331 struct bgp_info
*new;
4332 struct attr
*attr_new
;
4333 struct attr attr
= {0};
4334 struct bgp_info
*ri
;
4336 mpls_label_t label
= 0;
4342 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4345 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4347 attr
.nexthop
= bgp_static
->igpnexthop
;
4348 attr
.med
= bgp_static
->igpmetric
;
4349 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4351 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4352 || (safi
== SAFI_ENCAP
)) {
4353 if (afi
== AFI_IP
) {
4354 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4355 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4358 if (afi
== AFI_L2VPN
) {
4359 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4361 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4362 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4363 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4364 sizeof(struct in6_addr
));
4365 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4366 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4367 struct bgp_encap_type_vxlan bet
;
4368 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4369 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4370 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4372 if (bgp_static
->router_mac
) {
4373 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4376 /* Apply route-map. */
4377 if (bgp_static
->rmap
.name
) {
4378 struct attr attr_tmp
= attr
;
4379 struct bgp_info info
;
4382 info
.peer
= bgp
->peer_self
;
4383 info
.attr
= &attr_tmp
;
4385 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4387 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4389 bgp
->peer_self
->rmap_type
= 0;
4391 if (ret
== RMAP_DENYMATCH
) {
4392 /* Free uninterned attribute. */
4393 bgp_attr_flush(&attr_tmp
);
4395 /* Unintern original. */
4396 aspath_unintern(&attr
.aspath
);
4397 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4402 attr_new
= bgp_attr_intern(&attr_tmp
);
4404 attr_new
= bgp_attr_intern(&attr
);
4407 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4408 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4409 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4414 memset(&add
, 0, sizeof(union gw_addr
));
4415 if (attrhash_cmp(ri
->attr
, attr_new
)
4416 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4417 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4418 bgp_unlock_node(rn
);
4419 bgp_attr_unintern(&attr_new
);
4420 aspath_unintern(&attr
.aspath
);
4423 /* The attribute is changed. */
4424 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4426 /* Rewrite BGP route information. */
4427 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4428 bgp_info_restore(rn
, ri
);
4430 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4431 bgp_attr_unintern(&ri
->attr
);
4432 ri
->attr
= attr_new
;
4433 ri
->uptime
= bgp_clock();
4436 label
= decode_label(&ri
->extra
->label
);
4439 /* Process change. */
4440 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4441 bgp_process(bgp
, rn
, afi
, safi
);
4443 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4444 ri
->attr
, afi
, safi
, ri
->type
,
4445 ri
->sub_type
, &label
);
4447 bgp_unlock_node(rn
);
4448 aspath_unintern(&attr
.aspath
);
4454 /* Make new BGP info. */
4455 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4457 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4458 new->extra
= bgp_info_extra_new();
4459 new->extra
->label
= bgp_static
->label
;
4461 label
= decode_label(&bgp_static
->label
);
4464 /* Aggregate address increment. */
4465 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4467 /* Register new BGP information. */
4468 bgp_info_add(rn
, new);
4469 /* route_node_get lock */
4470 bgp_unlock_node(rn
);
4472 /* Process change. */
4473 bgp_process(bgp
, rn
, afi
, safi
);
4476 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4477 safi
, new->type
, new->sub_type
, &label
);
4480 /* Unintern original. */
4481 aspath_unintern(&attr
.aspath
);
4484 /* Configure static BGP network. When user don't run zebra, static
4485 route should be installed as valid. */
4486 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4487 const char *ip_str
, afi_t afi
, safi_t safi
,
4488 const char *rmap
, int backdoor
, u_int32_t label_index
)
4490 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4493 struct bgp_static
*bgp_static
;
4494 struct bgp_node
*rn
;
4495 u_char need_update
= 0;
4497 /* Convert IP prefix string to struct prefix. */
4498 ret
= str2prefix(ip_str
, &p
);
4500 vty_out(vty
, "%% Malformed prefix\n");
4501 return CMD_WARNING_CONFIG_FAILED
;
4503 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4504 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4505 return CMD_WARNING_CONFIG_FAILED
;
4512 /* Set BGP static route configuration. */
4513 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4517 "%% Can't find static route specified\n");
4518 return CMD_WARNING_CONFIG_FAILED
;
4521 bgp_static
= rn
->info
;
4523 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4524 && (label_index
!= bgp_static
->label_index
)) {
4526 "%% label-index doesn't match static route\n");
4527 return CMD_WARNING_CONFIG_FAILED
;
4530 if ((rmap
&& bgp_static
->rmap
.name
)
4531 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4533 "%% route-map name doesn't match static route\n");
4534 return CMD_WARNING_CONFIG_FAILED
;
4537 /* Update BGP RIB. */
4538 if (!bgp_static
->backdoor
)
4539 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4541 /* Clear configuration. */
4542 bgp_static_free(bgp_static
);
4544 bgp_unlock_node(rn
);
4545 bgp_unlock_node(rn
);
4548 /* Set BGP static route configuration. */
4549 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4552 /* Configuration change. */
4553 bgp_static
= rn
->info
;
4555 /* Label index cannot be changed. */
4556 if (bgp_static
->label_index
!= label_index
) {
4557 vty_out(vty
, "%% cannot change label-index\n");
4558 return CMD_WARNING_CONFIG_FAILED
;
4561 /* Check previous routes are installed into BGP. */
4562 if (bgp_static
->valid
&&
4563 bgp_static
->backdoor
!= backdoor
)
4566 bgp_static
->backdoor
= backdoor
;
4569 if (bgp_static
->rmap
.name
)
4570 XFREE(MTYPE_ROUTE_MAP_NAME
,
4571 bgp_static
->rmap
.name
);
4572 bgp_static
->rmap
.name
=
4573 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4574 bgp_static
->rmap
.map
=
4575 route_map_lookup_by_name(rmap
);
4577 if (bgp_static
->rmap
.name
)
4578 XFREE(MTYPE_ROUTE_MAP_NAME
,
4579 bgp_static
->rmap
.name
);
4580 bgp_static
->rmap
.name
= NULL
;
4581 bgp_static
->rmap
.map
= NULL
;
4582 bgp_static
->valid
= 0;
4584 bgp_unlock_node(rn
);
4586 /* New configuration. */
4587 bgp_static
= bgp_static_new();
4588 bgp_static
->backdoor
= backdoor
;
4589 bgp_static
->valid
= 0;
4590 bgp_static
->igpmetric
= 0;
4591 bgp_static
->igpnexthop
.s_addr
= 0;
4592 bgp_static
->label_index
= label_index
;
4595 if (bgp_static
->rmap
.name
)
4596 XFREE(MTYPE_ROUTE_MAP_NAME
,
4597 bgp_static
->rmap
.name
);
4598 bgp_static
->rmap
.name
=
4599 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4600 bgp_static
->rmap
.map
=
4601 route_map_lookup_by_name(rmap
);
4603 rn
->info
= bgp_static
;
4606 bgp_static
->valid
= 1;
4608 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4610 if (!bgp_static
->backdoor
)
4611 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4617 void bgp_static_add(struct bgp
*bgp
)
4621 struct bgp_node
*rn
;
4622 struct bgp_node
*rm
;
4623 struct bgp_table
*table
;
4624 struct bgp_static
*bgp_static
;
4626 FOREACH_AFI_SAFI (afi
, safi
)
4627 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4628 rn
= bgp_route_next(rn
)) {
4629 if (rn
->info
== NULL
)
4632 if ((safi
== SAFI_MPLS_VPN
) || (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(bgp
, &rm
->p
,
4644 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
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 FOREACH_AFI_SAFI (afi
, safi
)
4662 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4663 rn
= bgp_route_next(rn
)) {
4664 if (rn
->info
== NULL
)
4667 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4668 || (safi
== SAFI_EVPN
)) {
4671 for (rm
= bgp_table_top(table
); rm
;
4672 rm
= bgp_route_next(rm
)) {
4673 bgp_static
= rm
->info
;
4674 bgp_static_withdraw_safi(
4675 bgp
, &rm
->p
, AFI_IP
, safi
,
4676 (struct prefix_rd
*)&rn
->p
);
4677 bgp_static_free(bgp_static
);
4679 bgp_unlock_node(rn
);
4682 bgp_static
= rn
->info
;
4683 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4684 bgp_static_free(bgp_static
);
4686 bgp_unlock_node(rn
);
4691 void bgp_static_redo_import_check(struct bgp
*bgp
)
4695 struct bgp_node
*rn
;
4696 struct bgp_node
*rm
;
4697 struct bgp_table
*table
;
4698 struct bgp_static
*bgp_static
;
4700 /* Use this flag to force reprocessing of the route */
4701 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4702 FOREACH_AFI_SAFI (afi
, safi
) {
4703 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4704 rn
= bgp_route_next(rn
)) {
4705 if (rn
->info
== NULL
)
4708 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4709 || (safi
== SAFI_EVPN
)) {
4712 for (rm
= bgp_table_top(table
); rm
;
4713 rm
= bgp_route_next(rm
)) {
4714 bgp_static
= rm
->info
;
4715 bgp_static_update_safi(bgp
, &rm
->p
,
4720 bgp_static
= rn
->info
;
4721 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4726 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4729 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4732 struct bgp_table
*table
;
4733 struct bgp_node
*rn
;
4734 struct bgp_info
*ri
;
4736 table
= bgp
->rib
[afi
][safi
];
4737 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4738 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4739 if (ri
->peer
== bgp
->peer_self
4740 && ((ri
->type
== ZEBRA_ROUTE_BGP
4741 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4742 || (ri
->type
!= ZEBRA_ROUTE_BGP
4744 == BGP_ROUTE_REDISTRIBUTE
))) {
4745 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4747 bgp_unlink_nexthop(ri
);
4748 bgp_info_delete(rn
, ri
);
4749 bgp_process(bgp
, rn
, afi
, safi
);
4756 * Purge all networks and redistributed routes from routing table.
4757 * Invoked upon the instance going down.
4759 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4764 FOREACH_AFI_SAFI (afi
, safi
)
4765 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4770 * Currently this is used to set static routes for VPN and ENCAP.
4771 * I think it can probably be factored with bgp_static_set.
4773 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4774 const char *ip_str
, const char *rd_str
,
4775 const char *label_str
, const char *rmap_str
,
4776 int evpn_type
, const char *esi
, const char *gwip
,
4777 const char *ethtag
, const char *routermac
)
4779 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4782 struct prefix_rd prd
;
4783 struct bgp_node
*prn
;
4784 struct bgp_node
*rn
;
4785 struct bgp_table
*table
;
4786 struct bgp_static
*bgp_static
;
4787 mpls_label_t label
= MPLS_INVALID_LABEL
;
4788 struct prefix gw_ip
;
4790 /* validate ip prefix */
4791 ret
= str2prefix(ip_str
, &p
);
4793 vty_out(vty
, "%% Malformed prefix\n");
4794 return CMD_WARNING_CONFIG_FAILED
;
4797 if ((afi
== AFI_L2VPN
)
4798 && (bgp_build_evpn_prefix(evpn_type
,
4799 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4800 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4801 return CMD_WARNING_CONFIG_FAILED
;
4804 ret
= str2prefix_rd(rd_str
, &prd
);
4806 vty_out(vty
, "%% Malformed rd\n");
4807 return CMD_WARNING_CONFIG_FAILED
;
4811 unsigned long label_val
;
4812 label_val
= strtoul(label_str
, NULL
, 10);
4813 encode_label(label_val
, &label
);
4816 if (safi
== SAFI_EVPN
) {
4817 if (esi
&& str2esi(esi
, NULL
) == 0) {
4818 vty_out(vty
, "%% Malformed ESI\n");
4819 return CMD_WARNING_CONFIG_FAILED
;
4821 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4822 vty_out(vty
, "%% Malformed Router MAC\n");
4823 return CMD_WARNING_CONFIG_FAILED
;
4826 memset(&gw_ip
, 0, sizeof(struct prefix
));
4827 ret
= str2prefix(gwip
, &gw_ip
);
4829 vty_out(vty
, "%% Malformed GatewayIp\n");
4830 return CMD_WARNING_CONFIG_FAILED
;
4832 if ((gw_ip
.family
== AF_INET
4833 && IS_EVPN_PREFIX_IPADDR_V6(
4834 (struct prefix_evpn
*)&p
))
4835 || (gw_ip
.family
== AF_INET6
4836 && IS_EVPN_PREFIX_IPADDR_V4(
4837 (struct prefix_evpn
*)&p
))) {
4839 "%% GatewayIp family differs with IP prefix\n");
4840 return CMD_WARNING_CONFIG_FAILED
;
4844 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4845 if (prn
->info
== NULL
)
4846 prn
->info
= bgp_table_init(afi
, safi
);
4848 bgp_unlock_node(prn
);
4851 rn
= bgp_node_get(table
, &p
);
4854 vty_out(vty
, "%% Same network configuration exists\n");
4855 bgp_unlock_node(rn
);
4857 /* New configuration. */
4858 bgp_static
= bgp_static_new();
4859 bgp_static
->backdoor
= 0;
4860 bgp_static
->valid
= 0;
4861 bgp_static
->igpmetric
= 0;
4862 bgp_static
->igpnexthop
.s_addr
= 0;
4863 bgp_static
->label
= label
;
4864 bgp_static
->prd
= prd
;
4867 if (bgp_static
->rmap
.name
)
4868 XFREE(MTYPE_ROUTE_MAP_NAME
,
4869 bgp_static
->rmap
.name
);
4870 bgp_static
->rmap
.name
=
4871 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4872 bgp_static
->rmap
.map
=
4873 route_map_lookup_by_name(rmap_str
);
4876 if (safi
== SAFI_EVPN
) {
4878 bgp_static
->eth_s_id
=
4880 sizeof(struct eth_segment_id
));
4881 str2esi(esi
, bgp_static
->eth_s_id
);
4884 bgp_static
->router_mac
=
4885 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
4886 prefix_str2mac(routermac
,
4887 bgp_static
->router_mac
);
4890 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4892 rn
->info
= bgp_static
;
4894 bgp_static
->valid
= 1;
4895 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4901 /* Configure static BGP network. */
4902 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4903 const char *ip_str
, const char *rd_str
,
4904 const char *label_str
, int evpn_type
, const char *esi
,
4905 const char *gwip
, const char *ethtag
)
4907 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4910 struct prefix_rd prd
;
4911 struct bgp_node
*prn
;
4912 struct bgp_node
*rn
;
4913 struct bgp_table
*table
;
4914 struct bgp_static
*bgp_static
;
4915 mpls_label_t label
= MPLS_INVALID_LABEL
;
4917 /* Convert IP prefix string to struct prefix. */
4918 ret
= str2prefix(ip_str
, &p
);
4920 vty_out(vty
, "%% Malformed prefix\n");
4921 return CMD_WARNING_CONFIG_FAILED
;
4924 if ((afi
== AFI_L2VPN
)
4925 && (bgp_build_evpn_prefix(evpn_type
,
4926 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4927 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4928 return CMD_WARNING_CONFIG_FAILED
;
4930 ret
= str2prefix_rd(rd_str
, &prd
);
4932 vty_out(vty
, "%% Malformed rd\n");
4933 return CMD_WARNING_CONFIG_FAILED
;
4937 unsigned long label_val
;
4938 label_val
= strtoul(label_str
, NULL
, 10);
4939 encode_label(label_val
, &label
);
4942 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4943 if (prn
->info
== NULL
)
4944 prn
->info
= bgp_table_init(afi
, safi
);
4946 bgp_unlock_node(prn
);
4949 rn
= bgp_node_lookup(table
, &p
);
4952 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4954 bgp_static
= rn
->info
;
4955 bgp_static_free(bgp_static
);
4957 bgp_unlock_node(rn
);
4958 bgp_unlock_node(rn
);
4960 vty_out(vty
, "%% Can't find the route\n");
4965 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
4966 const char *rmap_name
)
4968 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4969 struct bgp_rmap
*rmap
;
4971 rmap
= &bgp
->table_map
[afi
][safi
];
4974 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4975 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
4976 rmap
->map
= route_map_lookup_by_name(rmap_name
);
4979 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
4984 if (bgp_fibupd_safi(safi
))
4985 bgp_zebra_announce_table(bgp
, afi
, safi
);
4990 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
4991 const char *rmap_name
)
4993 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4994 struct bgp_rmap
*rmap
;
4996 rmap
= &bgp
->table_map
[afi
][safi
];
4998 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5002 if (bgp_fibupd_safi(safi
))
5003 bgp_zebra_announce_table(bgp
, afi
, safi
);
5008 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5011 if (bgp
->table_map
[afi
][safi
].name
) {
5012 vty_out(vty
, " table-map %s\n",
5013 bgp
->table_map
[afi
][safi
].name
);
5017 DEFUN (bgp_table_map
,
5020 "BGP table to RIB route download filter\n"
5021 "Name of the route map\n")
5024 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5025 argv
[idx_word
]->arg
);
5027 DEFUN (no_bgp_table_map
,
5028 no_bgp_table_map_cmd
,
5029 "no table-map WORD",
5031 "BGP table to RIB route download filter\n"
5032 "Name of the route map\n")
5035 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5036 argv
[idx_word
]->arg
);
5042 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5043 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5044 backdoor$backdoor}]",
5046 "Specify a network to announce via BGP\n"
5051 "Route-map to modify the attributes\n"
5052 "Name of the route map\n"
5053 "Label index to associate with the prefix\n"
5054 "Label index value\n"
5055 "Specify a BGP backdoor route\n")
5057 char addr_prefix_str
[BUFSIZ
];
5062 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5065 vty_out(vty
, "%% Inconsistent address and mask\n");
5066 return CMD_WARNING_CONFIG_FAILED
;
5070 return bgp_static_set(vty
, no
, address_str
? addr_prefix_str
:prefix_str
,
5071 AFI_IP
, bgp_node_safi(vty
),
5072 map_name
, backdoor
?1:0,
5074 (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5077 DEFPY(ipv6_bgp_network
,
5078 ipv6_bgp_network_cmd
,
5079 "[no] network X:X::X:X/M$prefix \
5080 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5082 "Specify a network to announce via BGP\n"
5084 "Route-map to modify the attributes\n"
5085 "Name of the route map\n"
5086 "Label index to associate with the prefix\n"
5087 "Label index value\n")
5089 return bgp_static_set(vty
, no
, prefix_str
, AFI_IP6
,
5090 bgp_node_safi(vty
), map_name
, 0,
5092 (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5095 /* Aggreagete address:
5097 advertise-map Set condition to advertise attribute
5098 as-set Generate AS set path information
5099 attribute-map Set attributes of aggregate
5100 route-map Set parameters of aggregate
5101 summary-only Filter more specific routes from updates
5102 suppress-map Conditionally filter more specific routes from updates
5105 struct bgp_aggregate
{
5106 /* Summary-only flag. */
5107 u_char summary_only
;
5109 /* AS set generation. */
5112 /* Route-map for aggregated route. */
5113 struct route_map
*map
;
5115 /* Suppress-count. */
5116 unsigned long count
;
5118 /* SAFI configuration. */
5122 static struct bgp_aggregate
*bgp_aggregate_new(void)
5124 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5127 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5129 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5132 /* Update an aggregate as routes are added/removed from the BGP table */
5133 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5134 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5135 struct bgp_info
*del
,
5136 struct bgp_aggregate
*aggregate
)
5138 struct bgp_table
*table
;
5139 struct bgp_node
*top
;
5140 struct bgp_node
*rn
;
5142 struct aspath
*aspath
= NULL
;
5143 struct aspath
*asmerge
= NULL
;
5144 struct community
*community
= NULL
;
5145 struct community
*commerge
= NULL
;
5146 #if defined(AGGREGATE_NEXTHOP_CHECK)
5147 struct in_addr nexthop
;
5150 struct bgp_info
*ri
;
5151 struct bgp_info
*new;
5153 unsigned long match
= 0;
5154 u_char atomic_aggregate
= 0;
5156 /* Record adding route's nexthop and med. */
5158 #if defined(AGGREGATE_NEXTHOP_CHECK)
5159 nexthop
= rinew
->attr
->nexthop
;
5160 med
= rinew
->attr
->med
;
5164 /* ORIGIN attribute: If at least one route among routes that are
5165 aggregated has ORIGIN with the value INCOMPLETE, then the
5166 aggregated route must have the ORIGIN attribute with the value
5167 INCOMPLETE. Otherwise, if at least one route among routes that
5168 are aggregated has ORIGIN with the value EGP, then the aggregated
5169 route must have the origin attribute with the value EGP. In all
5170 other case the value of the ORIGIN attribute of the aggregated
5171 route is INTERNAL. */
5172 origin
= BGP_ORIGIN_IGP
;
5174 table
= bgp
->rib
[afi
][safi
];
5176 top
= bgp_node_get(table
, p
);
5177 for (rn
= bgp_node_get(table
, p
); rn
;
5178 rn
= bgp_route_next_until(rn
, top
))
5179 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5182 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5183 if (BGP_INFO_HOLDDOWN(ri
))
5186 if (del
&& ri
== del
)
5189 if (!rinew
&& first
) {
5190 #if defined(AGGREGATE_NEXTHOP_CHECK)
5191 nexthop
= ri
->attr
->nexthop
;
5192 med
= ri
->attr
->med
;
5197 #ifdef AGGREGATE_NEXTHOP_CHECK
5198 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5200 || ri
->attr
->med
!= med
) {
5202 aspath_free(aspath
);
5204 community_free(community
);
5205 bgp_unlock_node(rn
);
5206 bgp_unlock_node(top
);
5209 #endif /* AGGREGATE_NEXTHOP_CHECK */
5212 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5213 atomic_aggregate
= 1;
5215 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5216 if (aggregate
->summary_only
) {
5217 (bgp_info_extra_get(ri
))
5221 BGP_INFO_ATTR_CHANGED
);
5227 if (origin
< ri
->attr
->origin
)
5228 origin
= ri
->attr
->origin
;
5230 if (aggregate
->as_set
) {
5232 asmerge
= aspath_aggregate(
5235 aspath_free(aspath
);
5238 aspath
= aspath_dup(
5241 if (ri
->attr
->community
) {
5243 commerge
= community_merge(
5245 ri
->attr
->community
);
5246 community
= community_uniq_sort(
5251 community
= community_dup(
5252 ri
->attr
->community
);
5258 bgp_process(bgp
, rn
, afi
, safi
);
5260 bgp_unlock_node(top
);
5265 if (aggregate
->summary_only
)
5266 (bgp_info_extra_get(rinew
))->suppress
++;
5268 if (origin
< rinew
->attr
->origin
)
5269 origin
= rinew
->attr
->origin
;
5271 if (aggregate
->as_set
) {
5273 asmerge
= aspath_aggregate(aspath
,
5274 rinew
->attr
->aspath
);
5275 aspath_free(aspath
);
5278 aspath
= aspath_dup(rinew
->attr
->aspath
);
5280 if (rinew
->attr
->community
) {
5282 commerge
= community_merge(
5284 rinew
->attr
->community
);
5286 community_uniq_sort(commerge
);
5287 community_free(commerge
);
5289 community
= community_dup(
5290 rinew
->attr
->community
);
5295 if (aggregate
->count
> 0) {
5296 rn
= bgp_node_get(table
, p
);
5298 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5299 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5300 community
, aggregate
->as_set
,
5303 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5305 bgp_info_add(rn
, new);
5306 bgp_unlock_node(rn
);
5307 bgp_process(bgp
, rn
, afi
, safi
);
5310 aspath_free(aspath
);
5312 community_free(community
);
5316 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5317 struct bgp_aggregate
*);
5319 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5320 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5322 struct bgp_node
*child
;
5323 struct bgp_node
*rn
;
5324 struct bgp_aggregate
*aggregate
;
5325 struct bgp_table
*table
;
5327 /* MPLS-VPN aggregation is not yet supported. */
5328 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5329 || (safi
== SAFI_EVPN
))
5332 table
= bgp
->aggregate
[afi
][safi
];
5334 /* No aggregates configured. */
5335 if (bgp_table_top_nolock(table
) == NULL
)
5338 if (p
->prefixlen
== 0)
5341 if (BGP_INFO_HOLDDOWN(ri
))
5344 child
= bgp_node_get(table
, p
);
5346 /* Aggregate address configuration check. */
5347 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5348 if ((aggregate
= rn
->info
) != NULL
5349 && rn
->p
.prefixlen
< p
->prefixlen
) {
5350 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5351 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5354 bgp_unlock_node(child
);
5357 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5358 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5360 struct bgp_node
*child
;
5361 struct bgp_node
*rn
;
5362 struct bgp_aggregate
*aggregate
;
5363 struct bgp_table
*table
;
5365 /* MPLS-VPN aggregation is not yet supported. */
5366 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5367 || (safi
== SAFI_EVPN
))
5370 table
= bgp
->aggregate
[afi
][safi
];
5372 /* No aggregates configured. */
5373 if (bgp_table_top_nolock(table
) == NULL
)
5376 if (p
->prefixlen
== 0)
5379 child
= bgp_node_get(table
, p
);
5381 /* Aggregate address configuration check. */
5382 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5383 if ((aggregate
= rn
->info
) != NULL
5384 && rn
->p
.prefixlen
< p
->prefixlen
) {
5385 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5386 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5389 bgp_unlock_node(child
);
5392 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5393 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5394 safi_t safi
, struct bgp_aggregate
*aggregate
)
5396 struct bgp_table
*table
;
5397 struct bgp_node
*top
;
5398 struct bgp_node
*rn
;
5399 struct bgp_info
*new;
5400 struct bgp_info
*ri
;
5401 unsigned long match
;
5402 u_char origin
= BGP_ORIGIN_IGP
;
5403 struct aspath
*aspath
= NULL
;
5404 struct aspath
*asmerge
= NULL
;
5405 struct community
*community
= NULL
;
5406 struct community
*commerge
= NULL
;
5407 u_char atomic_aggregate
= 0;
5409 table
= bgp
->rib
[afi
][safi
];
5412 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5414 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5417 /* If routes exists below this node, generate aggregate routes. */
5418 top
= bgp_node_get(table
, p
);
5419 for (rn
= bgp_node_get(table
, p
); rn
;
5420 rn
= bgp_route_next_until(rn
, top
)) {
5421 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5426 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5427 if (BGP_INFO_HOLDDOWN(ri
))
5431 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5432 atomic_aggregate
= 1;
5434 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5437 /* summary-only aggregate route suppress
5438 * aggregated route announcement. */
5439 if (aggregate
->summary_only
) {
5440 (bgp_info_extra_get(ri
))->suppress
++;
5441 bgp_info_set_flag(rn
, ri
,
5442 BGP_INFO_ATTR_CHANGED
);
5446 /* If at least one route among routes that are
5447 * aggregated has ORIGIN with the value INCOMPLETE,
5448 * then the aggregated route MUST have the ORIGIN
5449 * attribute with the value INCOMPLETE. Otherwise, if
5450 * at least one route among routes that are aggregated
5451 * has ORIGIN with the value EGP, then the aggregated
5452 * route MUST have the ORIGIN attribute with the value
5455 if (origin
< ri
->attr
->origin
)
5456 origin
= ri
->attr
->origin
;
5458 /* as-set aggregate route generate origin, as path,
5459 * community aggregation. */
5460 if (aggregate
->as_set
) {
5462 asmerge
= aspath_aggregate(
5463 aspath
, ri
->attr
->aspath
);
5464 aspath_free(aspath
);
5467 aspath
= aspath_dup(ri
->attr
->aspath
);
5469 if (ri
->attr
->community
) {
5471 commerge
= community_merge(
5473 ri
->attr
->community
);
5474 community
= community_uniq_sort(
5476 community_free(commerge
);
5478 community
= community_dup(
5479 ri
->attr
->community
);
5485 /* If this node is suppressed, process the change. */
5487 bgp_process(bgp
, rn
, afi
, safi
);
5489 bgp_unlock_node(top
);
5491 /* Add aggregate route to BGP table. */
5492 if (aggregate
->count
) {
5493 rn
= bgp_node_get(table
, p
);
5495 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5496 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5497 community
, aggregate
->as_set
,
5500 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5502 bgp_info_add(rn
, new);
5503 bgp_unlock_node(rn
);
5505 /* Process change. */
5506 bgp_process(bgp
, rn
, afi
, safi
);
5509 aspath_free(aspath
);
5511 community_free(community
);
5515 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5516 safi_t safi
, struct bgp_aggregate
*aggregate
)
5518 struct bgp_table
*table
;
5519 struct bgp_node
*top
;
5520 struct bgp_node
*rn
;
5521 struct bgp_info
*ri
;
5522 unsigned long match
;
5524 table
= bgp
->rib
[afi
][safi
];
5526 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5528 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5531 /* If routes exists below this node, generate aggregate routes. */
5532 top
= bgp_node_get(table
, p
);
5533 for (rn
= bgp_node_get(table
, p
); rn
;
5534 rn
= bgp_route_next_until(rn
, top
)) {
5535 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5539 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5540 if (BGP_INFO_HOLDDOWN(ri
))
5543 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5546 if (aggregate
->summary_only
&& ri
->extra
) {
5547 ri
->extra
->suppress
--;
5549 if (ri
->extra
->suppress
== 0) {
5551 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5558 /* If this node was suppressed, process the change. */
5560 bgp_process(bgp
, rn
, afi
, safi
);
5562 bgp_unlock_node(top
);
5564 /* Delete aggregate route from BGP table. */
5565 rn
= bgp_node_get(table
, p
);
5567 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5568 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5569 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5572 /* Withdraw static BGP route from routing table. */
5574 bgp_info_delete(rn
, ri
);
5575 bgp_process(bgp
, rn
, afi
, safi
);
5578 /* Unlock bgp_node_lookup. */
5579 bgp_unlock_node(rn
);
5582 /* Aggregate route attribute. */
5583 #define AGGREGATE_SUMMARY_ONLY 1
5584 #define AGGREGATE_AS_SET 1
5586 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5587 afi_t afi
, safi_t safi
)
5589 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5592 struct bgp_node
*rn
;
5593 struct bgp_aggregate
*aggregate
;
5595 /* Convert string to prefix structure. */
5596 ret
= str2prefix(prefix_str
, &p
);
5598 vty_out(vty
, "Malformed prefix\n");
5599 return CMD_WARNING_CONFIG_FAILED
;
5603 /* Old configuration check. */
5604 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5607 "%% There is no aggregate-address configuration.\n");
5608 return CMD_WARNING_CONFIG_FAILED
;
5611 aggregate
= rn
->info
;
5612 if (aggregate
->safi
== SAFI_UNICAST
)
5613 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5614 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5615 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5617 if (aggregate
->safi
== SAFI_MULTICAST
)
5618 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5620 /* Unlock aggregate address configuration. */
5622 bgp_aggregate_free(aggregate
);
5623 bgp_unlock_node(rn
);
5624 bgp_unlock_node(rn
);
5629 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5630 safi_t safi
, u_char summary_only
, u_char as_set
)
5632 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5635 struct bgp_node
*rn
;
5636 struct bgp_aggregate
*aggregate
;
5638 /* Convert string to prefix structure. */
5639 ret
= str2prefix(prefix_str
, &p
);
5641 vty_out(vty
, "Malformed prefix\n");
5642 return CMD_WARNING_CONFIG_FAILED
;
5646 /* Old configuration check. */
5647 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5650 vty_out(vty
, "There is already same aggregate network.\n");
5651 /* try to remove the old entry */
5652 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5654 vty_out(vty
, "Error deleting aggregate.\n");
5655 bgp_unlock_node(rn
);
5656 return CMD_WARNING_CONFIG_FAILED
;
5660 /* Make aggregate address structure. */
5661 aggregate
= bgp_aggregate_new();
5662 aggregate
->summary_only
= summary_only
;
5663 aggregate
->as_set
= as_set
;
5664 aggregate
->safi
= safi
;
5665 rn
->info
= aggregate
;
5667 /* Aggregate address insert into BGP routing table. */
5668 if (safi
== SAFI_UNICAST
)
5669 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5670 if (safi
== SAFI_LABELED_UNICAST
)
5671 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5673 if (safi
== SAFI_MULTICAST
)
5674 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5679 DEFUN (aggregate_address
,
5680 aggregate_address_cmd
,
5681 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5682 "Configure BGP aggregate entries\n"
5683 "Aggregate prefix\n"
5684 "Generate AS set path information\n"
5685 "Filter more specific routes from updates\n"
5686 "Filter more specific routes from updates\n"
5687 "Generate AS set path information\n")
5690 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5691 char *prefix
= argv
[idx
]->arg
;
5693 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5695 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5696 ? AGGREGATE_SUMMARY_ONLY
5699 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5700 summary_only
, as_set
);
5703 DEFUN (aggregate_address_mask
,
5704 aggregate_address_mask_cmd
,
5705 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5706 "Configure BGP aggregate entries\n"
5707 "Aggregate address\n"
5709 "Generate AS set path information\n"
5710 "Filter more specific routes from updates\n"
5711 "Filter more specific routes from updates\n"
5712 "Generate AS set path information\n")
5715 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5716 char *prefix
= argv
[idx
]->arg
;
5717 char *mask
= argv
[idx
+ 1]->arg
;
5719 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5721 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5722 ? AGGREGATE_SUMMARY_ONLY
5725 char prefix_str
[BUFSIZ
];
5726 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5729 vty_out(vty
, "%% Inconsistent address and mask\n");
5730 return CMD_WARNING_CONFIG_FAILED
;
5733 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5734 summary_only
, as_set
);
5737 DEFUN (no_aggregate_address
,
5738 no_aggregate_address_cmd
,
5739 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5741 "Configure BGP aggregate entries\n"
5742 "Aggregate prefix\n"
5743 "Generate AS set path information\n"
5744 "Filter more specific routes from updates\n"
5745 "Filter more specific routes from updates\n"
5746 "Generate AS set path information\n")
5749 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5750 char *prefix
= argv
[idx
]->arg
;
5751 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5754 DEFUN (no_aggregate_address_mask
,
5755 no_aggregate_address_mask_cmd
,
5756 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5758 "Configure BGP aggregate entries\n"
5759 "Aggregate address\n"
5761 "Generate AS set path information\n"
5762 "Filter more specific routes from updates\n"
5763 "Filter more specific routes from updates\n"
5764 "Generate AS set path information\n")
5767 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5768 char *prefix
= argv
[idx
]->arg
;
5769 char *mask
= argv
[idx
+ 1]->arg
;
5771 char prefix_str
[BUFSIZ
];
5772 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5775 vty_out(vty
, "%% Inconsistent address and mask\n");
5776 return CMD_WARNING_CONFIG_FAILED
;
5779 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5782 DEFUN (ipv6_aggregate_address
,
5783 ipv6_aggregate_address_cmd
,
5784 "aggregate-address X:X::X:X/M [summary-only]",
5785 "Configure BGP aggregate entries\n"
5786 "Aggregate prefix\n"
5787 "Filter more specific routes from updates\n")
5790 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
5791 char *prefix
= argv
[idx
]->arg
;
5792 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5793 ? AGGREGATE_SUMMARY_ONLY
5795 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
5799 DEFUN (no_ipv6_aggregate_address
,
5800 no_ipv6_aggregate_address_cmd
,
5801 "no aggregate-address X:X::X:X/M [summary-only]",
5803 "Configure BGP aggregate entries\n"
5804 "Aggregate prefix\n"
5805 "Filter more specific routes from updates\n")
5808 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
5809 char *prefix
= argv
[idx
]->arg
;
5810 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
5813 /* Redistribute route treatment. */
5814 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
5815 const union g_addr
*nexthop
, ifindex_t ifindex
,
5816 enum nexthop_types_t nhtype
, uint32_t metric
,
5817 u_char type
, u_short instance
,
5820 struct bgp_info
*new;
5821 struct bgp_info
*bi
;
5822 struct bgp_info info
;
5823 struct bgp_node
*bn
;
5825 struct attr
*new_attr
;
5828 struct bgp_redist
*red
;
5830 /* Make default attribute. */
5831 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
5834 case NEXTHOP_TYPE_IFINDEX
:
5836 case NEXTHOP_TYPE_IPV4
:
5837 case NEXTHOP_TYPE_IPV4_IFINDEX
:
5838 attr
.nexthop
= nexthop
->ipv4
;
5840 case NEXTHOP_TYPE_IPV6
:
5841 case NEXTHOP_TYPE_IPV6_IFINDEX
:
5842 attr
.mp_nexthop_global
= nexthop
->ipv6
;
5843 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
5845 case NEXTHOP_TYPE_BLACKHOLE
:
5846 switch (p
->family
) {
5848 attr
.nexthop
.s_addr
= INADDR_ANY
;
5851 memset(&attr
.mp_nexthop_global
, 0,
5852 sizeof(attr
.mp_nexthop_global
));
5853 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
5858 attr
.nh_ifindex
= ifindex
;
5861 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5864 afi
= family2afi(p
->family
);
5866 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
5868 struct attr attr_new
;
5870 /* Copy attribute for modification. */
5871 bgp_attr_dup(&attr_new
, &attr
);
5873 if (red
->redist_metric_flag
)
5874 attr_new
.med
= red
->redist_metric
;
5876 /* Apply route-map. */
5877 if (red
->rmap
.name
) {
5878 info
.peer
= bgp
->peer_self
;
5879 info
.attr
= &attr_new
;
5881 SET_FLAG(bgp
->peer_self
->rmap_type
,
5882 PEER_RMAP_TYPE_REDISTRIBUTE
);
5884 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
5887 bgp
->peer_self
->rmap_type
= 0;
5889 if (ret
== RMAP_DENYMATCH
) {
5890 /* Free uninterned attribute. */
5891 bgp_attr_flush(&attr_new
);
5893 /* Unintern original. */
5894 aspath_unintern(&attr
.aspath
);
5895 bgp_redistribute_delete(bgp
, p
, type
, instance
);
5900 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5901 bgp_attr_add_gshut_community(&attr_new
);
5903 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
5904 SAFI_UNICAST
, p
, NULL
);
5906 new_attr
= bgp_attr_intern(&attr_new
);
5908 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
5909 if (bi
->peer
== bgp
->peer_self
5910 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
5914 /* Ensure the (source route) type is updated. */
5916 if (attrhash_cmp(bi
->attr
, new_attr
)
5917 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
5918 bgp_attr_unintern(&new_attr
);
5919 aspath_unintern(&attr
.aspath
);
5920 bgp_unlock_node(bn
);
5923 /* The attribute is changed. */
5924 bgp_info_set_flag(bn
, bi
,
5925 BGP_INFO_ATTR_CHANGED
);
5927 /* Rewrite BGP route information. */
5928 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
5929 bgp_info_restore(bn
, bi
);
5931 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
5933 bgp_attr_unintern(&bi
->attr
);
5934 bi
->attr
= new_attr
;
5935 bi
->uptime
= bgp_clock();
5937 /* Process change. */
5938 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
5940 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
5941 bgp_unlock_node(bn
);
5942 aspath_unintern(&attr
.aspath
);
5947 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
5948 bgp
->peer_self
, new_attr
, bn
);
5949 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5951 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
5952 bgp_info_add(bn
, new);
5953 bgp_unlock_node(bn
);
5954 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
5957 /* Unintern original. */
5958 aspath_unintern(&attr
.aspath
);
5961 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
5965 struct bgp_node
*rn
;
5966 struct bgp_info
*ri
;
5967 struct bgp_redist
*red
;
5969 afi
= family2afi(p
->family
);
5971 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
5973 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
5974 SAFI_UNICAST
, p
, NULL
);
5976 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5977 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
5981 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
5982 bgp_info_delete(rn
, ri
);
5983 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
5985 bgp_unlock_node(rn
);
5989 /* Withdraw specified route type's route. */
5990 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
5993 struct bgp_node
*rn
;
5994 struct bgp_info
*ri
;
5995 struct bgp_table
*table
;
5997 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
5999 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6000 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6001 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6002 && ri
->instance
== instance
)
6006 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6008 bgp_info_delete(rn
, ri
);
6009 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6014 /* Static function to display route. */
6015 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6019 u_int32_t destination
;
6022 if (p
->family
== AF_INET
) {
6024 len
= vty_out(vty
, "%s",
6025 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6027 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6029 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6030 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6031 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6032 || p
->u
.prefix4
.s_addr
== 0) {
6033 /* When mask is natural,
6034 mask is not displayed. */
6036 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6038 json_object_string_add(json
, "prefix",
6039 inet_ntop(p
->family
,
6042 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6044 } else if (p
->family
== AF_ETHERNET
) {
6045 prefix2str(p
, buf
, PREFIX_STRLEN
);
6046 len
= vty_out(vty
, "%s", buf
);
6047 } else if (p
->family
== AF_EVPN
) {
6048 #if defined(HAVE_CUMULUS)
6052 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6055 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6057 prefix2str(p
, buf
, PREFIX_STRLEN
);
6058 len
= vty_out(vty
, "%s", buf
);
6064 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6071 vty_out(vty
, "\n%*s", 20, " ");
6073 vty_out(vty
, "%*s", len
, " ");
6077 enum bgp_display_type
{
6081 /* Print the short form route status for a bgp_info */
6082 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6083 json_object
*json_path
)
6087 /* Route status display. */
6088 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6089 json_object_boolean_true_add(json_path
, "removed");
6091 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6092 json_object_boolean_true_add(json_path
, "stale");
6094 if (binfo
->extra
&& binfo
->extra
->suppress
)
6095 json_object_boolean_true_add(json_path
, "suppressed");
6097 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6098 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6099 json_object_boolean_true_add(json_path
, "valid");
6102 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6103 json_object_boolean_true_add(json_path
, "history");
6105 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6106 json_object_boolean_true_add(json_path
, "damped");
6108 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6109 json_object_boolean_true_add(json_path
, "bestpath");
6111 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6112 json_object_boolean_true_add(json_path
, "multipath");
6114 /* Internal route. */
6115 if ((binfo
->peer
->as
)
6116 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6117 json_object_string_add(json_path
, "pathFrom",
6120 json_object_string_add(json_path
, "pathFrom",
6126 /* Route status display. */
6127 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6129 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6131 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6133 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6134 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6140 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6142 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6144 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6146 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6151 /* Internal route. */
6152 if (binfo
->peer
&& (binfo
->peer
->as
)
6153 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6159 /* called from terminal list command */
6160 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6161 int display
, safi_t safi
, json_object
*json_paths
)
6164 json_object
*json_path
= NULL
;
6165 json_object
*json_nexthops
= NULL
;
6166 json_object
*json_nexthop_global
= NULL
;
6167 json_object
*json_nexthop_ll
= NULL
;
6170 json_path
= json_object_new_object();
6172 /* short status lead text */
6173 route_vty_short_status_out(vty
, binfo
, json_path
);
6176 /* print prefix and mask */
6178 route_vty_out_route(p
, vty
, json_path
);
6180 vty_out(vty
, "%*s", 17, " ");
6182 route_vty_out_route(p
, vty
, json_path
);
6185 /* Print attribute */
6189 json_object_array_add(json_paths
, json_path
);
6197 * For ENCAP and EVPN routes, nexthop address family is not
6198 * neccessarily the same as the prefix address family.
6199 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6200 * EVPN routes are also exchanged with a MP nexthop. Currently,
6202 * is only IPv4, the value will be present in either
6204 * attr->mp_nexthop_global_in
6206 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6209 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6213 sprintf(nexthop
, "%s",
6214 inet_ntop(af
, &attr
->mp_nexthop_global_in
,
6218 sprintf(nexthop
, "%s",
6219 inet_ntop(af
, &attr
->mp_nexthop_global
,
6223 sprintf(nexthop
, "?");
6228 json_nexthop_global
= json_object_new_object();
6230 json_object_string_add(json_nexthop_global
,
6234 json_object_string_add(json_nexthop_global
,
6238 json_object_boolean_true_add(json_nexthop_global
,
6241 vty_out(vty
, "%s", nexthop
);
6242 } else if (safi
== SAFI_EVPN
) {
6244 json_nexthop_global
= json_object_new_object();
6246 json_object_string_add(json_nexthop_global
, "ip",
6247 inet_ntoa(attr
->nexthop
));
6248 json_object_string_add(json_nexthop_global
,
6250 json_object_boolean_true_add(json_nexthop_global
,
6253 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6256 else if (p
->family
== AF_INET
6257 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6259 json_nexthop_global
= json_object_new_object();
6261 if ((safi
== SAFI_MPLS_VPN
)
6262 || (safi
== SAFI_EVPN
))
6263 json_object_string_add(json_nexthop_global
,
6265 inet_ntoa(attr
->mp_nexthop_global_in
));
6267 json_object_string_add(json_nexthop_global
,
6269 inet_ntoa(attr
->nexthop
));
6271 json_object_string_add(json_nexthop_global
,
6273 json_object_boolean_true_add(json_nexthop_global
,
6276 if ((safi
== SAFI_MPLS_VPN
)
6277 || (safi
== SAFI_EVPN
))
6278 vty_out(vty
, "%-16s",
6280 attr
->mp_nexthop_global_in
));
6282 vty_out(vty
, "%-16s",
6283 inet_ntoa(attr
->nexthop
));
6288 else if (p
->family
== AF_INET6
6289 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6294 json_nexthop_global
= json_object_new_object();
6295 json_object_string_add(json_nexthop_global
, "ip",
6297 &attr
->mp_nexthop_global
, buf
,
6299 json_object_string_add(json_nexthop_global
,
6301 json_object_string_add(json_nexthop_global
,
6304 /* We display both LL & GL if both have been
6306 if ((attr
->mp_nexthop_len
== 32)
6307 || (binfo
->peer
->conf_if
)) {
6309 json_object_new_object();
6310 json_object_string_add(
6311 json_nexthop_ll
, "ip",
6314 &attr
->mp_nexthop_local
,
6316 json_object_string_add(json_nexthop_ll
,
6318 json_object_string_add(json_nexthop_ll
,
6323 &attr
->mp_nexthop_global
,
6324 &attr
->mp_nexthop_local
)
6326 && !attr
->mp_nexthop_prefer_global
)
6327 json_object_boolean_true_add(
6331 json_object_boolean_true_add(
6332 json_nexthop_global
,
6335 json_object_boolean_true_add(
6336 json_nexthop_global
, "used");
6338 /* Display LL if LL/Global both in table unless
6339 * prefer-global is set */
6340 if (((attr
->mp_nexthop_len
== 32)
6341 && !attr
->mp_nexthop_prefer_global
)
6342 || (binfo
->peer
->conf_if
)) {
6343 if (binfo
->peer
->conf_if
) {
6346 binfo
->peer
->conf_if
);
6347 len
= 16 - len
; /* len of IPv6
6353 vty_out(vty
, "\n%*s",
6356 vty_out(vty
, "%*s", len
,
6363 &attr
->mp_nexthop_local
,
6368 vty_out(vty
, "\n%*s",
6371 vty_out(vty
, "%*s", len
,
6375 len
= vty_out(vty
, "%s",
6377 &attr
->mp_nexthop_global
,
6382 vty_out(vty
, "\n%*s", 36, " ");
6384 vty_out(vty
, "%*s", len
, " ");
6390 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6392 json_object_int_add(json_path
, "med",
6395 vty_out(vty
, "%10u", attr
->med
);
6396 else if (!json_paths
)
6400 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6402 json_object_int_add(json_path
, "localpref",
6405 vty_out(vty
, "%7u", attr
->local_pref
);
6406 else if (!json_paths
)
6410 json_object_int_add(json_path
, "weight", attr
->weight
);
6412 vty_out(vty
, "%7u ", attr
->weight
);
6416 json_object_string_add(json_path
, "peerId",
6417 sockunion2str(&binfo
->peer
->su
,
6425 json_object_string_add(json_path
, "aspath",
6428 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6433 json_object_string_add(
6434 json_path
, "origin",
6435 bgp_origin_long_str
[attr
->origin
]);
6437 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6440 if (json_nexthop_global
|| json_nexthop_ll
) {
6441 json_nexthops
= json_object_new_array();
6443 if (json_nexthop_global
)
6444 json_object_array_add(json_nexthops
,
6445 json_nexthop_global
);
6447 if (json_nexthop_ll
)
6448 json_object_array_add(json_nexthops
,
6451 json_object_object_add(json_path
, "nexthops",
6455 json_object_array_add(json_paths
, json_path
);
6459 /* prints an additional line, indented, with VNC info, if
6461 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6462 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6467 /* called from terminal list command */
6468 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6469 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6471 json_object
*json_status
= NULL
;
6472 json_object
*json_net
= NULL
;
6474 /* Route status display. */
6476 json_status
= json_object_new_object();
6477 json_net
= json_object_new_object();
6484 /* print prefix and mask */
6486 json_object_string_add(
6487 json_net
, "addrPrefix",
6488 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6490 route_vty_out_route(p
, vty
, NULL
);
6492 /* Print attribute */
6495 if (p
->family
== AF_INET
6496 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6497 || safi
== SAFI_EVPN
6498 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6499 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6500 || safi
== SAFI_EVPN
)
6501 json_object_string_add(
6502 json_net
, "nextHop",
6504 attr
->mp_nexthop_global_in
));
6506 json_object_string_add(
6507 json_net
, "nextHop",
6508 inet_ntoa(attr
->nexthop
));
6509 } else if (p
->family
== AF_INET6
6510 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6513 json_object_string_add(
6514 json_net
, "netHopGloabal",
6516 &attr
->mp_nexthop_global
, buf
,
6521 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6522 json_object_int_add(json_net
, "metric",
6525 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6526 json_object_int_add(json_net
, "localPref",
6529 json_object_int_add(json_net
, "weight", attr
->weight
);
6533 json_object_string_add(json_net
, "asPath",
6537 json_object_string_add(json_net
, "bgpOriginCode",
6538 bgp_origin_str
[attr
->origin
]);
6540 if (p
->family
== AF_INET
6541 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6542 || safi
== SAFI_EVPN
6543 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6544 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6545 || safi
== SAFI_EVPN
)
6546 vty_out(vty
, "%-16s",
6548 attr
->mp_nexthop_global_in
));
6550 vty_out(vty
, "%-16s",
6551 inet_ntoa(attr
->nexthop
));
6552 } else if (p
->family
== AF_INET6
6553 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6560 &attr
->mp_nexthop_global
, buf
,
6564 vty_out(vty
, "\n%*s", 36, " ");
6566 vty_out(vty
, "%*s", len
, " ");
6569 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6570 vty_out(vty
, "%10u", attr
->med
);
6574 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6575 vty_out(vty
, "%7u", attr
->local_pref
);
6579 vty_out(vty
, "%7u ", attr
->weight
);
6583 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6586 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6590 json_object_boolean_true_add(json_status
, "*");
6591 json_object_boolean_true_add(json_status
, ">");
6592 json_object_object_add(json_net
, "appliedStatusSymbols",
6594 char buf_cut
[BUFSIZ
];
6595 json_object_object_add(
6597 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6603 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6604 struct bgp_info
*binfo
, int display
, safi_t safi
,
6607 json_object
*json_out
= NULL
;
6609 mpls_label_t label
= MPLS_INVALID_LABEL
;
6615 json_out
= json_object_new_object();
6617 /* short status lead text */
6618 route_vty_short_status_out(vty
, binfo
, json_out
);
6620 /* print prefix and mask */
6623 route_vty_out_route(p
, vty
, NULL
);
6625 vty_out(vty
, "%*s", 17, " ");
6628 /* Print attribute */
6631 if (((p
->family
== AF_INET
)
6632 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6633 || (safi
== SAFI_EVPN
6634 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6635 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6636 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6637 || safi
== SAFI_EVPN
) {
6639 json_object_string_add(
6640 json_out
, "mpNexthopGlobalIn",
6642 attr
->mp_nexthop_global_in
));
6644 vty_out(vty
, "%-16s",
6646 attr
->mp_nexthop_global_in
));
6649 json_object_string_add(
6650 json_out
, "nexthop",
6651 inet_ntoa(attr
->nexthop
));
6653 vty_out(vty
, "%-16s",
6654 inet_ntoa(attr
->nexthop
));
6656 } else if (((p
->family
== AF_INET6
)
6657 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6658 || (safi
== SAFI_EVPN
6659 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6660 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6664 if (attr
->mp_nexthop_len
6665 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6667 json_object_string_add(
6668 json_out
, "mpNexthopGlobalIn",
6671 &attr
->mp_nexthop_global
,
6677 &attr
->mp_nexthop_global
,
6679 } else if (attr
->mp_nexthop_len
6680 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6683 &attr
->mp_nexthop_global
,
6686 &attr
->mp_nexthop_local
,
6688 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6689 json_object_string_add(
6691 "mpNexthopGlobalLocal", buf_c
);
6693 vty_out(vty
, "%s(%s)",
6696 &attr
->mp_nexthop_global
,
6700 &attr
->mp_nexthop_local
,
6706 label
= decode_label(&binfo
->extra
->label
);
6708 if (bgp_is_valid_label(&label
)) {
6710 json_object_int_add(json_out
, "notag", label
);
6711 json_object_array_add(json
, json_out
);
6713 vty_out(vty
, "notag/%d", label
);
6719 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6720 struct bgp_info
*binfo
, int display
,
6721 json_object
*json_paths
)
6725 json_object
*json_path
= NULL
;
6728 json_path
= json_object_new_object();
6733 /* short status lead text */
6734 route_vty_short_status_out(vty
, binfo
, json_path
);
6736 /* print prefix and mask */
6738 route_vty_out_route(p
, vty
, NULL
);
6740 vty_out(vty
, "%*s", 17, " ");
6742 /* Print attribute */
6746 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6750 vty_out(vty
, "%-16s",
6751 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6755 vty_out(vty
, "%s(%s)",
6756 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6758 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
6766 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
6767 char *str
= esi2str(id
);
6768 vty_out(vty
, "%s", str
);
6769 XFREE(MTYPE_TMP
, str
);
6770 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
6771 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
6772 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
6774 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
6777 if (attr
->ecommunity
) {
6779 struct ecommunity_val
*routermac
= ecommunity_lookup(
6780 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
6781 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
6783 mac
= ecom_mac2str((char *)routermac
->val
);
6785 vty_out(vty
, "/%s", (char *)mac
);
6786 XFREE(MTYPE_TMP
, mac
);
6792 /* dampening route */
6793 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6794 struct bgp_info
*binfo
, int display
, safi_t safi
,
6795 u_char use_json
, json_object
*json
)
6799 char timebuf
[BGP_UPTIME_LEN
];
6801 /* short status lead text */
6802 route_vty_short_status_out(vty
, binfo
, json
);
6804 /* print prefix and mask */
6807 route_vty_out_route(p
, vty
, NULL
);
6809 vty_out(vty
, "%*s", 17, " ");
6812 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6816 vty_out(vty
, "\n%*s", 34, " ");
6819 json_object_int_add(json
, "peerHost", len
);
6821 vty_out(vty
, "%*s", len
, " ");
6825 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
6828 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6832 /* Print attribute */
6838 json_object_string_add(json
, "asPath",
6841 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6846 json_object_string_add(json
, "origin",
6847 bgp_origin_str
[attr
->origin
]);
6849 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6856 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6857 struct bgp_info
*binfo
, int display
, safi_t safi
,
6858 u_char use_json
, json_object
*json
)
6861 struct bgp_damp_info
*bdi
;
6862 char timebuf
[BGP_UPTIME_LEN
];
6868 bdi
= binfo
->extra
->damp_info
;
6870 /* short status lead text */
6871 route_vty_short_status_out(vty
, binfo
, json
);
6873 /* print prefix and mask */
6876 route_vty_out_route(p
, vty
, NULL
);
6878 vty_out(vty
, "%*s", 17, " ");
6881 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6885 vty_out(vty
, "\n%*s", 33, " ");
6888 json_object_int_add(json
, "peerHost", len
);
6890 vty_out(vty
, "%*s", len
, " ");
6893 len
= vty_out(vty
, "%d", bdi
->flap
);
6900 json_object_int_add(json
, "bdiFlap", len
);
6902 vty_out(vty
, "%*s", len
, " ");
6906 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
6909 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
6910 BGP_UPTIME_LEN
, 0, NULL
));
6912 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
6913 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
6915 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6916 BGP_UPTIME_LEN
, use_json
, json
);
6919 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6924 vty_out(vty
, "%*s ", 8, " ");
6927 /* Print attribute */
6933 json_object_string_add(json
, "asPath",
6936 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6941 json_object_string_add(json
, "origin",
6942 bgp_origin_str
[attr
->origin
]);
6944 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6950 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
6951 int *first
, const char *header
,
6952 json_object
*json_adv_to
)
6954 char buf1
[INET6_ADDRSTRLEN
];
6955 json_object
*json_peer
= NULL
;
6958 /* 'advertised-to' is a dictionary of peers we have advertised
6960 * prefix too. The key is the peer's IP or swpX, the value is
6962 * hostname if we know it and "" if not.
6964 json_peer
= json_object_new_object();
6967 json_object_string_add(json_peer
, "hostname",
6971 json_object_object_add(json_adv_to
, peer
->conf_if
,
6974 json_object_object_add(
6976 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
6980 vty_out(vty
, "%s", header
);
6985 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
6987 vty_out(vty
, " %s(%s)", peer
->hostname
,
6990 vty_out(vty
, " %s(%s)", peer
->hostname
,
6991 sockunion2str(&peer
->su
, buf1
,
6995 vty_out(vty
, " %s", peer
->conf_if
);
6998 sockunion2str(&peer
->su
, buf1
,
7004 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7005 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7006 json_object
*json_paths
)
7008 char buf
[INET6_ADDRSTRLEN
];
7010 #if defined(HAVE_CUMULUS)
7011 char buf2
[EVPN_ROUTE_STRLEN
];
7014 int sockunion_vty_out(struct vty
*, union sockunion
*);
7016 json_object
*json_bestpath
= NULL
;
7017 json_object
*json_cluster_list
= NULL
;
7018 json_object
*json_cluster_list_list
= NULL
;
7019 json_object
*json_ext_community
= NULL
;
7020 json_object
*json_lcommunity
= NULL
;
7021 json_object
*json_last_update
= NULL
;
7022 json_object
*json_nexthop_global
= NULL
;
7023 json_object
*json_nexthop_ll
= NULL
;
7024 json_object
*json_nexthops
= NULL
;
7025 json_object
*json_path
= NULL
;
7026 json_object
*json_peer
= NULL
;
7027 json_object
*json_string
= NULL
;
7028 json_object
*json_adv_to
= NULL
;
7030 struct listnode
*node
, *nnode
;
7032 int addpath_capable
;
7034 unsigned int first_as
;
7037 json_path
= json_object_new_object();
7038 json_peer
= json_object_new_object();
7039 json_nexthop_global
= json_object_new_object();
7042 #if defined(HAVE_CUMULUS)
7043 if (!json_paths
&& safi
== SAFI_EVPN
) {
7046 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7047 vty_out(vty
, " Route %s", buf2
);
7050 bgp_evpn_label2str(&binfo
->extra
->label
, tag_buf
,
7052 vty_out(vty
, " VNI %s", tag_buf
);
7055 if (binfo
->extra
&& binfo
->extra
->parent
) {
7056 struct bgp_info
*parent_ri
;
7057 struct bgp_node
*rn
, *prn
;
7059 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7060 rn
= parent_ri
->net
;
7061 if (rn
&& rn
->prn
) {
7063 vty_out(vty
, " Imported from %s:%s\n",
7065 (struct prefix_rd
*)&prn
->p
,
7066 buf1
, sizeof(buf1
)),
7076 /* Line1 display AS-path, Aggregator */
7079 if (!attr
->aspath
->json
)
7080 aspath_str_update(attr
->aspath
, true);
7081 json_object_lock(attr
->aspath
->json
);
7082 json_object_object_add(json_path
, "aspath",
7083 attr
->aspath
->json
);
7085 if (attr
->aspath
->segments
)
7086 aspath_print_vty(vty
, " %s",
7089 vty_out(vty
, " Local");
7093 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7095 json_object_boolean_true_add(json_path
,
7098 vty_out(vty
, ", (removed)");
7101 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7103 json_object_boolean_true_add(json_path
,
7106 vty_out(vty
, ", (stale)");
7109 if (CHECK_FLAG(attr
->flag
,
7110 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7112 json_object_int_add(json_path
, "aggregatorAs",
7113 attr
->aggregator_as
);
7114 json_object_string_add(
7115 json_path
, "aggregatorId",
7116 inet_ntoa(attr
->aggregator_addr
));
7118 vty_out(vty
, ", (aggregated by %u %s)",
7119 attr
->aggregator_as
,
7120 inet_ntoa(attr
->aggregator_addr
));
7124 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7125 PEER_FLAG_REFLECTOR_CLIENT
)) {
7127 json_object_boolean_true_add(
7128 json_path
, "rxedFromRrClient");
7130 vty_out(vty
, ", (Received from a RR-client)");
7133 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7134 PEER_FLAG_RSERVER_CLIENT
)) {
7136 json_object_boolean_true_add(
7137 json_path
, "rxedFromRsClient");
7139 vty_out(vty
, ", (Received from a RS-client)");
7142 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7144 json_object_boolean_true_add(
7145 json_path
, "dampeningHistoryEntry");
7147 vty_out(vty
, ", (history entry)");
7148 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7150 json_object_boolean_true_add(
7151 json_path
, "dampeningSuppressed");
7153 vty_out(vty
, ", (suppressed due to dampening)");
7159 /* Line2 display Next-hop, Neighbor, Router-id */
7160 /* Display the nexthop */
7161 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
||
7162 p
->family
== AF_EVPN
)
7163 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7164 || safi
== SAFI_EVPN
7165 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7166 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7167 || safi
== SAFI_EVPN
) {
7169 json_object_string_add(
7170 json_nexthop_global
, "ip",
7172 attr
->mp_nexthop_global_in
));
7176 attr
->mp_nexthop_global_in
));
7179 json_object_string_add(
7180 json_nexthop_global
, "ip",
7181 inet_ntoa(attr
->nexthop
));
7184 inet_ntoa(attr
->nexthop
));
7188 json_object_string_add(json_nexthop_global
,
7192 json_object_string_add(
7193 json_nexthop_global
, "ip",
7195 &attr
->mp_nexthop_global
, buf
,
7197 json_object_string_add(json_nexthop_global
,
7199 json_object_string_add(json_nexthop_global
,
7204 &attr
->mp_nexthop_global
, buf
,
7209 /* Display the IGP cost or 'inaccessible' */
7210 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7212 json_object_boolean_false_add(
7213 json_nexthop_global
, "accessible");
7215 vty_out(vty
, " (inaccessible)");
7217 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7219 json_object_int_add(
7220 json_nexthop_global
, "metric",
7221 binfo
->extra
->igpmetric
);
7223 vty_out(vty
, " (metric %u)",
7224 binfo
->extra
->igpmetric
);
7227 /* IGP cost is 0, display this only for json */
7230 json_object_int_add(json_nexthop_global
,
7235 json_object_boolean_true_add(
7236 json_nexthop_global
, "accessible");
7239 /* Display peer "from" output */
7240 /* This path was originated locally */
7241 if (binfo
->peer
== bgp
->peer_self
) {
7243 if (safi
== SAFI_EVPN
7244 || (p
->family
== AF_INET
7245 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7247 json_object_string_add(
7248 json_peer
, "peerId", "0.0.0.0");
7250 vty_out(vty
, " from 0.0.0.0 ");
7253 json_object_string_add(json_peer
,
7256 vty_out(vty
, " from :: ");
7260 json_object_string_add(
7261 json_peer
, "routerId",
7262 inet_ntoa(bgp
->router_id
));
7264 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7267 /* We RXed this path from one of our peers */
7271 json_object_string_add(
7272 json_peer
, "peerId",
7273 sockunion2str(&binfo
->peer
->su
, buf
,
7275 json_object_string_add(
7276 json_peer
, "routerId",
7278 &binfo
->peer
->remote_id
, buf1
,
7281 if (binfo
->peer
->hostname
)
7282 json_object_string_add(
7283 json_peer
, "hostname",
7284 binfo
->peer
->hostname
);
7286 if (binfo
->peer
->domainname
)
7287 json_object_string_add(
7288 json_peer
, "domainname",
7289 binfo
->peer
->domainname
);
7291 if (binfo
->peer
->conf_if
)
7292 json_object_string_add(
7293 json_peer
, "interface",
7294 binfo
->peer
->conf_if
);
7296 if (binfo
->peer
->conf_if
) {
7297 if (binfo
->peer
->hostname
7300 BGP_FLAG_SHOW_HOSTNAME
))
7301 vty_out(vty
, " from %s(%s)",
7302 binfo
->peer
->hostname
,
7303 binfo
->peer
->conf_if
);
7305 vty_out(vty
, " from %s",
7306 binfo
->peer
->conf_if
);
7308 if (binfo
->peer
->hostname
7311 BGP_FLAG_SHOW_HOSTNAME
))
7312 vty_out(vty
, " from %s(%s)",
7313 binfo
->peer
->hostname
,
7316 vty_out(vty
, " from %s",
7325 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7326 vty_out(vty
, " (%s)",
7327 inet_ntoa(attr
->originator_id
));
7329 vty_out(vty
, " (%s)",
7332 &binfo
->peer
->remote_id
,
7333 buf1
, sizeof(buf1
)));
7340 /* display the link-local nexthop */
7341 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7343 json_nexthop_ll
= json_object_new_object();
7344 json_object_string_add(
7345 json_nexthop_ll
, "ip",
7347 &attr
->mp_nexthop_local
, buf
,
7349 json_object_string_add(json_nexthop_ll
, "afi",
7351 json_object_string_add(json_nexthop_ll
, "scope",
7354 json_object_boolean_true_add(json_nexthop_ll
,
7357 if (!attr
->mp_nexthop_prefer_global
)
7358 json_object_boolean_true_add(
7359 json_nexthop_ll
, "used");
7361 json_object_boolean_true_add(
7362 json_nexthop_global
, "used");
7364 vty_out(vty
, " (%s) %s\n",
7366 &attr
->mp_nexthop_local
, buf
,
7368 attr
->mp_nexthop_prefer_global
7373 /* If we do not have a link-local nexthop then we must flag the
7377 json_object_boolean_true_add(
7378 json_nexthop_global
, "used");
7381 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7382 * Int/Ext/Local, Atomic, best */
7384 json_object_string_add(
7385 json_path
, "origin",
7386 bgp_origin_long_str
[attr
->origin
]);
7388 vty_out(vty
, " Origin %s",
7389 bgp_origin_long_str
[attr
->origin
]);
7391 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7393 json_object_int_add(json_path
, "med",
7396 vty_out(vty
, ", metric %u", attr
->med
);
7399 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7401 json_object_int_add(json_path
, "localpref",
7404 vty_out(vty
, ", localpref %u",
7408 json_object_int_add(json_path
, "localpref",
7409 bgp
->default_local_pref
);
7411 vty_out(vty
, ", localpref %u",
7412 bgp
->default_local_pref
);
7415 if (attr
->weight
!= 0) {
7417 json_object_int_add(json_path
, "weight",
7420 vty_out(vty
, ", weight %u", attr
->weight
);
7423 if (attr
->tag
!= 0) {
7425 json_object_int_add(json_path
, "tag",
7428 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7432 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7434 json_object_boolean_false_add(json_path
,
7437 vty_out(vty
, ", invalid");
7438 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7440 json_object_boolean_true_add(json_path
,
7443 vty_out(vty
, ", valid");
7446 if (binfo
->peer
!= bgp
->peer_self
) {
7447 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7448 if (CHECK_FLAG(bgp
->config
,
7449 BGP_CONFIG_CONFEDERATION
)) {
7451 json_object_string_add(
7456 ", confed-internal");
7459 json_object_string_add(
7463 vty_out(vty
, ", internal");
7466 if (bgp_confederation_peers_check(
7467 bgp
, binfo
->peer
->as
)) {
7469 json_object_string_add(
7474 ", confed-external");
7477 json_object_string_add(
7481 vty_out(vty
, ", external");
7484 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7486 json_object_boolean_true_add(json_path
,
7488 json_object_boolean_true_add(json_path
,
7491 vty_out(vty
, ", aggregated, local");
7493 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7495 json_object_boolean_true_add(json_path
,
7498 vty_out(vty
, ", sourced");
7501 json_object_boolean_true_add(json_path
,
7503 json_object_boolean_true_add(json_path
,
7506 vty_out(vty
, ", sourced, local");
7510 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7512 json_object_boolean_true_add(json_path
,
7515 vty_out(vty
, ", atomic-aggregate");
7518 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7519 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7520 && bgp_info_mpath_count(binfo
))) {
7522 json_object_boolean_true_add(json_path
,
7525 vty_out(vty
, ", multipath");
7528 // Mark the bestpath(s)
7529 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7530 first_as
= aspath_get_first_as(attr
->aspath
);
7535 json_object_new_object();
7536 json_object_int_add(json_bestpath
,
7537 "bestpathFromAs", first_as
);
7540 vty_out(vty
, ", bestpath-from-AS %u",
7544 ", bestpath-from-AS Local");
7548 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7552 json_object_new_object();
7553 json_object_boolean_true_add(json_bestpath
,
7556 vty_out(vty
, ", best");
7560 json_object_object_add(json_path
, "bestpath",
7566 /* Line 4 display Community */
7567 if (attr
->community
) {
7569 if (!attr
->community
->json
)
7570 community_str(attr
->community
,
7572 json_object_lock(attr
->community
->json
);
7573 json_object_object_add(json_path
, "community",
7574 attr
->community
->json
);
7576 vty_out(vty
, " Community: %s\n",
7577 attr
->community
->str
);
7581 /* Line 5 display Extended-community */
7582 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7584 json_ext_community
= json_object_new_object();
7585 json_object_string_add(json_ext_community
,
7587 attr
->ecommunity
->str
);
7588 json_object_object_add(json_path
,
7589 "extendedCommunity",
7590 json_ext_community
);
7592 vty_out(vty
, " Extended Community: %s\n",
7593 attr
->ecommunity
->str
);
7597 /* Line 6 display Large community */
7598 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7600 json_lcommunity
= json_object_new_object();
7601 json_object_string_add(json_lcommunity
,
7603 attr
->lcommunity
->str
);
7604 json_object_object_add(json_path
,
7608 vty_out(vty
, " Large Community: %s\n",
7609 attr
->lcommunity
->str
);
7613 /* Line 7 display Originator, Cluster-id */
7614 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7615 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7617 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7619 json_object_string_add(
7620 json_path
, "originatorId",
7621 inet_ntoa(attr
->originator_id
));
7623 vty_out(vty
, " Originator: %s",
7624 inet_ntoa(attr
->originator_id
));
7627 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7632 json_object_new_object();
7633 json_cluster_list_list
=
7634 json_object_new_array();
7637 i
< attr
->cluster
->length
/ 4;
7639 json_string
= json_object_new_string(
7643 json_object_array_add(
7644 json_cluster_list_list
,
7648 /* struct cluster_list does not have
7650 * aspath and community do. Add this
7653 json_object_string_add(json_cluster_list,
7654 "string", attr->cluster->str);
7656 json_object_object_add(
7657 json_cluster_list
, "list",
7658 json_cluster_list_list
);
7659 json_object_object_add(
7660 json_path
, "clusterList",
7663 vty_out(vty
, ", Cluster list: ");
7666 i
< attr
->cluster
->length
/ 4;
7680 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7681 bgp_damp_info_vty(vty
, binfo
, json_path
);
7684 #if defined(HAVE_CUMULUS)
7685 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
)
7686 && safi
!= SAFI_EVPN
)
7688 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
))
7691 mpls_label_t label
= label_pton(&binfo
->extra
->label
);
7693 json_object_int_add(json_path
, "remoteLabel",
7696 vty_out(vty
, " Remote label: %d\n", label
);
7700 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7702 json_object_int_add(json_path
, "labelIndex",
7705 vty_out(vty
, " Label Index: %d\n",
7709 /* Line 8 display Addpath IDs */
7710 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7712 json_object_int_add(json_path
, "addpathRxId",
7713 binfo
->addpath_rx_id
);
7714 json_object_int_add(json_path
, "addpathTxId",
7715 binfo
->addpath_tx_id
);
7717 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7718 binfo
->addpath_rx_id
,
7719 binfo
->addpath_tx_id
);
7723 /* If we used addpath to TX a non-bestpath we need to display
7724 * "Advertised to" on a path-by-path basis */
7725 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7728 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7730 bgp_addpath_encode_tx(peer
, afi
, safi
);
7731 has_adj
= bgp_adj_out_lookup(
7732 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7734 if ((addpath_capable
&& has_adj
)
7735 || (!addpath_capable
&& has_adj
7736 && CHECK_FLAG(binfo
->flags
,
7737 BGP_INFO_SELECTED
))) {
7738 if (json_path
&& !json_adv_to
)
7740 json_object_new_object();
7742 route_vty_out_advertised_to(
7751 json_object_object_add(json_path
,
7762 /* Line 9 display Uptime */
7763 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
7765 json_last_update
= json_object_new_object();
7766 json_object_int_add(json_last_update
, "epoch", tbuf
);
7767 json_object_string_add(json_last_update
, "string",
7769 json_object_object_add(json_path
, "lastUpdate",
7772 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
7775 /* We've constructed the json object for this path, add it to the json
7779 if (json_nexthop_global
|| json_nexthop_ll
) {
7780 json_nexthops
= json_object_new_array();
7782 if (json_nexthop_global
)
7783 json_object_array_add(json_nexthops
,
7784 json_nexthop_global
);
7786 if (json_nexthop_ll
)
7787 json_object_array_add(json_nexthops
,
7790 json_object_object_add(json_path
, "nexthops",
7794 json_object_object_add(json_path
, "peer", json_peer
);
7795 json_object_array_add(json_paths
, json_path
);
7800 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7801 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7802 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
7804 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
7805 const char *prefix_list_str
, afi_t afi
,
7806 safi_t safi
, enum bgp_show_type type
);
7807 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
7808 const char *filter
, afi_t afi
, safi_t safi
,
7809 enum bgp_show_type type
);
7810 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
7811 const char *rmap_str
, afi_t afi
, safi_t safi
,
7812 enum bgp_show_type type
);
7813 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
7814 const char *com
, int exact
, afi_t afi
,
7816 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
7817 const char *prefix
, afi_t afi
, safi_t safi
,
7818 enum bgp_show_type type
);
7819 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
7820 const char *regstr
, afi_t afi
,
7821 safi_t safi
, enum bgp_show_type type
);
7822 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
7823 const char *comstr
, int exact
, afi_t afi
,
7827 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
7828 struct bgp_table
*table
, enum bgp_show_type type
,
7829 void *output_arg
, u_char use_json
,
7830 char *rd
, int is_last
,
7831 unsigned long *output_cum
, unsigned long *total_cum
)
7833 struct bgp_info
*ri
;
7834 struct bgp_node
*rn
;
7837 unsigned long output_count
= 0;
7838 unsigned long total_count
= 0;
7842 json_object
*json_paths
= NULL
;
7845 if (output_cum
&& *output_cum
!= 0)
7848 if (use_json
&& header
) {
7850 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
7851 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
7852 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : bgp
->vrf_id
,
7853 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
7855 table
->version
, inet_ntoa(bgp
->router_id
));
7857 vty_out(vty
, " \"routeDistinguishers\" : {");
7858 json_paths
= json_object_new_object();
7861 if (use_json
&& rd
) {
7862 vty_out(vty
, " \"%s\" : { ", rd
);
7865 /* Start processing of routes. */
7866 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7867 if (rn
->info
== NULL
)
7872 json_paths
= json_object_new_array();
7876 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
7878 if (type
== bgp_show_type_flap_statistics
7879 || type
== bgp_show_type_flap_neighbor
7880 || type
== bgp_show_type_dampend_paths
7881 || type
== bgp_show_type_damp_neighbor
) {
7883 && ri
->extra
->damp_info
))
7886 if (type
== bgp_show_type_regexp
) {
7887 regex_t
*regex
= output_arg
;
7889 if (bgp_regexec(regex
, ri
->attr
->aspath
)
7893 if (type
== bgp_show_type_prefix_list
) {
7894 struct prefix_list
*plist
= output_arg
;
7896 if (prefix_list_apply(plist
, &rn
->p
)
7900 if (type
== bgp_show_type_filter_list
) {
7901 struct as_list
*as_list
= output_arg
;
7903 if (as_list_apply(as_list
, ri
->attr
->aspath
)
7904 != AS_FILTER_PERMIT
)
7907 if (type
== bgp_show_type_route_map
) {
7908 struct route_map
*rmap
= output_arg
;
7909 struct bgp_info binfo
;
7910 struct attr dummy_attr
;
7913 bgp_attr_dup(&dummy_attr
, ri
->attr
);
7915 binfo
.peer
= ri
->peer
;
7916 binfo
.attr
= &dummy_attr
;
7918 ret
= route_map_apply(rmap
, &rn
->p
,
7920 if (ret
== RMAP_DENYMATCH
)
7923 if (type
== bgp_show_type_neighbor
7924 || type
== bgp_show_type_flap_neighbor
7925 || type
== bgp_show_type_damp_neighbor
) {
7926 union sockunion
*su
= output_arg
;
7928 if (ri
->peer
== NULL
7929 || ri
->peer
->su_remote
== NULL
7930 || !sockunion_same(ri
->peer
->su_remote
,
7934 if (type
== bgp_show_type_cidr_only
) {
7935 u_int32_t destination
;
7937 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
7938 if (IN_CLASSC(destination
)
7939 && rn
->p
.prefixlen
== 24)
7941 if (IN_CLASSB(destination
)
7942 && rn
->p
.prefixlen
== 16)
7944 if (IN_CLASSA(destination
)
7945 && rn
->p
.prefixlen
== 8)
7948 if (type
== bgp_show_type_prefix_longer
) {
7949 struct prefix
*p
= output_arg
;
7951 if (!prefix_match(p
, &rn
->p
))
7954 if (type
== bgp_show_type_community_all
) {
7955 if (!ri
->attr
->community
)
7958 if (type
== bgp_show_type_community
) {
7959 struct community
*com
= output_arg
;
7961 if (!ri
->attr
->community
7962 || !community_match(ri
->attr
->community
,
7966 if (type
== bgp_show_type_community_exact
) {
7967 struct community
*com
= output_arg
;
7969 if (!ri
->attr
->community
7970 || !community_cmp(ri
->attr
->community
,
7974 if (type
== bgp_show_type_community_list
) {
7975 struct community_list
*list
= output_arg
;
7977 if (!community_list_match(
7978 ri
->attr
->community
, list
))
7982 == bgp_show_type_community_list_exact
) {
7983 struct community_list
*list
= output_arg
;
7985 if (!community_list_exact_match(
7986 ri
->attr
->community
, list
))
7989 if (type
== bgp_show_type_lcommunity
) {
7990 struct lcommunity
*lcom
= output_arg
;
7992 if (!ri
->attr
->lcommunity
7993 || !lcommunity_match(ri
->attr
->lcommunity
,
7997 if (type
== bgp_show_type_lcommunity_list
) {
7998 struct community_list
*list
= output_arg
;
8000 if (!lcommunity_list_match(
8001 ri
->attr
->lcommunity
, list
))
8004 if (type
== bgp_show_type_lcommunity_all
) {
8005 if (!ri
->attr
->lcommunity
)
8008 if (type
== bgp_show_type_dampend_paths
8009 || type
== bgp_show_type_damp_neighbor
) {
8010 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8011 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8015 if (!use_json
&& header
) {
8017 "BGP table version is %" PRIu64
8018 ", local router ID is %s\n",
8020 inet_ntoa(bgp
->router_id
));
8021 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8022 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8023 if (type
== bgp_show_type_dampend_paths
8024 || type
== bgp_show_type_damp_neighbor
)
8025 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8027 type
== bgp_show_type_flap_statistics
8028 || type
== bgp_show_type_flap_neighbor
)
8029 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8031 vty_out(vty
, BGP_SHOW_HEADER
);
8034 if (rd
!= NULL
&& !display
&& !output_count
) {
8037 "Route Distinguisher: %s\n",
8040 if (type
== bgp_show_type_dampend_paths
8041 || type
== bgp_show_type_damp_neighbor
)
8042 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8045 else if (type
== bgp_show_type_flap_statistics
8046 || type
== bgp_show_type_flap_neighbor
)
8047 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8051 route_vty_out(vty
, &rn
->p
, ri
, display
,
8062 sprintf(buf2
, "%s/%d",
8063 inet_ntop(p
->family
, &p
->u
.prefix
,
8067 vty_out(vty
, "\"%s\": ", buf2
);
8069 vty_out(vty
, ",\"%s\": ", buf2
);
8072 json_object_to_json_string(json_paths
));
8073 json_object_free(json_paths
);
8080 output_count
+= *output_cum
;
8081 *output_cum
= output_count
;
8084 total_count
+= *total_cum
;
8085 *total_cum
= total_count
;
8089 json_object_free(json_paths
);
8091 vty_out(vty
, " } }\n");
8093 vty_out(vty
, " }, ");
8096 /* No route is displayed */
8097 if (output_count
== 0) {
8098 if (type
== bgp_show_type_normal
)
8100 "No BGP prefixes displayed, %ld exist\n",
8104 "\nDisplayed %ld routes and %ld total paths\n",
8105 output_count
, total_count
);
8112 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8113 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8114 enum bgp_show_type type
, void *output_arg
,
8117 struct bgp_node
*rn
, *next
;
8118 unsigned long output_cum
= 0;
8119 unsigned long total_cum
= 0;
8121 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8122 next
= bgp_route_next(rn
);
8123 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8125 if (rn
->info
!= NULL
) {
8126 struct prefix_rd prd
;
8127 char rd
[RD_ADDRSTRLEN
];
8129 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8130 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8131 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8132 output_arg
, use_json
,
8134 &output_cum
, &total_cum
);
8138 vty_out(vty
, " } }");
8141 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8142 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8144 struct bgp_table
*table
;
8147 bgp
= bgp_get_default();
8152 vty_out(vty
, "No BGP process is configured\n");
8154 vty_out(vty
, "{}\n");
8158 table
= bgp
->rib
[afi
][safi
];
8159 /* use MPLS and ENCAP specific shows until they are merged */
8160 if (safi
== SAFI_MPLS_VPN
) {
8161 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8162 output_arg
, use_json
);
8164 /* labeled-unicast routes live in the unicast table */
8165 else if (safi
== SAFI_LABELED_UNICAST
)
8166 safi
= SAFI_UNICAST
;
8168 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8169 NULL
, 1, NULL
, NULL
);
8172 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8173 safi_t safi
, u_char use_json
)
8175 struct listnode
*node
, *nnode
;
8180 vty_out(vty
, "{\n");
8182 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8185 vty_out(vty
, ",\n");
8189 vty_out(vty
, "\"%s\":",
8190 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8194 vty_out(vty
, "\nInstance %s:\n",
8195 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8199 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8204 vty_out(vty
, "}\n");
8207 /* Header of detailed BGP route information */
8208 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8209 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8210 afi_t afi
, safi_t safi
, json_object
*json
)
8212 struct bgp_info
*ri
;
8215 struct listnode
*node
, *nnode
;
8216 char buf1
[RD_ADDRSTRLEN
];
8217 char buf2
[INET6_ADDRSTRLEN
];
8218 #if defined(HAVE_CUMULUS)
8219 char buf3
[EVPN_ROUTE_STRLEN
];
8221 char prefix_str
[BUFSIZ
];
8226 int no_advertise
= 0;
8229 int has_valid_label
= 0;
8230 mpls_label_t label
= 0;
8231 json_object
*json_adv_to
= NULL
;
8234 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8236 if (has_valid_label
)
8237 label
= label_pton(&rn
->local_label
);
8240 if (has_valid_label
)
8241 json_object_int_add(json
, "localLabel", label
);
8243 json_object_string_add(
8245 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8247 #if defined(HAVE_CUMULUS)
8248 if (safi
== SAFI_EVPN
)
8249 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8250 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8253 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8254 buf3
, sizeof(buf3
)));
8256 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8257 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8258 ? prefix_rd2str(prd
, buf1
,
8261 safi
== SAFI_MPLS_VPN
? ":" : "",
8262 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8266 if (p
->family
== AF_ETHERNET
)
8267 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8269 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8271 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8272 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8273 || safi
== SAFI_EVPN
)
8274 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8276 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8278 buf2
, p
->prefixlen
);
8281 if (has_valid_label
)
8282 vty_out(vty
, "Local label: %d\n", label
);
8283 #if defined(HAVE_CUMULUS)
8284 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8286 if (bgp_labeled_safi(safi
))
8288 vty_out(vty
, "not allocated\n");
8291 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8293 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8295 if (ri
->extra
&& ri
->extra
->suppress
)
8297 if (ri
->attr
->community
!= NULL
) {
8298 if (community_include(ri
->attr
->community
,
8299 COMMUNITY_NO_ADVERTISE
))
8301 if (community_include(ri
->attr
->community
,
8302 COMMUNITY_NO_EXPORT
))
8304 if (community_include(ri
->attr
->community
,
8305 COMMUNITY_LOCAL_AS
))
8312 vty_out(vty
, "Paths: (%d available", count
);
8314 vty_out(vty
, ", best #%d", best
);
8315 if (safi
== SAFI_UNICAST
)
8316 vty_out(vty
, ", table %s",
8318 == BGP_INSTANCE_TYPE_DEFAULT
)
8319 ? "Default-IP-Routing-Table"
8322 vty_out(vty
, ", no best path");
8325 vty_out(vty
, ", not advertised to any peer");
8327 vty_out(vty
, ", not advertised to EBGP peer");
8329 vty_out(vty
, ", not advertised outside local AS");
8333 ", Advertisements suppressed by an aggregate.");
8334 vty_out(vty
, ")\n");
8337 /* If we are not using addpath then we can display Advertised to and
8339 * show what peers we advertised the bestpath to. If we are using
8341 * though then we must display Advertised to on a path-by-path basis. */
8342 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8343 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8344 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8345 if (json
&& !json_adv_to
)
8346 json_adv_to
= json_object_new_object();
8348 route_vty_out_advertised_to(
8350 " Advertised to non peer-group peers:\n ",
8357 json_object_object_add(json
, "advertisedTo",
8362 vty_out(vty
, " Not advertised to any peer");
8368 /* Display specified route of BGP table. */
8369 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8370 struct bgp_table
*rib
, const char *ip_str
,
8371 afi_t afi
, safi_t safi
,
8372 struct prefix_rd
*prd
, int prefix_check
,
8373 enum bgp_path_type pathtype
, u_char use_json
)
8378 struct prefix match
;
8379 struct bgp_node
*rn
;
8380 struct bgp_node
*rm
;
8381 struct bgp_info
*ri
;
8382 struct bgp_table
*table
;
8383 json_object
*json
= NULL
;
8384 json_object
*json_paths
= NULL
;
8386 /* Check IP address argument. */
8387 ret
= str2prefix(ip_str
, &match
);
8389 vty_out(vty
, "address is malformed\n");
8393 match
.family
= afi2family(afi
);
8396 json
= json_object_new_object();
8397 json_paths
= json_object_new_array();
8400 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8401 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8402 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8405 if ((table
= rn
->info
) == NULL
)
8410 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8414 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8415 bgp_unlock_node(rm
);
8419 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8421 route_vty_out_detail_header(
8423 (struct prefix_rd
*)&rn
->p
,
8424 AFI_IP
, safi
, json
);
8429 if (pathtype
== BGP_PATH_ALL
8430 || (pathtype
== BGP_PATH_BESTPATH
8431 && CHECK_FLAG(ri
->flags
,
8433 || (pathtype
== BGP_PATH_MULTIPATH
8434 && (CHECK_FLAG(ri
->flags
,
8436 || CHECK_FLAG(ri
->flags
,
8437 BGP_INFO_SELECTED
))))
8438 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8443 bgp_unlock_node(rm
);
8448 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8450 || rn
->p
.prefixlen
== match
.prefixlen
) {
8451 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8453 route_vty_out_detail_header(
8454 vty
, bgp
, rn
, NULL
, afi
,
8460 if (pathtype
== BGP_PATH_ALL
8461 || (pathtype
== BGP_PATH_BESTPATH
8465 || (pathtype
== BGP_PATH_MULTIPATH
8471 BGP_INFO_SELECTED
))))
8472 route_vty_out_detail(
8473 vty
, bgp
, &rn
->p
, ri
,
8474 afi
, safi
, json_paths
);
8478 bgp_unlock_node(rn
);
8484 json_object_object_add(json
, "paths", json_paths
);
8486 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8487 json
, JSON_C_TO_STRING_PRETTY
));
8488 json_object_free(json
);
8491 vty_out(vty
, "%% Network not in table\n");
8499 /* Display specified route of Main RIB */
8500 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8501 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8502 int prefix_check
, enum bgp_path_type pathtype
,
8506 bgp
= bgp_get_default();
8509 vty_out(vty
, "No BGP process is configured\n");
8511 vty_out(vty
, "{}\n");
8516 /* labeled-unicast routes live in the unicast table */
8517 if (safi
== SAFI_LABELED_UNICAST
)
8518 safi
= SAFI_UNICAST
;
8520 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8521 afi
, safi
, prd
, prefix_check
, pathtype
,
8525 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8526 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8529 struct lcommunity
*lcom
;
8535 b
= buffer_new(1024);
8536 for (i
= 0; i
< argc
; i
++) {
8538 buffer_putc(b
, ' ');
8540 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8542 buffer_putstr(b
, argv
[i
]->arg
);
8546 buffer_putc(b
, '\0');
8548 str
= buffer_getstr(b
);
8551 lcom
= lcommunity_str2com(str
);
8552 XFREE(MTYPE_TMP
, str
);
8554 vty_out(vty
, "%% Large-community malformed\n");
8558 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8562 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8563 const char *lcom
, afi_t afi
, safi_t safi
,
8566 struct community_list
*list
;
8568 list
= community_list_lookup(bgp_clist
, lcom
,
8569 LARGE_COMMUNITY_LIST_MASTER
);
8571 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8576 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8580 DEFUN (show_ip_bgp_large_community_list
,
8581 show_ip_bgp_large_community_list_cmd
,
8582 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8586 BGP_INSTANCE_HELP_STR
8588 BGP_SAFI_WITH_LABEL_HELP_STR
8589 "Display routes matching the large-community-list\n"
8590 "large-community-list number\n"
8591 "large-community-list name\n"
8595 afi_t afi
= AFI_IP6
;
8596 safi_t safi
= SAFI_UNICAST
;
8599 if (argv_find(argv
, argc
, "ip", &idx
))
8601 if (argv_find(argv
, argc
, "view", &idx
)
8602 || argv_find(argv
, argc
, "vrf", &idx
))
8603 vrf
= argv
[++idx
]->arg
;
8604 if (argv_find(argv
, argc
, "ipv4", &idx
)
8605 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8606 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8607 if (argv_find(argv
, argc
, "unicast", &idx
)
8608 || argv_find(argv
, argc
, "multicast", &idx
))
8609 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8612 int uj
= use_json(argc
, argv
);
8614 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8616 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8620 argv_find(argv
, argc
, "large-community-list", &idx
);
8621 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8624 DEFUN (show_ip_bgp_large_community
,
8625 show_ip_bgp_large_community_cmd
,
8626 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8630 BGP_INSTANCE_HELP_STR
8632 BGP_SAFI_WITH_LABEL_HELP_STR
8633 "Display routes matching the large-communities\n"
8634 "List of large-community numbers\n"
8638 afi_t afi
= AFI_IP6
;
8639 safi_t safi
= SAFI_UNICAST
;
8642 if (argv_find(argv
, argc
, "ip", &idx
))
8644 if (argv_find(argv
, argc
, "view", &idx
)
8645 || argv_find(argv
, argc
, "vrf", &idx
))
8646 vrf
= argv
[++idx
]->arg
;
8647 if (argv_find(argv
, argc
, "ipv4", &idx
)
8648 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8649 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8650 if (argv_find(argv
, argc
, "unicast", &idx
)
8651 || argv_find(argv
, argc
, "multicast", &idx
))
8652 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8655 int uj
= use_json(argc
, argv
);
8657 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8659 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8663 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8664 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8666 return bgp_show(vty
, bgp
, afi
, safi
,
8667 bgp_show_type_lcommunity_all
, NULL
, uj
);
8670 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8674 /* BGP route print out function without JSON */
8677 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8678 <dampening <parameters>\
8683 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
8684 |community-list <(1-500)|WORD> [exact-match]\
8685 |A.B.C.D/M longer-prefixes\
8686 |X:X::X:X/M longer-prefixes\
8691 BGP_INSTANCE_HELP_STR
8693 BGP_SAFI_WITH_LABEL_HELP_STR
8694 "Display detailed information about dampening\n"
8695 "Display detail of configured dampening parameters\n"
8696 "Display routes matching the route-map\n"
8697 "A route-map to match on\n"
8698 "Display routes conforming to the prefix-list\n"
8699 "Prefix-list name\n"
8700 "Display routes conforming to the filter-list\n"
8701 "Regular expression access list name\n"
8702 "BGP RIB advertisement statistics\n"
8703 "Display routes matching the communities\n"
8705 "Do not send outside local AS (well-known community)\n"
8706 "Do not advertise to any peer (well-known community)\n"
8707 "Do not export to next AS (well-known community)\n"
8708 "Graceful shutdown (well-known community)\n"
8709 "Exact match of the communities\n"
8710 "Display routes matching the community-list\n"
8711 "community-list number\n"
8712 "community-list name\n"
8713 "Exact match of the communities\n"
8715 "Display route and more specific routes\n"
8717 "Display route and more specific routes\n")
8719 afi_t afi
= AFI_IP6
;
8720 safi_t safi
= SAFI_UNICAST
;
8721 int exact_match
= 0;
8722 struct bgp
*bgp
= NULL
;
8724 int idx_community_type
= 0;
8726 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8731 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8732 if (argv_find(argv
, argc
, "parameters", &idx
))
8733 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8736 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8737 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8738 safi
, bgp_show_type_prefix_list
);
8740 if (argv_find(argv
, argc
, "filter-list", &idx
))
8741 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8742 safi
, bgp_show_type_filter_list
);
8744 if (argv_find(argv
, argc
, "statistics", &idx
))
8745 return bgp_table_stats(vty
, bgp
, afi
, safi
);
8747 if (argv_find(argv
, argc
, "route-map", &idx
))
8748 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8749 safi
, bgp_show_type_route_map
);
8751 if (argv_find(argv
, argc
, "community", &idx
)) {
8752 /* show a specific community */
8753 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
8754 || argv_find(argv
, argc
, "no-advertise", &idx_community_type
)
8755 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
8756 || argv_find(argv
, argc
, "graceful-shutdown", &idx_community_type
)
8757 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
8759 if (argv_find(argv
, argc
, "exact-match", &idx
))
8761 return bgp_show_community(vty
, bgp
, argv
[idx_community_type
]->arg
,
8762 exact_match
, afi
, safi
);
8766 if (argv_find(argv
, argc
, "community-list", &idx
)) {
8767 const char *clist_number_or_name
= argv
[++idx
]->arg
;
8768 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
8770 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
8771 exact_match
, afi
, safi
);
8774 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8775 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8776 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
8778 bgp_show_type_prefix_longer
);
8783 /* BGP route print out function with JSON */
8784 DEFUN (show_ip_bgp_json
,
8785 show_ip_bgp_json_cmd
,
8786 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8789 |dampening <flap-statistics|dampened-paths>\
8795 BGP_INSTANCE_HELP_STR
8797 BGP_SAFI_WITH_LABEL_HELP_STR
8798 "Display only routes with non-natural netmasks\n"
8799 "Display detailed information about dampening\n"
8800 "Display flap statistics of routes\n"
8801 "Display paths suppressed due to dampening\n"
8802 "Display routes matching the communities\n"
8805 afi_t afi
= AFI_IP6
;
8806 safi_t safi
= SAFI_UNICAST
;
8807 enum bgp_show_type sh_type
= bgp_show_type_normal
;
8808 struct bgp
*bgp
= NULL
;
8811 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8816 int uj
= use_json(argc
, argv
);
8820 if (argv_find(argv
, argc
, "cidr-only", &idx
))
8821 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
8824 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8825 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
8826 return bgp_show(vty
, bgp
, afi
, safi
,
8827 bgp_show_type_dampend_paths
, NULL
, uj
);
8828 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
8829 return bgp_show(vty
, bgp
, afi
, safi
,
8830 bgp_show_type_flap_statistics
, NULL
,
8834 if (argv_find(argv
, argc
, "community", &idx
)) {
8835 /* show all communities */
8836 return bgp_show(vty
, bgp
, afi
, safi
,
8837 bgp_show_type_community_all
, NULL
, uj
);
8839 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
8842 DEFUN (show_ip_bgp_route
,
8843 show_ip_bgp_route_cmd
,
8844 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
8845 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
8849 BGP_INSTANCE_HELP_STR
8851 BGP_SAFI_WITH_LABEL_HELP_STR
8852 "Network in the BGP routing table to display\n"
8854 "Network in the BGP routing table to display\n"
8856 "Display only the bestpath\n"
8857 "Display only multipaths\n"
8860 int prefix_check
= 0;
8862 afi_t afi
= AFI_IP6
;
8863 safi_t safi
= SAFI_UNICAST
;
8864 char *prefix
= NULL
;
8865 struct bgp
*bgp
= NULL
;
8866 enum bgp_path_type path_type
;
8867 u_char uj
= use_json(argc
, argv
);
8871 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8878 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8882 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8883 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
8884 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
8886 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8887 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8890 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
8891 && afi
!= AFI_IP6
) {
8893 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
8896 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
8899 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
8903 prefix
= argv
[idx
]->arg
;
8905 /* [<bestpath|multipath>] */
8906 if (argv_find(argv
, argc
, "bestpath", &idx
))
8907 path_type
= BGP_PATH_BESTPATH
;
8908 else if (argv_find(argv
, argc
, "multipath", &idx
))
8909 path_type
= BGP_PATH_MULTIPATH
;
8911 path_type
= BGP_PATH_ALL
;
8913 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
8917 DEFUN (show_ip_bgp_regexp
,
8918 show_ip_bgp_regexp_cmd
,
8919 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
8923 BGP_INSTANCE_HELP_STR
8925 BGP_SAFI_WITH_LABEL_HELP_STR
8926 "Display routes matching the AS path regular expression\n"
8927 "A regular-expression to match the BGP AS paths\n")
8929 afi_t afi
= AFI_IP6
;
8930 safi_t safi
= SAFI_UNICAST
;
8931 struct bgp
*bgp
= NULL
;
8934 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8939 // get index of regex
8940 argv_find(argv
, argc
, "regexp", &idx
);
8943 char *regstr
= argv_concat(argv
, argc
, idx
);
8944 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
8945 bgp_show_type_regexp
);
8946 XFREE(MTYPE_TMP
, regstr
);
8950 DEFUN (show_ip_bgp_instance_all
,
8951 show_ip_bgp_instance_all_cmd
,
8952 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
8956 BGP_INSTANCE_ALL_HELP_STR
8958 BGP_SAFI_WITH_LABEL_HELP_STR
8962 safi_t safi
= SAFI_UNICAST
;
8963 struct bgp
*bgp
= NULL
;
8966 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8971 int uj
= use_json(argc
, argv
);
8975 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
8979 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
,
8980 const char *regstr
, afi_t afi
,
8981 safi_t safi
, enum bgp_show_type type
)
8986 regex
= bgp_regcomp(regstr
);
8988 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
8992 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
8993 bgp_regex_free(regex
);
8997 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8998 const char *prefix_list_str
, afi_t afi
,
8999 safi_t safi
, enum bgp_show_type type
)
9001 struct prefix_list
*plist
;
9003 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9004 if (plist
== NULL
) {
9005 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9010 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9013 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9014 const char *filter
, afi_t afi
, safi_t safi
,
9015 enum bgp_show_type type
)
9017 struct as_list
*as_list
;
9019 as_list
= as_list_lookup(filter
);
9020 if (as_list
== NULL
) {
9021 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9026 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9029 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9030 const char *rmap_str
, afi_t afi
, safi_t safi
,
9031 enum bgp_show_type type
)
9033 struct route_map
*rmap
;
9035 rmap
= route_map_lookup_by_name(rmap_str
);
9037 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9041 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9044 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9045 const char *comstr
, int exact
, afi_t afi
,
9048 struct community
*com
;
9051 com
= community_str2com(comstr
);
9053 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9057 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9058 (exact
? bgp_show_type_community_exact
9059 : bgp_show_type_community
),
9061 community_free(com
);
9066 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9067 const char *com
, int exact
, afi_t afi
,
9070 struct community_list
*list
;
9072 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9074 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9078 return bgp_show(vty
, bgp
, afi
, safi
,
9079 (exact
? bgp_show_type_community_list_exact
9080 : bgp_show_type_community_list
),
9084 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9085 const char *prefix
, afi_t afi
, safi_t safi
,
9086 enum bgp_show_type type
)
9093 ret
= str2prefix(prefix
, p
);
9095 vty_out(vty
, "%% Malformed Prefix\n");
9099 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9104 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9105 const char *ip_str
, u_char use_json
)
9111 /* Get peer sockunion. */
9112 ret
= str2sockunion(ip_str
, &su
);
9114 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9116 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9120 json_object
*json_no
= NULL
;
9121 json_no
= json_object_new_object();
9122 json_object_string_add(
9124 "malformedAddressOrName",
9126 vty_out(vty
, "%s\n",
9127 json_object_to_json_string_ext(
9128 json_no
, JSON_C_TO_STRING_PRETTY
));
9129 json_object_free(json_no
);
9132 "%% Malformed address or name: %s\n",
9140 /* Peer structure lookup. */
9141 peer
= peer_lookup(bgp
, &su
);
9144 json_object
*json_no
= NULL
;
9145 json_no
= json_object_new_object();
9146 json_object_string_add(json_no
, "warning",
9147 "No such neighbor");
9148 vty_out(vty
, "%s\n",
9149 json_object_to_json_string_ext(json_no
,
9150 JSON_C_TO_STRING_PRETTY
));
9151 json_object_free(json_no
);
9153 vty_out(vty
, "No such neighbor\n");
9161 BGP_STATS_MAXBITLEN
= 0,
9165 BGP_STATS_UNAGGREGATEABLE
,
9166 BGP_STATS_MAX_AGGREGATEABLE
,
9167 BGP_STATS_AGGREGATES
,
9169 BGP_STATS_ASPATH_COUNT
,
9170 BGP_STATS_ASPATH_MAXHOPS
,
9171 BGP_STATS_ASPATH_TOTHOPS
,
9172 BGP_STATS_ASPATH_MAXSIZE
,
9173 BGP_STATS_ASPATH_TOTSIZE
,
9174 BGP_STATS_ASN_HIGHEST
,
9178 static const char *table_stats_strs
[] = {
9179 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9180 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9181 [BGP_STATS_RIB
] = "Total Advertisements",
9182 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9183 [BGP_STATS_MAX_AGGREGATEABLE
] =
9184 "Maximum aggregateable prefixes",
9185 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9186 [BGP_STATS_SPACE
] = "Address space advertised",
9187 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9188 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9189 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9190 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9191 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9192 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9193 [BGP_STATS_MAX
] = NULL
,
9196 struct bgp_table_stats
{
9197 struct bgp_table
*table
;
9198 unsigned long long counts
[BGP_STATS_MAX
];
9203 #define TALLY_SIGFIG 100000
9204 static unsigned long
9205 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9207 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9208 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9209 unsigned long ret
= newtot
/ count
;
9211 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9218 static int bgp_table_stats_walker(struct thread
*t
)
9220 struct bgp_node
*rn
;
9221 struct bgp_node
*top
;
9222 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9223 unsigned int space
= 0;
9225 if (!(top
= bgp_table_top(ts
->table
)))
9228 switch (top
->p
.family
) {
9230 space
= IPV4_MAX_BITLEN
;
9233 space
= IPV6_MAX_BITLEN
;
9237 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9239 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9240 struct bgp_info
*ri
;
9241 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9242 unsigned int rinum
= 0;
9250 ts
->counts
[BGP_STATS_PREFIXES
]++;
9251 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9254 ts
->counts
[BGP_STATS_AVGPLEN
]
9255 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9256 ts
->counts
[BGP_STATS_AVGPLEN
],
9260 /* check if the prefix is included by any other announcements */
9261 while (prn
&& !prn
->info
)
9262 prn
= bgp_node_parent_nolock(prn
);
9264 if (prn
== NULL
|| prn
== top
) {
9265 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9266 /* announced address space */
9268 ts
->total_space
+= pow(2.0,
9269 space
- rn
->p
.prefixlen
);
9270 } else if (prn
->info
)
9271 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9273 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9275 ts
->counts
[BGP_STATS_RIB
]++;
9278 && (CHECK_FLAG(ri
->attr
->flag
,
9280 BGP_ATTR_ATOMIC_AGGREGATE
))))
9281 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9284 if (ri
->attr
&& ri
->attr
->aspath
) {
9286 aspath_count_hops(ri
->attr
->aspath
);
9288 aspath_size(ri
->attr
->aspath
);
9289 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9291 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9293 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9294 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9297 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9298 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9301 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9302 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9304 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9305 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9306 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9308 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9309 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9310 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9313 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9314 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9322 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9325 struct bgp_table_stats ts
;
9328 if (!bgp
->rib
[afi
][safi
]) {
9329 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9334 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9336 /* labeled-unicast routes live in the unicast table */
9337 if (safi
== SAFI_LABELED_UNICAST
)
9338 safi
= SAFI_UNICAST
;
9340 memset(&ts
, 0, sizeof(ts
));
9341 ts
.table
= bgp
->rib
[afi
][safi
];
9342 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9344 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9345 if (!table_stats_strs
[i
])
9350 case BGP_STATS_ASPATH_AVGHOPS
:
9351 case BGP_STATS_ASPATH_AVGSIZE
:
9352 case BGP_STATS_AVGPLEN
:
9353 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9354 vty_out (vty
, "%12.2f",
9355 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9358 case BGP_STATS_ASPATH_TOTHOPS
:
9359 case BGP_STATS_ASPATH_TOTSIZE
:
9360 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9361 vty_out(vty
, "%12.2f",
9363 ? (float)ts
.counts
[i
]
9365 [BGP_STATS_ASPATH_COUNT
]
9368 case BGP_STATS_TOTPLEN
:
9369 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9370 vty_out(vty
, "%12.2f",
9372 ? (float)ts
.counts
[i
]
9374 [BGP_STATS_PREFIXES
]
9377 case BGP_STATS_SPACE
:
9378 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9379 vty_out(vty
, "%12g\n", ts
.total_space
);
9381 if (afi
== AFI_IP6
) {
9382 vty_out(vty
, "%30s: ", "/32 equivalent ");
9383 vty_out(vty
, "%12g\n",
9384 ts
.total_space
* pow(2.0, -128+32));
9385 vty_out(vty
, "%30s: ", "/48 equivalent ");
9386 vty_out(vty
, "%12g\n",
9387 ts
.total_space
* pow(2.0, -128+48));
9389 vty_out(vty
, "%30s: ", "% announced ");
9390 vty_out(vty
, "%12.2f\n",
9391 ts
.total_space
* 100. * pow(2.0, -32));
9392 vty_out(vty
, "%30s: ", "/8 equivalent ");
9393 vty_out(vty
, "%12.2f\n",
9394 ts
.total_space
* pow(2.0, -32+8));
9395 vty_out(vty
, "%30s: ", "/24 equivalent ");
9396 vty_out(vty
, "%12.2f\n",
9397 ts
.total_space
* pow(2.0, -32+24));
9401 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9402 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9419 PCOUNT_PFCNT
, /* the figure we display to users */
9423 static const char *pcount_strs
[] = {
9424 [PCOUNT_ADJ_IN
] = "Adj-in",
9425 [PCOUNT_DAMPED
] = "Damped",
9426 [PCOUNT_REMOVED
] = "Removed",
9427 [PCOUNT_HISTORY
] = "History",
9428 [PCOUNT_STALE
] = "Stale",
9429 [PCOUNT_VALID
] = "Valid",
9430 [PCOUNT_ALL
] = "All RIB",
9431 [PCOUNT_COUNTED
] = "PfxCt counted",
9432 [PCOUNT_PFCNT
] = "Useable",
9433 [PCOUNT_MAX
] = NULL
,
9436 struct peer_pcounts
{
9437 unsigned int count
[PCOUNT_MAX
];
9438 const struct peer
*peer
;
9439 const struct bgp_table
*table
;
9442 static int bgp_peer_count_walker(struct thread
*t
)
9444 struct bgp_node
*rn
;
9445 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9446 const struct peer
*peer
= pc
->peer
;
9448 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9449 struct bgp_adj_in
*ain
;
9450 struct bgp_info
*ri
;
9452 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9453 if (ain
->peer
== peer
)
9454 pc
->count
[PCOUNT_ADJ_IN
]++;
9456 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9457 char buf
[SU_ADDRSTRLEN
];
9459 if (ri
->peer
!= peer
)
9462 pc
->count
[PCOUNT_ALL
]++;
9464 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9465 pc
->count
[PCOUNT_DAMPED
]++;
9466 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9467 pc
->count
[PCOUNT_HISTORY
]++;
9468 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9469 pc
->count
[PCOUNT_REMOVED
]++;
9470 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9471 pc
->count
[PCOUNT_STALE
]++;
9472 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9473 pc
->count
[PCOUNT_VALID
]++;
9474 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9475 pc
->count
[PCOUNT_PFCNT
]++;
9477 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9478 pc
->count
[PCOUNT_COUNTED
]++;
9479 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9481 "%s [pcount] %s/%d is counted but flags 0x%x",
9483 inet_ntop(rn
->p
.family
,
9484 &rn
->p
.u
.prefix
, buf
,
9486 rn
->p
.prefixlen
, ri
->flags
);
9488 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9490 "%s [pcount] %s/%d not counted but flags 0x%x",
9492 inet_ntop(rn
->p
.family
,
9493 &rn
->p
.u
.prefix
, buf
,
9495 rn
->p
.prefixlen
, ri
->flags
);
9502 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9503 safi_t safi
, u_char use_json
)
9505 struct peer_pcounts pcounts
= {.peer
= peer
};
9507 json_object
*json
= NULL
;
9508 json_object
*json_loop
= NULL
;
9511 json
= json_object_new_object();
9512 json_loop
= json_object_new_object();
9515 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9516 || !peer
->bgp
->rib
[afi
][safi
]) {
9518 json_object_string_add(
9520 "No such neighbor or address family");
9521 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9522 json_object_free(json
);
9524 vty_out(vty
, "%% No such neighbor or address family\n");
9529 memset(&pcounts
, 0, sizeof(pcounts
));
9530 pcounts
.peer
= peer
;
9531 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9533 /* in-place call via thread subsystem so as to record execution time
9534 * * stats for the thread-walk (i.e. ensure this can't be blamed on
9535 * * on just vty_read()).
9537 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9540 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9541 json_object_string_add(json
, "multiProtocol",
9542 afi_safi_print(afi
, safi
));
9543 json_object_int_add(json
, "pfxCounter",
9544 peer
->pcount
[afi
][safi
]);
9546 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9547 json_object_int_add(json_loop
, pcount_strs
[i
],
9550 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9552 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9553 json_object_string_add(json
, "pfxctDriftFor",
9555 json_object_string_add(
9556 json
, "recommended",
9557 "Please report this bug, with the above command output");
9559 vty_out(vty
, "%s\n", json_object_to_json_string_ext(json
,
9560 JSON_C_TO_STRING_PRETTY
));
9561 json_object_free(json
);
9565 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9566 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9567 peer
->hostname
, peer
->host
,
9568 afi_safi_print(afi
, safi
));
9570 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9571 afi_safi_print(afi
, safi
));
9574 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9575 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9577 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9578 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9581 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9582 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9584 "Please report this bug, with the above command output\n");
9591 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9592 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9593 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9594 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9598 BGP_INSTANCE_HELP_STR
9601 "Detailed information on TCP and BGP neighbor connections\n"
9602 "Neighbor to display information about\n"
9603 "Neighbor to display information about\n"
9604 "Neighbor on BGP configured interface\n"
9605 "Display detailed prefix count information\n"
9608 afi_t afi
= AFI_IP6
;
9609 safi_t safi
= SAFI_UNICAST
;
9612 struct bgp
*bgp
= NULL
;
9614 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9619 int uj
= use_json(argc
, argv
);
9623 argv_find(argv
, argc
, "neighbors", &idx
);
9624 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9628 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9631 #ifdef KEEP_OLD_VPN_COMMANDS
9632 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9633 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9634 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9639 "Display information about all VPNv4 NLRIs\n"
9640 "Detailed information on TCP and BGP neighbor connections\n"
9641 "Neighbor to display information about\n"
9642 "Neighbor to display information about\n"
9643 "Neighbor on BGP configured interface\n"
9644 "Display detailed prefix count information\n"
9649 u_char uj
= use_json(argc
, argv
);
9651 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9655 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9658 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9659 show_ip_bgp_vpn_all_route_prefix_cmd
,
9660 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9665 "Display information about all VPNv4 NLRIs\n"
9666 "Network in the BGP routing table to display\n"
9667 "Network in the BGP routing table to display\n"
9671 char *network
= NULL
;
9672 struct bgp
*bgp
= bgp_get_default();
9674 vty_out(vty
, "Can't find default instance\n");
9678 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9679 network
= argv
[idx
]->arg
;
9680 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9681 network
= argv
[idx
]->arg
;
9683 vty_out(vty
, "Unable to figure out Network\n");
9687 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9688 BGP_PATH_ALL
, use_json(argc
, argv
));
9690 #endif /* KEEP_OLD_VPN_COMMANDS */
9692 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9693 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9694 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9700 "Display information about all EVPN NLRIs\n"
9701 "Network in the BGP routing table to display\n"
9702 "Network in the BGP routing table to display\n"
9706 char *network
= NULL
;
9708 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9709 network
= argv
[idx
]->arg
;
9710 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9711 network
= argv
[idx
]->arg
;
9713 vty_out(vty
, "Unable to figure out Network\n");
9716 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9717 BGP_PATH_ALL
, use_json(argc
, argv
));
9720 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9721 safi_t safi
, int in
, const char *rmap_name
,
9722 u_char use_json
, json_object
*json
)
9724 struct bgp_table
*table
;
9725 struct bgp_adj_in
*ain
;
9726 struct bgp_adj_out
*adj
;
9727 unsigned long output_count
;
9728 unsigned long filtered_count
;
9729 struct bgp_node
*rn
;
9735 struct update_subgroup
*subgrp
;
9736 json_object
*json_scode
= NULL
;
9737 json_object
*json_ocode
= NULL
;
9738 json_object
*json_ar
= NULL
;
9739 struct peer_af
*paf
;
9742 json_scode
= json_object_new_object();
9743 json_ocode
= json_object_new_object();
9744 json_ar
= json_object_new_object();
9746 json_object_string_add(json_scode
, "suppressed", "s");
9747 json_object_string_add(json_scode
, "damped", "d");
9748 json_object_string_add(json_scode
, "history", "h");
9749 json_object_string_add(json_scode
, "valid", "*");
9750 json_object_string_add(json_scode
, "best", ">");
9751 json_object_string_add(json_scode
, "multipath", "=");
9752 json_object_string_add(json_scode
, "internal", "i");
9753 json_object_string_add(json_scode
, "ribFailure", "r");
9754 json_object_string_add(json_scode
, "stale", "S");
9755 json_object_string_add(json_scode
, "removed", "R");
9757 json_object_string_add(json_ocode
, "igp", "i");
9758 json_object_string_add(json_ocode
, "egp", "e");
9759 json_object_string_add(json_ocode
, "incomplete", "?");
9766 json_object_string_add(json
, "alert", "no BGP");
9767 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9768 json_object_free(json
);
9770 vty_out(vty
, "%% No bgp\n");
9774 table
= bgp
->rib
[afi
][safi
];
9776 output_count
= filtered_count
= 0;
9777 subgrp
= peer_subgroup(peer
, afi
, safi
);
9780 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
9782 json_object_int_add(json
, "bgpTableVersion",
9784 json_object_string_add(json
, "bgpLocalRouterId",
9785 inet_ntoa(bgp
->router_id
));
9786 json_object_object_add(json
, "bgpStatusCodes",
9788 json_object_object_add(json
, "bgpOriginCodes",
9790 json_object_string_add(json
,
9791 "bgpOriginatingDefaultNetwork",
9794 vty_out(vty
, "BGP table version is %" PRIu64
9795 ", local router ID is %s\n",
9796 table
->version
, inet_ntoa(bgp
->router_id
));
9797 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9798 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9800 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
9805 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9807 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
9808 if (ain
->peer
!= peer
)
9812 json_object_int_add(
9813 json
, "bgpTableVersion",
9815 json_object_string_add(
9820 json_object_object_add(
9821 json
, "bgpStatusCodes",
9823 json_object_object_add(
9824 json
, "bgpOriginCodes",
9828 "BGP table version is 0, local router ID is %s\n",
9832 BGP_SHOW_SCODE_HEADER
);
9834 BGP_SHOW_OCODE_HEADER
);
9840 vty_out(vty
, BGP_SHOW_HEADER
);
9844 bgp_attr_dup(&attr
, ain
->attr
);
9845 if (bgp_input_modifier(peer
, &rn
->p
,
9849 route_vty_out_tmp(vty
, &rn
->p
,
9859 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
9860 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
9861 if (paf
->peer
!= peer
)
9866 json_object_int_add(
9870 json_object_string_add(
9875 json_object_object_add(
9879 json_object_object_add(
9885 "BGP table version is %" PRIu64
9886 ", local router ID is %s\n",
9891 BGP_SHOW_SCODE_HEADER
);
9893 BGP_SHOW_OCODE_HEADER
);
9908 ret
= bgp_output_modifier(
9913 if (ret
!= RMAP_DENY
) {
9925 bgp_attr_undup(&attr
,
9932 json_object_object_add(json
, "advertisedRoutes", json_ar
);
9934 if (output_count
!= 0) {
9936 json_object_int_add(json
, "totalPrefixCounter",
9939 vty_out(vty
, "\nTotal number of prefixes %ld\n",
9943 vty_out(vty
, "%s\n", json_object_to_json_string_ext(json
,
9944 JSON_C_TO_STRING_PRETTY
));
9945 json_object_free(json
);
9949 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9950 safi_t safi
, int in
, const char *rmap_name
,
9953 json_object
*json
= NULL
;
9956 json
= json_object_new_object();
9958 /* labeled-unicast routes live in the unicast table */
9959 if (safi
== SAFI_LABELED_UNICAST
)
9960 safi
= SAFI_UNICAST
;
9962 if (!peer
|| !peer
->afc
[afi
][safi
]) {
9964 json_object_string_add(
9966 "No such neighbor or address family");
9967 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9968 json_object_free(json
);
9970 vty_out(vty
, "%% No such neighbor or address family\n");
9976 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
9977 PEER_FLAG_SOFT_RECONFIG
)) {
9979 json_object_string_add(
9981 "Inbound soft reconfiguration not enabled");
9982 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9983 json_object_free(json
);
9986 "%% Inbound soft reconfiguration not enabled\n");
9991 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
9996 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
9997 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
9998 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
9999 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10003 BGP_INSTANCE_HELP_STR
10005 BGP_SAFI_WITH_LABEL_HELP_STR
10006 "Detailed information on TCP and BGP neighbor connections\n"
10007 "Neighbor to display information about\n"
10008 "Neighbor to display information about\n"
10009 "Neighbor on BGP configured interface\n"
10010 "Display the received routes from neighbor\n"
10011 "Display the routes advertised to a BGP neighbor\n"
10012 "Route-map to modify the attributes\n"
10013 "Name of the route map\n"
10016 afi_t afi
= AFI_IP6
;
10017 safi_t safi
= SAFI_UNICAST
;
10018 char *rmap_name
= NULL
;
10019 char *peerstr
= NULL
;
10021 struct bgp
*bgp
= NULL
;
10026 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10029 return CMD_WARNING
;
10031 int uj
= use_json(argc
, argv
);
10035 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10036 argv_find(argv
, argc
, "neighbors", &idx
);
10037 peerstr
= argv
[++idx
]->arg
;
10039 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10041 return CMD_WARNING
;
10043 if (argv_find(argv
, argc
, "received-routes", &idx
))
10045 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10047 if (argv_find(argv
, argc
, "route-map", &idx
))
10048 rmap_name
= argv
[++idx
]->arg
;
10050 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10053 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10054 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10055 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10061 "Address Family modifier\n"
10062 "Detailed information on TCP and BGP neighbor connections\n"
10063 "Neighbor to display information about\n"
10064 "Neighbor to display information about\n"
10065 "Neighbor on BGP configured interface\n"
10066 "Display information received from a BGP neighbor\n"
10067 "Display the prefixlist filter\n"
10070 afi_t afi
= AFI_IP6
;
10071 safi_t safi
= SAFI_UNICAST
;
10072 char *peerstr
= NULL
;
10075 union sockunion su
;
10081 /* show [ip] bgp */
10082 if (argv_find(argv
, argc
, "ip", &idx
))
10084 /* [<ipv4|ipv6> [unicast]] */
10085 if (argv_find(argv
, argc
, "ipv4", &idx
))
10087 if (argv_find(argv
, argc
, "ipv6", &idx
))
10089 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10090 argv_find(argv
, argc
, "neighbors", &idx
);
10091 peerstr
= argv
[++idx
]->arg
;
10093 u_char uj
= use_json(argc
, argv
);
10095 ret
= str2sockunion(peerstr
, &su
);
10097 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10100 vty_out(vty
, "{}\n");
10103 "%% Malformed address or name: %s\n",
10105 return CMD_WARNING
;
10108 peer
= peer_lookup(NULL
, &su
);
10111 vty_out(vty
, "{}\n");
10113 vty_out(vty
, "No peer\n");
10114 return CMD_WARNING
;
10118 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10119 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10122 vty_out(vty
, "Address Family: %s\n",
10123 afi_safi_print(afi
, safi
));
10124 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10127 vty_out(vty
, "{}\n");
10129 vty_out(vty
, "No functional output\n");
10132 return CMD_SUCCESS
;
10135 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10136 afi_t afi
, safi_t safi
,
10137 enum bgp_show_type type
, u_char use_json
)
10139 /* labeled-unicast routes live in the unicast table */
10140 if (safi
== SAFI_LABELED_UNICAST
)
10141 safi
= SAFI_UNICAST
;
10143 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10145 json_object
*json_no
= NULL
;
10146 json_no
= json_object_new_object();
10147 json_object_string_add(
10148 json_no
, "warning",
10149 "No such neighbor or address family");
10150 vty_out(vty
, "%s\n",
10151 json_object_to_json_string(json_no
));
10152 json_object_free(json_no
);
10154 vty_out(vty
, "%% No such neighbor or address family\n");
10155 return CMD_WARNING
;
10158 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10161 DEFUN (show_ip_bgp_neighbor_routes
,
10162 show_ip_bgp_neighbor_routes_cmd
,
10163 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10164 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10168 BGP_INSTANCE_HELP_STR
10170 BGP_SAFI_WITH_LABEL_HELP_STR
10171 "Detailed information on TCP and BGP neighbor connections\n"
10172 "Neighbor to display information about\n"
10173 "Neighbor to display information about\n"
10174 "Neighbor on BGP configured interface\n"
10175 "Display flap statistics of the routes learned from neighbor\n"
10176 "Display the dampened routes received from neighbor\n"
10177 "Display routes learned from neighbor\n"
10180 char *peerstr
= NULL
;
10181 struct bgp
*bgp
= NULL
;
10182 afi_t afi
= AFI_IP6
;
10183 safi_t safi
= SAFI_UNICAST
;
10185 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10189 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10192 return CMD_WARNING
;
10194 int uj
= use_json(argc
, argv
);
10198 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10199 argv_find(argv
, argc
, "neighbors", &idx
);
10200 peerstr
= argv
[++idx
]->arg
;
10202 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10204 vty_out(vty
, "No such neighbor\n");
10205 return CMD_WARNING
;
10208 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10209 sh_type
= bgp_show_type_flap_neighbor
;
10210 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10211 sh_type
= bgp_show_type_damp_neighbor
;
10212 else if (argv_find(argv
, argc
, "routes", &idx
))
10213 sh_type
= bgp_show_type_neighbor
;
10215 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10218 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10220 struct bgp_distance
{
10221 /* Distance value for the IP source prefix. */
10224 /* Name of the access-list to be matched. */
10228 DEFUN (show_bgp_afi_vpn_rd_route
,
10229 show_bgp_afi_vpn_rd_route_cmd
,
10230 "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]",
10234 "Address Family modifier\n"
10235 "Display information for a route distinguisher\n"
10236 "Route Distinguisher\n"
10237 "Network in the BGP routing table to display\n"
10238 "Network in the BGP routing table to display\n"
10242 struct prefix_rd prd
;
10243 afi_t afi
= AFI_MAX
;
10246 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10247 vty_out(vty
, "%% Malformed Address Family\n");
10248 return CMD_WARNING
;
10251 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10253 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10254 return CMD_WARNING
;
10257 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10258 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10261 static struct bgp_distance
*bgp_distance_new(void)
10263 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10266 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10268 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10271 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10272 const char *ip_str
, const char *access_list_str
)
10279 struct bgp_node
*rn
;
10280 struct bgp_distance
*bdistance
;
10282 afi
= bgp_node_afi(vty
);
10283 safi
= bgp_node_safi(vty
);
10285 ret
= str2prefix(ip_str
, &p
);
10287 vty_out(vty
, "Malformed prefix\n");
10288 return CMD_WARNING_CONFIG_FAILED
;
10291 distance
= atoi(distance_str
);
10293 /* Get BGP distance node. */
10294 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10296 bdistance
= rn
->info
;
10297 bgp_unlock_node(rn
);
10299 bdistance
= bgp_distance_new();
10300 rn
->info
= bdistance
;
10303 /* Set distance value. */
10304 bdistance
->distance
= distance
;
10306 /* Reset access-list configuration. */
10307 if (bdistance
->access_list
) {
10308 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10309 bdistance
->access_list
= NULL
;
10311 if (access_list_str
)
10312 bdistance
->access_list
=
10313 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10315 return CMD_SUCCESS
;
10318 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10319 const char *ip_str
, const char *access_list_str
)
10326 struct bgp_node
*rn
;
10327 struct bgp_distance
*bdistance
;
10329 afi
= bgp_node_afi(vty
);
10330 safi
= bgp_node_safi(vty
);
10332 ret
= str2prefix(ip_str
, &p
);
10334 vty_out(vty
, "Malformed prefix\n");
10335 return CMD_WARNING_CONFIG_FAILED
;
10338 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10339 (struct prefix
*)&p
);
10341 vty_out(vty
, "Can't find specified prefix\n");
10342 return CMD_WARNING_CONFIG_FAILED
;
10345 bdistance
= rn
->info
;
10346 distance
= atoi(distance_str
);
10348 if (bdistance
->distance
!= distance
) {
10349 vty_out(vty
, "Distance does not match configured\n");
10350 return CMD_WARNING_CONFIG_FAILED
;
10353 if (bdistance
->access_list
)
10354 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10355 bgp_distance_free(bdistance
);
10358 bgp_unlock_node(rn
);
10359 bgp_unlock_node(rn
);
10361 return CMD_SUCCESS
;
10364 /* Apply BGP information to distance method. */
10365 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10366 safi_t safi
, struct bgp
*bgp
)
10368 struct bgp_node
*rn
;
10371 struct bgp_distance
*bdistance
;
10372 struct access_list
*alist
;
10373 struct bgp_static
*bgp_static
;
10378 peer
= rinfo
->peer
;
10380 /* Check source address. */
10381 sockunion2hostprefix(&peer
->su
, &q
);
10382 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10384 bdistance
= rn
->info
;
10385 bgp_unlock_node(rn
);
10387 if (bdistance
->access_list
) {
10388 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10390 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10391 return bdistance
->distance
;
10393 return bdistance
->distance
;
10396 /* Backdoor check. */
10397 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10399 bgp_static
= rn
->info
;
10400 bgp_unlock_node(rn
);
10402 if (bgp_static
->backdoor
) {
10403 if (bgp
->distance_local
[afi
][safi
])
10404 return bgp
->distance_local
[afi
][safi
];
10406 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10410 if (peer
->sort
== BGP_PEER_EBGP
) {
10411 if (bgp
->distance_ebgp
[afi
][safi
])
10412 return bgp
->distance_ebgp
[afi
][safi
];
10413 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10415 if (bgp
->distance_ibgp
[afi
][safi
])
10416 return bgp
->distance_ibgp
[afi
][safi
];
10417 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10421 DEFUN (bgp_distance
,
10423 "distance bgp (1-255) (1-255) (1-255)",
10424 "Define an administrative distance\n"
10426 "Distance for routes external to the AS\n"
10427 "Distance for routes internal to the AS\n"
10428 "Distance for local routes\n")
10430 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10431 int idx_number
= 2;
10432 int idx_number_2
= 3;
10433 int idx_number_3
= 4;
10437 afi
= bgp_node_afi(vty
);
10438 safi
= bgp_node_safi(vty
);
10440 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10441 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10442 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10443 return CMD_SUCCESS
;
10446 DEFUN (no_bgp_distance
,
10447 no_bgp_distance_cmd
,
10448 "no distance bgp [(1-255) (1-255) (1-255)]",
10450 "Define an administrative distance\n"
10452 "Distance for routes external to the AS\n"
10453 "Distance for routes internal to the AS\n"
10454 "Distance for local routes\n")
10456 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10460 afi
= bgp_node_afi(vty
);
10461 safi
= bgp_node_safi(vty
);
10463 bgp
->distance_ebgp
[afi
][safi
] = 0;
10464 bgp
->distance_ibgp
[afi
][safi
] = 0;
10465 bgp
->distance_local
[afi
][safi
] = 0;
10466 return CMD_SUCCESS
;
10470 DEFUN (bgp_distance_source
,
10471 bgp_distance_source_cmd
,
10472 "distance (1-255) A.B.C.D/M",
10473 "Define an administrative distance\n"
10474 "Administrative distance\n"
10475 "IP source prefix\n")
10477 int idx_number
= 1;
10478 int idx_ipv4_prefixlen
= 2;
10479 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10480 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10481 return CMD_SUCCESS
;
10484 DEFUN (no_bgp_distance_source
,
10485 no_bgp_distance_source_cmd
,
10486 "no distance (1-255) A.B.C.D/M",
10488 "Define an administrative distance\n"
10489 "Administrative distance\n"
10490 "IP source prefix\n")
10492 int idx_number
= 2;
10493 int idx_ipv4_prefixlen
= 3;
10494 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10495 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10496 return CMD_SUCCESS
;
10499 DEFUN (bgp_distance_source_access_list
,
10500 bgp_distance_source_access_list_cmd
,
10501 "distance (1-255) A.B.C.D/M WORD",
10502 "Define an administrative distance\n"
10503 "Administrative distance\n"
10504 "IP source prefix\n"
10505 "Access list name\n")
10507 int idx_number
= 1;
10508 int idx_ipv4_prefixlen
= 2;
10510 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10511 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10512 return CMD_SUCCESS
;
10515 DEFUN (no_bgp_distance_source_access_list
,
10516 no_bgp_distance_source_access_list_cmd
,
10517 "no distance (1-255) A.B.C.D/M WORD",
10519 "Define an administrative distance\n"
10520 "Administrative distance\n"
10521 "IP source prefix\n"
10522 "Access list name\n")
10524 int idx_number
= 2;
10525 int idx_ipv4_prefixlen
= 3;
10527 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10528 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10529 return CMD_SUCCESS
;
10532 DEFUN (ipv6_bgp_distance_source
,
10533 ipv6_bgp_distance_source_cmd
,
10534 "distance (1-255) X:X::X:X/M",
10535 "Define an administrative distance\n"
10536 "Administrative distance\n"
10537 "IP source prefix\n")
10539 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10540 return CMD_SUCCESS
;
10543 DEFUN (no_ipv6_bgp_distance_source
,
10544 no_ipv6_bgp_distance_source_cmd
,
10545 "no distance (1-255) X:X::X:X/M",
10547 "Define an administrative distance\n"
10548 "Administrative distance\n"
10549 "IP source prefix\n")
10551 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10552 return CMD_SUCCESS
;
10555 DEFUN (ipv6_bgp_distance_source_access_list
,
10556 ipv6_bgp_distance_source_access_list_cmd
,
10557 "distance (1-255) X:X::X:X/M WORD",
10558 "Define an administrative distance\n"
10559 "Administrative distance\n"
10560 "IP source prefix\n"
10561 "Access list name\n")
10563 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10564 return CMD_SUCCESS
;
10567 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10568 no_ipv6_bgp_distance_source_access_list_cmd
,
10569 "no distance (1-255) X:X::X:X/M WORD",
10571 "Define an administrative distance\n"
10572 "Administrative distance\n"
10573 "IP source prefix\n"
10574 "Access list name\n")
10576 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10577 return CMD_SUCCESS
;
10580 DEFUN (bgp_damp_set
,
10582 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10583 "BGP Specific commands\n"
10584 "Enable route-flap dampening\n"
10585 "Half-life time for the penalty\n"
10586 "Value to start reusing a route\n"
10587 "Value to start suppressing a route\n"
10588 "Maximum duration to suppress a stable route\n")
10590 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10591 int idx_half_life
= 2;
10593 int idx_suppress
= 4;
10594 int idx_max_suppress
= 5;
10595 int half
= DEFAULT_HALF_LIFE
* 60;
10596 int reuse
= DEFAULT_REUSE
;
10597 int suppress
= DEFAULT_SUPPRESS
;
10598 int max
= 4 * half
;
10601 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10602 reuse
= atoi(argv
[idx_reuse
]->arg
);
10603 suppress
= atoi(argv
[idx_suppress
]->arg
);
10604 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10605 } else if (argc
== 3) {
10606 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10610 if (suppress
< reuse
) {
10612 "Suppress value cannot be less than reuse value \n");
10616 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10617 reuse
, suppress
, max
);
10620 DEFUN (bgp_damp_unset
,
10621 bgp_damp_unset_cmd
,
10622 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10624 "BGP Specific commands\n"
10625 "Enable route-flap dampening\n"
10626 "Half-life time for the penalty\n"
10627 "Value to start reusing a route\n"
10628 "Value to start suppressing a route\n"
10629 "Maximum duration to suppress a stable route\n")
10631 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10632 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10635 /* Display specified route of BGP table. */
10636 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10637 const char *ip_str
, afi_t afi
, safi_t safi
,
10638 struct prefix_rd
*prd
, int prefix_check
)
10641 struct prefix match
;
10642 struct bgp_node
*rn
;
10643 struct bgp_node
*rm
;
10644 struct bgp_info
*ri
;
10645 struct bgp_info
*ri_temp
;
10647 struct bgp_table
*table
;
10649 /* BGP structure lookup. */
10651 bgp
= bgp_lookup_by_name(view_name
);
10653 vty_out(vty
, "%% Can't find BGP instance %s\n",
10655 return CMD_WARNING
;
10658 bgp
= bgp_get_default();
10660 vty_out(vty
, "%% No BGP process is configured\n");
10661 return CMD_WARNING
;
10665 /* Check IP address argument. */
10666 ret
= str2prefix(ip_str
, &match
);
10668 vty_out(vty
, "%% address is malformed\n");
10669 return CMD_WARNING
;
10672 match
.family
= afi2family(afi
);
10674 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10675 || (safi
== SAFI_EVPN
)) {
10676 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10677 rn
= bgp_route_next(rn
)) {
10678 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10680 if ((table
= rn
->info
) == NULL
)
10682 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10686 || rm
->p
.prefixlen
== match
.prefixlen
) {
10689 if (ri
->extra
&& ri
->extra
->damp_info
) {
10690 ri_temp
= ri
->next
;
10691 bgp_damp_info_free(
10692 ri
->extra
->damp_info
,
10700 bgp_unlock_node(rm
);
10703 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10706 || rn
->p
.prefixlen
== match
.prefixlen
) {
10709 if (ri
->extra
&& ri
->extra
->damp_info
) {
10710 ri_temp
= ri
->next
;
10711 bgp_damp_info_free(
10712 ri
->extra
->damp_info
,
10720 bgp_unlock_node(rn
);
10724 return CMD_SUCCESS
;
10727 DEFUN (clear_ip_bgp_dampening
,
10728 clear_ip_bgp_dampening_cmd
,
10729 "clear ip bgp dampening",
10733 "Clear route flap dampening information\n")
10735 bgp_damp_info_clean();
10736 return CMD_SUCCESS
;
10739 DEFUN (clear_ip_bgp_dampening_prefix
,
10740 clear_ip_bgp_dampening_prefix_cmd
,
10741 "clear ip bgp dampening A.B.C.D/M",
10745 "Clear route flap dampening information\n"
10748 int idx_ipv4_prefixlen
= 4;
10749 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10750 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
10753 DEFUN (clear_ip_bgp_dampening_address
,
10754 clear_ip_bgp_dampening_address_cmd
,
10755 "clear ip bgp dampening A.B.C.D",
10759 "Clear route flap dampening information\n"
10760 "Network to clear damping information\n")
10763 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
10764 SAFI_UNICAST
, NULL
, 0);
10767 DEFUN (clear_ip_bgp_dampening_address_mask
,
10768 clear_ip_bgp_dampening_address_mask_cmd
,
10769 "clear ip bgp dampening A.B.C.D A.B.C.D",
10773 "Clear route flap dampening information\n"
10774 "Network to clear damping information\n"
10778 int idx_ipv4_2
= 5;
10780 char prefix_str
[BUFSIZ
];
10782 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
10785 vty_out(vty
, "%% Inconsistent address and mask\n");
10786 return CMD_WARNING
;
10789 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
10793 /* also used for encap safi */
10794 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
10795 afi_t afi
, safi_t safi
)
10797 struct bgp_node
*prn
;
10798 struct bgp_node
*rn
;
10799 struct bgp_table
*table
;
10801 struct prefix_rd
*prd
;
10802 struct bgp_static
*bgp_static
;
10803 mpls_label_t label
;
10804 char buf
[SU_ADDRSTRLEN
];
10805 char rdbuf
[RD_ADDRSTRLEN
];
10807 /* Network configuration. */
10808 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10809 prn
= bgp_route_next(prn
)) {
10810 if ((table
= prn
->info
) == NULL
)
10813 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10814 if ((bgp_static
= rn
->info
) == NULL
)
10818 prd
= (struct prefix_rd
*)&prn
->p
;
10820 /* "network" configuration display. */
10821 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
10822 label
= decode_label(&bgp_static
->label
);
10824 vty_out(vty
, " network %s/%d rd %s",
10825 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10827 p
->prefixlen
, rdbuf
);
10828 if (safi
== SAFI_MPLS_VPN
)
10829 vty_out(vty
, " label %u", label
);
10831 if (bgp_static
->rmap
.name
)
10832 vty_out(vty
, " route-map %s",
10833 bgp_static
->rmap
.name
);
10835 if (bgp_static
->backdoor
)
10836 vty_out(vty
, " backdoor");
10838 vty_out(vty
, "\n");
10843 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
10844 afi_t afi
, safi_t safi
)
10846 struct bgp_node
*prn
;
10847 struct bgp_node
*rn
;
10848 struct bgp_table
*table
;
10850 struct prefix_rd
*prd
;
10851 struct bgp_static
*bgp_static
;
10852 char buf
[PREFIX_STRLEN
];
10853 char buf2
[SU_ADDRSTRLEN
];
10854 char rdbuf
[RD_ADDRSTRLEN
];
10856 /* Network configuration. */
10857 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10858 prn
= bgp_route_next(prn
)) {
10859 if ((table
= prn
->info
) == NULL
)
10862 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10863 if ((bgp_static
= rn
->info
) == NULL
)
10866 char *macrouter
= NULL
;
10869 if (bgp_static
->router_mac
)
10870 macrouter
= prefix_mac2str(
10871 bgp_static
->router_mac
, NULL
, 0);
10872 if (bgp_static
->eth_s_id
)
10873 esi
= esi2str(bgp_static
->eth_s_id
);
10875 prd
= (struct prefix_rd
*)&prn
->p
;
10877 /* "network" configuration display. */
10878 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
10879 if (p
->u
.prefix_evpn
.route_type
== 5) {
10880 char local_buf
[PREFIX_STRLEN
];
10881 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)
10884 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
, local_buf
,
10886 sprintf(buf
, "%s/%u", local_buf
,p
->u
.prefix_evpn
.ip_prefix_length
);
10888 prefix2str(p
, buf
, sizeof(buf
));
10891 if (bgp_static
->gatewayIp
.family
== AF_INET
||
10892 bgp_static
->gatewayIp
.family
== AF_INET6
)
10893 inet_ntop(bgp_static
->gatewayIp
.family
,
10894 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
10897 " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
10898 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
10899 decode_label(&bgp_static
->label
), esi
, buf2
,
10903 XFREE(MTYPE_TMP
, macrouter
);
10905 XFREE(MTYPE_TMP
, esi
);
10910 /* Configuration of static route announcement and aggregate
10912 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10915 struct bgp_node
*rn
;
10917 struct bgp_static
*bgp_static
;
10918 struct bgp_aggregate
*bgp_aggregate
;
10919 char buf
[SU_ADDRSTRLEN
];
10921 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
10922 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
10926 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
10927 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
10931 /* Network configuration. */
10932 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
10933 rn
= bgp_route_next(rn
)) {
10934 if ((bgp_static
= rn
->info
) == NULL
)
10939 /* "network" configuration display. */
10940 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
10941 u_int32_t destination
;
10942 struct in_addr netmask
;
10944 destination
= ntohl(p
->u
.prefix4
.s_addr
);
10945 masklen2ip(p
->prefixlen
, &netmask
);
10946 vty_out(vty
, " network %s",
10947 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10950 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
10951 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
10952 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
10953 || p
->u
.prefix4
.s_addr
== 0) {
10954 /* Natural mask is not display. */
10956 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
10958 vty_out(vty
, " network %s/%d",
10959 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10964 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
10965 vty_out(vty
, " label-index %u",
10966 bgp_static
->label_index
);
10968 if (bgp_static
->rmap
.name
)
10969 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
10971 if (bgp_static
->backdoor
)
10972 vty_out(vty
, " backdoor");
10974 vty_out(vty
, "\n");
10977 /* Aggregate-address configuration. */
10978 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
10979 rn
= bgp_route_next(rn
)) {
10980 if ((bgp_aggregate
= rn
->info
) == NULL
)
10985 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
10986 struct in_addr netmask
;
10988 masklen2ip(p
->prefixlen
, &netmask
);
10989 vty_out(vty
, " aggregate-address %s %s",
10990 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10992 inet_ntoa(netmask
));
10994 vty_out(vty
, " aggregate-address %s/%d",
10995 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11000 if (bgp_aggregate
->as_set
)
11001 vty_out(vty
, " as-set");
11003 if (bgp_aggregate
->summary_only
)
11004 vty_out(vty
, " summary-only");
11006 vty_out(vty
, "\n");
11010 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11013 struct bgp_node
*rn
;
11014 struct bgp_distance
*bdistance
;
11016 /* Distance configuration. */
11017 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11018 && bgp
->distance_local
[afi
][safi
]
11019 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11020 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11021 || bgp
->distance_local
[afi
][safi
]
11022 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11023 vty_out(vty
, " distance bgp %d %d %d\n",
11024 bgp
->distance_ebgp
[afi
][safi
],
11025 bgp
->distance_ibgp
[afi
][safi
],
11026 bgp
->distance_local
[afi
][safi
]);
11029 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11030 rn
= bgp_route_next(rn
))
11031 if ((bdistance
= rn
->info
) != NULL
) {
11032 char buf
[PREFIX_STRLEN
];
11034 vty_out(vty
, " distance %d %s %s\n",
11035 bdistance
->distance
,
11036 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11037 bdistance
->access_list
? bdistance
->access_list
11042 /* Allocate routing table structure and install commands. */
11043 void bgp_route_init(void)
11048 /* Init BGP distance table. */
11049 FOREACH_AFI_SAFI (afi
, safi
)
11050 bgp_distance_table
[afi
][safi
] = bgp_table_init(afi
, safi
);
11052 /* IPv4 BGP commands. */
11053 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11054 install_element(BGP_NODE
, &bgp_network_cmd
);
11055 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11057 install_element(BGP_NODE
, &aggregate_address_cmd
);
11058 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11059 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11060 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11062 /* IPv4 unicast configuration. */
11063 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11064 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11065 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11067 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11068 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11069 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11070 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11072 /* IPv4 multicast configuration. */
11073 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11074 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11075 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11076 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11077 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11078 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11079 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11081 /* IPv4 labeled-unicast configuration. */
11082 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11083 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11084 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11085 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11086 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11088 install_element(VIEW_NODE
,
11089 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11090 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11091 install_element(VIEW_NODE
,
11092 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11093 #ifdef KEEP_OLD_VPN_COMMANDS
11094 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11095 #endif /* KEEP_OLD_VPN_COMMANDS */
11096 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11097 install_element(VIEW_NODE
,
11098 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11100 /* BGP dampening clear commands */
11101 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11102 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11104 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11105 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11108 install_element(ENABLE_NODE
,
11109 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11110 #ifdef KEEP_OLD_VPN_COMMANDS
11111 install_element(ENABLE_NODE
,
11112 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11113 #endif /* KEEP_OLD_VPN_COMMANDS */
11115 /* New config IPv6 BGP commands. */
11116 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11117 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11118 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11120 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11121 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11123 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11125 install_element(BGP_NODE
, &bgp_distance_cmd
);
11126 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11127 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11128 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11129 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11130 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11131 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11132 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11133 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11134 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11135 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11136 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11137 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11138 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11139 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11140 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11141 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11142 install_element(BGP_IPV4M_NODE
,
11143 &no_bgp_distance_source_access_list_cmd
);
11144 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11145 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11146 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11147 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11148 install_element(BGP_IPV6_NODE
,
11149 &ipv6_bgp_distance_source_access_list_cmd
);
11150 install_element(BGP_IPV6_NODE
,
11151 &no_ipv6_bgp_distance_source_access_list_cmd
);
11152 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11153 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11154 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11155 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11156 install_element(BGP_IPV6M_NODE
,
11157 &ipv6_bgp_distance_source_access_list_cmd
);
11158 install_element(BGP_IPV6M_NODE
,
11159 &no_ipv6_bgp_distance_source_access_list_cmd
);
11161 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11162 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11163 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11164 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11166 /* IPv4 Multicast Mode */
11167 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11168 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11170 /* Large Communities */
11171 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11172 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11175 void bgp_route_finish(void)
11180 FOREACH_AFI_SAFI (afi
, safi
) {
11181 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11182 bgp_distance_table
[afi
][safi
] = NULL
;