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
[0] = MPLS_INVALID_LABEL
;
155 static void bgp_info_extra_free(struct bgp_info_extra
**extra
)
157 if (extra
&& *extra
) {
158 if ((*extra
)->damp_info
)
159 bgp_damp_info_free((*extra
)->damp_info
, 0);
161 (*extra
)->damp_info
= NULL
;
163 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
169 /* Get bgp_info extra information for the given bgp_info, lazy allocated
172 struct bgp_info_extra
*bgp_info_extra_get(struct bgp_info
*ri
)
175 ri
->extra
= bgp_info_extra_new();
179 /* Allocate new bgp info structure. */
180 struct bgp_info
*bgp_info_new(void)
182 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
185 /* Free bgp route information. */
186 static void bgp_info_free(struct bgp_info
*binfo
)
189 bgp_attr_unintern(&binfo
->attr
);
191 bgp_unlink_nexthop(binfo
);
192 bgp_info_extra_free(&binfo
->extra
);
193 bgp_info_mpath_free(&binfo
->mpath
);
195 peer_unlock(binfo
->peer
); /* bgp_info peer reference */
197 XFREE(MTYPE_BGP_ROUTE
, binfo
);
200 struct bgp_info
*bgp_info_lock(struct bgp_info
*binfo
)
206 struct bgp_info
*bgp_info_unlock(struct bgp_info
*binfo
)
208 assert(binfo
&& binfo
->lock
> 0);
211 if (binfo
->lock
== 0) {
213 zlog_debug ("%s: unlocked and freeing", __func__
);
214 zlog_backtrace (LOG_DEBUG
);
216 bgp_info_free(binfo
);
221 if (binfo
->lock
== 1)
223 zlog_debug ("%s: unlocked to 1", __func__
);
224 zlog_backtrace (LOG_DEBUG
);
231 void bgp_info_add(struct bgp_node
*rn
, struct bgp_info
*ri
)
233 struct bgp_info
*top
;
245 peer_lock(ri
->peer
); /* bgp_info peer reference */
248 /* Do the actual removal of info from RIB, for use by bgp_process
249 completion callback *only* */
250 void bgp_info_reap(struct bgp_node
*rn
, struct bgp_info
*ri
)
253 ri
->next
->prev
= ri
->prev
;
255 ri
->prev
->next
= ri
->next
;
259 bgp_info_mpath_dequeue(ri
);
264 void bgp_info_delete(struct bgp_node
*rn
, struct bgp_info
*ri
)
266 bgp_info_set_flag(rn
, ri
, BGP_INFO_REMOVED
);
267 /* set of previous already took care of pcount */
268 UNSET_FLAG(ri
->flags
, BGP_INFO_VALID
);
271 /* undo the effects of a previous call to bgp_info_delete; typically
272 called when a route is deleted and then quickly re-added before the
273 deletion has been processed */
274 void bgp_info_restore(struct bgp_node
*rn
, struct bgp_info
*ri
)
276 bgp_info_unset_flag(rn
, ri
, BGP_INFO_REMOVED
);
277 /* unset of previous already took care of pcount */
278 SET_FLAG(ri
->flags
, BGP_INFO_VALID
);
281 /* Adjust pcount as required */
282 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_info
*ri
)
284 struct bgp_table
*table
;
286 assert(rn
&& bgp_node_table(rn
));
287 assert(ri
&& ri
->peer
&& ri
->peer
->bgp
);
289 table
= bgp_node_table(rn
);
291 if (ri
->peer
== ri
->peer
->bgp
->peer_self
)
294 if (!BGP_INFO_COUNTABLE(ri
)
295 && CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
297 UNSET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
299 /* slight hack, but more robust against errors. */
300 if (ri
->peer
->pcount
[table
->afi
][table
->safi
])
301 ri
->peer
->pcount
[table
->afi
][table
->safi
]--;
304 "%s: Asked to decrement 0 prefix count for peer %s",
305 __func__
, ri
->peer
->host
);
306 zlog_backtrace(LOG_WARNING
);
307 zlog_warn("%s: Please report to Quagga bugzilla",
310 } else if (BGP_INFO_COUNTABLE(ri
)
311 && !CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
312 SET_FLAG(ri
->flags
, BGP_INFO_COUNTED
);
313 ri
->peer
->pcount
[table
->afi
][table
->safi
]++;
317 static int bgp_label_index_differs(struct bgp_info
*ri1
, struct bgp_info
*ri2
)
319 return (!(ri1
->attr
->label_index
== ri2
->attr
->label_index
));
322 /* Set/unset bgp_info flags, adjusting any other state as needed.
323 * This is here primarily to keep prefix-count in check.
325 void bgp_info_set_flag(struct bgp_node
*rn
, struct bgp_info
*ri
, u_int32_t flag
)
327 SET_FLAG(ri
->flags
, flag
);
329 /* early bath if we know it's not a flag that changes countability state
331 if (!CHECK_FLAG(flag
,
332 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
335 bgp_pcount_adjust(rn
, ri
);
338 void bgp_info_unset_flag(struct bgp_node
*rn
, struct bgp_info
*ri
,
341 UNSET_FLAG(ri
->flags
, flag
);
343 /* early bath if we know it's not a flag that changes countability state
345 if (!CHECK_FLAG(flag
,
346 BGP_INFO_VALID
| BGP_INFO_HISTORY
| BGP_INFO_REMOVED
))
349 bgp_pcount_adjust(rn
, ri
);
352 /* Get MED value. If MED value is missing and "bgp bestpath
353 missing-as-worst" is specified, treat it as the worst value. */
354 static u_int32_t
bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
356 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
359 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
366 void bgp_info_path_with_addpath_rx_str(struct bgp_info
*ri
, char *buf
)
368 if (ri
->addpath_rx_id
)
369 sprintf(buf
, "path %s (addpath rxid %d)", ri
->peer
->host
,
372 sprintf(buf
, "path %s", ri
->peer
->host
);
375 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
377 static int bgp_info_cmp(struct bgp
*bgp
, struct bgp_info
*new,
378 struct bgp_info
*exist
, int *paths_eq
,
379 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
380 char *pfx_buf
, afi_t afi
, safi_t safi
)
382 struct attr
*newattr
, *existattr
;
383 bgp_peer_sort_t new_sort
;
384 bgp_peer_sort_t exist_sort
;
386 u_int32_t exist_pref
;
389 u_int32_t new_weight
;
390 u_int32_t exist_weight
;
391 uint32_t newm
, existm
;
392 struct in_addr new_id
;
393 struct in_addr exist_id
;
396 int internal_as_route
;
399 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
400 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
401 u_int32_t new_mm_seq
;
402 u_int32_t exist_mm_seq
;
409 zlog_debug("%s: new is NULL", pfx_buf
);
414 bgp_info_path_with_addpath_rx_str(new, new_buf
);
418 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
424 bgp_info_path_with_addpath_rx_str(exist
, exist_buf
);
425 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
426 pfx_buf
, new_buf
, new->flags
, exist_buf
,
431 existattr
= exist
->attr
;
433 /* For EVPN routes, we cannot just go by local vs remote, we have to
434 * look at the MAC mobility sequence number, if present.
436 if (safi
== SAFI_EVPN
) {
437 /* This is an error condition described in RFC 7432 Section
439 * states that in this scenario "the PE MUST alert the operator"
441 * does not state what other action to take. In order to provide
443 * consistency in this scenario we are going to prefer the path
447 if (newattr
->sticky
!= existattr
->sticky
) {
449 prefix2str(&new->net
->p
, pfx_buf
,
451 * PREFIX2STR_BUFFER
);
452 bgp_info_path_with_addpath_rx_str(new, new_buf
);
453 bgp_info_path_with_addpath_rx_str(exist
,
457 if (newattr
->sticky
&& !existattr
->sticky
) {
459 "%s: %s wins over %s due to sticky MAC flag",
460 pfx_buf
, new_buf
, exist_buf
);
464 if (!newattr
->sticky
&& existattr
->sticky
) {
466 "%s: %s loses to %s due to sticky MAC flag",
467 pfx_buf
, new_buf
, exist_buf
);
472 new_mm_seq
= mac_mobility_seqnum(newattr
);
473 exist_mm_seq
= mac_mobility_seqnum(existattr
);
475 if (new_mm_seq
> exist_mm_seq
) {
478 "%s: %s wins over %s due to MM seq %u > %u",
479 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
484 if (new_mm_seq
< exist_mm_seq
) {
487 "%s: %s loses to %s due to MM seq %u < %u",
488 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
494 /* 1. Weight check. */
495 new_weight
= newattr
->weight
;
496 exist_weight
= existattr
->weight
;
498 if (new_weight
> exist_weight
) {
500 zlog_debug("%s: %s wins over %s due to weight %d > %d",
501 pfx_buf
, new_buf
, exist_buf
, new_weight
,
506 if (new_weight
< exist_weight
) {
508 zlog_debug("%s: %s loses to %s due to weight %d < %d",
509 pfx_buf
, new_buf
, exist_buf
, new_weight
,
514 /* 2. Local preference check. */
515 new_pref
= exist_pref
= bgp
->default_local_pref
;
517 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
518 new_pref
= newattr
->local_pref
;
519 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
520 exist_pref
= existattr
->local_pref
;
522 if (new_pref
> exist_pref
) {
525 "%s: %s wins over %s due to localpref %d > %d",
526 pfx_buf
, new_buf
, exist_buf
, new_pref
,
531 if (new_pref
< exist_pref
) {
534 "%s: %s loses to %s due to localpref %d < %d",
535 pfx_buf
, new_buf
, exist_buf
, new_pref
,
540 /* 3. Local route check. We prefer:
542 * - BGP_ROUTE_AGGREGATE
543 * - BGP_ROUTE_REDISTRIBUTE
545 if (!(new->sub_type
== BGP_ROUTE_NORMAL
)) {
548 "%s: %s wins over %s due to preferred BGP_ROUTE type",
549 pfx_buf
, new_buf
, exist_buf
);
553 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
)) {
556 "%s: %s loses to %s due to preferred BGP_ROUTE type",
557 pfx_buf
, new_buf
, exist_buf
);
561 /* 4. AS path length check. */
562 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
563 int exist_hops
= aspath_count_hops(existattr
->aspath
);
564 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
566 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
569 aspath_hops
= aspath_count_hops(newattr
->aspath
);
570 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
572 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
575 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
576 pfx_buf
, new_buf
, exist_buf
,
578 (exist_hops
+ exist_confeds
));
582 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
585 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
586 pfx_buf
, new_buf
, exist_buf
,
588 (exist_hops
+ exist_confeds
));
592 int newhops
= aspath_count_hops(newattr
->aspath
);
594 if (newhops
< exist_hops
) {
597 "%s: %s wins over %s due to aspath hopcount %d < %d",
598 pfx_buf
, new_buf
, exist_buf
,
599 newhops
, exist_hops
);
603 if (newhops
> exist_hops
) {
606 "%s: %s loses to %s due to aspath hopcount %d > %d",
607 pfx_buf
, new_buf
, exist_buf
,
608 newhops
, exist_hops
);
614 /* 5. Origin check. */
615 if (newattr
->origin
< existattr
->origin
) {
617 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
618 pfx_buf
, new_buf
, exist_buf
,
619 bgp_origin_long_str
[newattr
->origin
],
620 bgp_origin_long_str
[existattr
->origin
]);
624 if (newattr
->origin
> existattr
->origin
) {
626 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
627 pfx_buf
, new_buf
, exist_buf
,
628 bgp_origin_long_str
[newattr
->origin
],
629 bgp_origin_long_str
[existattr
->origin
]);
634 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
635 && aspath_count_hops(existattr
->aspath
) == 0);
636 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
637 && aspath_count_confeds(existattr
->aspath
) > 0
638 && aspath_count_hops(newattr
->aspath
) == 0
639 && aspath_count_hops(existattr
->aspath
) == 0);
641 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
642 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
643 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
644 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
645 || internal_as_route
) {
646 new_med
= bgp_med_value(new->attr
, bgp
);
647 exist_med
= bgp_med_value(exist
->attr
, bgp
);
649 if (new_med
< exist_med
) {
652 "%s: %s wins over %s due to MED %d < %d",
653 pfx_buf
, new_buf
, exist_buf
, new_med
,
658 if (new_med
> exist_med
) {
661 "%s: %s loses to %s due to MED %d > %d",
662 pfx_buf
, new_buf
, exist_buf
, new_med
,
668 /* 7. Peer type check. */
669 new_sort
= new->peer
->sort
;
670 exist_sort
= exist
->peer
->sort
;
672 if (new_sort
== BGP_PEER_EBGP
673 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
676 "%s: %s wins over %s due to eBGP peer > iBGP peer",
677 pfx_buf
, new_buf
, exist_buf
);
681 if (exist_sort
== BGP_PEER_EBGP
682 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
685 "%s: %s loses to %s due to iBGP peer < eBGP peer",
686 pfx_buf
, new_buf
, exist_buf
);
690 /* 8. IGP metric check. */
694 newm
= new->extra
->igpmetric
;
696 existm
= exist
->extra
->igpmetric
;
701 "%s: %s wins over %s due to IGP metric %d < %d",
702 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
709 "%s: %s loses to %s due to IGP metric %d > %d",
710 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
714 /* 9. Same IGP metric. Compare the cluster list length as
715 representative of IGP hops metric. Rewrite the metric value
716 pair (newm, existm) with the cluster list length. Prefer the
717 path with smaller cluster list length. */
718 if (newm
== existm
) {
719 if (peer_sort(new->peer
) == BGP_PEER_IBGP
720 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
721 && (mpath_cfg
== NULL
723 mpath_cfg
->ibgp_flags
,
724 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
725 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
726 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
731 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
732 pfx_buf
, new_buf
, exist_buf
,
740 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
741 pfx_buf
, new_buf
, exist_buf
,
748 /* 10. confed-external vs. confed-internal */
749 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
750 if (new_sort
== BGP_PEER_CONFED
751 && exist_sort
== BGP_PEER_IBGP
) {
754 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
755 pfx_buf
, new_buf
, exist_buf
);
759 if (exist_sort
== BGP_PEER_CONFED
760 && new_sort
== BGP_PEER_IBGP
) {
763 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
764 pfx_buf
, new_buf
, exist_buf
);
769 /* 11. Maximum path check. */
770 if (newm
== existm
) {
771 /* If one path has a label but the other does not, do not treat
772 * them as equals for multipath
774 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
776 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
779 "%s: %s and %s cannot be multipath, one has a label while the other does not",
780 pfx_buf
, new_buf
, exist_buf
);
781 } else if (bgp_flag_check(bgp
,
782 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
785 * For the two paths, all comparison steps till IGP
787 * have succeeded - including AS_PATH hop count. Since
789 * bestpath as-path multipath-relax' knob is on, we
791 * an exact match of AS_PATH. Thus, mark the paths are
793 * That will trigger both these paths to get into the
801 "%s: %s and %s are equal via multipath-relax",
802 pfx_buf
, new_buf
, exist_buf
);
803 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
804 if (aspath_cmp(new->attr
->aspath
,
805 exist
->attr
->aspath
)) {
810 "%s: %s and %s are equal via matching aspaths",
811 pfx_buf
, new_buf
, exist_buf
);
813 } else if (new->peer
->as
== exist
->peer
->as
) {
818 "%s: %s and %s are equal via same remote-as",
819 pfx_buf
, new_buf
, exist_buf
);
823 * TODO: If unequal cost ibgp multipath is enabled we can
824 * mark the paths as equal here instead of returning
829 "%s: %s wins over %s after IGP metric comparison",
830 pfx_buf
, new_buf
, exist_buf
);
833 "%s: %s loses to %s after IGP metric comparison",
834 pfx_buf
, new_buf
, exist_buf
);
839 /* 12. If both paths are external, prefer the path that was received
840 first (the oldest one). This step minimizes route-flap, since a
841 newer path won't displace an older one, even if it was the
842 preferred route based on the additional decision criteria below. */
843 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
844 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
845 if (CHECK_FLAG(new->flags
, BGP_INFO_SELECTED
)) {
848 "%s: %s wins over %s due to oldest external",
849 pfx_buf
, new_buf
, exist_buf
);
853 if (CHECK_FLAG(exist
->flags
, BGP_INFO_SELECTED
)) {
856 "%s: %s loses to %s due to oldest external",
857 pfx_buf
, new_buf
, exist_buf
);
862 /* 13. Router-ID comparision. */
863 /* If one of the paths is "stale", the corresponding peer router-id will
864 * be 0 and would always win over the other path. If originator id is
865 * used for the comparision, it will decide which path is better.
867 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
868 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
870 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
871 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
872 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
874 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
876 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
879 "%s: %s wins over %s due to Router-ID comparison",
880 pfx_buf
, new_buf
, exist_buf
);
884 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
887 "%s: %s loses to %s due to Router-ID comparison",
888 pfx_buf
, new_buf
, exist_buf
);
892 /* 14. Cluster length comparision. */
893 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
894 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
896 if (new_cluster
< exist_cluster
) {
899 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
900 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
905 if (new_cluster
> exist_cluster
) {
908 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
909 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
914 /* 15. Neighbor address comparision. */
915 /* Do this only if neither path is "stale" as stale paths do not have
916 * valid peer information (as the connection may or may not be up).
918 if (CHECK_FLAG(exist
->flags
, BGP_INFO_STALE
)) {
921 "%s: %s wins over %s due to latter path being STALE",
922 pfx_buf
, new_buf
, exist_buf
);
926 if (CHECK_FLAG(new->flags
, BGP_INFO_STALE
)) {
929 "%s: %s loses to %s due to former path being STALE",
930 pfx_buf
, new_buf
, exist_buf
);
934 /* locally configured routes to advertise do not have su_remote */
935 if (new->peer
->su_remote
== NULL
)
937 if (exist
->peer
->su_remote
== NULL
)
940 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
945 "%s: %s loses to %s due to Neighor IP comparison",
946 pfx_buf
, new_buf
, exist_buf
);
953 "%s: %s wins over %s due to Neighor IP comparison",
954 pfx_buf
, new_buf
, exist_buf
);
959 zlog_debug("%s: %s wins over %s due to nothing left to compare",
960 pfx_buf
, new_buf
, exist_buf
);
965 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
966 * is preferred, or 0 if they are the same (usually will only occur if
967 * multipath is enabled
968 * This version is compatible with */
969 int bgp_info_cmp_compatible(struct bgp
*bgp
, struct bgp_info
*new,
970 struct bgp_info
*exist
, char *pfx_buf
, afi_t afi
,
975 ret
= bgp_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
, afi
,
989 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
990 struct attr
*attr
, afi_t afi
,
993 struct bgp_filter
*filter
;
995 filter
= &peer
->filter
[afi
][safi
];
997 #define FILTER_EXIST_WARN(F, f, filter) \
998 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
999 zlog_warn("%s: Could not find configured input %s-list %s!", \
1000 peer->host, #f, F##_IN_NAME(filter));
1002 if (DISTRIBUTE_IN_NAME(filter
)) {
1003 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1005 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1009 if (PREFIX_LIST_IN_NAME(filter
)) {
1010 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1012 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1016 if (FILTER_LIST_IN_NAME(filter
)) {
1017 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1019 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1024 return FILTER_PERMIT
;
1025 #undef FILTER_EXIST_WARN
1028 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1029 struct attr
*attr
, afi_t afi
,
1032 struct bgp_filter
*filter
;
1034 filter
= &peer
->filter
[afi
][safi
];
1036 #define FILTER_EXIST_WARN(F, f, filter) \
1037 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1038 zlog_warn("%s: Could not find configured output %s-list %s!", \
1039 peer->host, #f, F##_OUT_NAME(filter));
1041 if (DISTRIBUTE_OUT_NAME(filter
)) {
1042 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1044 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1048 if (PREFIX_LIST_OUT_NAME(filter
)) {
1049 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1051 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1056 if (FILTER_LIST_OUT_NAME(filter
)) {
1057 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1059 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1064 return FILTER_PERMIT
;
1065 #undef FILTER_EXIST_WARN
1068 /* If community attribute includes no_export then return 1. */
1069 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1071 if (attr
->community
) {
1072 /* NO_ADVERTISE check. */
1073 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1076 /* NO_EXPORT check. */
1077 if (peer
->sort
== BGP_PEER_EBGP
1078 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1081 /* NO_EXPORT_SUBCONFED check. */
1082 if (peer
->sort
== BGP_PEER_EBGP
1083 || peer
->sort
== BGP_PEER_CONFED
)
1084 if (community_include(attr
->community
,
1085 COMMUNITY_NO_EXPORT_SUBCONFED
))
1091 /* Route reflection loop check. */
1092 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1094 struct in_addr cluster_id
;
1096 if (attr
->cluster
) {
1097 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1098 cluster_id
= peer
->bgp
->cluster_id
;
1100 cluster_id
= peer
->bgp
->router_id
;
1102 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1108 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1109 struct attr
*attr
, afi_t afi
, safi_t safi
,
1110 const char *rmap_name
)
1112 struct bgp_filter
*filter
;
1113 struct bgp_info info
;
1114 route_map_result_t ret
;
1115 struct route_map
*rmap
= NULL
;
1117 filter
= &peer
->filter
[afi
][safi
];
1119 /* Apply default weight value. */
1120 if (peer
->weight
[afi
][safi
])
1121 attr
->weight
= peer
->weight
[afi
][safi
];
1124 rmap
= route_map_lookup_by_name(rmap_name
);
1129 if (ROUTE_MAP_IN_NAME(filter
)) {
1130 rmap
= ROUTE_MAP_IN(filter
);
1137 /* Route map apply. */
1139 /* Duplicate current value to new strucutre for modification. */
1143 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1145 /* Apply BGP route map to the attribute. */
1146 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1148 peer
->rmap_type
= 0;
1150 if (ret
== RMAP_DENYMATCH
) {
1151 /* Free newly generated AS path and community by
1153 bgp_attr_flush(attr
);
1160 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1161 struct attr
*attr
, afi_t afi
, safi_t safi
,
1162 const char *rmap_name
)
1164 struct bgp_info info
;
1165 route_map_result_t ret
;
1166 struct route_map
*rmap
= NULL
;
1170 * So if we get to this point and have no rmap_name
1171 * we want to just show the output as it currently
1177 /* Apply default weight value. */
1178 if (peer
->weight
[afi
][safi
])
1179 attr
->weight
= peer
->weight
[afi
][safi
];
1181 rmap
= route_map_lookup_by_name(rmap_name
);
1184 * If we have a route map name and we do not find
1185 * the routemap that means we have an implicit
1191 /* Route map apply. */
1192 /* Duplicate current value to new strucutre for modification. */
1196 rmap_type
= peer
->rmap_type
;
1197 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1199 /* Apply BGP route map to the attribute. */
1200 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &info
);
1202 peer
->rmap_type
= rmap_type
;
1204 if (ret
== RMAP_DENYMATCH
)
1206 * caller has multiple error paths with bgp_attr_flush()
1213 /* If this is an EBGP peer with remove-private-AS */
1214 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1215 struct peer
*peer
, struct attr
*attr
)
1217 if (peer
->sort
== BGP_PEER_EBGP
1218 && (peer_af_flag_check(peer
, afi
, safi
,
1219 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1220 || peer_af_flag_check(peer
, afi
, safi
,
1221 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1222 || peer_af_flag_check(peer
, afi
, safi
,
1223 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1224 || peer_af_flag_check(peer
, afi
, safi
,
1225 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1226 // Take action on the entire aspath
1227 if (peer_af_flag_check(peer
, afi
, safi
,
1228 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1229 || peer_af_flag_check(peer
, afi
, safi
,
1230 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1231 if (peer_af_flag_check(
1233 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1234 attr
->aspath
= aspath_replace_private_asns(
1235 attr
->aspath
, bgp
->as
);
1237 // The entire aspath consists of private ASNs so create
1239 else if (aspath_private_as_check(attr
->aspath
))
1240 attr
->aspath
= aspath_empty_get();
1242 // There are some public and some private ASNs, remove
1245 attr
->aspath
= aspath_remove_private_asns(
1249 // 'all' was not specified so the entire aspath must be private
1251 // for us to do anything
1252 else if (aspath_private_as_check(attr
->aspath
)) {
1253 if (peer_af_flag_check(
1255 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1256 attr
->aspath
= aspath_replace_private_asns(
1257 attr
->aspath
, bgp
->as
);
1259 attr
->aspath
= aspath_empty_get();
1264 /* If this is an EBGP peer with as-override */
1265 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1266 struct peer
*peer
, struct attr
*attr
)
1268 if (peer
->sort
== BGP_PEER_EBGP
1269 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1270 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1271 attr
->aspath
= aspath_replace_specific_asn(
1272 attr
->aspath
, peer
->as
, bgp
->as
);
1276 void bgp_attr_add_gshut_community(struct attr
*attr
)
1278 struct community
*old
;
1279 struct community
*new;
1280 struct community
*merge
;
1281 struct community
*gshut
;
1283 old
= attr
->community
;
1284 gshut
= community_str2com("graceful-shutdown");
1287 merge
= community_merge(community_dup(old
), gshut
);
1289 if (old
->refcnt
== 0)
1290 community_free(old
);
1292 new = community_uniq_sort(merge
);
1293 community_free(merge
);
1295 new = community_dup(gshut
);
1298 community_free(gshut
);
1299 attr
->community
= new;
1300 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1302 /* When we add the graceful-shutdown community we must also
1303 * lower the local-preference */
1304 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1305 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1309 static void subgroup_announce_reset_nhop(u_char family
, struct attr
*attr
)
1311 if (family
== AF_INET
)
1312 attr
->nexthop
.s_addr
= 0;
1313 if (family
== AF_INET6
)
1314 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1317 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_info
*ri
,
1318 struct update_subgroup
*subgrp
, struct prefix
*p
,
1321 struct bgp_filter
*filter
;
1324 struct peer
*onlypeer
;
1326 struct attr
*riattr
;
1327 char buf
[PREFIX_STRLEN
];
1333 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1335 if (DISABLE_BGP_ANNOUNCE
)
1338 afi
= SUBGRP_AFI(subgrp
);
1339 safi
= SUBGRP_SAFI(subgrp
);
1340 peer
= SUBGRP_PEER(subgrp
);
1342 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1343 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1346 filter
= &peer
->filter
[afi
][safi
];
1347 bgp
= SUBGRP_INST(subgrp
);
1348 riattr
= bgp_info_mpath_count(ri
) ? bgp_info_mpath_attr(ri
) : ri
->attr
;
1351 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1352 && ((ri
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1353 || (ri
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1356 * direct and direct_ext type routes originate internally even
1357 * though they can have peer pointers that reference other
1360 prefix2str(p
, buf
, PREFIX_STRLEN
);
1361 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1367 /* With addpath we may be asked to TX all kinds of paths so make sure
1369 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
)
1370 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)
1371 || CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
1375 /* If this is not the bestpath then check to see if there is an enabled
1377 * feature that requires us to advertise it */
1378 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
1379 if (!bgp_addpath_tx_path(peer
, afi
, safi
, ri
)) {
1384 /* Aggregate-address suppress check. */
1385 if (ri
->extra
&& ri
->extra
->suppress
)
1386 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1390 /* If it's labeled safi, make sure the route has a valid label. */
1391 if (safi
== SAFI_LABELED_UNICAST
) {
1392 mpls_label_t label
= bgp_adv_label(rn
, ri
, peer
, afi
, safi
);
1393 if (!bgp_is_valid_label(&label
)) {
1394 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1395 zlog_debug("u%" PRIu64
":s%" PRIu64
1396 " %s/%d is filtered - no label (%p)",
1397 subgrp
->update_group
->id
, subgrp
->id
,
1398 inet_ntop(p
->family
, &p
->u
.prefix
,
1399 buf
, SU_ADDRSTRLEN
),
1400 p
->prefixlen
, &label
);
1405 /* Do not send back route to sender. */
1406 if (onlypeer
&& from
== onlypeer
) {
1410 /* Do not send the default route in the BGP table if the neighbor is
1411 * configured for default-originate */
1412 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1413 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1414 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1416 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1420 /* Transparency check. */
1421 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1422 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1427 /* If community is not disabled check the no-export and local. */
1428 if (!transparent
&& bgp_community_filter(peer
, riattr
)) {
1429 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1431 "subgrpannouncecheck: community filter check fail");
1435 /* If the attribute has originator-id and it is same as remote
1437 if (onlypeer
&& riattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1438 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &riattr
->originator_id
))) {
1439 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1441 "%s [Update:SEND] %s originator-id is same as "
1444 prefix2str(p
, buf
, sizeof(buf
)));
1448 /* ORF prefix-list filter check */
1449 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1450 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1451 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1452 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1453 if (peer
->orf_plist
[afi
][safi
]) {
1454 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1456 if (bgp_debug_update(NULL
, p
,
1457 subgrp
->update_group
, 0))
1459 "%s [Update:SEND] %s is filtered via ORF",
1467 /* Output filter check. */
1468 if (bgp_output_filter(peer
, p
, riattr
, afi
, safi
) == FILTER_DENY
) {
1469 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1470 zlog_debug("%s [Update:SEND] %s is filtered",
1471 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1475 #ifdef BGP_SEND_ASPATH_CHECK
1476 /* AS path loop check. */
1477 if (onlypeer
&& aspath_loop_check(riattr
->aspath
, onlypeer
->as
)) {
1478 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1480 "%s [Update:SEND] suppress announcement to peer AS %u "
1481 "that is part of AS path.",
1482 onlypeer
->host
, onlypeer
->as
);
1485 #endif /* BGP_SEND_ASPATH_CHECK */
1487 /* If we're a CONFED we need to loop check the CONFED ID too */
1488 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1489 if (aspath_loop_check(riattr
->aspath
, bgp
->confed_id
)) {
1490 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1492 "%s [Update:SEND] suppress announcement to peer AS %u"
1494 peer
->host
, bgp
->confed_id
);
1499 /* Route-Reflect check. */
1500 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1505 /* IBGP reflection check. */
1506 if (reflect
&& !samepeer_safe
) {
1507 /* A route from a Client peer. */
1508 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1509 PEER_FLAG_REFLECTOR_CLIENT
)) {
1510 /* Reflect to all the Non-Client peers and also to the
1511 Client peers other than the originator. Originator
1513 is already done. So there is noting to do. */
1514 /* no bgp client-to-client reflection check. */
1515 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1516 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1517 PEER_FLAG_REFLECTOR_CLIENT
))
1520 /* A route from a Non-client peer. Reflect to all other
1522 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1523 PEER_FLAG_REFLECTOR_CLIENT
))
1528 /* For modify attribute, copy it to temporary structure. */
1529 bgp_attr_dup(attr
, riattr
);
1531 /* If local-preference is not set. */
1532 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1533 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1534 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1535 attr
->local_pref
= bgp
->default_local_pref
;
1538 /* If originator-id is not set and the route is to be reflected,
1539 set the originator id */
1541 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1542 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1543 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1546 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1548 if (peer
->sort
== BGP_PEER_EBGP
1549 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1550 if (from
!= bgp
->peer_self
&& !transparent
1551 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1552 PEER_FLAG_MED_UNCHANGED
))
1554 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1557 /* Since the nexthop attribute can vary per peer, it is not explicitly
1559 * in announce check, only certain flags and length (or number of
1561 * -- for IPv6/MP_REACH) are set here in order to guide the update
1563 * code in setting the nexthop(s) on a per peer basis in
1565 * Typically, the source nexthop in the attribute is preserved but in
1567 * scenarios where we know it will always be overwritten, we reset the
1568 * nexthop to "0" in an attempt to achieve better Update packing. An
1569 * example of this is when a prefix from each of 2 IBGP peers needs to
1571 * announced to an EBGP peer (and they have the same attributes barring
1575 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1577 #define NEXTHOP_IS_V6 \
1578 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1579 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1580 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1581 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1583 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1585 * the peer (group) is configured to receive link-local nexthop
1587 * and it is available in the prefix OR we're not reflecting the route
1589 * the peer (group) to whom we're going to announce is on a shared
1591 * and this is either a self-originated route or the peer is EBGP.
1593 if (NEXTHOP_IS_V6
) {
1594 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1595 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1596 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1597 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1598 || (!reflect
&& peer
->shared_network
1599 && (from
== bgp
->peer_self
1600 || peer
->sort
== BGP_PEER_EBGP
))) {
1601 attr
->mp_nexthop_len
=
1602 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1605 /* Clear off link-local nexthop in source, whenever it is not
1607 * ensure more prefixes share the same attribute for
1610 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1611 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1612 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1615 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1616 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1618 /* Route map & unsuppress-map apply. */
1619 if (ROUTE_MAP_OUT_NAME(filter
) || (ri
->extra
&& ri
->extra
->suppress
)) {
1620 struct bgp_info info
;
1621 struct bgp_info_extra dummy_info_extra
;
1622 struct attr dummy_attr
;
1628 memcpy(&dummy_info_extra
, ri
->extra
,
1629 sizeof(struct bgp_info_extra
));
1630 info
.extra
= &dummy_info_extra
;
1633 /* don't confuse inbound and outbound setting */
1634 RESET_FLAG(attr
->rmap_change_flags
);
1637 * The route reflector is not allowed to modify the attributes
1638 * of the reflected IBGP routes unless explicitly allowed.
1640 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1641 && !bgp_flag_check(bgp
,
1642 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1643 bgp_attr_dup(&dummy_attr
, attr
);
1644 info
.attr
= &dummy_attr
;
1647 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1649 if (ri
->extra
&& ri
->extra
->suppress
)
1650 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1653 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1656 peer
->rmap_type
= 0;
1658 if (ret
== RMAP_DENYMATCH
) {
1659 bgp_attr_flush(attr
);
1664 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1665 if (peer
->sort
== BGP_PEER_IBGP
1666 || peer
->sort
== BGP_PEER_CONFED
) {
1667 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1668 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1670 bgp_attr_add_gshut_community(attr
);
1674 /* After route-map has been applied, we check to see if the nexthop to
1675 * be carried in the attribute (that is used for the announcement) can
1676 * be cleared off or not. We do this in all cases where we would be
1677 * setting the nexthop to "ourselves". For IPv6, we only need to
1679 * the global nexthop here; the link-local nexthop would have been
1681 * already, and if not, it is required by the update formation code.
1682 * Also see earlier comments in this function.
1685 * If route-map has performed some operation on the nexthop or the peer
1686 * configuration says to pass it unchanged, we cannot reset the nexthop
1687 * here, so only attempt to do it if these aren't true. Note that the
1688 * route-map handler itself might have cleared the nexthop, if for
1690 * it is configured as 'peer-address'.
1692 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1693 riattr
->rmap_change_flags
)
1695 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1696 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1697 /* We can reset the nexthop, if setting (or forcing) it to
1699 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1700 PEER_FLAG_NEXTHOP_SELF
)
1701 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1702 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1704 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1705 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1706 subgroup_announce_reset_nhop(
1707 (peer_cap_enhe(peer
, afi
, safi
)
1711 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1712 /* Can also reset the nexthop if announcing to EBGP, but
1714 * no peer in the subgroup is on a shared subnet.
1715 * Note: 3rd party nexthop currently implemented for
1718 if (!bgp_subgrp_multiaccess_check_v4(riattr
->nexthop
,
1720 subgroup_announce_reset_nhop(
1721 (peer_cap_enhe(peer
, afi
, safi
)
1726 /* If IPv6/MP and nexthop does not have any override and happens
1728 * be a link-local address, reset it so that we don't pass along
1730 * source's link-local IPv6 address to recipients who may not be
1732 * the same interface.
1734 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1735 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1736 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1743 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1744 struct bgp_maxpaths_cfg
*mpath_cfg
,
1745 struct bgp_info_pair
*result
, afi_t afi
, safi_t safi
)
1747 struct bgp_info
*new_select
;
1748 struct bgp_info
*old_select
;
1749 struct bgp_info
*ri
;
1750 struct bgp_info
*ri1
;
1751 struct bgp_info
*ri2
;
1752 struct bgp_info
*nextri
= NULL
;
1753 int paths_eq
, do_mpath
, debug
;
1754 struct list mp_list
;
1755 char pfx_buf
[PREFIX2STR_BUFFER
];
1756 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1758 bgp_mp_list_init(&mp_list
);
1760 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1762 debug
= bgp_debug_bestpath(&rn
->p
);
1765 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1767 /* bgp deterministic-med */
1769 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1771 /* Clear BGP_INFO_DMED_SELECTED for all paths */
1772 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
)
1773 bgp_info_unset_flag(rn
, ri1
, BGP_INFO_DMED_SELECTED
);
1775 for (ri1
= rn
->info
; ri1
; ri1
= ri1
->next
) {
1776 if (CHECK_FLAG(ri1
->flags
, BGP_INFO_DMED_CHECK
))
1778 if (BGP_INFO_HOLDDOWN(ri1
))
1780 if (ri1
->peer
&& ri1
->peer
!= bgp
->peer_self
)
1781 if (ri1
->peer
->status
!= Established
)
1786 for (ri2
= ri1
->next
; ri2
; ri2
= ri2
->next
) {
1787 if (CHECK_FLAG(ri2
->flags
,
1788 BGP_INFO_DMED_CHECK
))
1790 if (BGP_INFO_HOLDDOWN(ri2
))
1793 && ri2
->peer
!= bgp
->peer_self
1796 PEER_STATUS_NSF_WAIT
))
1797 if (ri2
->peer
->status
1801 if (aspath_cmp_left(ri1
->attr
->aspath
,
1803 || aspath_cmp_left_confed(
1805 ri2
->attr
->aspath
)) {
1806 if (bgp_info_cmp(bgp
, ri2
,
1812 bgp_info_unset_flag(
1814 BGP_INFO_DMED_SELECTED
);
1820 BGP_INFO_DMED_CHECK
);
1824 bgp_info_set_flag(rn
, new_select
, BGP_INFO_DMED_CHECK
);
1825 bgp_info_set_flag(rn
, new_select
,
1826 BGP_INFO_DMED_SELECTED
);
1829 bgp_info_path_with_addpath_rx_str(new_select
,
1831 zlog_debug("%s: %s is the bestpath from AS %d",
1833 aspath_get_first_as(
1834 new_select
->attr
->aspath
));
1839 /* Check old selected route and new selected route. */
1842 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1844 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
))
1847 if (BGP_INFO_HOLDDOWN(ri
)) {
1848 /* reap REMOVED routes, if needs be
1849 * selected route must stay for a while longer though
1851 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
1852 && (ri
!= old_select
))
1853 bgp_info_reap(rn
, ri
);
1858 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1859 && !CHECK_FLAG(ri
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1860 if (ri
->peer
->status
!= Established
)
1863 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1864 && (!CHECK_FLAG(ri
->flags
, BGP_INFO_DMED_SELECTED
))) {
1865 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1869 bgp_info_unset_flag(rn
, ri
, BGP_INFO_DMED_CHECK
);
1871 if (bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1872 debug
, pfx_buf
, afi
, safi
)) {
1877 /* Now that we know which path is the bestpath see if any of the other
1879 * qualify as multipaths
1883 bgp_info_path_with_addpath_rx_str(new_select
, path_buf
);
1885 sprintf(path_buf
, "NONE");
1887 "%s: After path selection, newbest is %s oldbest was %s",
1889 old_select
? old_select
->peer
->host
: "NONE");
1892 if (do_mpath
&& new_select
) {
1893 for (ri
= rn
->info
; (ri
!= NULL
) && (nextri
= ri
->next
, 1);
1897 bgp_info_path_with_addpath_rx_str(ri
, path_buf
);
1899 if (ri
== new_select
) {
1902 "%s: %s is the bestpath, add to the multipath list",
1904 bgp_mp_list_add(&mp_list
, ri
);
1908 if (BGP_INFO_HOLDDOWN(ri
))
1911 if (ri
->peer
&& ri
->peer
!= bgp
->peer_self
1912 && !CHECK_FLAG(ri
->peer
->sflags
,
1913 PEER_STATUS_NSF_WAIT
))
1914 if (ri
->peer
->status
!= Established
)
1917 if (!bgp_info_nexthop_cmp(ri
, new_select
)) {
1920 "%s: %s has the same nexthop as the bestpath, skip it",
1925 bgp_info_cmp(bgp
, ri
, new_select
, &paths_eq
, mpath_cfg
,
1926 debug
, pfx_buf
, afi
, safi
);
1931 "%s: %s is equivalent to the bestpath, add to the multipath list",
1933 bgp_mp_list_add(&mp_list
, ri
);
1938 bgp_info_mpath_update(rn
, new_select
, old_select
, &mp_list
, mpath_cfg
);
1939 bgp_info_mpath_aggregate_update(new_select
, old_select
);
1940 bgp_mp_list_clear(&mp_list
);
1942 result
->old
= old_select
;
1943 result
->new = new_select
;
1949 * A new route/change in bestpath of an existing route. Evaluate the path
1950 * for advertisement to the subgroup.
1952 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
1953 struct bgp_info
*selected
,
1954 struct bgp_node
*rn
,
1955 u_int32_t addpath_tx_id
)
1958 struct peer
*onlypeer
;
1964 afi
= SUBGRP_AFI(subgrp
);
1965 safi
= SUBGRP_SAFI(subgrp
);
1966 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
1969 /* First update is deferred until ORF or ROUTE-REFRESH is received */
1970 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
1971 PEER_STATUS_ORF_WAIT_REFRESH
))
1974 memset(&attr
, 0, sizeof(struct attr
));
1975 /* It's initialized in bgp_announce_check() */
1977 /* Announcement to the subgroup. If the route is filtered withdraw it.
1980 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
1981 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
1983 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
1984 selected
->addpath_tx_id
);
1987 /* If selected is NULL we must withdraw the path using addpath_tx_id */
1989 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
1996 * Clear IGP changed flag and attribute changed flag for a route (all paths).
1997 * This is called at the end of route processing.
1999 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2001 struct bgp_info
*ri
;
2003 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2004 if (BGP_INFO_HOLDDOWN(ri
))
2006 UNSET_FLAG(ri
->flags
, BGP_INFO_IGP_CHANGED
);
2007 UNSET_FLAG(ri
->flags
, BGP_INFO_ATTR_CHANGED
);
2012 * Has the route changed from the RIB's perspective? This is invoked only
2013 * if the route selection returns the same best route as earlier - to
2014 * determine if we need to update zebra or not.
2016 int bgp_zebra_has_route_changed(struct bgp_node
*rn
, struct bgp_info
*selected
)
2018 struct bgp_info
*mpinfo
;
2020 /* If this is multipath, check all selected paths for any nexthop change
2022 * attribute change. Some attribute changes (e.g., community) aren't of
2023 * relevance to the RIB, but we'll update zebra to ensure we handle the
2024 * case of BGP nexthop change. This is the behavior when the best path
2026 * an attribute change anyway.
2028 if (CHECK_FLAG(selected
->flags
, BGP_INFO_IGP_CHANGED
)
2029 || CHECK_FLAG(selected
->flags
, BGP_INFO_MULTIPATH_CHG
))
2032 /* If this is multipath, check all selected paths for any nexthop change
2034 for (mpinfo
= bgp_info_mpath_first(selected
); mpinfo
;
2035 mpinfo
= bgp_info_mpath_next(mpinfo
)) {
2036 if (CHECK_FLAG(mpinfo
->flags
, BGP_INFO_IGP_CHANGED
)
2037 || CHECK_FLAG(mpinfo
->flags
, BGP_INFO_ATTR_CHANGED
))
2041 /* Nothing has changed from the RIB's perspective. */
2045 struct bgp_process_queue
{
2047 STAILQ_HEAD(, bgp_node
) pqueue
;
2048 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2050 unsigned int queued
;
2053 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2054 afi_t afi
, safi_t safi
)
2056 struct prefix
*p
= &rn
->p
;
2057 struct bgp_info
*new_select
;
2058 struct bgp_info
*old_select
;
2059 struct bgp_info_pair old_and_new
;
2061 /* Is it end of initial update? (after startup) */
2063 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2064 sizeof(bgp
->update_delay_zebra_resume_time
));
2066 bgp
->main_zebra_update_hold
= 0;
2067 FOREACH_AFI_SAFI (afi
, safi
) {
2068 if (bgp_fibupd_safi(safi
))
2069 bgp_zebra_announce_table(bgp
, afi
, safi
);
2071 bgp
->main_peers_update_hold
= 0;
2073 bgp_start_routeadv(bgp
);
2077 /* Best path selection. */
2078 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2080 old_select
= old_and_new
.old
;
2081 new_select
= old_and_new
.new;
2083 /* Do we need to allocate or free labels?
2084 * Right now, since we only deal with per-prefix labels, it is not
2085 * necessary to do this upon changes to best path except if the label
2088 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2091 || bgp_label_index_differs(new_select
, old_select
)
2092 || new_select
->sub_type
!= old_select
->sub_type
) {
2093 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2094 && new_select
->attr
->flag
2096 BGP_ATTR_PREFIX_SID
)
2097 && new_select
->attr
->label_index
2098 != BGP_INVALID_LABEL_INDEX
) {
2101 BGP_NODE_REGISTERED_FOR_LABEL
))
2102 bgp_unregister_for_label(rn
);
2103 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2105 bgp_set_valid_label(&rn
->local_label
);
2107 bgp_register_for_label(rn
, new_select
);
2109 } else if (CHECK_FLAG(rn
->flags
,
2110 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2111 bgp_unregister_for_label(rn
);
2113 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2114 bgp_unregister_for_label(rn
);
2117 /* If best route remains the same and this is not due to user-initiated
2118 * clear, see exactly what needs to be done.
2121 if (old_select
&& old_select
== new_select
2122 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2123 && !CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2124 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2125 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2127 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2128 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2130 if (bgp_fibupd_safi(safi
)
2131 && !bgp_option_check(BGP_OPT_NO_FIB
)
2132 && new_select
->type
== ZEBRA_ROUTE_BGP
2133 && new_select
->sub_type
== BGP_ROUTE_NORMAL
)
2134 bgp_zebra_announce(rn
, p
, old_select
, bgp
, afi
,
2137 UNSET_FLAG(old_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2138 bgp_zebra_clear_route_change_flags(rn
);
2140 /* If there is a change of interest to peers, reannounce the
2142 if (CHECK_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
)
2143 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2144 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2146 /* unicast routes must also be annouced to
2147 * labeled-unicast update-groups */
2148 if (safi
== SAFI_UNICAST
)
2149 group_announce_route(bgp
, afi
,
2150 SAFI_LABELED_UNICAST
, rn
,
2153 UNSET_FLAG(old_select
->flags
, BGP_INFO_ATTR_CHANGED
);
2154 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2157 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2161 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2163 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2165 /* bestpath has changed; bump version */
2166 if (old_select
|| new_select
) {
2167 bgp_bump_version(rn
);
2169 if (!bgp
->t_rmap_def_originate_eval
) {
2173 update_group_refresh_default_originate_route_map
,
2174 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2175 &bgp
->t_rmap_def_originate_eval
);
2180 bgp_info_unset_flag(rn
, old_select
, BGP_INFO_SELECTED
);
2182 bgp_info_set_flag(rn
, new_select
, BGP_INFO_SELECTED
);
2183 bgp_info_unset_flag(rn
, new_select
, BGP_INFO_ATTR_CHANGED
);
2184 UNSET_FLAG(new_select
->flags
, BGP_INFO_MULTIPATH_CHG
);
2188 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2189 if (old_select
!= new_select
) {
2191 vnc_import_bgp_exterior_del_route(bgp
, p
,
2193 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2196 vnc_import_bgp_exterior_add_route(bgp
, p
,
2198 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2204 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2206 /* unicast routes must also be annouced to labeled-unicast update-groups
2208 if (safi
== SAFI_UNICAST
)
2209 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2213 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2214 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2215 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2216 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2217 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2218 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2220 /* Withdraw the route from the kernel. */
2221 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2222 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2223 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
))
2224 bgp_zebra_withdraw(p
, old_select
, safi
);
2228 /* advertise/withdraw type-5 routes */
2229 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2231 && (!new_select
->extra
|| !new_select
->extra
->parent
))
2232 bgp_evpn_advertise_type5_route(
2233 bgp
, &rn
->p
, new_select
->attr
, afi
, safi
);
2235 && (!old_select
->extra
|| !old_select
->extra
->parent
))
2236 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2239 /* Clear any route change flags. */
2240 bgp_zebra_clear_route_change_flags(rn
);
2242 /* Reap old select bgp_info, if it has been removed */
2243 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_INFO_REMOVED
))
2244 bgp_info_reap(rn
, old_select
);
2246 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2250 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2252 struct bgp_process_queue
*pqnode
= data
;
2253 struct bgp
*bgp
= pqnode
->bgp
;
2254 struct bgp_table
*table
;
2255 struct bgp_node
*rn
;
2258 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2259 bgp_process_main_one(bgp
, NULL
, 0, 0);
2260 /* should always have dedicated wq call */
2261 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2265 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2266 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2267 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2268 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2269 table
= bgp_node_table(rn
);
2270 /* note, new RNs may be added as part of processing */
2271 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2273 bgp_unlock_node(rn
);
2274 bgp_table_unlock(table
);
2280 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2282 struct bgp_process_queue
*pqnode
= data
;
2284 bgp_unlock(pqnode
->bgp
);
2286 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2289 void bgp_process_queue_init(void)
2291 if (!bm
->process_main_queue
) {
2292 bm
->process_main_queue
=
2293 work_queue_new(bm
->master
, "process_main_queue");
2295 if (!bm
->process_main_queue
) {
2296 zlog_err("%s: Failed to allocate work queue", __func__
);
2301 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2302 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2303 bm
->process_main_queue
->spec
.max_retries
= 0;
2304 bm
->process_main_queue
->spec
.hold
= 50;
2305 /* Use a higher yield value of 50ms for main queue processing */
2306 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2309 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2311 struct bgp_process_queue
*pqnode
;
2313 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2314 sizeof(struct bgp_process_queue
));
2316 /* unlocked in bgp_processq_del */
2317 pqnode
->bgp
= bgp_lock(bgp
);
2318 STAILQ_INIT(&pqnode
->pqueue
);
2323 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2325 #define ARBITRARY_PROCESS_QLEN 10000
2326 struct work_queue
*wq
= bm
->process_main_queue
;
2327 struct bgp_process_queue
*pqnode
;
2328 int pqnode_reuse
= 0;
2330 /* already scheduled for processing? */
2331 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2337 /* Add route nodes to an existing work queue item until reaching the
2338 limit only if is from the same BGP view and it's not an EOIU marker
2340 if (work_queue_item_count(wq
)) {
2341 struct work_queue_item
*item
= work_queue_last_item(wq
);
2342 pqnode
= item
->data
;
2344 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2345 || pqnode
->bgp
!= bgp
2346 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2347 pqnode
= bgp_processq_alloc(bgp
);
2351 pqnode
= bgp_processq_alloc(bgp
);
2352 /* all unlocked in bgp_process_wq */
2353 bgp_table_lock(bgp_node_table(rn
));
2355 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2358 /* can't be enqueued twice */
2359 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2360 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2364 work_queue_add(wq
, pqnode
);
2369 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2371 struct bgp_process_queue
*pqnode
;
2373 if (bm
->process_main_queue
== NULL
)
2376 pqnode
= bgp_processq_alloc(bgp
);
2378 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2379 work_queue_add(bm
->process_main_queue
, pqnode
);
2382 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2386 peer
= THREAD_ARG(thread
);
2387 peer
->t_pmax_restart
= NULL
;
2389 if (bgp_debug_neighbor_events(peer
))
2391 "%s Maximum-prefix restart timer expired, restore peering",
2394 peer_clear(peer
, NULL
);
2399 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2403 iana_safi_t pkt_safi
;
2405 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2408 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2409 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2410 PEER_STATUS_PREFIX_LIMIT
)
2415 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2417 afi_safi_print(afi
, safi
), peer
->host
,
2418 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2419 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2421 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2422 PEER_FLAG_MAX_PREFIX_WARNING
))
2425 /* Convert AFI, SAFI to values for packet. */
2426 pkt_afi
= afi_int2iana(afi
);
2427 pkt_safi
= safi_int2iana(safi
);
2431 ndata
[0] = (pkt_afi
>> 8);
2433 ndata
[2] = pkt_safi
;
2434 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2435 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2436 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2437 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2439 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2440 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2441 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2445 /* Dynamic peers will just close their connection. */
2446 if (peer_dynamic_neighbor(peer
))
2449 /* restart timer start */
2450 if (peer
->pmax_restart
[afi
][safi
]) {
2451 peer
->v_pmax_restart
=
2452 peer
->pmax_restart
[afi
][safi
] * 60;
2454 if (bgp_debug_neighbor_events(peer
))
2456 "%s Maximum-prefix restart timer started for %d secs",
2457 peer
->host
, peer
->v_pmax_restart
);
2459 BGP_TIMER_ON(peer
->t_pmax_restart
,
2460 bgp_maximum_prefix_restart_timer
,
2461 peer
->v_pmax_restart
);
2466 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2467 PEER_STATUS_PREFIX_LIMIT
);
2469 if (peer
->pcount
[afi
][safi
]
2470 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2471 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2472 PEER_STATUS_PREFIX_THRESHOLD
)
2477 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2478 afi_safi_print(afi
, safi
), peer
->host
,
2479 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2480 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2481 PEER_STATUS_PREFIX_THRESHOLD
);
2483 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2484 PEER_STATUS_PREFIX_THRESHOLD
);
2488 /* Unconditionally remove the route from the RIB, without taking
2489 * damping into consideration (eg, because the session went down)
2491 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_info
*ri
, struct peer
*peer
,
2492 afi_t afi
, safi_t safi
)
2494 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
, safi
);
2496 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2497 bgp_info_delete(rn
, ri
); /* keep historical info */
2499 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2502 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_info
*ri
,
2503 struct peer
*peer
, afi_t afi
, safi_t safi
,
2504 struct prefix_rd
*prd
)
2506 int status
= BGP_DAMP_NONE
;
2508 /* apply dampening, if result is suppressed, we'll be retaining
2509 * the bgp_info in the RIB for historical reference.
2511 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2512 && peer
->sort
== BGP_PEER_EBGP
)
2513 if ((status
= bgp_damp_withdraw(ri
, rn
, afi
, safi
, 0))
2514 == BGP_DAMP_SUPPRESSED
) {
2515 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, ri
, afi
,
2521 if (safi
== SAFI_MPLS_VPN
) {
2522 struct bgp_node
*prn
= NULL
;
2523 struct bgp_table
*table
= NULL
;
2525 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2526 (struct prefix
*)prd
);
2528 table
= (struct bgp_table
*)(prn
->info
);
2530 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2531 peer
->bgp
, prd
, table
, &rn
->p
, ri
);
2533 bgp_unlock_node(prn
);
2535 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2536 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2538 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, ri
);
2539 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2545 /* If this is an EVPN route, process for un-import. */
2546 if (safi
== SAFI_EVPN
)
2547 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, ri
);
2549 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
2552 struct bgp_info
*info_make(int type
, int sub_type
, u_short instance
,
2553 struct peer
*peer
, struct attr
*attr
,
2554 struct bgp_node
*rn
)
2556 struct bgp_info
*new;
2558 /* Make new BGP info. */
2559 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_info
));
2561 new->instance
= instance
;
2562 new->sub_type
= sub_type
;
2565 new->uptime
= bgp_clock();
2567 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2571 static void overlay_index_update(struct attr
*attr
,
2572 struct eth_segment_id
*eth_s_id
,
2573 union gw_addr
*gw_ip
)
2578 if (eth_s_id
== NULL
) {
2579 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2580 sizeof(struct eth_segment_id
));
2582 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2583 sizeof(struct eth_segment_id
));
2585 if (gw_ip
== NULL
) {
2586 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2588 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2589 sizeof(union gw_addr
));
2593 static bool overlay_index_equal(afi_t afi
, struct bgp_info
*info
,
2594 struct eth_segment_id
*eth_s_id
,
2595 union gw_addr
*gw_ip
)
2597 struct eth_segment_id
*info_eth_s_id
, *info_eth_s_id_remote
;
2598 union gw_addr
*info_gw_ip
, *info_gw_ip_remote
;
2601 if (afi
!= AFI_L2VPN
)
2604 memset(&temp
, 0, 16);
2605 info_eth_s_id
= (struct eth_segment_id
*)&temp
;
2606 info_gw_ip
= (union gw_addr
*)&temp
;
2607 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2610 info_eth_s_id
= &(info
->attr
->evpn_overlay
.eth_s_id
);
2611 info_gw_ip
= &(info
->attr
->evpn_overlay
.gw_ip
);
2614 info_gw_ip_remote
= (union gw_addr
*)&temp
;
2616 info_gw_ip_remote
= gw_ip
;
2617 if (eth_s_id
== NULL
)
2618 info_eth_s_id_remote
= (struct eth_segment_id
*)&temp
;
2620 info_eth_s_id_remote
= eth_s_id
;
2621 if (!memcmp(info_gw_ip
, info_gw_ip_remote
, sizeof(union gw_addr
)))
2623 return !memcmp(info_eth_s_id
, info_eth_s_id_remote
,
2624 sizeof(struct eth_segment_id
));
2627 /* Check if received nexthop is valid or not. */
2628 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2633 /* Only validated for unicast and multicast currently. */
2634 /* Also valid for EVPN where the nexthop is an IP address. */
2635 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2638 /* If NEXT_HOP is present, validate it. */
2639 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2640 if (attr
->nexthop
.s_addr
== 0
2641 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2642 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2646 /* If MP_NEXTHOP is present, validate it. */
2647 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2648 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2649 * it is not an IPv6 link-local address.
2651 if (attr
->mp_nexthop_len
) {
2652 switch (attr
->mp_nexthop_len
) {
2653 case BGP_ATTR_NHLEN_IPV4
:
2654 case BGP_ATTR_NHLEN_VPNV4
:
2655 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2656 || IPV4_CLASS_DE(ntohl(
2657 attr
->mp_nexthop_global_in
.s_addr
))
2658 || bgp_nexthop_self(bgp
,
2659 attr
->mp_nexthop_global_in
));
2662 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2663 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2664 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2665 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2666 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2667 || IN6_IS_ADDR_MULTICAST(
2668 &attr
->mp_nexthop_global
));
2680 int bgp_update(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
2681 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2682 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2683 u_int32_t num_labels
, int soft_reconfig
,
2684 struct bgp_route_evpn
*evpn
)
2687 int aspath_loop_count
= 0;
2688 struct bgp_node
*rn
;
2690 struct attr new_attr
;
2691 struct attr
*attr_new
;
2692 struct bgp_info
*ri
;
2693 struct bgp_info
*new;
2694 struct bgp_info_extra
*extra
;
2696 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2698 int do_loop_check
= 1;
2699 int has_valid_label
= 0;
2701 int vnc_implicit_withdraw
= 0;
2705 memset(&new_attr
, 0, sizeof(struct attr
));
2706 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2707 new_attr
.label
= MPLS_INVALID_LABEL
;
2710 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2711 /* TODO: Check to see if we can get rid of "is_valid_label" */
2712 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2713 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2715 has_valid_label
= bgp_is_valid_label(label
);
2717 /* When peer's soft reconfiguration enabled. Record input packet in
2720 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2721 && peer
!= bgp
->peer_self
)
2722 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2724 /* Check previously received route. */
2725 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
2726 if (ri
->peer
== peer
&& ri
->type
== type
2727 && ri
->sub_type
== sub_type
2728 && ri
->addpath_rx_id
== addpath_id
)
2731 /* AS path local-as loop check. */
2732 if (peer
->change_local_as
) {
2733 if (peer
->allowas_in
[afi
][safi
])
2734 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2735 else if (!CHECK_FLAG(peer
->flags
,
2736 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2737 aspath_loop_count
= 1;
2739 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2740 > aspath_loop_count
) {
2741 reason
= "as-path contains our own AS;";
2746 /* If the peer is configured for "allowas-in origin" and the last ASN in
2748 * as-path is our ASN then we do not need to call aspath_loop_check
2750 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2751 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2754 /* AS path loop check. */
2755 if (do_loop_check
) {
2756 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2757 > peer
->allowas_in
[afi
][safi
]
2758 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2759 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2760 > peer
->allowas_in
[afi
][safi
])) {
2761 reason
= "as-path contains our own AS;";
2766 /* Route reflector originator ID check. */
2767 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2768 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2769 reason
= "originator is us;";
2773 /* Route reflector cluster ID check. */
2774 if (bgp_cluster_filter(peer
, attr
)) {
2775 reason
= "reflected from the same cluster;";
2779 /* Apply incoming filter. */
2780 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
2785 bgp_attr_dup(&new_attr
, attr
);
2787 /* Apply incoming route-map.
2788 * NB: new_attr may now contain newly allocated values from route-map
2790 * commands, so we need bgp_attr_flush in the error paths, until we
2792 * the attr (which takes over the memory references) */
2793 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
2795 reason
= "route-map;";
2796 bgp_attr_flush(&new_attr
);
2800 if (peer
->sort
== BGP_PEER_EBGP
) {
2802 /* If we receive the graceful-shutdown community from an eBGP
2803 * peer we must lower local-preference */
2804 if (new_attr
.community
2805 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
2806 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
2807 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
2809 /* If graceful-shutdown is configured then add the GSHUT
2810 * community to all paths received from eBGP peers */
2811 } else if (bgp_flag_check(peer
->bgp
,
2812 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
2813 bgp_attr_add_gshut_community(&new_attr
);
2817 /* next hop check. */
2818 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
2819 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
2820 reason
= "martian or self next-hop;";
2821 bgp_attr_flush(&new_attr
);
2825 attr_new
= bgp_attr_intern(&new_attr
);
2827 /* If the update is implicit withdraw. */
2829 ri
->uptime
= bgp_clock();
2830 same_attr
= attrhash_cmp(ri
->attr
, attr_new
);
2832 /* Same attribute comes in. */
2833 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
2834 && attrhash_cmp(ri
->attr
, attr_new
)
2835 && (!has_valid_label
2836 || memcmp(&(bgp_info_extra_get(ri
))->label
, label
,
2837 num_labels
* sizeof(mpls_label_t
))
2839 && (overlay_index_equal(
2840 afi
, ri
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
2841 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
2842 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
2843 BGP_CONFIG_DAMPENING
)
2844 && peer
->sort
== BGP_PEER_EBGP
2845 && CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
)) {
2846 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2847 bgp_debug_rdpfxpath2str(
2848 afi
, safi
, prd
, p
, label
,
2849 num_labels
, addpath_id
? 1 : 0,
2850 addpath_id
, pfx_buf
,
2852 zlog_debug("%s rcvd %s", peer
->host
,
2856 if (bgp_damp_update(ri
, rn
, afi
, safi
)
2857 != BGP_DAMP_SUPPRESSED
) {
2858 bgp_aggregate_increment(bgp
, p
, ri
, afi
,
2860 bgp_process(bgp
, rn
, afi
, safi
);
2862 } else /* Duplicate - odd */
2864 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2865 if (!peer
->rcvd_attr_printed
) {
2867 "%s rcvd UPDATE w/ attr: %s",
2869 peer
->rcvd_attr_str
);
2870 peer
->rcvd_attr_printed
= 1;
2873 bgp_debug_rdpfxpath2str(
2874 afi
, safi
, prd
, p
, label
,
2875 num_labels
, addpath_id
? 1 : 0,
2876 addpath_id
, pfx_buf
,
2879 "%s rcvd %s...duplicate ignored",
2880 peer
->host
, pfx_buf
);
2883 /* graceful restart STALE flag unset. */
2884 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)) {
2885 bgp_info_unset_flag(rn
, ri
,
2887 bgp_process(bgp
, rn
, afi
, safi
);
2891 bgp_unlock_node(rn
);
2892 bgp_attr_unintern(&attr_new
);
2897 /* Withdraw/Announce before we fully processed the withdraw */
2898 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
2899 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2900 bgp_debug_rdpfxpath2str(
2901 afi
, safi
, prd
, p
, label
, num_labels
,
2902 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
2905 "%s rcvd %s, flapped quicker than processing",
2906 peer
->host
, pfx_buf
);
2909 bgp_info_restore(rn
, ri
);
2912 /* Received Logging. */
2913 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
2914 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
2915 num_labels
, addpath_id
? 1 : 0,
2916 addpath_id
, pfx_buf
,
2918 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
2921 /* graceful restart STALE flag unset. */
2922 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
2923 bgp_info_unset_flag(rn
, ri
, BGP_INFO_STALE
);
2925 /* The attribute is changed. */
2926 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
2928 /* implicit withdraw, decrement aggregate and pcount here.
2929 * only if update is accepted, they'll increment below.
2931 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
2933 /* Update bgp route dampening information. */
2934 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2935 && peer
->sort
== BGP_PEER_EBGP
) {
2936 /* This is implicit withdraw so we should update
2939 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
2940 bgp_damp_withdraw(ri
, rn
, afi
, safi
, 1);
2943 if (safi
== SAFI_MPLS_VPN
) {
2944 struct bgp_node
*prn
= NULL
;
2945 struct bgp_table
*table
= NULL
;
2947 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
2948 (struct prefix
*)prd
);
2950 table
= (struct bgp_table
*)(prn
->info
);
2952 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2953 bgp
, prd
, table
, p
, ri
);
2955 bgp_unlock_node(prn
);
2957 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
2958 && (safi
== SAFI_UNICAST
)) {
2959 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
2961 * Implicit withdraw case.
2963 ++vnc_implicit_withdraw
;
2964 vnc_import_bgp_del_route(bgp
, p
, ri
);
2965 vnc_import_bgp_exterior_del_route(bgp
, p
, ri
);
2970 /* Special handling for EVPN update of an existing route. If the
2971 * extended community attribute has changed, we need to
2973 * the route using its existing extended community. It will be
2974 * subsequently processed for import with the new extended
2977 if (safi
== SAFI_EVPN
&& !same_attr
) {
2979 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
2981 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
2984 cmp
= ecommunity_cmp(ri
->attr
->ecommunity
,
2985 attr_new
->ecommunity
);
2987 if (bgp_debug_update(peer
, p
, NULL
, 1))
2989 "Change in EXT-COMM, existing %s new %s",
2991 ri
->attr
->ecommunity
),
2993 attr_new
->ecommunity
));
2994 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3000 /* Update to new attribute. */
3001 bgp_attr_unintern(&ri
->attr
);
3002 ri
->attr
= attr_new
;
3004 /* Update MPLS label */
3005 if (has_valid_label
) {
3006 extra
= bgp_info_extra_get(ri
);
3007 memcpy(&extra
->label
, label
,
3008 num_labels
* sizeof(mpls_label_t
));
3009 extra
->num_labels
= num_labels
;
3010 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3011 bgp_set_valid_label(&extra
->label
[0]);
3015 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3016 && (safi
== SAFI_UNICAST
)) {
3017 if (vnc_implicit_withdraw
) {
3019 * Add back the route with its new attributes
3021 * The route is still selected, until the route
3023 * queued by bgp_process actually runs. We have
3025 * update to the VNC side immediately to avoid
3027 * configuration changes (e.g., route-map
3029 * trigger re-importation of the entire RIB.
3031 vnc_import_bgp_add_route(bgp
, p
, ri
);
3032 vnc_import_bgp_exterior_add_route(bgp
, p
, ri
);
3036 /* Update Overlay Index */
3037 if (afi
== AFI_L2VPN
) {
3038 overlay_index_update(
3039 ri
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3040 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3043 /* Update bgp route dampening information. */
3044 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3045 && peer
->sort
== BGP_PEER_EBGP
) {
3046 /* Now we do normal update dampening. */
3047 ret
= bgp_damp_update(ri
, rn
, afi
, safi
);
3048 if (ret
== BGP_DAMP_SUPPRESSED
) {
3049 bgp_unlock_node(rn
);
3054 /* Nexthop reachability check - for unicast and
3055 * labeled-unicast.. */
3056 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3057 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3058 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3059 && !CHECK_FLAG(peer
->flags
,
3060 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3062 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3067 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
3069 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3070 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3072 if (BGP_DEBUG(nht
, NHT
)) {
3073 char buf1
[INET6_ADDRSTRLEN
];
3075 (const void *)&attr_new
3077 buf1
, INET6_ADDRSTRLEN
);
3078 zlog_debug("%s(%s): NH unresolved",
3079 __FUNCTION__
, buf1
);
3081 bgp_info_unset_flag(rn
, ri
, BGP_INFO_VALID
);
3084 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
3087 if (safi
== SAFI_MPLS_VPN
) {
3088 struct bgp_node
*prn
= NULL
;
3089 struct bgp_table
*table
= NULL
;
3091 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3092 (struct prefix
*)prd
);
3094 table
= (struct bgp_table
*)(prn
->info
);
3096 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3097 bgp
, prd
, table
, p
, ri
);
3099 bgp_unlock_node(prn
);
3103 /* If this is an EVPN route and some attribute has changed,
3105 * route for import. If the extended community has changed, we
3107 * have done the un-import earlier and the import would result
3109 * route getting injected into appropriate L2 VNIs. If it is
3111 * some other attribute change, the import will result in
3113 * the attributes for the route in the VNI(s).
3115 if (safi
== SAFI_EVPN
&& !same_attr
)
3116 bgp_evpn_import_route(bgp
, afi
, safi
, p
, ri
);
3118 /* Process change. */
3119 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
3121 bgp_process(bgp
, rn
, afi
, safi
);
3122 bgp_unlock_node(rn
);
3125 if (SAFI_MPLS_VPN
== safi
) {
3126 mpls_label_t label_decoded
= decode_label(label
);
3128 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3129 type
, sub_type
, &label_decoded
);
3131 if (SAFI_ENCAP
== safi
) {
3132 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3133 type
, sub_type
, NULL
);
3138 } // End of implicit withdraw
3140 /* Received Logging. */
3141 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3142 if (!peer
->rcvd_attr_printed
) {
3143 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3144 peer
->rcvd_attr_str
);
3145 peer
->rcvd_attr_printed
= 1;
3148 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3149 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3151 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3154 /* Make new BGP info. */
3155 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3157 /* Update MPLS label */
3158 if (has_valid_label
) {
3159 extra
= bgp_info_extra_get(new);
3160 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3161 extra
->num_labels
= num_labels
;
3162 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3163 bgp_set_valid_label(&extra
->label
[0]);
3166 /* Update Overlay Index */
3167 if (afi
== AFI_L2VPN
) {
3168 overlay_index_update(new->attr
,
3169 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3170 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3172 /* Nexthop reachability check. */
3173 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3174 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3175 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3176 && !CHECK_FLAG(peer
->flags
,
3177 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3178 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3183 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, connected
)
3184 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3185 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3187 if (BGP_DEBUG(nht
, NHT
)) {
3188 char buf1
[INET6_ADDRSTRLEN
];
3190 (const void *)&attr_new
->nexthop
,
3191 buf1
, INET6_ADDRSTRLEN
);
3192 zlog_debug("%s(%s): NH unresolved",
3193 __FUNCTION__
, buf1
);
3195 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
3198 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
3201 new->addpath_rx_id
= addpath_id
;
3203 /* Increment prefix */
3204 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3206 /* Register new BGP information. */
3207 bgp_info_add(rn
, new);
3209 /* route_node_get lock */
3210 bgp_unlock_node(rn
);
3213 if (safi
== SAFI_MPLS_VPN
) {
3214 struct bgp_node
*prn
= NULL
;
3215 struct bgp_table
*table
= NULL
;
3217 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3219 table
= (struct bgp_table
*)(prn
->info
);
3221 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3222 bgp
, prd
, table
, p
, new);
3224 bgp_unlock_node(prn
);
3228 /* If maximum prefix count is configured and current prefix
3230 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3233 /* If this is an EVPN route, process for import. */
3234 if (safi
== SAFI_EVPN
)
3235 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3237 /* Process change. */
3238 bgp_process(bgp
, rn
, afi
, safi
);
3241 if (SAFI_MPLS_VPN
== safi
) {
3242 mpls_label_t label_decoded
= decode_label(label
);
3244 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3245 sub_type
, &label_decoded
);
3247 if (SAFI_ENCAP
== safi
) {
3248 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3255 /* This BGP update is filtered. Log the reason then update BGP
3258 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3259 if (!peer
->rcvd_attr_printed
) {
3260 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3261 peer
->rcvd_attr_str
);
3262 peer
->rcvd_attr_printed
= 1;
3265 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3266 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3268 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3269 peer
->host
, pfx_buf
, reason
);
3273 /* If this is an EVPN route, un-import it as it is now filtered.
3275 if (safi
== SAFI_EVPN
)
3276 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, ri
);
3278 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3281 bgp_unlock_node(rn
);
3285 * Filtered update is treated as an implicit withdrawal (see
3287 * a few lines above)
3289 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3290 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3298 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, u_int32_t addpath_id
,
3299 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3300 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3301 u_int32_t num_labels
, struct bgp_route_evpn
*evpn
)
3304 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3305 struct bgp_node
*rn
;
3306 struct bgp_info
*ri
;
3309 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3310 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3318 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3320 /* If peer is soft reconfiguration enabled. Record input packet for
3321 * further calculation.
3323 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3324 * routes that are filtered. This tanks out Quagga RS pretty badly due
3326 * the iteration over all RS clients.
3327 * Since we need to remove the entry from adj_in anyway, do that first
3329 * if there was no entry, we don't need to do anything more.
3331 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3332 && peer
!= bgp
->peer_self
)
3333 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3334 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3335 bgp_debug_rdpfxpath2str(
3336 afi
, safi
, prd
, p
, label
, num_labels
,
3337 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3340 "%s withdrawing route %s not in adj-in",
3341 peer
->host
, pfx_buf
);
3343 bgp_unlock_node(rn
);
3347 /* Lookup withdrawn route. */
3348 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
3349 if (ri
->peer
== peer
&& ri
->type
== type
3350 && ri
->sub_type
== sub_type
3351 && ri
->addpath_rx_id
== addpath_id
)
3355 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3356 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3357 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3359 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3363 /* Withdraw specified route from routing table. */
3364 if (ri
&& !CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
3365 bgp_rib_withdraw(rn
, ri
, peer
, afi
, safi
, prd
);
3366 else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3367 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3368 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3370 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3373 /* Unlock bgp_node_get() lock. */
3374 bgp_unlock_node(rn
);
3379 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3382 struct update_subgroup
*subgrp
;
3383 subgrp
= peer_subgroup(peer
, afi
, safi
);
3384 subgroup_default_originate(subgrp
, withdraw
);
3389 * bgp_stop_announce_route_timer
3391 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3393 if (!paf
->t_announce_route
)
3396 THREAD_TIMER_OFF(paf
->t_announce_route
);
3400 * bgp_announce_route_timer_expired
3402 * Callback that is invoked when the route announcement timer for a
3405 static int bgp_announce_route_timer_expired(struct thread
*t
)
3407 struct peer_af
*paf
;
3410 paf
= THREAD_ARG(t
);
3413 if (peer
->status
!= Established
)
3416 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3419 peer_af_announce_route(paf
, 1);
3424 * bgp_announce_route
3426 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3428 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3430 struct peer_af
*paf
;
3431 struct update_subgroup
*subgrp
;
3433 paf
= peer_af_find(peer
, afi
, safi
);
3436 subgrp
= PAF_SUBGRP(paf
);
3439 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3440 * or a refresh has already been triggered.
3442 if (!subgrp
|| paf
->t_announce_route
)
3446 * Start a timer to stagger/delay the announce. This serves
3447 * two purposes - announcement can potentially be combined for
3448 * multiple peers and the announcement doesn't happen in the
3451 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3452 (subgrp
->peer_count
== 1)
3453 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3454 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3455 &paf
->t_announce_route
);
3459 * Announce routes from all AF tables to a peer.
3461 * This should ONLY be called when there is a need to refresh the
3462 * routes to the peer based on a policy change for this peer alone
3463 * or a route refresh request received from the peer.
3464 * The operation will result in splitting the peer from its existing
3465 * subgroups and putting it in new subgroups.
3467 void bgp_announce_route_all(struct peer
*peer
)
3472 FOREACH_AFI_SAFI (afi
, safi
)
3473 bgp_announce_route(peer
, afi
, safi
);
3476 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3477 struct bgp_table
*table
,
3478 struct prefix_rd
*prd
)
3481 struct bgp_node
*rn
;
3482 struct bgp_adj_in
*ain
;
3485 table
= peer
->bgp
->rib
[afi
][safi
];
3487 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3488 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3489 if (ain
->peer
!= peer
)
3492 struct bgp_info
*ri
= rn
->info
;
3493 u_int32_t num_labels
= 0;
3494 mpls_label_t
*label_pnt
= NULL
;
3496 if (ri
&& ri
->extra
)
3497 num_labels
= ri
->extra
->num_labels
;
3499 label_pnt
= &ri
->extra
->label
[0];
3501 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3502 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3503 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3504 num_labels
, 1, NULL
);
3507 bgp_unlock_node(rn
);
3513 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3515 struct bgp_node
*rn
;
3516 struct bgp_table
*table
;
3518 if (peer
->status
!= Established
)
3521 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3522 && (safi
!= SAFI_EVPN
))
3523 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3525 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3526 rn
= bgp_route_next(rn
))
3527 if ((table
= rn
->info
) != NULL
) {
3528 struct prefix_rd prd
;
3529 prd
.family
= AF_UNSPEC
;
3531 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3533 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3539 struct bgp_clear_node_queue
{
3540 struct bgp_node
*rn
;
3543 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3545 struct bgp_clear_node_queue
*cnq
= data
;
3546 struct bgp_node
*rn
= cnq
->rn
;
3547 struct peer
*peer
= wq
->spec
.data
;
3548 struct bgp_info
*ri
;
3549 afi_t afi
= bgp_node_table(rn
)->afi
;
3550 safi_t safi
= bgp_node_table(rn
)->safi
;
3554 /* It is possible that we have multiple paths for a prefix from a peer
3555 * if that peer is using AddPath.
3557 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3558 if (ri
->peer
!= peer
)
3561 /* graceful restart STALE flag set. */
3562 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3563 && peer
->nsf
[afi
][safi
]
3564 && !CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
)
3565 && !CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
3566 bgp_info_set_flag(rn
, ri
, BGP_INFO_STALE
);
3568 /* If this is an EVPN route, process for
3570 if (safi
== SAFI_EVPN
)
3571 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
,
3573 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3579 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3581 struct bgp_clear_node_queue
*cnq
= data
;
3582 struct bgp_node
*rn
= cnq
->rn
;
3583 struct bgp_table
*table
= bgp_node_table(rn
);
3585 bgp_unlock_node(rn
);
3586 bgp_table_unlock(table
);
3587 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3590 static void bgp_clear_node_complete(struct work_queue
*wq
)
3592 struct peer
*peer
= wq
->spec
.data
;
3594 /* Tickle FSM to start moving again */
3595 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3597 peer_unlock(peer
); /* bgp_clear_route */
3600 static void bgp_clear_node_queue_init(struct peer
*peer
)
3602 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3604 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3605 #undef CLEAR_QUEUE_NAME_LEN
3607 if ((peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
))
3609 zlog_err("%s: Failed to allocate work queue", __func__
);
3612 peer
->clear_node_queue
->spec
.hold
= 10;
3613 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3614 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3615 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3616 peer
->clear_node_queue
->spec
.max_retries
= 0;
3618 /* we only 'lock' this peer reference when the queue is actually active
3620 peer
->clear_node_queue
->spec
.data
= peer
;
3623 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3624 struct bgp_table
*table
)
3626 struct bgp_node
*rn
;
3627 int force
= bm
->process_main_queue
? 0 : 1;
3630 table
= peer
->bgp
->rib
[afi
][safi
];
3632 /* If still no table => afi/safi isn't configured at all or smth. */
3636 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3637 struct bgp_info
*ri
, *next
;
3638 struct bgp_adj_in
*ain
;
3639 struct bgp_adj_in
*ain_next
;
3641 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3642 * queued for every clearing peer, regardless of whether it is
3643 * relevant to the peer at hand.
3645 * Overview: There are 3 different indices which need to be
3646 * scrubbed, potentially, when a peer is removed:
3648 * 1 peer's routes visible via the RIB (ie accepted routes)
3649 * 2 peer's routes visible by the (optional) peer's adj-in index
3650 * 3 other routes visible by the peer's adj-out index
3652 * 3 there is no hurry in scrubbing, once the struct peer is
3653 * removed from bgp->peer, we could just GC such deleted peer's
3654 * adj-outs at our leisure.
3656 * 1 and 2 must be 'scrubbed' in some way, at least made
3657 * invisible via RIB index before peer session is allowed to be
3658 * brought back up. So one needs to know when such a 'search' is
3663 * - there'd be a single global queue or a single RIB walker
3664 * - rather than tracking which route_nodes still need to be
3665 * examined on a peer basis, we'd track which peers still
3668 * Given that our per-peer prefix-counts now should be reliable,
3669 * this may actually be achievable. It doesn't seem to be a huge
3670 * problem at this time,
3672 * It is possible that we have multiple paths for a prefix from
3674 * if that peer is using AddPath.
3678 ain_next
= ain
->next
;
3680 if (ain
->peer
== peer
) {
3681 bgp_adj_in_remove(rn
, ain
);
3682 bgp_unlock_node(rn
);
3688 for (ri
= rn
->info
; ri
; ri
= next
) {
3690 if (ri
->peer
!= peer
)
3694 bgp_info_reap(rn
, ri
);
3696 struct bgp_clear_node_queue
*cnq
;
3698 /* both unlocked in bgp_clear_node_queue_del */
3699 bgp_table_lock(bgp_node_table(rn
));
3702 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3703 sizeof(struct bgp_clear_node_queue
));
3705 work_queue_add(peer
->clear_node_queue
, cnq
);
3713 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3715 struct bgp_node
*rn
;
3716 struct bgp_table
*table
;
3718 if (peer
->clear_node_queue
== NULL
)
3719 bgp_clear_node_queue_init(peer
);
3721 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
3722 * Idle until it receives a Clearing_Completed event. This protects
3723 * against peers which flap faster than we can we clear, which could
3726 * a) race with routes from the new session being installed before
3727 * clear_route_node visits the node (to delete the route of that
3729 * b) resource exhaustion, clear_route_node likely leads to an entry
3730 * on the process_main queue. Fast-flapping could cause that queue
3734 /* lock peer in assumption that clear-node-queue will get nodes; if so,
3735 * the unlock will happen upon work-queue completion; other wise, the
3736 * unlock happens at the end of this function.
3738 if (!peer
->clear_node_queue
->thread
)
3741 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
3742 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
3744 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3745 rn
= bgp_route_next(rn
))
3746 if ((table
= rn
->info
) != NULL
)
3747 bgp_clear_route_table(peer
, afi
, safi
, table
);
3749 /* unlock if no nodes got added to the clear-node-queue. */
3750 if (!peer
->clear_node_queue
->thread
)
3754 void bgp_clear_route_all(struct peer
*peer
)
3759 FOREACH_AFI_SAFI (afi
, safi
)
3760 bgp_clear_route(peer
, afi
, safi
);
3763 rfapiProcessPeerDown(peer
);
3767 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3769 struct bgp_table
*table
;
3770 struct bgp_node
*rn
;
3771 struct bgp_adj_in
*ain
;
3772 struct bgp_adj_in
*ain_next
;
3774 table
= peer
->bgp
->rib
[afi
][safi
];
3776 /* It is possible that we have multiple paths for a prefix from a peer
3777 * if that peer is using AddPath.
3779 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3783 ain_next
= ain
->next
;
3785 if (ain
->peer
== peer
) {
3786 bgp_adj_in_remove(rn
, ain
);
3787 bgp_unlock_node(rn
);
3795 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3797 struct bgp_node
*rn
;
3798 struct bgp_info
*ri
;
3799 struct bgp_table
*table
;
3801 if (safi
== SAFI_MPLS_VPN
) {
3802 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3803 rn
= bgp_route_next(rn
)) {
3804 struct bgp_node
*rm
;
3805 struct bgp_info
*ri
;
3807 /* look for neighbor in tables */
3808 if ((table
= rn
->info
) == NULL
)
3811 for (rm
= bgp_table_top(table
); rm
;
3812 rm
= bgp_route_next(rm
))
3813 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
3814 if (ri
->peer
!= peer
)
3816 if (!CHECK_FLAG(ri
->flags
,
3820 bgp_rib_remove(rm
, ri
, peer
, afi
, safi
);
3825 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3826 rn
= bgp_route_next(rn
))
3827 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
3828 if (ri
->peer
!= peer
)
3830 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
3832 bgp_rib_remove(rn
, ri
, peer
, afi
, safi
);
3838 static void bgp_cleanup_table(struct bgp_table
*table
, safi_t safi
)
3840 struct bgp_node
*rn
;
3841 struct bgp_info
*ri
;
3842 struct bgp_info
*next
;
3844 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3845 for (ri
= rn
->info
; ri
; ri
= next
) {
3847 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)
3848 && ri
->type
== ZEBRA_ROUTE_BGP
3849 && (ri
->sub_type
== BGP_ROUTE_NORMAL
3850 || ri
->sub_type
== BGP_ROUTE_AGGREGATE
)) {
3851 if (bgp_fibupd_safi(safi
))
3852 bgp_zebra_withdraw(&rn
->p
, ri
, safi
);
3853 bgp_info_reap(rn
, ri
);
3858 /* Delete all kernel routes. */
3859 void bgp_cleanup_routes(struct bgp
*bgp
)
3862 struct bgp_node
*rn
;
3864 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
3865 if (afi
== AFI_L2VPN
)
3867 bgp_cleanup_table(bgp
->rib
[afi
][SAFI_UNICAST
], SAFI_UNICAST
);
3869 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
3871 if (afi
!= AFI_L2VPN
) {
3873 safi
= SAFI_MPLS_VPN
;
3874 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3875 rn
= bgp_route_next(rn
)) {
3878 (struct bgp_table
*)(rn
->info
),
3880 bgp_table_finish((struct bgp_table
**)&(
3883 bgp_unlock_node(rn
);
3887 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
3888 rn
= bgp_route_next(rn
)) {
3891 (struct bgp_table
*)(rn
->info
),
3893 bgp_table_finish((struct bgp_table
**)&(
3896 bgp_unlock_node(rn
);
3901 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
3902 rn
= bgp_route_next(rn
)) {
3904 bgp_cleanup_table((struct bgp_table
*)(rn
->info
),
3906 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
3908 bgp_unlock_node(rn
);
3913 void bgp_reset(void)
3916 bgp_zclient_reset();
3917 access_list_reset();
3918 prefix_list_reset();
3921 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
3923 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
3924 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
3925 PEER_CAP_ADDPATH_AF_TX_RCV
));
3928 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
3930 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
3931 struct bgp_nlri
*packet
)
3940 int addpath_encoded
;
3941 u_int32_t addpath_id
;
3943 /* Check peer status. */
3944 if (peer
->status
!= Established
)
3948 lim
= pnt
+ packet
->length
;
3950 safi
= packet
->safi
;
3952 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
3954 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
3955 syntactic validity. If the field is syntactically incorrect,
3956 then the Error Subcode is set to Invalid Network Field. */
3957 for (; pnt
< lim
; pnt
+= psize
) {
3958 /* Clear prefix structure. */
3959 memset(&p
, 0, sizeof(struct prefix
));
3961 if (addpath_encoded
) {
3963 /* When packet overflow occurs return immediately. */
3964 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
3967 addpath_id
= ntohl(*((uint32_t *)pnt
));
3968 pnt
+= BGP_ADDPATH_ID_LEN
;
3971 /* Fetch prefix length. */
3972 p
.prefixlen
= *pnt
++;
3973 /* afi/safi validity already verified by caller,
3974 * bgp_update_receive */
3975 p
.family
= afi2family(afi
);
3977 /* Prefix length check. */
3978 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
3980 "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
3981 peer
->host
, p
.prefixlen
, packet
->afi
);
3985 /* Packet size overflow check. */
3986 psize
= PSIZE(p
.prefixlen
);
3988 /* When packet overflow occur return immediately. */
3989 if (pnt
+ psize
> lim
) {
3991 "%s [Error] Update packet error (prefix length %d overflows packet)",
3992 peer
->host
, p
.prefixlen
);
3996 /* Defensive coding, double-check the psize fits in a struct
3998 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4000 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4001 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4005 /* Fetch prefix from NLRI packet. */
4006 memcpy(&p
.u
.prefix
, pnt
, psize
);
4008 /* Check address. */
4009 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4010 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4011 /* From RFC4271 Section 6.3:
4013 * If a prefix in the NLRI field is semantically
4015 * (e.g., an unexpected multicast IP address),
4017 * be logged locally, and the prefix SHOULD be
4021 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4022 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4027 /* Check address. */
4028 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4029 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4033 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4035 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4040 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4044 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4046 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4053 /* Normal process. */
4055 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4056 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4057 NULL
, NULL
, 0, 0, NULL
);
4059 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4060 safi
, ZEBRA_ROUTE_BGP
,
4061 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4064 /* Address family configuration mismatch or maximum-prefix count
4070 /* Packet length consistency check. */
4073 "%s [Error] Update packet error (prefix length mismatch with total length)",
4081 static struct bgp_static
*bgp_static_new(void)
4083 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4086 static void bgp_static_free(struct bgp_static
*bgp_static
)
4088 if (bgp_static
->rmap
.name
)
4089 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4090 if (bgp_static
->eth_s_id
)
4091 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4092 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4095 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4096 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4098 struct bgp_node
*rn
;
4099 struct bgp_info
*ri
;
4100 struct bgp_info
*new;
4101 struct bgp_info info
;
4103 struct attr
*attr_new
;
4106 int vnc_implicit_withdraw
= 0;
4113 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4115 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4117 attr
.nexthop
= bgp_static
->igpnexthop
;
4118 attr
.med
= bgp_static
->igpmetric
;
4119 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4121 if (bgp_static
->atomic
)
4122 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4124 /* Store label index, if required. */
4125 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4126 attr
.label_index
= bgp_static
->label_index
;
4127 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4130 /* Apply route-map. */
4131 if (bgp_static
->rmap
.name
) {
4132 struct attr attr_tmp
= attr
;
4133 info
.peer
= bgp
->peer_self
;
4134 info
.attr
= &attr_tmp
;
4136 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4138 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4140 bgp
->peer_self
->rmap_type
= 0;
4142 if (ret
== RMAP_DENYMATCH
) {
4143 /* Free uninterned attribute. */
4144 bgp_attr_flush(&attr_tmp
);
4146 /* Unintern original. */
4147 aspath_unintern(&attr
.aspath
);
4148 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4152 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4153 bgp_attr_add_gshut_community(&attr_tmp
);
4155 attr_new
= bgp_attr_intern(&attr_tmp
);
4158 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4159 bgp_attr_add_gshut_community(&attr
);
4161 attr_new
= bgp_attr_intern(&attr
);
4164 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4165 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4166 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4170 if (attrhash_cmp(ri
->attr
, attr_new
)
4171 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)
4172 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4173 bgp_unlock_node(rn
);
4174 bgp_attr_unintern(&attr_new
);
4175 aspath_unintern(&attr
.aspath
);
4178 /* The attribute is changed. */
4179 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4181 /* Rewrite BGP route information. */
4182 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4183 bgp_info_restore(rn
, ri
);
4185 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4187 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4188 && (safi
== SAFI_UNICAST
)) {
4189 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
4191 * Implicit withdraw case.
4192 * We have to do this before ri is
4195 ++vnc_implicit_withdraw
;
4196 vnc_import_bgp_del_route(bgp
, p
, ri
);
4197 vnc_import_bgp_exterior_del_route(
4202 bgp_attr_unintern(&ri
->attr
);
4203 ri
->attr
= attr_new
;
4204 ri
->uptime
= bgp_clock();
4206 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4207 && (safi
== SAFI_UNICAST
)) {
4208 if (vnc_implicit_withdraw
) {
4209 vnc_import_bgp_add_route(bgp
, p
, ri
);
4210 vnc_import_bgp_exterior_add_route(
4216 /* Nexthop reachability check. */
4217 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4218 && (safi
== SAFI_UNICAST
4219 || safi
== SAFI_LABELED_UNICAST
)) {
4220 if (bgp_find_or_add_nexthop(bgp
, afi
, ri
, NULL
,
4222 bgp_info_set_flag(rn
, ri
,
4225 if (BGP_DEBUG(nht
, NHT
)) {
4226 char buf1
[INET6_ADDRSTRLEN
];
4227 inet_ntop(p
->family
,
4231 "%s(%s): Route not in table, not advertising",
4232 __FUNCTION__
, buf1
);
4234 bgp_info_unset_flag(rn
, ri
,
4238 /* Delete the NHT structure if any, if we're
4240 * enabling/disabling import check. We
4241 * deregister the route
4242 * from NHT to avoid overloading NHT and the
4243 * process interaction
4245 bgp_unlink_nexthop(ri
);
4246 bgp_info_set_flag(rn
, ri
, BGP_INFO_VALID
);
4248 /* Process change. */
4249 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4250 bgp_process(bgp
, rn
, afi
, safi
);
4251 bgp_unlock_node(rn
);
4252 aspath_unintern(&attr
.aspath
);
4257 /* Make new BGP info. */
4258 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4260 /* Nexthop reachability check. */
4261 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4262 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4263 if (bgp_find_or_add_nexthop(bgp
, afi
, new, NULL
, 0))
4264 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4266 if (BGP_DEBUG(nht
, NHT
)) {
4267 char buf1
[INET6_ADDRSTRLEN
];
4268 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4271 "%s(%s): Route not in table, not advertising",
4272 __FUNCTION__
, buf1
);
4274 bgp_info_unset_flag(rn
, new, BGP_INFO_VALID
);
4277 /* Delete the NHT structure if any, if we're toggling between
4278 * enabling/disabling import check. We deregister the route
4279 * from NHT to avoid overloading NHT and the process interaction
4281 bgp_unlink_nexthop(new);
4283 bgp_info_set_flag(rn
, new, BGP_INFO_VALID
);
4286 /* Aggregate address increment. */
4287 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4289 /* Register new BGP information. */
4290 bgp_info_add(rn
, new);
4292 /* route_node_get lock */
4293 bgp_unlock_node(rn
);
4295 /* Process change. */
4296 bgp_process(bgp
, rn
, afi
, safi
);
4298 /* Unintern original. */
4299 aspath_unintern(&attr
.aspath
);
4302 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4305 struct bgp_node
*rn
;
4306 struct bgp_info
*ri
;
4308 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4310 /* Check selected route and self inserted route. */
4311 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4312 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4313 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4316 /* Withdraw static BGP route from routing table. */
4318 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4319 bgp_unlink_nexthop(ri
);
4320 bgp_info_delete(rn
, ri
);
4321 bgp_process(bgp
, rn
, afi
, safi
);
4324 /* Unlock bgp_node_lookup. */
4325 bgp_unlock_node(rn
);
4329 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4331 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4332 afi_t afi
, safi_t safi
,
4333 struct prefix_rd
*prd
)
4335 struct bgp_node
*rn
;
4336 struct bgp_info
*ri
;
4338 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4340 /* Check selected route and self inserted route. */
4341 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4342 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4343 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4346 /* Withdraw static BGP route from routing table. */
4349 rfapiProcessWithdraw(
4350 ri
->peer
, NULL
, p
, prd
, ri
->attr
, afi
, safi
, ri
->type
,
4351 1); /* Kill, since it is an administrative change */
4353 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4354 bgp_info_delete(rn
, ri
);
4355 bgp_process(bgp
, rn
, afi
, safi
);
4358 /* Unlock bgp_node_lookup. */
4359 bgp_unlock_node(rn
);
4362 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4363 struct bgp_static
*bgp_static
, afi_t afi
,
4366 struct bgp_node
*rn
;
4367 struct bgp_info
*new;
4368 struct attr
*attr_new
;
4369 struct attr attr
= {0};
4370 struct bgp_info
*ri
;
4372 mpls_label_t label
= 0;
4374 u_int32_t num_labels
= 0;
4379 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4381 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4384 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4386 attr
.nexthop
= bgp_static
->igpnexthop
;
4387 attr
.med
= bgp_static
->igpmetric
;
4388 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4390 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4391 || (safi
== SAFI_ENCAP
)) {
4392 if (afi
== AFI_IP
) {
4393 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4394 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4397 if (afi
== AFI_L2VPN
) {
4398 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4400 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4401 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4402 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4403 sizeof(struct in6_addr
));
4404 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4405 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4406 struct bgp_encap_type_vxlan bet
;
4407 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4408 bet
.vnid
= p
->u
.prefix_evpn
.eth_tag
;
4409 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4411 if (bgp_static
->router_mac
) {
4412 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4415 /* Apply route-map. */
4416 if (bgp_static
->rmap
.name
) {
4417 struct attr attr_tmp
= attr
;
4418 struct bgp_info info
;
4421 info
.peer
= bgp
->peer_self
;
4422 info
.attr
= &attr_tmp
;
4424 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4426 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
, &info
);
4428 bgp
->peer_self
->rmap_type
= 0;
4430 if (ret
== RMAP_DENYMATCH
) {
4431 /* Free uninterned attribute. */
4432 bgp_attr_flush(&attr_tmp
);
4434 /* Unintern original. */
4435 aspath_unintern(&attr
.aspath
);
4436 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4441 attr_new
= bgp_attr_intern(&attr_tmp
);
4443 attr_new
= bgp_attr_intern(&attr
);
4446 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
4447 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
4448 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4453 memset(&add
, 0, sizeof(union gw_addr
));
4454 if (attrhash_cmp(ri
->attr
, attr_new
)
4455 && overlay_index_equal(afi
, ri
, bgp_static
->eth_s_id
, &add
)
4456 && !CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
)) {
4457 bgp_unlock_node(rn
);
4458 bgp_attr_unintern(&attr_new
);
4459 aspath_unintern(&attr
.aspath
);
4462 /* The attribute is changed. */
4463 bgp_info_set_flag(rn
, ri
, BGP_INFO_ATTR_CHANGED
);
4465 /* Rewrite BGP route information. */
4466 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
4467 bgp_info_restore(rn
, ri
);
4469 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, safi
);
4470 bgp_attr_unintern(&ri
->attr
);
4471 ri
->attr
= attr_new
;
4472 ri
->uptime
= bgp_clock();
4475 label
= decode_label(&ri
->extra
->label
[0]);
4478 /* Process change. */
4479 bgp_aggregate_increment(bgp
, p
, ri
, afi
, safi
);
4480 bgp_process(bgp
, rn
, afi
, safi
);
4482 rfapiProcessUpdate(ri
->peer
, NULL
, p
, &bgp_static
->prd
,
4483 ri
->attr
, afi
, safi
, ri
->type
,
4484 ri
->sub_type
, &label
);
4486 bgp_unlock_node(rn
);
4487 aspath_unintern(&attr
.aspath
);
4493 /* Make new BGP info. */
4494 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4496 SET_FLAG(new->flags
, BGP_INFO_VALID
);
4497 new->extra
= bgp_info_extra_new();
4499 new->extra
->label
[0] = bgp_static
->label
;
4500 new->extra
->num_labels
= num_labels
;
4503 label
= decode_label(&bgp_static
->label
);
4506 /* Aggregate address increment. */
4507 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4509 /* Register new BGP information. */
4510 bgp_info_add(rn
, new);
4511 /* route_node_get lock */
4512 bgp_unlock_node(rn
);
4514 /* Process change. */
4515 bgp_process(bgp
, rn
, afi
, safi
);
4518 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4519 safi
, new->type
, new->sub_type
, &label
);
4522 /* Unintern original. */
4523 aspath_unintern(&attr
.aspath
);
4526 /* Configure static BGP network. When user don't run zebra, static
4527 route should be installed as valid. */
4528 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4529 const char *ip_str
, afi_t afi
, safi_t safi
,
4530 const char *rmap
, int backdoor
, u_int32_t label_index
)
4532 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4535 struct bgp_static
*bgp_static
;
4536 struct bgp_node
*rn
;
4537 u_char need_update
= 0;
4539 /* Convert IP prefix string to struct prefix. */
4540 ret
= str2prefix(ip_str
, &p
);
4542 vty_out(vty
, "%% Malformed prefix\n");
4543 return CMD_WARNING_CONFIG_FAILED
;
4545 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4546 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4547 return CMD_WARNING_CONFIG_FAILED
;
4554 /* Set BGP static route configuration. */
4555 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4558 vty_out(vty
, "%% Can't find static route specified\n");
4559 return CMD_WARNING_CONFIG_FAILED
;
4562 bgp_static
= rn
->info
;
4564 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4565 && (label_index
!= bgp_static
->label_index
)) {
4567 "%% label-index doesn't match static route\n");
4568 return CMD_WARNING_CONFIG_FAILED
;
4571 if ((rmap
&& bgp_static
->rmap
.name
)
4572 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4574 "%% route-map name doesn't match static route\n");
4575 return CMD_WARNING_CONFIG_FAILED
;
4578 /* Update BGP RIB. */
4579 if (!bgp_static
->backdoor
)
4580 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4582 /* Clear configuration. */
4583 bgp_static_free(bgp_static
);
4585 bgp_unlock_node(rn
);
4586 bgp_unlock_node(rn
);
4589 /* Set BGP static route configuration. */
4590 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4593 /* Configuration change. */
4594 bgp_static
= rn
->info
;
4596 /* Label index cannot be changed. */
4597 if (bgp_static
->label_index
!= label_index
) {
4598 vty_out(vty
, "%% cannot change label-index\n");
4599 return CMD_WARNING_CONFIG_FAILED
;
4602 /* Check previous routes are installed into BGP. */
4603 if (bgp_static
->valid
4604 && bgp_static
->backdoor
!= backdoor
)
4607 bgp_static
->backdoor
= backdoor
;
4610 if (bgp_static
->rmap
.name
)
4611 XFREE(MTYPE_ROUTE_MAP_NAME
,
4612 bgp_static
->rmap
.name
);
4613 bgp_static
->rmap
.name
=
4614 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4615 bgp_static
->rmap
.map
=
4616 route_map_lookup_by_name(rmap
);
4618 if (bgp_static
->rmap
.name
)
4619 XFREE(MTYPE_ROUTE_MAP_NAME
,
4620 bgp_static
->rmap
.name
);
4621 bgp_static
->rmap
.name
= NULL
;
4622 bgp_static
->rmap
.map
= NULL
;
4623 bgp_static
->valid
= 0;
4625 bgp_unlock_node(rn
);
4627 /* New configuration. */
4628 bgp_static
= bgp_static_new();
4629 bgp_static
->backdoor
= backdoor
;
4630 bgp_static
->valid
= 0;
4631 bgp_static
->igpmetric
= 0;
4632 bgp_static
->igpnexthop
.s_addr
= 0;
4633 bgp_static
->label_index
= label_index
;
4636 if (bgp_static
->rmap
.name
)
4637 XFREE(MTYPE_ROUTE_MAP_NAME
,
4638 bgp_static
->rmap
.name
);
4639 bgp_static
->rmap
.name
=
4640 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4641 bgp_static
->rmap
.map
=
4642 route_map_lookup_by_name(rmap
);
4644 rn
->info
= bgp_static
;
4647 bgp_static
->valid
= 1;
4649 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4651 if (!bgp_static
->backdoor
)
4652 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4658 void bgp_static_add(struct bgp
*bgp
)
4662 struct bgp_node
*rn
;
4663 struct bgp_node
*rm
;
4664 struct bgp_table
*table
;
4665 struct bgp_static
*bgp_static
;
4667 FOREACH_AFI_SAFI (afi
, safi
)
4668 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4669 rn
= bgp_route_next(rn
)) {
4670 if (rn
->info
== NULL
)
4673 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4674 || (safi
== SAFI_EVPN
)) {
4677 for (rm
= bgp_table_top(table
); rm
;
4678 rm
= bgp_route_next(rm
)) {
4679 bgp_static
= rm
->info
;
4680 bgp_static_update_safi(bgp
, &rm
->p
,
4685 bgp_static_update(bgp
, &rn
->p
, rn
->info
, afi
,
4691 /* Called from bgp_delete(). Delete all static routes from the BGP
4693 void bgp_static_delete(struct bgp
*bgp
)
4697 struct bgp_node
*rn
;
4698 struct bgp_node
*rm
;
4699 struct bgp_table
*table
;
4700 struct bgp_static
*bgp_static
;
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_withdraw_safi(
4716 bgp
, &rm
->p
, AFI_IP
, safi
,
4717 (struct prefix_rd
*)&rn
->p
);
4718 bgp_static_free(bgp_static
);
4720 bgp_unlock_node(rn
);
4723 bgp_static
= rn
->info
;
4724 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
4725 bgp_static_free(bgp_static
);
4727 bgp_unlock_node(rn
);
4732 void bgp_static_redo_import_check(struct bgp
*bgp
)
4736 struct bgp_node
*rn
;
4737 struct bgp_node
*rm
;
4738 struct bgp_table
*table
;
4739 struct bgp_static
*bgp_static
;
4741 /* Use this flag to force reprocessing of the route */
4742 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4743 FOREACH_AFI_SAFI (afi
, safi
) {
4744 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
4745 rn
= bgp_route_next(rn
)) {
4746 if (rn
->info
== NULL
)
4749 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
4750 || (safi
== SAFI_EVPN
)) {
4753 for (rm
= bgp_table_top(table
); rm
;
4754 rm
= bgp_route_next(rm
)) {
4755 bgp_static
= rm
->info
;
4756 bgp_static_update_safi(bgp
, &rm
->p
,
4761 bgp_static
= rn
->info
;
4762 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
4767 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
4770 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
4773 struct bgp_table
*table
;
4774 struct bgp_node
*rn
;
4775 struct bgp_info
*ri
;
4777 table
= bgp
->rib
[afi
][safi
];
4778 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4779 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
4780 if (ri
->peer
== bgp
->peer_self
4781 && ((ri
->type
== ZEBRA_ROUTE_BGP
4782 && ri
->sub_type
== BGP_ROUTE_STATIC
)
4783 || (ri
->type
!= ZEBRA_ROUTE_BGP
4785 == BGP_ROUTE_REDISTRIBUTE
))) {
4786 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
4788 bgp_unlink_nexthop(ri
);
4789 bgp_info_delete(rn
, ri
);
4790 bgp_process(bgp
, rn
, afi
, safi
);
4797 * Purge all networks and redistributed routes from routing table.
4798 * Invoked upon the instance going down.
4800 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
4805 FOREACH_AFI_SAFI (afi
, safi
)
4806 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
4811 * Currently this is used to set static routes for VPN and ENCAP.
4812 * I think it can probably be factored with bgp_static_set.
4814 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4815 const char *ip_str
, const char *rd_str
,
4816 const char *label_str
, const char *rmap_str
,
4817 int evpn_type
, const char *esi
, const char *gwip
,
4818 const char *ethtag
, const char *routermac
)
4820 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4823 struct prefix_rd prd
;
4824 struct bgp_node
*prn
;
4825 struct bgp_node
*rn
;
4826 struct bgp_table
*table
;
4827 struct bgp_static
*bgp_static
;
4828 mpls_label_t label
= MPLS_INVALID_LABEL
;
4829 struct prefix gw_ip
;
4831 /* validate ip prefix */
4832 ret
= str2prefix(ip_str
, &p
);
4834 vty_out(vty
, "%% Malformed prefix\n");
4835 return CMD_WARNING_CONFIG_FAILED
;
4838 if ((afi
== AFI_L2VPN
)
4839 && (bgp_build_evpn_prefix(evpn_type
,
4840 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4841 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4842 return CMD_WARNING_CONFIG_FAILED
;
4845 ret
= str2prefix_rd(rd_str
, &prd
);
4847 vty_out(vty
, "%% Malformed rd\n");
4848 return CMD_WARNING_CONFIG_FAILED
;
4852 unsigned long label_val
;
4853 label_val
= strtoul(label_str
, NULL
, 10);
4854 encode_label(label_val
, &label
);
4857 if (safi
== SAFI_EVPN
) {
4858 if (esi
&& str2esi(esi
, NULL
) == 0) {
4859 vty_out(vty
, "%% Malformed ESI\n");
4860 return CMD_WARNING_CONFIG_FAILED
;
4862 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
4863 vty_out(vty
, "%% Malformed Router MAC\n");
4864 return CMD_WARNING_CONFIG_FAILED
;
4867 memset(&gw_ip
, 0, sizeof(struct prefix
));
4868 ret
= str2prefix(gwip
, &gw_ip
);
4870 vty_out(vty
, "%% Malformed GatewayIp\n");
4871 return CMD_WARNING_CONFIG_FAILED
;
4873 if ((gw_ip
.family
== AF_INET
4874 && IS_EVPN_PREFIX_IPADDR_V6(
4875 (struct prefix_evpn
*)&p
))
4876 || (gw_ip
.family
== AF_INET6
4877 && IS_EVPN_PREFIX_IPADDR_V4(
4878 (struct prefix_evpn
*)&p
))) {
4880 "%% GatewayIp family differs with IP prefix\n");
4881 return CMD_WARNING_CONFIG_FAILED
;
4885 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4886 if (prn
->info
== NULL
)
4887 prn
->info
= bgp_table_init(afi
, safi
);
4889 bgp_unlock_node(prn
);
4892 rn
= bgp_node_get(table
, &p
);
4895 vty_out(vty
, "%% Same network configuration exists\n");
4896 bgp_unlock_node(rn
);
4898 /* New configuration. */
4899 bgp_static
= bgp_static_new();
4900 bgp_static
->backdoor
= 0;
4901 bgp_static
->valid
= 0;
4902 bgp_static
->igpmetric
= 0;
4903 bgp_static
->igpnexthop
.s_addr
= 0;
4904 bgp_static
->label
= label
;
4905 bgp_static
->prd
= prd
;
4908 if (bgp_static
->rmap
.name
)
4909 XFREE(MTYPE_ROUTE_MAP_NAME
,
4910 bgp_static
->rmap
.name
);
4911 bgp_static
->rmap
.name
=
4912 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
4913 bgp_static
->rmap
.map
=
4914 route_map_lookup_by_name(rmap_str
);
4917 if (safi
== SAFI_EVPN
) {
4919 bgp_static
->eth_s_id
=
4921 sizeof(struct eth_segment_id
));
4922 str2esi(esi
, bgp_static
->eth_s_id
);
4925 bgp_static
->router_mac
=
4926 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
4927 prefix_str2mac(routermac
,
4928 bgp_static
->router_mac
);
4931 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
4933 rn
->info
= bgp_static
;
4935 bgp_static
->valid
= 1;
4936 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
4942 /* Configure static BGP network. */
4943 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
4944 const char *ip_str
, const char *rd_str
,
4945 const char *label_str
, int evpn_type
, const char *esi
,
4946 const char *gwip
, const char *ethtag
)
4948 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4951 struct prefix_rd prd
;
4952 struct bgp_node
*prn
;
4953 struct bgp_node
*rn
;
4954 struct bgp_table
*table
;
4955 struct bgp_static
*bgp_static
;
4956 mpls_label_t label
= MPLS_INVALID_LABEL
;
4958 /* Convert IP prefix string to struct prefix. */
4959 ret
= str2prefix(ip_str
, &p
);
4961 vty_out(vty
, "%% Malformed prefix\n");
4962 return CMD_WARNING_CONFIG_FAILED
;
4965 if ((afi
== AFI_L2VPN
)
4966 && (bgp_build_evpn_prefix(evpn_type
,
4967 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
4968 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
4969 return CMD_WARNING_CONFIG_FAILED
;
4971 ret
= str2prefix_rd(rd_str
, &prd
);
4973 vty_out(vty
, "%% Malformed rd\n");
4974 return CMD_WARNING_CONFIG_FAILED
;
4978 unsigned long label_val
;
4979 label_val
= strtoul(label_str
, NULL
, 10);
4980 encode_label(label_val
, &label
);
4983 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
4984 if (prn
->info
== NULL
)
4985 prn
->info
= bgp_table_init(afi
, safi
);
4987 bgp_unlock_node(prn
);
4990 rn
= bgp_node_lookup(table
, &p
);
4993 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
4995 bgp_static
= rn
->info
;
4996 bgp_static_free(bgp_static
);
4998 bgp_unlock_node(rn
);
4999 bgp_unlock_node(rn
);
5001 vty_out(vty
, "%% Can't find the route\n");
5006 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5007 const char *rmap_name
)
5009 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5010 struct bgp_rmap
*rmap
;
5012 rmap
= &bgp
->table_map
[afi
][safi
];
5015 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5016 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5017 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5020 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5025 if (bgp_fibupd_safi(safi
))
5026 bgp_zebra_announce_table(bgp
, afi
, safi
);
5031 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5032 const char *rmap_name
)
5034 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5035 struct bgp_rmap
*rmap
;
5037 rmap
= &bgp
->table_map
[afi
][safi
];
5039 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5043 if (bgp_fibupd_safi(safi
))
5044 bgp_zebra_announce_table(bgp
, afi
, safi
);
5049 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5052 if (bgp
->table_map
[afi
][safi
].name
) {
5053 vty_out(vty
, " table-map %s\n",
5054 bgp
->table_map
[afi
][safi
].name
);
5058 DEFUN (bgp_table_map
,
5061 "BGP table to RIB route download filter\n"
5062 "Name of the route map\n")
5065 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5066 argv
[idx_word
]->arg
);
5068 DEFUN (no_bgp_table_map
,
5069 no_bgp_table_map_cmd
,
5070 "no table-map WORD",
5072 "BGP table to RIB route download filter\n"
5073 "Name of the route map\n")
5076 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5077 argv
[idx_word
]->arg
);
5083 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5084 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5085 backdoor$backdoor}]",
5087 "Specify a network to announce via BGP\n"
5092 "Route-map to modify the attributes\n"
5093 "Name of the route map\n"
5094 "Label index to associate with the prefix\n"
5095 "Label index value\n"
5096 "Specify a BGP backdoor route\n")
5098 char addr_prefix_str
[BUFSIZ
];
5103 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5106 vty_out(vty
, "%% Inconsistent address and mask\n");
5107 return CMD_WARNING_CONFIG_FAILED
;
5111 return bgp_static_set(
5112 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5113 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5114 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5117 DEFPY(ipv6_bgp_network
,
5118 ipv6_bgp_network_cmd
,
5119 "[no] network X:X::X:X/M$prefix \
5120 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5122 "Specify a network to announce via BGP\n"
5124 "Route-map to modify the attributes\n"
5125 "Name of the route map\n"
5126 "Label index to associate with the prefix\n"
5127 "Label index value\n")
5129 return bgp_static_set(
5130 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5131 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5134 /* Aggreagete address:
5136 advertise-map Set condition to advertise attribute
5137 as-set Generate AS set path information
5138 attribute-map Set attributes of aggregate
5139 route-map Set parameters of aggregate
5140 summary-only Filter more specific routes from updates
5141 suppress-map Conditionally filter more specific routes from updates
5144 struct bgp_aggregate
{
5145 /* Summary-only flag. */
5146 u_char summary_only
;
5148 /* AS set generation. */
5151 /* Route-map for aggregated route. */
5152 struct route_map
*map
;
5154 /* Suppress-count. */
5155 unsigned long count
;
5157 /* SAFI configuration. */
5161 static struct bgp_aggregate
*bgp_aggregate_new(void)
5163 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5166 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5168 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5171 /* Update an aggregate as routes are added/removed from the BGP table */
5172 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5173 struct bgp_info
*rinew
, afi_t afi
, safi_t safi
,
5174 struct bgp_info
*del
,
5175 struct bgp_aggregate
*aggregate
)
5177 struct bgp_table
*table
;
5178 struct bgp_node
*top
;
5179 struct bgp_node
*rn
;
5181 struct aspath
*aspath
= NULL
;
5182 struct aspath
*asmerge
= NULL
;
5183 struct community
*community
= NULL
;
5184 struct community
*commerge
= NULL
;
5185 #if defined(AGGREGATE_NEXTHOP_CHECK)
5186 struct in_addr nexthop
;
5189 struct bgp_info
*ri
;
5190 struct bgp_info
*new;
5192 unsigned long match
= 0;
5193 u_char atomic_aggregate
= 0;
5195 /* Record adding route's nexthop and med. */
5197 #if defined(AGGREGATE_NEXTHOP_CHECK)
5198 nexthop
= rinew
->attr
->nexthop
;
5199 med
= rinew
->attr
->med
;
5203 /* ORIGIN attribute: If at least one route among routes that are
5204 aggregated has ORIGIN with the value INCOMPLETE, then the
5205 aggregated route must have the ORIGIN attribute with the value
5206 INCOMPLETE. Otherwise, if at least one route among routes that
5207 are aggregated has ORIGIN with the value EGP, then the aggregated
5208 route must have the origin attribute with the value EGP. In all
5209 other case the value of the ORIGIN attribute of the aggregated
5210 route is INTERNAL. */
5211 origin
= BGP_ORIGIN_IGP
;
5213 table
= bgp
->rib
[afi
][safi
];
5215 top
= bgp_node_get(table
, p
);
5216 for (rn
= bgp_node_get(table
, p
); rn
;
5217 rn
= bgp_route_next_until(rn
, top
))
5218 if (rn
->p
.prefixlen
> p
->prefixlen
) {
5221 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5222 if (BGP_INFO_HOLDDOWN(ri
))
5225 if (del
&& ri
== del
)
5228 if (!rinew
&& first
) {
5229 #if defined(AGGREGATE_NEXTHOP_CHECK)
5230 nexthop
= ri
->attr
->nexthop
;
5231 med
= ri
->attr
->med
;
5236 #ifdef AGGREGATE_NEXTHOP_CHECK
5237 if (!IPV4_ADDR_SAME(&ri
->attr
->nexthop
,
5239 || ri
->attr
->med
!= med
) {
5241 aspath_free(aspath
);
5243 community_free(community
);
5244 bgp_unlock_node(rn
);
5245 bgp_unlock_node(top
);
5248 #endif /* AGGREGATE_NEXTHOP_CHECK */
5251 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5252 atomic_aggregate
= 1;
5254 if (ri
->sub_type
!= BGP_ROUTE_AGGREGATE
) {
5255 if (aggregate
->summary_only
) {
5256 (bgp_info_extra_get(ri
))
5260 BGP_INFO_ATTR_CHANGED
);
5266 if (origin
< ri
->attr
->origin
)
5267 origin
= ri
->attr
->origin
;
5269 if (aggregate
->as_set
) {
5271 asmerge
= aspath_aggregate(
5274 aspath_free(aspath
);
5277 aspath
= aspath_dup(
5280 if (ri
->attr
->community
) {
5282 commerge
= community_merge(
5284 ri
->attr
->community
);
5285 community
= community_uniq_sort(
5290 community
= community_dup(
5291 ri
->attr
->community
);
5297 bgp_process(bgp
, rn
, afi
, safi
);
5299 bgp_unlock_node(top
);
5304 if (aggregate
->summary_only
)
5305 (bgp_info_extra_get(rinew
))->suppress
++;
5307 if (origin
< rinew
->attr
->origin
)
5308 origin
= rinew
->attr
->origin
;
5310 if (aggregate
->as_set
) {
5312 asmerge
= aspath_aggregate(aspath
,
5313 rinew
->attr
->aspath
);
5314 aspath_free(aspath
);
5317 aspath
= aspath_dup(rinew
->attr
->aspath
);
5319 if (rinew
->attr
->community
) {
5321 commerge
= community_merge(
5323 rinew
->attr
->community
);
5325 community_uniq_sort(commerge
);
5326 community_free(commerge
);
5328 community
= community_dup(
5329 rinew
->attr
->community
);
5334 if (aggregate
->count
> 0) {
5335 rn
= bgp_node_get(table
, p
);
5337 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5338 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5339 community
, aggregate
->as_set
,
5342 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5344 bgp_info_add(rn
, new);
5345 bgp_unlock_node(rn
);
5346 bgp_process(bgp
, rn
, afi
, safi
);
5349 aspath_free(aspath
);
5351 community_free(community
);
5355 void bgp_aggregate_delete(struct bgp
*, struct prefix
*, afi_t
, safi_t
,
5356 struct bgp_aggregate
*);
5358 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5359 struct bgp_info
*ri
, afi_t afi
, safi_t safi
)
5361 struct bgp_node
*child
;
5362 struct bgp_node
*rn
;
5363 struct bgp_aggregate
*aggregate
;
5364 struct bgp_table
*table
;
5366 /* MPLS-VPN aggregation is not yet supported. */
5367 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5368 || (safi
== SAFI_EVPN
))
5371 table
= bgp
->aggregate
[afi
][safi
];
5373 /* No aggregates configured. */
5374 if (bgp_table_top_nolock(table
) == NULL
)
5377 if (p
->prefixlen
== 0)
5380 if (BGP_INFO_HOLDDOWN(ri
))
5383 child
= bgp_node_get(table
, p
);
5385 /* Aggregate address configuration check. */
5386 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5387 if ((aggregate
= rn
->info
) != NULL
5388 && rn
->p
.prefixlen
< p
->prefixlen
) {
5389 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5390 bgp_aggregate_route(bgp
, &rn
->p
, ri
, afi
, safi
, NULL
,
5393 bgp_unlock_node(child
);
5396 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5397 struct bgp_info
*del
, afi_t afi
, safi_t safi
)
5399 struct bgp_node
*child
;
5400 struct bgp_node
*rn
;
5401 struct bgp_aggregate
*aggregate
;
5402 struct bgp_table
*table
;
5404 /* MPLS-VPN aggregation is not yet supported. */
5405 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5406 || (safi
== SAFI_EVPN
))
5409 table
= bgp
->aggregate
[afi
][safi
];
5411 /* No aggregates configured. */
5412 if (bgp_table_top_nolock(table
) == NULL
)
5415 if (p
->prefixlen
== 0)
5418 child
= bgp_node_get(table
, p
);
5420 /* Aggregate address configuration check. */
5421 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
))
5422 if ((aggregate
= rn
->info
) != NULL
5423 && rn
->p
.prefixlen
< p
->prefixlen
) {
5424 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5425 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5428 bgp_unlock_node(child
);
5431 /* Called via bgp_aggregate_set when the user configures aggregate-address */
5432 static void bgp_aggregate_add(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5433 safi_t safi
, struct bgp_aggregate
*aggregate
)
5435 struct bgp_table
*table
;
5436 struct bgp_node
*top
;
5437 struct bgp_node
*rn
;
5438 struct bgp_info
*new;
5439 struct bgp_info
*ri
;
5440 unsigned long match
;
5441 u_char origin
= BGP_ORIGIN_IGP
;
5442 struct aspath
*aspath
= NULL
;
5443 struct aspath
*asmerge
= NULL
;
5444 struct community
*community
= NULL
;
5445 struct community
*commerge
= NULL
;
5446 u_char atomic_aggregate
= 0;
5448 table
= bgp
->rib
[afi
][safi
];
5451 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5453 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5456 /* If routes exists below this node, generate aggregate routes. */
5457 top
= bgp_node_get(table
, p
);
5458 for (rn
= bgp_node_get(table
, p
); rn
;
5459 rn
= bgp_route_next_until(rn
, top
)) {
5460 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5465 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5466 if (BGP_INFO_HOLDDOWN(ri
))
5470 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5471 atomic_aggregate
= 1;
5473 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5476 /* summary-only aggregate route suppress
5477 * aggregated route announcement. */
5478 if (aggregate
->summary_only
) {
5479 (bgp_info_extra_get(ri
))->suppress
++;
5480 bgp_info_set_flag(rn
, ri
,
5481 BGP_INFO_ATTR_CHANGED
);
5485 /* If at least one route among routes that are
5486 * aggregated has ORIGIN with the value INCOMPLETE,
5487 * then the aggregated route MUST have the ORIGIN
5488 * attribute with the value INCOMPLETE. Otherwise, if
5489 * at least one route among routes that are aggregated
5490 * has ORIGIN with the value EGP, then the aggregated
5491 * route MUST have the ORIGIN attribute with the value
5494 if (origin
< ri
->attr
->origin
)
5495 origin
= ri
->attr
->origin
;
5497 /* as-set aggregate route generate origin, as path,
5498 * community aggregation. */
5499 if (aggregate
->as_set
) {
5501 asmerge
= aspath_aggregate(
5502 aspath
, ri
->attr
->aspath
);
5503 aspath_free(aspath
);
5506 aspath
= aspath_dup(ri
->attr
->aspath
);
5508 if (ri
->attr
->community
) {
5510 commerge
= community_merge(
5512 ri
->attr
->community
);
5513 community
= community_uniq_sort(
5515 community_free(commerge
);
5517 community
= community_dup(
5518 ri
->attr
->community
);
5524 /* If this node is suppressed, process the change. */
5526 bgp_process(bgp
, rn
, afi
, safi
);
5528 bgp_unlock_node(top
);
5530 /* Add aggregate route to BGP table. */
5531 if (aggregate
->count
) {
5532 rn
= bgp_node_get(table
, p
);
5534 ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0, bgp
->peer_self
,
5535 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5536 community
, aggregate
->as_set
,
5539 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5541 bgp_info_add(rn
, new);
5542 bgp_unlock_node(rn
);
5544 /* Process change. */
5545 bgp_process(bgp
, rn
, afi
, safi
);
5548 aspath_free(aspath
);
5550 community_free(community
);
5554 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5555 safi_t safi
, struct bgp_aggregate
*aggregate
)
5557 struct bgp_table
*table
;
5558 struct bgp_node
*top
;
5559 struct bgp_node
*rn
;
5560 struct bgp_info
*ri
;
5561 unsigned long match
;
5563 table
= bgp
->rib
[afi
][safi
];
5565 if (afi
== AFI_IP
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
5567 if (afi
== AFI_IP6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)
5570 /* If routes exists below this node, generate aggregate routes. */
5571 top
= bgp_node_get(table
, p
);
5572 for (rn
= bgp_node_get(table
, p
); rn
;
5573 rn
= bgp_route_next_until(rn
, top
)) {
5574 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5578 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
5579 if (BGP_INFO_HOLDDOWN(ri
))
5582 if (ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5585 if (aggregate
->summary_only
&& ri
->extra
) {
5586 ri
->extra
->suppress
--;
5588 if (ri
->extra
->suppress
== 0) {
5590 rn
, ri
, BGP_INFO_ATTR_CHANGED
);
5597 /* If this node was suppressed, process the change. */
5599 bgp_process(bgp
, rn
, afi
, safi
);
5601 bgp_unlock_node(top
);
5603 /* Delete aggregate route from BGP table. */
5604 rn
= bgp_node_get(table
, p
);
5606 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
5607 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== ZEBRA_ROUTE_BGP
5608 && ri
->sub_type
== BGP_ROUTE_AGGREGATE
)
5611 /* Withdraw static BGP route from routing table. */
5613 bgp_info_delete(rn
, ri
);
5614 bgp_process(bgp
, rn
, afi
, safi
);
5617 /* Unlock bgp_node_lookup. */
5618 bgp_unlock_node(rn
);
5621 /* Aggregate route attribute. */
5622 #define AGGREGATE_SUMMARY_ONLY 1
5623 #define AGGREGATE_AS_SET 1
5625 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5626 afi_t afi
, safi_t safi
)
5628 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5631 struct bgp_node
*rn
;
5632 struct bgp_aggregate
*aggregate
;
5634 /* Convert string to prefix structure. */
5635 ret
= str2prefix(prefix_str
, &p
);
5637 vty_out(vty
, "Malformed prefix\n");
5638 return CMD_WARNING_CONFIG_FAILED
;
5642 /* Old configuration check. */
5643 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5646 "%% There is no aggregate-address configuration.\n");
5647 return CMD_WARNING_CONFIG_FAILED
;
5650 aggregate
= rn
->info
;
5651 if (aggregate
->safi
== SAFI_UNICAST
)
5652 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5653 if (aggregate
->safi
== SAFI_LABELED_UNICAST
)
5654 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5656 if (aggregate
->safi
== SAFI_MULTICAST
)
5657 bgp_aggregate_delete(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5659 /* Unlock aggregate address configuration. */
5661 bgp_aggregate_free(aggregate
);
5662 bgp_unlock_node(rn
);
5663 bgp_unlock_node(rn
);
5668 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5669 safi_t safi
, u_char summary_only
, u_char as_set
)
5671 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5674 struct bgp_node
*rn
;
5675 struct bgp_aggregate
*aggregate
;
5677 /* Convert string to prefix structure. */
5678 ret
= str2prefix(prefix_str
, &p
);
5680 vty_out(vty
, "Malformed prefix\n");
5681 return CMD_WARNING_CONFIG_FAILED
;
5685 /* Old configuration check. */
5686 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
5689 vty_out(vty
, "There is already same aggregate network.\n");
5690 /* try to remove the old entry */
5691 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
5693 vty_out(vty
, "Error deleting aggregate.\n");
5694 bgp_unlock_node(rn
);
5695 return CMD_WARNING_CONFIG_FAILED
;
5699 /* Make aggregate address structure. */
5700 aggregate
= bgp_aggregate_new();
5701 aggregate
->summary_only
= summary_only
;
5702 aggregate
->as_set
= as_set
;
5703 aggregate
->safi
= safi
;
5704 rn
->info
= aggregate
;
5706 /* Aggregate address insert into BGP routing table. */
5707 if (safi
== SAFI_UNICAST
)
5708 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_UNICAST
, aggregate
);
5709 if (safi
== SAFI_LABELED_UNICAST
)
5710 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_LABELED_UNICAST
,
5712 if (safi
== SAFI_MULTICAST
)
5713 bgp_aggregate_add(bgp
, &p
, afi
, SAFI_MULTICAST
, aggregate
);
5718 DEFUN (aggregate_address
,
5719 aggregate_address_cmd
,
5720 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5721 "Configure BGP aggregate entries\n"
5722 "Aggregate prefix\n"
5723 "Generate AS set path information\n"
5724 "Filter more specific routes from updates\n"
5725 "Filter more specific routes from updates\n"
5726 "Generate AS set path information\n")
5729 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5730 char *prefix
= argv
[idx
]->arg
;
5732 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5734 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5735 ? AGGREGATE_SUMMARY_ONLY
5738 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
5739 summary_only
, as_set
);
5742 DEFUN (aggregate_address_mask
,
5743 aggregate_address_mask_cmd
,
5744 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5745 "Configure BGP aggregate entries\n"
5746 "Aggregate address\n"
5748 "Generate AS set path information\n"
5749 "Filter more specific routes from updates\n"
5750 "Filter more specific routes from updates\n"
5751 "Generate AS set path information\n")
5754 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5755 char *prefix
= argv
[idx
]->arg
;
5756 char *mask
= argv
[idx
+ 1]->arg
;
5758 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
5760 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5761 ? AGGREGATE_SUMMARY_ONLY
5764 char prefix_str
[BUFSIZ
];
5765 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5768 vty_out(vty
, "%% Inconsistent address and mask\n");
5769 return CMD_WARNING_CONFIG_FAILED
;
5772 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
5773 summary_only
, as_set
);
5776 DEFUN (no_aggregate_address
,
5777 no_aggregate_address_cmd
,
5778 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
5780 "Configure BGP aggregate entries\n"
5781 "Aggregate prefix\n"
5782 "Generate AS set path information\n"
5783 "Filter more specific routes from updates\n"
5784 "Filter more specific routes from updates\n"
5785 "Generate AS set path information\n")
5788 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
5789 char *prefix
= argv
[idx
]->arg
;
5790 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
5793 DEFUN (no_aggregate_address_mask
,
5794 no_aggregate_address_mask_cmd
,
5795 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
5797 "Configure BGP aggregate entries\n"
5798 "Aggregate address\n"
5800 "Generate AS set path information\n"
5801 "Filter more specific routes from updates\n"
5802 "Filter more specific routes from updates\n"
5803 "Generate AS set path information\n")
5806 argv_find(argv
, argc
, "A.B.C.D", &idx
);
5807 char *prefix
= argv
[idx
]->arg
;
5808 char *mask
= argv
[idx
+ 1]->arg
;
5810 char prefix_str
[BUFSIZ
];
5811 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
5814 vty_out(vty
, "%% Inconsistent address and mask\n");
5815 return CMD_WARNING_CONFIG_FAILED
;
5818 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
5821 DEFUN (ipv6_aggregate_address
,
5822 ipv6_aggregate_address_cmd
,
5823 "aggregate-address X:X::X:X/M [summary-only]",
5824 "Configure BGP aggregate entries\n"
5825 "Aggregate prefix\n"
5826 "Filter more specific routes from updates\n")
5829 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
5830 char *prefix
= argv
[idx
]->arg
;
5831 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
5832 ? AGGREGATE_SUMMARY_ONLY
5834 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
5838 DEFUN (no_ipv6_aggregate_address
,
5839 no_ipv6_aggregate_address_cmd
,
5840 "no aggregate-address X:X::X:X/M [summary-only]",
5842 "Configure BGP aggregate entries\n"
5843 "Aggregate prefix\n"
5844 "Filter more specific routes from updates\n")
5847 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
5848 char *prefix
= argv
[idx
]->arg
;
5849 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
5852 /* Redistribute route treatment. */
5853 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
5854 const union g_addr
*nexthop
, ifindex_t ifindex
,
5855 enum nexthop_types_t nhtype
, uint32_t metric
,
5856 u_char type
, u_short instance
, route_tag_t tag
)
5858 struct bgp_info
*new;
5859 struct bgp_info
*bi
;
5860 struct bgp_info info
;
5861 struct bgp_node
*bn
;
5863 struct attr
*new_attr
;
5866 struct bgp_redist
*red
;
5868 /* Make default attribute. */
5869 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
5872 case NEXTHOP_TYPE_IFINDEX
:
5874 case NEXTHOP_TYPE_IPV4
:
5875 case NEXTHOP_TYPE_IPV4_IFINDEX
:
5876 attr
.nexthop
= nexthop
->ipv4
;
5878 case NEXTHOP_TYPE_IPV6
:
5879 case NEXTHOP_TYPE_IPV6_IFINDEX
:
5880 attr
.mp_nexthop_global
= nexthop
->ipv6
;
5881 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
5883 case NEXTHOP_TYPE_BLACKHOLE
:
5884 switch (p
->family
) {
5886 attr
.nexthop
.s_addr
= INADDR_ANY
;
5889 memset(&attr
.mp_nexthop_global
, 0,
5890 sizeof(attr
.mp_nexthop_global
));
5891 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
5896 attr
.nh_ifindex
= ifindex
;
5899 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
5902 afi
= family2afi(p
->family
);
5904 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
5906 struct attr attr_new
;
5908 /* Copy attribute for modification. */
5909 bgp_attr_dup(&attr_new
, &attr
);
5911 if (red
->redist_metric_flag
)
5912 attr_new
.med
= red
->redist_metric
;
5914 /* Apply route-map. */
5915 if (red
->rmap
.name
) {
5916 info
.peer
= bgp
->peer_self
;
5917 info
.attr
= &attr_new
;
5919 SET_FLAG(bgp
->peer_self
->rmap_type
,
5920 PEER_RMAP_TYPE_REDISTRIBUTE
);
5922 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
5925 bgp
->peer_self
->rmap_type
= 0;
5927 if (ret
== RMAP_DENYMATCH
) {
5928 /* Free uninterned attribute. */
5929 bgp_attr_flush(&attr_new
);
5931 /* Unintern original. */
5932 aspath_unintern(&attr
.aspath
);
5933 bgp_redistribute_delete(bgp
, p
, type
, instance
);
5938 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
5939 bgp_attr_add_gshut_community(&attr_new
);
5941 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
5942 SAFI_UNICAST
, p
, NULL
);
5944 new_attr
= bgp_attr_intern(&attr_new
);
5946 for (bi
= bn
->info
; bi
; bi
= bi
->next
)
5947 if (bi
->peer
== bgp
->peer_self
5948 && bi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
5952 /* Ensure the (source route) type is updated. */
5954 if (attrhash_cmp(bi
->attr
, new_attr
)
5955 && !CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
)) {
5956 bgp_attr_unintern(&new_attr
);
5957 aspath_unintern(&attr
.aspath
);
5958 bgp_unlock_node(bn
);
5961 /* The attribute is changed. */
5962 bgp_info_set_flag(bn
, bi
,
5963 BGP_INFO_ATTR_CHANGED
);
5965 /* Rewrite BGP route information. */
5966 if (CHECK_FLAG(bi
->flags
, BGP_INFO_REMOVED
))
5967 bgp_info_restore(bn
, bi
);
5969 bgp_aggregate_decrement(bgp
, p
, bi
, afi
,
5971 bgp_attr_unintern(&bi
->attr
);
5972 bi
->attr
= new_attr
;
5973 bi
->uptime
= bgp_clock();
5975 /* Process change. */
5976 bgp_aggregate_increment(bgp
, p
, bi
, afi
,
5978 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
5979 bgp_unlock_node(bn
);
5980 aspath_unintern(&attr
.aspath
);
5985 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
5986 bgp
->peer_self
, new_attr
, bn
);
5987 SET_FLAG(new->flags
, BGP_INFO_VALID
);
5989 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
5990 bgp_info_add(bn
, new);
5991 bgp_unlock_node(bn
);
5992 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
5995 /* Unintern original. */
5996 aspath_unintern(&attr
.aspath
);
5999 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, u_char type
,
6003 struct bgp_node
*rn
;
6004 struct bgp_info
*ri
;
6005 struct bgp_redist
*red
;
6007 afi
= family2afi(p
->family
);
6009 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6011 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6012 SAFI_UNICAST
, p
, NULL
);
6014 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6015 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
)
6019 bgp_aggregate_decrement(bgp
, p
, ri
, afi
, SAFI_UNICAST
);
6020 bgp_info_delete(rn
, ri
);
6021 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6023 bgp_unlock_node(rn
);
6027 /* Withdraw specified route type's route. */
6028 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6031 struct bgp_node
*rn
;
6032 struct bgp_info
*ri
;
6033 struct bgp_table
*table
;
6035 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6037 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6038 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
6039 if (ri
->peer
== bgp
->peer_self
&& ri
->type
== type
6040 && ri
->instance
== instance
)
6044 bgp_aggregate_decrement(bgp
, &rn
->p
, ri
, afi
,
6046 bgp_info_delete(rn
, ri
);
6047 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6052 /* Static function to display route. */
6053 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6057 u_int32_t destination
;
6060 if (p
->family
== AF_INET
) {
6062 len
= vty_out(vty
, "%s",
6063 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
6065 destination
= ntohl(p
->u
.prefix4
.s_addr
);
6067 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
6068 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
6069 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
6070 || p
->u
.prefix4
.s_addr
== 0) {
6071 /* When mask is natural,
6072 mask is not displayed. */
6074 len
+= vty_out(vty
, "/%d", p
->prefixlen
);
6076 json_object_string_add(json
, "prefix",
6077 inet_ntop(p
->family
,
6080 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6082 } else if (p
->family
== AF_ETHERNET
) {
6083 prefix2str(p
, buf
, PREFIX_STRLEN
);
6084 len
= vty_out(vty
, "%s", buf
);
6085 } else if (p
->family
== AF_EVPN
) {
6086 #if defined(HAVE_CUMULUS)
6090 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6093 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6095 prefix2str(p
, buf
, PREFIX_STRLEN
);
6096 len
= vty_out(vty
, "%s", buf
);
6102 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6109 vty_out(vty
, "\n%*s", 20, " ");
6111 vty_out(vty
, "%*s", len
, " ");
6115 enum bgp_display_type
{
6119 /* Print the short form route status for a bgp_info */
6120 static void route_vty_short_status_out(struct vty
*vty
, struct bgp_info
*binfo
,
6121 json_object
*json_path
)
6125 /* Route status display. */
6126 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6127 json_object_boolean_true_add(json_path
, "removed");
6129 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6130 json_object_boolean_true_add(json_path
, "stale");
6132 if (binfo
->extra
&& binfo
->extra
->suppress
)
6133 json_object_boolean_true_add(json_path
, "suppressed");
6135 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6136 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6137 json_object_boolean_true_add(json_path
, "valid");
6140 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6141 json_object_boolean_true_add(json_path
, "history");
6143 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6144 json_object_boolean_true_add(json_path
, "damped");
6146 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6147 json_object_boolean_true_add(json_path
, "bestpath");
6149 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6150 json_object_boolean_true_add(json_path
, "multipath");
6152 /* Internal route. */
6153 if ((binfo
->peer
->as
)
6154 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6155 json_object_string_add(json_path
, "pathFrom",
6158 json_object_string_add(json_path
, "pathFrom",
6164 /* Route status display. */
6165 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
))
6167 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
))
6169 else if (binfo
->extra
&& binfo
->extra
->suppress
)
6171 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)
6172 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6178 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
))
6180 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
))
6182 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
))
6184 else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
))
6189 /* Internal route. */
6190 if (binfo
->peer
&& (binfo
->peer
->as
)
6191 && (binfo
->peer
->as
== binfo
->peer
->local_as
))
6197 /* called from terminal list command */
6198 void route_vty_out(struct vty
*vty
, struct prefix
*p
, struct bgp_info
*binfo
,
6199 int display
, safi_t safi
, json_object
*json_paths
)
6202 json_object
*json_path
= NULL
;
6203 json_object
*json_nexthops
= NULL
;
6204 json_object
*json_nexthop_global
= NULL
;
6205 json_object
*json_nexthop_ll
= NULL
;
6208 json_path
= json_object_new_object();
6210 /* short status lead text */
6211 route_vty_short_status_out(vty
, binfo
, json_path
);
6214 /* print prefix and mask */
6216 route_vty_out_route(p
, vty
, json_path
);
6218 vty_out(vty
, "%*s", 17, " ");
6220 route_vty_out_route(p
, vty
, json_path
);
6223 /* Print attribute */
6227 json_object_array_add(json_paths
, json_path
);
6235 * For ENCAP and EVPN routes, nexthop address family is not
6236 * neccessarily the same as the prefix address family.
6237 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6238 * EVPN routes are also exchanged with a MP nexthop. Currently,
6240 * is only IPv4, the value will be present in either
6242 * attr->mp_nexthop_global_in
6244 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6247 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6251 sprintf(nexthop
, "%s",
6252 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6256 sprintf(nexthop
, "%s",
6257 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6261 sprintf(nexthop
, "?");
6266 json_nexthop_global
= json_object_new_object();
6268 json_object_string_add(json_nexthop_global
, "afi",
6269 (af
== AF_INET
) ? "ip" : "ipv6");
6270 json_object_string_add(json_nexthop_global
,
6271 (af
== AF_INET
) ? "ip" : "ipv6",
6273 json_object_boolean_true_add(json_nexthop_global
,
6276 vty_out(vty
, "%s", nexthop
);
6277 } else if (safi
== SAFI_EVPN
) {
6279 json_nexthop_global
= json_object_new_object();
6281 json_object_string_add(json_nexthop_global
, "ip",
6282 inet_ntoa(attr
->nexthop
));
6283 json_object_string_add(json_nexthop_global
, "afi",
6285 json_object_boolean_true_add(json_nexthop_global
,
6288 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6291 else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6293 json_nexthop_global
= json_object_new_object();
6295 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6296 json_object_string_add(
6297 json_nexthop_global
, "ip",
6298 inet_ntoa(attr
->mp_nexthop_global_in
));
6300 json_object_string_add(
6301 json_nexthop_global
, "ip",
6302 inet_ntoa(attr
->nexthop
));
6304 json_object_string_add(json_nexthop_global
, "afi",
6306 json_object_boolean_true_add(json_nexthop_global
,
6309 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6310 vty_out(vty
, "%-16s",
6311 inet_ntoa(attr
->mp_nexthop_global_in
));
6313 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6318 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6323 json_nexthop_global
= json_object_new_object();
6324 json_object_string_add(
6325 json_nexthop_global
, "ip",
6326 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6328 json_object_string_add(json_nexthop_global
, "afi",
6330 json_object_string_add(json_nexthop_global
, "scope",
6333 /* We display both LL & GL if both have been
6335 if ((attr
->mp_nexthop_len
== 32)
6336 || (binfo
->peer
->conf_if
)) {
6337 json_nexthop_ll
= json_object_new_object();
6338 json_object_string_add(
6339 json_nexthop_ll
, "ip",
6341 &attr
->mp_nexthop_local
, buf
,
6343 json_object_string_add(json_nexthop_ll
, "afi",
6345 json_object_string_add(json_nexthop_ll
, "scope",
6348 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6349 &attr
->mp_nexthop_local
)
6351 && !attr
->mp_nexthop_prefer_global
)
6352 json_object_boolean_true_add(
6353 json_nexthop_ll
, "used");
6355 json_object_boolean_true_add(
6356 json_nexthop_global
, "used");
6358 json_object_boolean_true_add(
6359 json_nexthop_global
, "used");
6361 /* Display LL if LL/Global both in table unless
6362 * prefer-global is set */
6363 if (((attr
->mp_nexthop_len
== 32)
6364 && !attr
->mp_nexthop_prefer_global
)
6365 || (binfo
->peer
->conf_if
)) {
6366 if (binfo
->peer
->conf_if
) {
6367 len
= vty_out(vty
, "%s",
6368 binfo
->peer
->conf_if
);
6369 len
= 16 - len
; /* len of IPv6
6375 vty_out(vty
, "\n%*s", 36, " ");
6377 vty_out(vty
, "%*s", len
, " ");
6383 &attr
->mp_nexthop_local
,
6388 vty_out(vty
, "\n%*s", 36, " ");
6390 vty_out(vty
, "%*s", len
, " ");
6396 &attr
->mp_nexthop_global
, buf
,
6401 vty_out(vty
, "\n%*s", 36, " ");
6403 vty_out(vty
, "%*s", len
, " ");
6409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6411 json_object_int_add(json_path
, "med", attr
->med
);
6413 vty_out(vty
, "%10u", attr
->med
);
6414 else if (!json_paths
)
6418 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6420 json_object_int_add(json_path
, "localpref",
6423 vty_out(vty
, "%7u", attr
->local_pref
);
6424 else if (!json_paths
)
6428 json_object_int_add(json_path
, "weight", attr
->weight
);
6430 vty_out(vty
, "%7u ", attr
->weight
);
6434 json_object_string_add(
6435 json_path
, "peerId",
6436 sockunion2str(&binfo
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6442 json_object_string_add(json_path
, "aspath",
6445 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6450 json_object_string_add(json_path
, "origin",
6451 bgp_origin_long_str
[attr
->origin
]);
6453 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6456 if (json_nexthop_global
|| json_nexthop_ll
) {
6457 json_nexthops
= json_object_new_array();
6459 if (json_nexthop_global
)
6460 json_object_array_add(json_nexthops
,
6461 json_nexthop_global
);
6463 if (json_nexthop_ll
)
6464 json_object_array_add(json_nexthops
,
6467 json_object_object_add(json_path
, "nexthops",
6471 json_object_array_add(json_paths
, json_path
);
6475 /* prints an additional line, indented, with VNC info, if
6477 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6478 rfapi_vty_out_vncinfo(vty
, p
, binfo
, safi
);
6483 /* called from terminal list command */
6484 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6485 safi_t safi
, u_char use_json
, json_object
*json_ar
)
6487 json_object
*json_status
= NULL
;
6488 json_object
*json_net
= NULL
;
6490 /* Route status display. */
6492 json_status
= json_object_new_object();
6493 json_net
= json_object_new_object();
6500 /* print prefix and mask */
6502 json_object_string_add(
6503 json_net
, "addrPrefix",
6504 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6506 route_vty_out_route(p
, vty
, NULL
);
6508 /* Print attribute */
6511 if (p
->family
== AF_INET
6512 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6513 || safi
== SAFI_EVPN
6514 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6515 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6516 || safi
== SAFI_EVPN
)
6517 json_object_string_add(
6518 json_net
, "nextHop",
6520 attr
->mp_nexthop_global_in
));
6522 json_object_string_add(
6523 json_net
, "nextHop",
6524 inet_ntoa(attr
->nexthop
));
6525 } else if (p
->family
== AF_INET6
6526 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6529 json_object_string_add(
6530 json_net
, "netHopGloabal",
6532 &attr
->mp_nexthop_global
, buf
,
6537 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6538 json_object_int_add(json_net
, "metric",
6541 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6542 json_object_int_add(json_net
, "localPref",
6545 json_object_int_add(json_net
, "weight", attr
->weight
);
6549 json_object_string_add(json_net
, "asPath",
6553 json_object_string_add(json_net
, "bgpOriginCode",
6554 bgp_origin_str
[attr
->origin
]);
6556 if (p
->family
== AF_INET
6557 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6558 || safi
== SAFI_EVPN
6559 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6560 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6561 || safi
== SAFI_EVPN
)
6562 vty_out(vty
, "%-16s",
6564 attr
->mp_nexthop_global_in
));
6566 vty_out(vty
, "%-16s",
6567 inet_ntoa(attr
->nexthop
));
6568 } else if (p
->family
== AF_INET6
6569 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6576 &attr
->mp_nexthop_global
, buf
,
6580 vty_out(vty
, "\n%*s", 36, " ");
6582 vty_out(vty
, "%*s", len
, " ");
6585 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6586 vty_out(vty
, "%10u", attr
->med
);
6590 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6591 vty_out(vty
, "%7u", attr
->local_pref
);
6595 vty_out(vty
, "%7u ", attr
->weight
);
6599 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6602 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6606 json_object_boolean_true_add(json_status
, "*");
6607 json_object_boolean_true_add(json_status
, ">");
6608 json_object_object_add(json_net
, "appliedStatusSymbols",
6610 char buf_cut
[BUFSIZ
];
6611 json_object_object_add(
6613 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
6619 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
6620 struct bgp_info
*binfo
, int display
, safi_t safi
,
6623 json_object
*json_out
= NULL
;
6625 mpls_label_t label
= MPLS_INVALID_LABEL
;
6631 json_out
= json_object_new_object();
6633 /* short status lead text */
6634 route_vty_short_status_out(vty
, binfo
, json_out
);
6636 /* print prefix and mask */
6639 route_vty_out_route(p
, vty
, NULL
);
6641 vty_out(vty
, "%*s", 17, " ");
6644 /* Print attribute */
6647 if (((p
->family
== AF_INET
)
6648 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6649 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6650 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6651 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6652 || safi
== SAFI_EVPN
) {
6654 json_object_string_add(
6655 json_out
, "mpNexthopGlobalIn",
6657 attr
->mp_nexthop_global_in
));
6659 vty_out(vty
, "%-16s",
6661 attr
->mp_nexthop_global_in
));
6664 json_object_string_add(
6665 json_out
, "nexthop",
6666 inet_ntoa(attr
->nexthop
));
6668 vty_out(vty
, "%-16s",
6669 inet_ntoa(attr
->nexthop
));
6671 } else if (((p
->family
== AF_INET6
)
6672 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
6673 || (safi
== SAFI_EVPN
6674 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
6675 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6679 if (attr
->mp_nexthop_len
6680 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
6682 json_object_string_add(
6683 json_out
, "mpNexthopGlobalIn",
6686 &attr
->mp_nexthop_global
,
6692 &attr
->mp_nexthop_global
,
6694 } else if (attr
->mp_nexthop_len
6695 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
6698 &attr
->mp_nexthop_global
,
6701 &attr
->mp_nexthop_local
,
6703 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
6704 json_object_string_add(
6706 "mpNexthopGlobalLocal", buf_c
);
6708 vty_out(vty
, "%s(%s)",
6711 &attr
->mp_nexthop_global
,
6715 &attr
->mp_nexthop_local
,
6721 label
= decode_label(&binfo
->extra
->label
[0]);
6723 if (bgp_is_valid_label(&label
)) {
6725 json_object_int_add(json_out
, "notag", label
);
6726 json_object_array_add(json
, json_out
);
6728 vty_out(vty
, "notag/%d", label
);
6734 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
6735 struct bgp_info
*binfo
, int display
,
6736 json_object
*json_paths
)
6740 json_object
*json_path
= NULL
;
6743 json_path
= json_object_new_object();
6748 /* short status lead text */
6749 route_vty_short_status_out(vty
, binfo
, json_path
);
6751 /* print prefix and mask */
6753 route_vty_out_route(p
, vty
, NULL
);
6755 vty_out(vty
, "%*s", 17, " ");
6757 /* Print attribute */
6761 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6765 vty_out(vty
, "%-16s",
6766 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6770 vty_out(vty
, "%s(%s)",
6771 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6773 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
6781 struct eth_segment_id
*id
= &(attr
->evpn_overlay
.eth_s_id
);
6782 char *str
= esi2str(id
);
6783 vty_out(vty
, "%s", str
);
6784 XFREE(MTYPE_TMP
, str
);
6785 if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn
*)p
)) {
6786 vty_out(vty
, "/%s", inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
6787 } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn
*)p
)) {
6789 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
),
6792 if (attr
->ecommunity
) {
6794 struct ecommunity_val
*routermac
= ecommunity_lookup(
6795 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
6796 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
6798 mac
= ecom_mac2str((char *)routermac
->val
);
6800 vty_out(vty
, "/%s", (char *)mac
);
6801 XFREE(MTYPE_TMP
, mac
);
6807 /* dampening route */
6808 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6809 struct bgp_info
*binfo
, int display
, safi_t safi
,
6810 u_char use_json
, json_object
*json
)
6814 char timebuf
[BGP_UPTIME_LEN
];
6816 /* short status lead text */
6817 route_vty_short_status_out(vty
, binfo
, json
);
6819 /* print prefix and mask */
6822 route_vty_out_route(p
, vty
, NULL
);
6824 vty_out(vty
, "%*s", 17, " ");
6827 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6831 vty_out(vty
, "\n%*s", 34, " ");
6834 json_object_int_add(json
, "peerHost", len
);
6836 vty_out(vty
, "%*s", len
, " ");
6840 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
, BGP_UPTIME_LEN
,
6843 vty_out(vty
, "%s ", bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6847 /* Print attribute */
6853 json_object_string_add(json
, "asPath",
6856 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6861 json_object_string_add(json
, "origin",
6862 bgp_origin_str
[attr
->origin
]);
6864 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6871 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
6872 struct bgp_info
*binfo
, int display
, safi_t safi
,
6873 u_char use_json
, json_object
*json
)
6876 struct bgp_damp_info
*bdi
;
6877 char timebuf
[BGP_UPTIME_LEN
];
6883 bdi
= binfo
->extra
->damp_info
;
6885 /* short status lead text */
6886 route_vty_short_status_out(vty
, binfo
, json
);
6888 /* print prefix and mask */
6891 route_vty_out_route(p
, vty
, NULL
);
6893 vty_out(vty
, "%*s", 17, " ");
6896 len
= vty_out(vty
, "%s", binfo
->peer
->host
);
6900 vty_out(vty
, "\n%*s", 33, " ");
6903 json_object_int_add(json
, "peerHost", len
);
6905 vty_out(vty
, "%*s", len
, " ");
6908 len
= vty_out(vty
, "%d", bdi
->flap
);
6915 json_object_int_add(json
, "bdiFlap", len
);
6917 vty_out(vty
, "%*s", len
, " ");
6921 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
6924 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
6925 BGP_UPTIME_LEN
, 0, NULL
));
6927 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)
6928 && !CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
6930 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6931 BGP_UPTIME_LEN
, use_json
, json
);
6934 bgp_damp_reuse_time_vty(vty
, binfo
, timebuf
,
6939 vty_out(vty
, "%*s ", 8, " ");
6942 /* Print attribute */
6948 json_object_string_add(json
, "asPath",
6951 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6956 json_object_string_add(json
, "origin",
6957 bgp_origin_str
[attr
->origin
]);
6959 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6965 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
6966 int *first
, const char *header
,
6967 json_object
*json_adv_to
)
6969 char buf1
[INET6_ADDRSTRLEN
];
6970 json_object
*json_peer
= NULL
;
6973 /* 'advertised-to' is a dictionary of peers we have advertised
6975 * prefix too. The key is the peer's IP or swpX, the value is
6977 * hostname if we know it and "" if not.
6979 json_peer
= json_object_new_object();
6982 json_object_string_add(json_peer
, "hostname",
6986 json_object_object_add(json_adv_to
, peer
->conf_if
,
6989 json_object_object_add(
6991 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
6995 vty_out(vty
, "%s", header
);
7000 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7002 vty_out(vty
, " %s(%s)", peer
->hostname
,
7005 vty_out(vty
, " %s(%s)", peer
->hostname
,
7006 sockunion2str(&peer
->su
, buf1
,
7010 vty_out(vty
, " %s", peer
->conf_if
);
7013 sockunion2str(&peer
->su
, buf1
,
7019 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7020 struct bgp_info
*binfo
, afi_t afi
, safi_t safi
,
7021 json_object
*json_paths
)
7023 char buf
[INET6_ADDRSTRLEN
];
7025 #if defined(HAVE_CUMULUS)
7026 char buf2
[EVPN_ROUTE_STRLEN
];
7029 int sockunion_vty_out(struct vty
*, union sockunion
*);
7031 json_object
*json_bestpath
= NULL
;
7032 json_object
*json_cluster_list
= NULL
;
7033 json_object
*json_cluster_list_list
= NULL
;
7034 json_object
*json_ext_community
= NULL
;
7035 json_object
*json_lcommunity
= NULL
;
7036 json_object
*json_last_update
= NULL
;
7037 json_object
*json_nexthop_global
= NULL
;
7038 json_object
*json_nexthop_ll
= NULL
;
7039 json_object
*json_nexthops
= NULL
;
7040 json_object
*json_path
= NULL
;
7041 json_object
*json_peer
= NULL
;
7042 json_object
*json_string
= NULL
;
7043 json_object
*json_adv_to
= NULL
;
7045 struct listnode
*node
, *nnode
;
7047 int addpath_capable
;
7049 unsigned int first_as
;
7052 json_path
= json_object_new_object();
7053 json_peer
= json_object_new_object();
7054 json_nexthop_global
= json_object_new_object();
7057 #if defined(HAVE_CUMULUS)
7058 if (!json_paths
&& safi
== SAFI_EVPN
) {
7061 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7062 vty_out(vty
, " Route %s", buf2
);
7064 if (binfo
->extra
&& binfo
->extra
->num_labels
) {
7065 bgp_evpn_label2str(binfo
->extra
->label
,
7066 binfo
->extra
->num_labels
, tag_buf
,
7068 vty_out(vty
, " VNI %s", tag_buf
);
7071 if (binfo
->extra
&& binfo
->extra
->parent
) {
7072 struct bgp_info
*parent_ri
;
7073 struct bgp_node
*rn
, *prn
;
7075 parent_ri
= (struct bgp_info
*)binfo
->extra
->parent
;
7076 rn
= parent_ri
->net
;
7077 if (rn
&& rn
->prn
) {
7079 vty_out(vty
, " Imported from %s:%s\n",
7081 (struct prefix_rd
*)&prn
->p
,
7082 buf1
, sizeof(buf1
)),
7092 /* Line1 display AS-path, Aggregator */
7095 if (!attr
->aspath
->json
)
7096 aspath_str_update(attr
->aspath
, true);
7097 json_object_lock(attr
->aspath
->json
);
7098 json_object_object_add(json_path
, "aspath",
7099 attr
->aspath
->json
);
7101 if (attr
->aspath
->segments
)
7102 aspath_print_vty(vty
, " %s",
7105 vty_out(vty
, " Local");
7109 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_REMOVED
)) {
7111 json_object_boolean_true_add(json_path
,
7114 vty_out(vty
, ", (removed)");
7117 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_STALE
)) {
7119 json_object_boolean_true_add(json_path
,
7122 vty_out(vty
, ", (stale)");
7125 if (CHECK_FLAG(attr
->flag
,
7126 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7128 json_object_int_add(json_path
, "aggregatorAs",
7129 attr
->aggregator_as
);
7130 json_object_string_add(
7131 json_path
, "aggregatorId",
7132 inet_ntoa(attr
->aggregator_addr
));
7134 vty_out(vty
, ", (aggregated by %u %s)",
7135 attr
->aggregator_as
,
7136 inet_ntoa(attr
->aggregator_addr
));
7140 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7141 PEER_FLAG_REFLECTOR_CLIENT
)) {
7143 json_object_boolean_true_add(
7144 json_path
, "rxedFromRrClient");
7146 vty_out(vty
, ", (Received from a RR-client)");
7149 if (CHECK_FLAG(binfo
->peer
->af_flags
[afi
][safi
],
7150 PEER_FLAG_RSERVER_CLIENT
)) {
7152 json_object_boolean_true_add(
7153 json_path
, "rxedFromRsClient");
7155 vty_out(vty
, ", (Received from a RS-client)");
7158 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7160 json_object_boolean_true_add(
7161 json_path
, "dampeningHistoryEntry");
7163 vty_out(vty
, ", (history entry)");
7164 } else if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DAMPED
)) {
7166 json_object_boolean_true_add(
7167 json_path
, "dampeningSuppressed");
7169 vty_out(vty
, ", (suppressed due to dampening)");
7175 /* Line2 display Next-hop, Neighbor, Router-id */
7176 /* Display the nexthop */
7177 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7178 || p
->family
== AF_EVPN
)
7179 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7180 || safi
== SAFI_EVPN
7181 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7182 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7183 || safi
== SAFI_EVPN
) {
7185 json_object_string_add(
7186 json_nexthop_global
, "ip",
7188 attr
->mp_nexthop_global_in
));
7192 attr
->mp_nexthop_global_in
));
7195 json_object_string_add(
7196 json_nexthop_global
, "ip",
7197 inet_ntoa(attr
->nexthop
));
7200 inet_ntoa(attr
->nexthop
));
7204 json_object_string_add(json_nexthop_global
,
7208 json_object_string_add(
7209 json_nexthop_global
, "ip",
7211 &attr
->mp_nexthop_global
, buf
,
7213 json_object_string_add(json_nexthop_global
,
7215 json_object_string_add(json_nexthop_global
,
7220 &attr
->mp_nexthop_global
, buf
,
7225 /* Display the IGP cost or 'inaccessible' */
7226 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7228 json_object_boolean_false_add(
7229 json_nexthop_global
, "accessible");
7231 vty_out(vty
, " (inaccessible)");
7233 if (binfo
->extra
&& binfo
->extra
->igpmetric
) {
7235 json_object_int_add(
7236 json_nexthop_global
, "metric",
7237 binfo
->extra
->igpmetric
);
7239 vty_out(vty
, " (metric %u)",
7240 binfo
->extra
->igpmetric
);
7243 /* IGP cost is 0, display this only for json */
7246 json_object_int_add(json_nexthop_global
,
7251 json_object_boolean_true_add(
7252 json_nexthop_global
, "accessible");
7255 /* Display peer "from" output */
7256 /* This path was originated locally */
7257 if (binfo
->peer
== bgp
->peer_self
) {
7259 if (safi
== SAFI_EVPN
7260 || (p
->family
== AF_INET
7261 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7263 json_object_string_add(
7264 json_peer
, "peerId", "0.0.0.0");
7266 vty_out(vty
, " from 0.0.0.0 ");
7269 json_object_string_add(json_peer
,
7272 vty_out(vty
, " from :: ");
7276 json_object_string_add(
7277 json_peer
, "routerId",
7278 inet_ntoa(bgp
->router_id
));
7280 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7283 /* We RXed this path from one of our peers */
7287 json_object_string_add(
7288 json_peer
, "peerId",
7289 sockunion2str(&binfo
->peer
->su
, buf
,
7291 json_object_string_add(
7292 json_peer
, "routerId",
7294 &binfo
->peer
->remote_id
, buf1
,
7297 if (binfo
->peer
->hostname
)
7298 json_object_string_add(
7299 json_peer
, "hostname",
7300 binfo
->peer
->hostname
);
7302 if (binfo
->peer
->domainname
)
7303 json_object_string_add(
7304 json_peer
, "domainname",
7305 binfo
->peer
->domainname
);
7307 if (binfo
->peer
->conf_if
)
7308 json_object_string_add(
7309 json_peer
, "interface",
7310 binfo
->peer
->conf_if
);
7312 if (binfo
->peer
->conf_if
) {
7313 if (binfo
->peer
->hostname
7316 BGP_FLAG_SHOW_HOSTNAME
))
7317 vty_out(vty
, " from %s(%s)",
7318 binfo
->peer
->hostname
,
7319 binfo
->peer
->conf_if
);
7321 vty_out(vty
, " from %s",
7322 binfo
->peer
->conf_if
);
7324 if (binfo
->peer
->hostname
7327 BGP_FLAG_SHOW_HOSTNAME
))
7328 vty_out(vty
, " from %s(%s)",
7329 binfo
->peer
->hostname
,
7332 vty_out(vty
, " from %s",
7341 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7342 vty_out(vty
, " (%s)",
7343 inet_ntoa(attr
->originator_id
));
7345 vty_out(vty
, " (%s)",
7348 &binfo
->peer
->remote_id
,
7349 buf1
, sizeof(buf1
)));
7356 /* display the link-local nexthop */
7357 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7359 json_nexthop_ll
= json_object_new_object();
7360 json_object_string_add(
7361 json_nexthop_ll
, "ip",
7363 &attr
->mp_nexthop_local
, buf
,
7365 json_object_string_add(json_nexthop_ll
, "afi",
7367 json_object_string_add(json_nexthop_ll
, "scope",
7370 json_object_boolean_true_add(json_nexthop_ll
,
7373 if (!attr
->mp_nexthop_prefer_global
)
7374 json_object_boolean_true_add(
7375 json_nexthop_ll
, "used");
7377 json_object_boolean_true_add(
7378 json_nexthop_global
, "used");
7380 vty_out(vty
, " (%s) %s\n",
7382 &attr
->mp_nexthop_local
, buf
,
7384 attr
->mp_nexthop_prefer_global
7389 /* If we do not have a link-local nexthop then we must flag the
7393 json_object_boolean_true_add(
7394 json_nexthop_global
, "used");
7397 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7398 * Int/Ext/Local, Atomic, best */
7400 json_object_string_add(
7401 json_path
, "origin",
7402 bgp_origin_long_str
[attr
->origin
]);
7404 vty_out(vty
, " Origin %s",
7405 bgp_origin_long_str
[attr
->origin
]);
7407 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7409 json_object_int_add(json_path
, "med",
7412 vty_out(vty
, ", metric %u", attr
->med
);
7415 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7417 json_object_int_add(json_path
, "localpref",
7420 vty_out(vty
, ", localpref %u",
7424 json_object_int_add(json_path
, "localpref",
7425 bgp
->default_local_pref
);
7427 vty_out(vty
, ", localpref %u",
7428 bgp
->default_local_pref
);
7431 if (attr
->weight
!= 0) {
7433 json_object_int_add(json_path
, "weight",
7436 vty_out(vty
, ", weight %u", attr
->weight
);
7439 if (attr
->tag
!= 0) {
7441 json_object_int_add(json_path
, "tag",
7444 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7448 if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_VALID
)) {
7450 json_object_boolean_false_add(json_path
,
7453 vty_out(vty
, ", invalid");
7454 } else if (!CHECK_FLAG(binfo
->flags
, BGP_INFO_HISTORY
)) {
7456 json_object_boolean_true_add(json_path
,
7459 vty_out(vty
, ", valid");
7462 if (binfo
->peer
!= bgp
->peer_self
) {
7463 if (binfo
->peer
->as
== binfo
->peer
->local_as
) {
7464 if (CHECK_FLAG(bgp
->config
,
7465 BGP_CONFIG_CONFEDERATION
)) {
7467 json_object_string_add(
7472 ", confed-internal");
7475 json_object_string_add(
7479 vty_out(vty
, ", internal");
7482 if (bgp_confederation_peers_check(
7483 bgp
, binfo
->peer
->as
)) {
7485 json_object_string_add(
7490 ", confed-external");
7493 json_object_string_add(
7497 vty_out(vty
, ", external");
7500 } else if (binfo
->sub_type
== BGP_ROUTE_AGGREGATE
) {
7502 json_object_boolean_true_add(json_path
,
7504 json_object_boolean_true_add(json_path
,
7507 vty_out(vty
, ", aggregated, local");
7509 } else if (binfo
->type
!= ZEBRA_ROUTE_BGP
) {
7511 json_object_boolean_true_add(json_path
,
7514 vty_out(vty
, ", sourced");
7517 json_object_boolean_true_add(json_path
,
7519 json_object_boolean_true_add(json_path
,
7522 vty_out(vty
, ", sourced, local");
7526 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
7528 json_object_boolean_true_add(json_path
,
7531 vty_out(vty
, ", atomic-aggregate");
7534 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_MULTIPATH
)
7535 || (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)
7536 && bgp_info_mpath_count(binfo
))) {
7538 json_object_boolean_true_add(json_path
,
7541 vty_out(vty
, ", multipath");
7544 // Mark the bestpath(s)
7545 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_DMED_SELECTED
)) {
7546 first_as
= aspath_get_first_as(attr
->aspath
);
7551 json_object_new_object();
7552 json_object_int_add(json_bestpath
,
7553 "bestpathFromAs", first_as
);
7556 vty_out(vty
, ", bestpath-from-AS %u",
7560 ", bestpath-from-AS Local");
7564 if (CHECK_FLAG(binfo
->flags
, BGP_INFO_SELECTED
)) {
7568 json_object_new_object();
7569 json_object_boolean_true_add(json_bestpath
,
7572 vty_out(vty
, ", best");
7576 json_object_object_add(json_path
, "bestpath",
7582 /* Line 4 display Community */
7583 if (attr
->community
) {
7585 if (!attr
->community
->json
)
7586 community_str(attr
->community
, true);
7587 json_object_lock(attr
->community
->json
);
7588 json_object_object_add(json_path
, "community",
7589 attr
->community
->json
);
7591 vty_out(vty
, " Community: %s\n",
7592 attr
->community
->str
);
7596 /* Line 5 display Extended-community */
7597 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7599 json_ext_community
= json_object_new_object();
7600 json_object_string_add(json_ext_community
,
7602 attr
->ecommunity
->str
);
7603 json_object_object_add(json_path
,
7604 "extendedCommunity",
7605 json_ext_community
);
7607 vty_out(vty
, " Extended Community: %s\n",
7608 attr
->ecommunity
->str
);
7612 /* Line 6 display Large community */
7613 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
7615 json_lcommunity
= json_object_new_object();
7616 json_object_string_add(json_lcommunity
,
7618 attr
->lcommunity
->str
);
7619 json_object_object_add(json_path
,
7623 vty_out(vty
, " Large Community: %s\n",
7624 attr
->lcommunity
->str
);
7628 /* Line 7 display Originator, Cluster-id */
7629 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7630 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
7632 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
7634 json_object_string_add(
7635 json_path
, "originatorId",
7636 inet_ntoa(attr
->originator_id
));
7638 vty_out(vty
, " Originator: %s",
7639 inet_ntoa(attr
->originator_id
));
7642 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
7647 json_object_new_object();
7648 json_cluster_list_list
=
7649 json_object_new_array();
7652 i
< attr
->cluster
->length
/ 4;
7654 json_string
= json_object_new_string(
7658 json_object_array_add(
7659 json_cluster_list_list
,
7663 /* struct cluster_list does not have
7665 * aspath and community do. Add this
7668 json_object_string_add(json_cluster_list,
7669 "string", attr->cluster->str);
7671 json_object_object_add(
7672 json_cluster_list
, "list",
7673 json_cluster_list_list
);
7674 json_object_object_add(
7675 json_path
, "clusterList",
7678 vty_out(vty
, ", Cluster list: ");
7681 i
< attr
->cluster
->length
/ 4;
7695 if (binfo
->extra
&& binfo
->extra
->damp_info
)
7696 bgp_damp_info_vty(vty
, binfo
, json_path
);
7699 #if defined(HAVE_CUMULUS)
7700 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0])
7701 && safi
!= SAFI_EVPN
)
7703 if (binfo
->extra
&& bgp_is_valid_label(&binfo
->extra
->label
[0]))
7706 mpls_label_t label
=
7707 label_pton(&binfo
->extra
->label
[0]);
7709 json_object_int_add(json_path
, "remoteLabel",
7712 vty_out(vty
, " Remote label: %d\n", label
);
7716 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
7718 json_object_int_add(json_path
, "labelIndex",
7721 vty_out(vty
, " Label Index: %d\n",
7725 /* Line 8 display Addpath IDs */
7726 if (binfo
->addpath_rx_id
|| binfo
->addpath_tx_id
) {
7728 json_object_int_add(json_path
, "addpathRxId",
7729 binfo
->addpath_rx_id
);
7730 json_object_int_add(json_path
, "addpathTxId",
7731 binfo
->addpath_tx_id
);
7733 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
7734 binfo
->addpath_rx_id
,
7735 binfo
->addpath_tx_id
);
7739 /* If we used addpath to TX a non-bestpath we need to display
7740 * "Advertised to" on a path-by-path basis */
7741 if (bgp
->addpath_tx_used
[afi
][safi
]) {
7744 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
7746 bgp_addpath_encode_tx(peer
, afi
, safi
);
7747 has_adj
= bgp_adj_out_lookup(
7748 peer
, binfo
->net
, binfo
->addpath_tx_id
);
7750 if ((addpath_capable
&& has_adj
)
7751 || (!addpath_capable
&& has_adj
7752 && CHECK_FLAG(binfo
->flags
,
7753 BGP_INFO_SELECTED
))) {
7754 if (json_path
&& !json_adv_to
)
7756 json_object_new_object();
7758 route_vty_out_advertised_to(
7767 json_object_object_add(json_path
,
7778 /* Line 9 display Uptime */
7779 tbuf
= time(NULL
) - (bgp_clock() - binfo
->uptime
);
7781 json_last_update
= json_object_new_object();
7782 json_object_int_add(json_last_update
, "epoch", tbuf
);
7783 json_object_string_add(json_last_update
, "string",
7785 json_object_object_add(json_path
, "lastUpdate",
7788 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
7791 /* We've constructed the json object for this path, add it to the json
7795 if (json_nexthop_global
|| json_nexthop_ll
) {
7796 json_nexthops
= json_object_new_array();
7798 if (json_nexthop_global
)
7799 json_object_array_add(json_nexthops
,
7800 json_nexthop_global
);
7802 if (json_nexthop_ll
)
7803 json_object_array_add(json_nexthops
,
7806 json_object_object_add(json_path
, "nexthops",
7810 json_object_object_add(json_path
, "peer", json_peer
);
7811 json_object_array_add(json_paths
, json_path
);
7816 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
7817 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
7818 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
7820 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
7821 const char *prefix_list_str
, afi_t afi
,
7822 safi_t safi
, enum bgp_show_type type
);
7823 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
7824 const char *filter
, afi_t afi
, safi_t safi
,
7825 enum bgp_show_type type
);
7826 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
7827 const char *rmap_str
, afi_t afi
, safi_t safi
,
7828 enum bgp_show_type type
);
7829 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
7830 const char *com
, int exact
, afi_t afi
,
7832 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
7833 const char *prefix
, afi_t afi
, safi_t safi
,
7834 enum bgp_show_type type
);
7835 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
7836 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
7837 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
7838 const char *comstr
, int exact
, afi_t afi
,
7842 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
7843 struct bgp_table
*table
, enum bgp_show_type type
,
7844 void *output_arg
, u_char use_json
, char *rd
,
7845 int is_last
, unsigned long *output_cum
,
7846 unsigned long *total_cum
,
7847 unsigned long *json_header_depth
)
7849 struct bgp_info
*ri
;
7850 struct bgp_node
*rn
;
7853 unsigned long output_count
= 0;
7854 unsigned long total_count
= 0;
7858 json_object
*json_paths
= NULL
;
7861 if (output_cum
&& *output_cum
!= 0)
7864 if (use_json
&& !*json_header_depth
) {
7866 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
7867 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
7868 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
7869 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
? "Default"
7871 table
->version
, inet_ntoa(bgp
->router_id
));
7872 *json_header_depth
= 2;
7874 vty_out(vty
, " \"routeDistinguishers\" : {");
7875 ++*json_header_depth
;
7877 json_paths
= json_object_new_object();
7880 if (use_json
&& rd
) {
7881 vty_out(vty
, " \"%s\" : { ", rd
);
7884 /* Start processing of routes. */
7885 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
7886 if (rn
->info
== NULL
)
7891 json_paths
= json_object_new_array();
7895 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
7897 if (type
== bgp_show_type_flap_statistics
7898 || type
== bgp_show_type_flap_neighbor
7899 || type
== bgp_show_type_dampend_paths
7900 || type
== bgp_show_type_damp_neighbor
) {
7901 if (!(ri
->extra
&& ri
->extra
->damp_info
))
7904 if (type
== bgp_show_type_regexp
) {
7905 regex_t
*regex
= output_arg
;
7907 if (bgp_regexec(regex
, ri
->attr
->aspath
)
7911 if (type
== bgp_show_type_prefix_list
) {
7912 struct prefix_list
*plist
= output_arg
;
7914 if (prefix_list_apply(plist
, &rn
->p
)
7918 if (type
== bgp_show_type_filter_list
) {
7919 struct as_list
*as_list
= output_arg
;
7921 if (as_list_apply(as_list
, ri
->attr
->aspath
)
7922 != AS_FILTER_PERMIT
)
7925 if (type
== bgp_show_type_route_map
) {
7926 struct route_map
*rmap
= output_arg
;
7927 struct bgp_info binfo
;
7928 struct attr dummy_attr
;
7931 bgp_attr_dup(&dummy_attr
, ri
->attr
);
7933 binfo
.peer
= ri
->peer
;
7934 binfo
.attr
= &dummy_attr
;
7936 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
7938 if (ret
== RMAP_DENYMATCH
)
7941 if (type
== bgp_show_type_neighbor
7942 || type
== bgp_show_type_flap_neighbor
7943 || type
== bgp_show_type_damp_neighbor
) {
7944 union sockunion
*su
= output_arg
;
7946 if (ri
->peer
== NULL
7947 || ri
->peer
->su_remote
== NULL
7948 || !sockunion_same(ri
->peer
->su_remote
, su
))
7951 if (type
== bgp_show_type_cidr_only
) {
7952 u_int32_t destination
;
7954 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
7955 if (IN_CLASSC(destination
)
7956 && rn
->p
.prefixlen
== 24)
7958 if (IN_CLASSB(destination
)
7959 && rn
->p
.prefixlen
== 16)
7961 if (IN_CLASSA(destination
)
7962 && rn
->p
.prefixlen
== 8)
7965 if (type
== bgp_show_type_prefix_longer
) {
7966 struct prefix
*p
= output_arg
;
7968 if (!prefix_match(p
, &rn
->p
))
7971 if (type
== bgp_show_type_community_all
) {
7972 if (!ri
->attr
->community
)
7975 if (type
== bgp_show_type_community
) {
7976 struct community
*com
= output_arg
;
7978 if (!ri
->attr
->community
7979 || !community_match(ri
->attr
->community
,
7983 if (type
== bgp_show_type_community_exact
) {
7984 struct community
*com
= output_arg
;
7986 if (!ri
->attr
->community
7987 || !community_cmp(ri
->attr
->community
, com
))
7990 if (type
== bgp_show_type_community_list
) {
7991 struct community_list
*list
= output_arg
;
7993 if (!community_list_match(ri
->attr
->community
,
7997 if (type
== bgp_show_type_community_list_exact
) {
7998 struct community_list
*list
= output_arg
;
8000 if (!community_list_exact_match(
8001 ri
->attr
->community
, list
))
8004 if (type
== bgp_show_type_lcommunity
) {
8005 struct lcommunity
*lcom
= output_arg
;
8007 if (!ri
->attr
->lcommunity
8008 || !lcommunity_match(ri
->attr
->lcommunity
,
8012 if (type
== bgp_show_type_lcommunity_list
) {
8013 struct community_list
*list
= output_arg
;
8015 if (!lcommunity_list_match(ri
->attr
->lcommunity
,
8019 if (type
== bgp_show_type_lcommunity_all
) {
8020 if (!ri
->attr
->lcommunity
)
8023 if (type
== bgp_show_type_dampend_paths
8024 || type
== bgp_show_type_damp_neighbor
) {
8025 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
)
8026 || CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
8030 if (!use_json
&& header
) {
8031 vty_out(vty
, "BGP table version is %" PRIu64
8032 ", local router ID is %s\n",
8034 inet_ntoa(bgp
->router_id
));
8035 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8036 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8037 if (type
== bgp_show_type_dampend_paths
8038 || type
== bgp_show_type_damp_neighbor
)
8039 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8040 else if (type
== bgp_show_type_flap_statistics
8041 || type
== bgp_show_type_flap_neighbor
)
8042 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8044 vty_out(vty
, BGP_SHOW_HEADER
);
8047 if (rd
!= NULL
&& !display
&& !output_count
) {
8050 "Route Distinguisher: %s\n",
8053 if (type
== bgp_show_type_dampend_paths
8054 || type
== bgp_show_type_damp_neighbor
)
8055 damp_route_vty_out(vty
, &rn
->p
, ri
, display
,
8056 safi
, use_json
, json_paths
);
8057 else if (type
== bgp_show_type_flap_statistics
8058 || type
== bgp_show_type_flap_neighbor
)
8059 flap_route_vty_out(vty
, &rn
->p
, ri
, display
,
8060 safi
, use_json
, json_paths
);
8062 route_vty_out(vty
, &rn
->p
, ri
, display
, safi
,
8073 sprintf(buf2
, "%s/%d",
8074 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
8077 vty_out(vty
, "\"%s\": ", buf2
);
8079 vty_out(vty
, ",\"%s\": ", buf2
);
8082 json_object_to_json_string(json_paths
));
8083 json_object_free(json_paths
);
8090 output_count
+= *output_cum
;
8091 *output_cum
= output_count
;
8094 total_count
+= *total_cum
;
8095 *total_cum
= total_count
;
8099 json_object_free(json_paths
);
8101 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8105 for (i
= 0; i
< *json_header_depth
; ++i
)
8106 vty_out(vty
, " } ");
8110 /* No route is displayed */
8111 if (output_count
== 0) {
8112 if (type
== bgp_show_type_normal
)
8114 "No BGP prefixes displayed, %ld exist\n",
8118 "\nDisplayed %ld routes and %ld total paths\n",
8119 output_count
, total_count
);
8126 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8127 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8128 enum bgp_show_type type
, void *output_arg
,
8131 struct bgp_node
*rn
, *next
;
8132 unsigned long output_cum
= 0;
8133 unsigned long total_cum
= 0;
8134 unsigned long json_header_depth
= 0;
8137 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8139 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8140 next
= bgp_route_next(rn
);
8141 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8143 if (rn
->info
!= NULL
) {
8144 struct prefix_rd prd
;
8145 char rd
[RD_ADDRSTRLEN
];
8147 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8148 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8149 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8150 output_arg
, use_json
, rd
, next
== NULL
,
8151 &output_cum
, &total_cum
,
8152 &json_header_depth
);
8158 if (output_cum
== 0)
8159 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8163 "\nDisplayed %ld routes and %ld total paths\n",
8164 output_cum
, total_cum
);
8168 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8169 enum bgp_show_type type
, void *output_arg
, u_char use_json
)
8171 struct bgp_table
*table
;
8172 unsigned long json_header_depth
= 0;
8175 bgp
= bgp_get_default();
8180 vty_out(vty
, "No BGP process is configured\n");
8182 vty_out(vty
, "{}\n");
8186 table
= bgp
->rib
[afi
][safi
];
8187 /* use MPLS and ENCAP specific shows until they are merged */
8188 if (safi
== SAFI_MPLS_VPN
) {
8189 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8190 output_arg
, use_json
);
8192 /* labeled-unicast routes live in the unicast table */
8193 else if (safi
== SAFI_LABELED_UNICAST
)
8194 safi
= SAFI_UNICAST
;
8196 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8197 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8200 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8201 safi_t safi
, u_char use_json
)
8203 struct listnode
*node
, *nnode
;
8208 vty_out(vty
, "{\n");
8210 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8213 vty_out(vty
, ",\n");
8217 vty_out(vty
, "\"%s\":",
8218 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8222 vty_out(vty
, "\nInstance %s:\n",
8223 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8227 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8232 vty_out(vty
, "}\n");
8235 /* Header of detailed BGP route information */
8236 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8237 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8238 afi_t afi
, safi_t safi
, json_object
*json
)
8240 struct bgp_info
*ri
;
8243 struct listnode
*node
, *nnode
;
8244 char buf1
[RD_ADDRSTRLEN
];
8245 char buf2
[INET6_ADDRSTRLEN
];
8246 #if defined(HAVE_CUMULUS)
8247 char buf3
[EVPN_ROUTE_STRLEN
];
8249 char prefix_str
[BUFSIZ
];
8254 int no_advertise
= 0;
8257 int has_valid_label
= 0;
8258 mpls_label_t label
= 0;
8259 json_object
*json_adv_to
= NULL
;
8262 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8264 if (has_valid_label
)
8265 label
= label_pton(&rn
->local_label
);
8268 if (has_valid_label
)
8269 json_object_int_add(json
, "localLabel", label
);
8271 json_object_string_add(
8273 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8275 #if defined(HAVE_CUMULUS)
8276 if (safi
== SAFI_EVPN
)
8277 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8278 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8281 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8282 buf3
, sizeof(buf3
)));
8284 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8285 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8286 ? prefix_rd2str(prd
, buf1
,
8289 safi
== SAFI_MPLS_VPN
? ":" : "",
8290 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8294 if (p
->family
== AF_ETHERNET
)
8295 prefix2str(p
, buf2
, INET6_ADDRSTRLEN
);
8297 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8299 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8300 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8301 || safi
== SAFI_EVPN
)
8302 ? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8304 ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
)) ? ":"
8306 buf2
, p
->prefixlen
);
8309 if (has_valid_label
)
8310 vty_out(vty
, "Local label: %d\n", label
);
8311 #if defined(HAVE_CUMULUS)
8312 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8314 if (bgp_labeled_safi(safi
))
8316 vty_out(vty
, "not allocated\n");
8319 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8321 if (CHECK_FLAG(ri
->flags
, BGP_INFO_SELECTED
)) {
8323 if (ri
->extra
&& ri
->extra
->suppress
)
8325 if (ri
->attr
->community
!= NULL
) {
8326 if (community_include(ri
->attr
->community
,
8327 COMMUNITY_NO_ADVERTISE
))
8329 if (community_include(ri
->attr
->community
,
8330 COMMUNITY_NO_EXPORT
))
8332 if (community_include(ri
->attr
->community
,
8333 COMMUNITY_LOCAL_AS
))
8340 vty_out(vty
, "Paths: (%d available", count
);
8342 vty_out(vty
, ", best #%d", best
);
8343 if (safi
== SAFI_UNICAST
)
8344 vty_out(vty
, ", table %s",
8346 == BGP_INSTANCE_TYPE_DEFAULT
)
8347 ? "Default-IP-Routing-Table"
8350 vty_out(vty
, ", no best path");
8353 vty_out(vty
, ", not advertised to any peer");
8355 vty_out(vty
, ", not advertised to EBGP peer");
8357 vty_out(vty
, ", not advertised outside local AS");
8361 ", Advertisements suppressed by an aggregate.");
8362 vty_out(vty
, ")\n");
8365 /* If we are not using addpath then we can display Advertised to and
8367 * show what peers we advertised the bestpath to. If we are using
8369 * though then we must display Advertised to on a path-by-path basis. */
8370 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8371 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8372 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8373 if (json
&& !json_adv_to
)
8374 json_adv_to
= json_object_new_object();
8376 route_vty_out_advertised_to(
8378 " Advertised to non peer-group peers:\n ",
8385 json_object_object_add(json
, "advertisedTo",
8390 vty_out(vty
, " Not advertised to any peer");
8396 /* Display specified route of BGP table. */
8397 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8398 struct bgp_table
*rib
, const char *ip_str
,
8399 afi_t afi
, safi_t safi
,
8400 struct prefix_rd
*prd
, int prefix_check
,
8401 enum bgp_path_type pathtype
, u_char use_json
)
8406 struct prefix match
;
8407 struct bgp_node
*rn
;
8408 struct bgp_node
*rm
;
8409 struct bgp_info
*ri
;
8410 struct bgp_table
*table
;
8411 json_object
*json
= NULL
;
8412 json_object
*json_paths
= NULL
;
8414 /* Check IP address argument. */
8415 ret
= str2prefix(ip_str
, &match
);
8417 vty_out(vty
, "address is malformed\n");
8421 match
.family
= afi2family(afi
);
8424 json
= json_object_new_object();
8425 json_paths
= json_object_new_array();
8428 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
8429 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
8430 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
8433 if ((table
= rn
->info
) == NULL
)
8438 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
8442 && rm
->p
.prefixlen
!= match
.prefixlen
) {
8443 bgp_unlock_node(rm
);
8447 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
8449 route_vty_out_detail_header(
8451 (struct prefix_rd
*)&rn
->p
,
8452 AFI_IP
, safi
, json
);
8457 if (pathtype
== BGP_PATH_ALL
8458 || (pathtype
== BGP_PATH_BESTPATH
8459 && CHECK_FLAG(ri
->flags
,
8461 || (pathtype
== BGP_PATH_MULTIPATH
8462 && (CHECK_FLAG(ri
->flags
,
8464 || CHECK_FLAG(ri
->flags
,
8465 BGP_INFO_SELECTED
))))
8466 route_vty_out_detail(vty
, bgp
, &rm
->p
,
8471 bgp_unlock_node(rm
);
8476 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
8478 || rn
->p
.prefixlen
== match
.prefixlen
) {
8479 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
8481 route_vty_out_detail_header(
8482 vty
, bgp
, rn
, NULL
, afi
,
8488 if (pathtype
== BGP_PATH_ALL
8489 || (pathtype
== BGP_PATH_BESTPATH
8493 || (pathtype
== BGP_PATH_MULTIPATH
8499 BGP_INFO_SELECTED
))))
8500 route_vty_out_detail(
8501 vty
, bgp
, &rn
->p
, ri
,
8502 afi
, safi
, json_paths
);
8506 bgp_unlock_node(rn
);
8512 json_object_object_add(json
, "paths", json_paths
);
8514 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8515 json
, JSON_C_TO_STRING_PRETTY
));
8516 json_object_free(json
);
8519 vty_out(vty
, "%% Network not in table\n");
8527 /* Display specified route of Main RIB */
8528 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
8529 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
8530 int prefix_check
, enum bgp_path_type pathtype
,
8534 bgp
= bgp_get_default();
8537 vty_out(vty
, "No BGP process is configured\n");
8539 vty_out(vty
, "{}\n");
8544 /* labeled-unicast routes live in the unicast table */
8545 if (safi
== SAFI_LABELED_UNICAST
)
8546 safi
= SAFI_UNICAST
;
8548 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
8549 afi
, safi
, prd
, prefix_check
, pathtype
,
8553 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
8554 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
8557 struct lcommunity
*lcom
;
8563 b
= buffer_new(1024);
8564 for (i
= 0; i
< argc
; i
++) {
8566 buffer_putc(b
, ' ');
8568 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
8570 buffer_putstr(b
, argv
[i
]->arg
);
8574 buffer_putc(b
, '\0');
8576 str
= buffer_getstr(b
);
8579 lcom
= lcommunity_str2com(str
);
8580 XFREE(MTYPE_TMP
, str
);
8582 vty_out(vty
, "%% Large-community malformed\n");
8586 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
8590 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
8591 const char *lcom
, afi_t afi
, safi_t safi
,
8594 struct community_list
*list
;
8596 list
= community_list_lookup(bgp_clist
, lcom
,
8597 LARGE_COMMUNITY_LIST_MASTER
);
8599 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
8604 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
8608 DEFUN (show_ip_bgp_large_community_list
,
8609 show_ip_bgp_large_community_list_cmd
,
8610 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
8614 BGP_INSTANCE_HELP_STR
8616 BGP_SAFI_WITH_LABEL_HELP_STR
8617 "Display routes matching the large-community-list\n"
8618 "large-community-list number\n"
8619 "large-community-list name\n"
8623 afi_t afi
= AFI_IP6
;
8624 safi_t safi
= SAFI_UNICAST
;
8627 if (argv_find(argv
, argc
, "ip", &idx
))
8629 if (argv_find(argv
, argc
, "view", &idx
)
8630 || argv_find(argv
, argc
, "vrf", &idx
))
8631 vrf
= argv
[++idx
]->arg
;
8632 if (argv_find(argv
, argc
, "ipv4", &idx
)
8633 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8634 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8635 if (argv_find(argv
, argc
, "unicast", &idx
)
8636 || argv_find(argv
, argc
, "multicast", &idx
))
8637 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8640 int uj
= use_json(argc
, argv
);
8642 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8644 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8648 argv_find(argv
, argc
, "large-community-list", &idx
);
8649 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
8652 DEFUN (show_ip_bgp_large_community
,
8653 show_ip_bgp_large_community_cmd
,
8654 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
8658 BGP_INSTANCE_HELP_STR
8660 BGP_SAFI_WITH_LABEL_HELP_STR
8661 "Display routes matching the large-communities\n"
8662 "List of large-community numbers\n"
8666 afi_t afi
= AFI_IP6
;
8667 safi_t safi
= SAFI_UNICAST
;
8670 if (argv_find(argv
, argc
, "ip", &idx
))
8672 if (argv_find(argv
, argc
, "view", &idx
)
8673 || argv_find(argv
, argc
, "vrf", &idx
))
8674 vrf
= argv
[++idx
]->arg
;
8675 if (argv_find(argv
, argc
, "ipv4", &idx
)
8676 || argv_find(argv
, argc
, "ipv6", &idx
)) {
8677 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
8678 if (argv_find(argv
, argc
, "unicast", &idx
)
8679 || argv_find(argv
, argc
, "multicast", &idx
))
8680 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
8683 int uj
= use_json(argc
, argv
);
8685 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
8687 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
8691 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
8692 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
8694 return bgp_show(vty
, bgp
, afi
, safi
,
8695 bgp_show_type_lcommunity_all
, NULL
, uj
);
8698 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
8702 /* BGP route print out function without JSON */
8705 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8706 <dampening <parameters>\
8711 |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
8712 |community-list <(1-500)|WORD> [exact-match]\
8713 |A.B.C.D/M longer-prefixes\
8714 |X:X::X:X/M longer-prefixes\
8719 BGP_INSTANCE_HELP_STR
8721 BGP_SAFI_WITH_LABEL_HELP_STR
8722 "Display detailed information about dampening\n"
8723 "Display detail of configured dampening parameters\n"
8724 "Display routes matching the route-map\n"
8725 "A route-map to match on\n"
8726 "Display routes conforming to the prefix-list\n"
8727 "Prefix-list name\n"
8728 "Display routes conforming to the filter-list\n"
8729 "Regular expression access list name\n"
8730 "BGP RIB advertisement statistics\n"
8731 "Display routes matching the communities\n"
8733 "Do not send outside local AS (well-known community)\n"
8734 "Do not advertise to any peer (well-known community)\n"
8735 "Do not export to next AS (well-known community)\n"
8736 "Graceful shutdown (well-known community)\n"
8737 "Exact match of the communities\n"
8738 "Display routes matching the community-list\n"
8739 "community-list number\n"
8740 "community-list name\n"
8741 "Exact match of the communities\n"
8743 "Display route and more specific routes\n"
8745 "Display route and more specific routes\n")
8747 afi_t afi
= AFI_IP6
;
8748 safi_t safi
= SAFI_UNICAST
;
8749 int exact_match
= 0;
8750 struct bgp
*bgp
= NULL
;
8752 int idx_community_type
= 0;
8754 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8759 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8760 if (argv_find(argv
, argc
, "parameters", &idx
))
8761 return bgp_show_dampening_parameters(vty
, afi
, safi
);
8764 if (argv_find(argv
, argc
, "prefix-list", &idx
))
8765 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8766 safi
, bgp_show_type_prefix_list
);
8768 if (argv_find(argv
, argc
, "filter-list", &idx
))
8769 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8770 safi
, bgp_show_type_filter_list
);
8772 if (argv_find(argv
, argc
, "statistics", &idx
))
8773 return bgp_table_stats(vty
, bgp
, afi
, safi
);
8775 if (argv_find(argv
, argc
, "route-map", &idx
))
8776 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
8777 safi
, bgp_show_type_route_map
);
8779 if (argv_find(argv
, argc
, "community", &idx
)) {
8780 /* show a specific community */
8781 if (argv_find(argv
, argc
, "local-AS", &idx_community_type
)
8782 || argv_find(argv
, argc
, "no-advertise",
8783 &idx_community_type
)
8784 || argv_find(argv
, argc
, "no-export", &idx_community_type
)
8785 || argv_find(argv
, argc
, "graceful-shutdown",
8786 &idx_community_type
)
8787 || argv_find(argv
, argc
, "AA:NN", &idx_community_type
)) {
8789 if (argv_find(argv
, argc
, "exact-match", &idx
))
8791 return bgp_show_community(vty
, bgp
,
8792 argv
[idx_community_type
]->arg
,
8793 exact_match
, afi
, safi
);
8797 if (argv_find(argv
, argc
, "community-list", &idx
)) {
8798 const char *clist_number_or_name
= argv
[++idx
]->arg
;
8799 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
8801 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
8802 exact_match
, afi
, safi
);
8805 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8806 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8807 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
8809 bgp_show_type_prefix_longer
);
8814 /* BGP route print out function with JSON */
8815 DEFUN (show_ip_bgp_json
,
8816 show_ip_bgp_json_cmd
,
8817 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
8820 |dampening <flap-statistics|dampened-paths>\
8826 BGP_INSTANCE_HELP_STR
8828 BGP_SAFI_WITH_LABEL_HELP_STR
8829 "Display only routes with non-natural netmasks\n"
8830 "Display detailed information about dampening\n"
8831 "Display flap statistics of routes\n"
8832 "Display paths suppressed due to dampening\n"
8833 "Display routes matching the communities\n"
8836 afi_t afi
= AFI_IP6
;
8837 safi_t safi
= SAFI_UNICAST
;
8838 enum bgp_show_type sh_type
= bgp_show_type_normal
;
8839 struct bgp
*bgp
= NULL
;
8842 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8847 int uj
= use_json(argc
, argv
);
8851 if (argv_find(argv
, argc
, "cidr-only", &idx
))
8852 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
8855 if (argv_find(argv
, argc
, "dampening", &idx
)) {
8856 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
8857 return bgp_show(vty
, bgp
, afi
, safi
,
8858 bgp_show_type_dampend_paths
, NULL
, uj
);
8859 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
8860 return bgp_show(vty
, bgp
, afi
, safi
,
8861 bgp_show_type_flap_statistics
, NULL
,
8865 if (argv_find(argv
, argc
, "community", &idx
)) {
8866 /* show all communities */
8867 return bgp_show(vty
, bgp
, afi
, safi
,
8868 bgp_show_type_community_all
, NULL
, uj
);
8870 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
8873 DEFUN (show_ip_bgp_route
,
8874 show_ip_bgp_route_cmd
,
8875 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
8876 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
8880 BGP_INSTANCE_HELP_STR
8882 BGP_SAFI_WITH_LABEL_HELP_STR
8883 "Network in the BGP routing table to display\n"
8885 "Network in the BGP routing table to display\n"
8887 "Display only the bestpath\n"
8888 "Display only multipaths\n"
8891 int prefix_check
= 0;
8893 afi_t afi
= AFI_IP6
;
8894 safi_t safi
= SAFI_UNICAST
;
8895 char *prefix
= NULL
;
8896 struct bgp
*bgp
= NULL
;
8897 enum bgp_path_type path_type
;
8898 u_char uj
= use_json(argc
, argv
);
8902 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8909 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
8913 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
8914 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
8915 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
8917 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
8918 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
8921 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
8922 && afi
!= AFI_IP6
) {
8924 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
8927 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
8930 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
8934 prefix
= argv
[idx
]->arg
;
8936 /* [<bestpath|multipath>] */
8937 if (argv_find(argv
, argc
, "bestpath", &idx
))
8938 path_type
= BGP_PATH_BESTPATH
;
8939 else if (argv_find(argv
, argc
, "multipath", &idx
))
8940 path_type
= BGP_PATH_MULTIPATH
;
8942 path_type
= BGP_PATH_ALL
;
8944 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
8948 DEFUN (show_ip_bgp_regexp
,
8949 show_ip_bgp_regexp_cmd
,
8950 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
8954 BGP_INSTANCE_HELP_STR
8956 BGP_SAFI_WITH_LABEL_HELP_STR
8957 "Display routes matching the AS path regular expression\n"
8958 "A regular-expression to match the BGP AS paths\n")
8960 afi_t afi
= AFI_IP6
;
8961 safi_t safi
= SAFI_UNICAST
;
8962 struct bgp
*bgp
= NULL
;
8965 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
8970 // get index of regex
8971 argv_find(argv
, argc
, "regexp", &idx
);
8974 char *regstr
= argv_concat(argv
, argc
, idx
);
8975 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
8976 bgp_show_type_regexp
);
8977 XFREE(MTYPE_TMP
, regstr
);
8981 DEFUN (show_ip_bgp_instance_all
,
8982 show_ip_bgp_instance_all_cmd
,
8983 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
8987 BGP_INSTANCE_ALL_HELP_STR
8989 BGP_SAFI_WITH_LABEL_HELP_STR
8993 safi_t safi
= SAFI_UNICAST
;
8994 struct bgp
*bgp
= NULL
;
8997 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9002 int uj
= use_json(argc
, argv
);
9006 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9010 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9011 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9016 regex
= bgp_regcomp(regstr
);
9018 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9022 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9023 bgp_regex_free(regex
);
9027 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9028 const char *prefix_list_str
, afi_t afi
,
9029 safi_t safi
, enum bgp_show_type type
)
9031 struct prefix_list
*plist
;
9033 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9034 if (plist
== NULL
) {
9035 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9040 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9043 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9044 const char *filter
, afi_t afi
, safi_t safi
,
9045 enum bgp_show_type type
)
9047 struct as_list
*as_list
;
9049 as_list
= as_list_lookup(filter
);
9050 if (as_list
== NULL
) {
9051 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9056 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9059 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9060 const char *rmap_str
, afi_t afi
, safi_t safi
,
9061 enum bgp_show_type type
)
9063 struct route_map
*rmap
;
9065 rmap
= route_map_lookup_by_name(rmap_str
);
9067 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9071 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9074 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9075 const char *comstr
, int exact
, afi_t afi
,
9078 struct community
*com
;
9081 com
= community_str2com(comstr
);
9083 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9087 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9088 (exact
? bgp_show_type_community_exact
9089 : bgp_show_type_community
),
9091 community_free(com
);
9096 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9097 const char *com
, int exact
, afi_t afi
,
9100 struct community_list
*list
;
9102 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9104 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9108 return bgp_show(vty
, bgp
, afi
, safi
,
9109 (exact
? bgp_show_type_community_list_exact
9110 : bgp_show_type_community_list
),
9114 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9115 const char *prefix
, afi_t afi
, safi_t safi
,
9116 enum bgp_show_type type
)
9123 ret
= str2prefix(prefix
, p
);
9125 vty_out(vty
, "%% Malformed Prefix\n");
9129 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9134 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9135 const char *ip_str
, u_char use_json
)
9141 /* Get peer sockunion. */
9142 ret
= str2sockunion(ip_str
, &su
);
9144 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9146 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9150 json_object
*json_no
= NULL
;
9151 json_no
= json_object_new_object();
9152 json_object_string_add(
9154 "malformedAddressOrName",
9156 vty_out(vty
, "%s\n",
9157 json_object_to_json_string_ext(
9159 JSON_C_TO_STRING_PRETTY
));
9160 json_object_free(json_no
);
9163 "%% Malformed address or name: %s\n",
9171 /* Peer structure lookup. */
9172 peer
= peer_lookup(bgp
, &su
);
9175 json_object
*json_no
= NULL
;
9176 json_no
= json_object_new_object();
9177 json_object_string_add(json_no
, "warning",
9178 "No such neighbor");
9179 vty_out(vty
, "%s\n",
9180 json_object_to_json_string_ext(
9181 json_no
, JSON_C_TO_STRING_PRETTY
));
9182 json_object_free(json_no
);
9184 vty_out(vty
, "No such neighbor\n");
9192 BGP_STATS_MAXBITLEN
= 0,
9196 BGP_STATS_UNAGGREGATEABLE
,
9197 BGP_STATS_MAX_AGGREGATEABLE
,
9198 BGP_STATS_AGGREGATES
,
9200 BGP_STATS_ASPATH_COUNT
,
9201 BGP_STATS_ASPATH_MAXHOPS
,
9202 BGP_STATS_ASPATH_TOTHOPS
,
9203 BGP_STATS_ASPATH_MAXSIZE
,
9204 BGP_STATS_ASPATH_TOTSIZE
,
9205 BGP_STATS_ASN_HIGHEST
,
9209 static const char *table_stats_strs
[] = {
9210 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9211 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9212 [BGP_STATS_RIB
] = "Total Advertisements",
9213 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9214 [BGP_STATS_MAX_AGGREGATEABLE
] =
9215 "Maximum aggregateable prefixes",
9216 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9217 [BGP_STATS_SPACE
] = "Address space advertised",
9218 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9219 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9220 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9221 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9222 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9223 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9224 [BGP_STATS_MAX
] = NULL
,
9227 struct bgp_table_stats
{
9228 struct bgp_table
*table
;
9229 unsigned long long counts
[BGP_STATS_MAX
];
9234 #define TALLY_SIGFIG 100000
9235 static unsigned long
9236 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9238 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9239 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9240 unsigned long ret
= newtot
/ count
;
9242 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9249 static int bgp_table_stats_walker(struct thread
*t
)
9251 struct bgp_node
*rn
;
9252 struct bgp_node
*top
;
9253 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9254 unsigned int space
= 0;
9256 if (!(top
= bgp_table_top(ts
->table
)))
9259 switch (top
->p
.family
) {
9261 space
= IPV4_MAX_BITLEN
;
9264 space
= IPV6_MAX_BITLEN
;
9268 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9270 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9271 struct bgp_info
*ri
;
9272 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9273 unsigned int rinum
= 0;
9281 ts
->counts
[BGP_STATS_PREFIXES
]++;
9282 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9285 ts
->counts
[BGP_STATS_AVGPLEN
]
9286 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9287 ts
->counts
[BGP_STATS_AVGPLEN
],
9291 /* check if the prefix is included by any other announcements */
9292 while (prn
&& !prn
->info
)
9293 prn
= bgp_node_parent_nolock(prn
);
9295 if (prn
== NULL
|| prn
== top
) {
9296 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9297 /* announced address space */
9300 pow(2.0, space
- rn
->p
.prefixlen
);
9301 } else if (prn
->info
)
9302 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9304 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9306 ts
->counts
[BGP_STATS_RIB
]++;
9309 && (CHECK_FLAG(ri
->attr
->flag
,
9311 BGP_ATTR_ATOMIC_AGGREGATE
))))
9312 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9315 if (ri
->attr
&& ri
->attr
->aspath
) {
9317 aspath_count_hops(ri
->attr
->aspath
);
9319 aspath_size(ri
->attr
->aspath
);
9320 as_t highest
= aspath_highest(ri
->attr
->aspath
);
9322 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9324 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9325 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9328 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9329 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9332 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9333 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9335 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9336 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9337 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9339 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9340 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9341 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9344 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9345 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9353 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9356 struct bgp_table_stats ts
;
9359 if (!bgp
->rib
[afi
][safi
]) {
9360 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9365 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9367 /* labeled-unicast routes live in the unicast table */
9368 if (safi
== SAFI_LABELED_UNICAST
)
9369 safi
= SAFI_UNICAST
;
9371 memset(&ts
, 0, sizeof(ts
));
9372 ts
.table
= bgp
->rib
[afi
][safi
];
9373 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9375 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9376 if (!table_stats_strs
[i
])
9381 case BGP_STATS_ASPATH_AVGHOPS
:
9382 case BGP_STATS_ASPATH_AVGSIZE
:
9383 case BGP_STATS_AVGPLEN
:
9384 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9385 vty_out (vty
, "%12.2f",
9386 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9389 case BGP_STATS_ASPATH_TOTHOPS
:
9390 case BGP_STATS_ASPATH_TOTSIZE
:
9391 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9392 vty_out(vty
, "%12.2f",
9394 ? (float)ts
.counts
[i
]
9396 [BGP_STATS_ASPATH_COUNT
]
9399 case BGP_STATS_TOTPLEN
:
9400 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9401 vty_out(vty
, "%12.2f",
9403 ? (float)ts
.counts
[i
]
9405 [BGP_STATS_PREFIXES
]
9408 case BGP_STATS_SPACE
:
9409 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9410 vty_out(vty
, "%12g\n", ts
.total_space
);
9412 if (afi
== AFI_IP6
) {
9413 vty_out(vty
, "%30s: ", "/32 equivalent ");
9414 vty_out(vty
, "%12g\n",
9415 ts
.total_space
* pow(2.0, -128 + 32));
9416 vty_out(vty
, "%30s: ", "/48 equivalent ");
9417 vty_out(vty
, "%12g\n",
9418 ts
.total_space
* pow(2.0, -128 + 48));
9420 vty_out(vty
, "%30s: ", "% announced ");
9421 vty_out(vty
, "%12.2f\n",
9422 ts
.total_space
* 100. * pow(2.0, -32));
9423 vty_out(vty
, "%30s: ", "/8 equivalent ");
9424 vty_out(vty
, "%12.2f\n",
9425 ts
.total_space
* pow(2.0, -32 + 8));
9426 vty_out(vty
, "%30s: ", "/24 equivalent ");
9427 vty_out(vty
, "%12.2f\n",
9428 ts
.total_space
* pow(2.0, -32 + 24));
9432 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9433 vty_out(vty
, "%12llu", ts
.counts
[i
]);
9450 PCOUNT_PFCNT
, /* the figure we display to users */
9454 static const char *pcount_strs
[] = {
9455 [PCOUNT_ADJ_IN
] = "Adj-in",
9456 [PCOUNT_DAMPED
] = "Damped",
9457 [PCOUNT_REMOVED
] = "Removed",
9458 [PCOUNT_HISTORY
] = "History",
9459 [PCOUNT_STALE
] = "Stale",
9460 [PCOUNT_VALID
] = "Valid",
9461 [PCOUNT_ALL
] = "All RIB",
9462 [PCOUNT_COUNTED
] = "PfxCt counted",
9463 [PCOUNT_PFCNT
] = "Useable",
9464 [PCOUNT_MAX
] = NULL
,
9467 struct peer_pcounts
{
9468 unsigned int count
[PCOUNT_MAX
];
9469 const struct peer
*peer
;
9470 const struct bgp_table
*table
;
9473 static int bgp_peer_count_walker(struct thread
*t
)
9475 struct bgp_node
*rn
;
9476 struct peer_pcounts
*pc
= THREAD_ARG(t
);
9477 const struct peer
*peer
= pc
->peer
;
9479 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
9480 struct bgp_adj_in
*ain
;
9481 struct bgp_info
*ri
;
9483 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
9484 if (ain
->peer
== peer
)
9485 pc
->count
[PCOUNT_ADJ_IN
]++;
9487 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
9488 char buf
[SU_ADDRSTRLEN
];
9490 if (ri
->peer
!= peer
)
9493 pc
->count
[PCOUNT_ALL
]++;
9495 if (CHECK_FLAG(ri
->flags
, BGP_INFO_DAMPED
))
9496 pc
->count
[PCOUNT_DAMPED
]++;
9497 if (CHECK_FLAG(ri
->flags
, BGP_INFO_HISTORY
))
9498 pc
->count
[PCOUNT_HISTORY
]++;
9499 if (CHECK_FLAG(ri
->flags
, BGP_INFO_REMOVED
))
9500 pc
->count
[PCOUNT_REMOVED
]++;
9501 if (CHECK_FLAG(ri
->flags
, BGP_INFO_STALE
))
9502 pc
->count
[PCOUNT_STALE
]++;
9503 if (CHECK_FLAG(ri
->flags
, BGP_INFO_VALID
))
9504 pc
->count
[PCOUNT_VALID
]++;
9505 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9506 pc
->count
[PCOUNT_PFCNT
]++;
9508 if (CHECK_FLAG(ri
->flags
, BGP_INFO_COUNTED
)) {
9509 pc
->count
[PCOUNT_COUNTED
]++;
9510 if (CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9512 "%s [pcount] %s/%d is counted but flags 0x%x",
9514 inet_ntop(rn
->p
.family
,
9515 &rn
->p
.u
.prefix
, buf
,
9517 rn
->p
.prefixlen
, ri
->flags
);
9519 if (!CHECK_FLAG(ri
->flags
, BGP_INFO_UNUSEABLE
))
9521 "%s [pcount] %s/%d not counted but flags 0x%x",
9523 inet_ntop(rn
->p
.family
,
9524 &rn
->p
.u
.prefix
, buf
,
9526 rn
->p
.prefixlen
, ri
->flags
);
9533 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9534 safi_t safi
, u_char use_json
)
9536 struct peer_pcounts pcounts
= {.peer
= peer
};
9538 json_object
*json
= NULL
;
9539 json_object
*json_loop
= NULL
;
9542 json
= json_object_new_object();
9543 json_loop
= json_object_new_object();
9546 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
9547 || !peer
->bgp
->rib
[afi
][safi
]) {
9549 json_object_string_add(
9551 "No such neighbor or address family");
9552 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9553 json_object_free(json
);
9555 vty_out(vty
, "%% No such neighbor or address family\n");
9560 memset(&pcounts
, 0, sizeof(pcounts
));
9561 pcounts
.peer
= peer
;
9562 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
9564 /* in-place call via thread subsystem so as to record execution time
9565 * stats for the thread-walk (i.e. ensure this can't be blamed on
9566 * on just vty_read()).
9568 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
9571 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
9572 json_object_string_add(json
, "multiProtocol",
9573 afi_safi_print(afi
, safi
));
9574 json_object_int_add(json
, "pfxCounter",
9575 peer
->pcount
[afi
][safi
]);
9577 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9578 json_object_int_add(json_loop
, pcount_strs
[i
],
9581 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
9583 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9584 json_object_string_add(json
, "pfxctDriftFor",
9586 json_object_string_add(
9587 json
, "recommended",
9588 "Please report this bug, with the above command output");
9590 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9591 json
, JSON_C_TO_STRING_PRETTY
));
9592 json_object_free(json
);
9596 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
9597 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
9598 peer
->hostname
, peer
->host
,
9599 afi_safi_print(afi
, safi
));
9601 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
9602 afi_safi_print(afi
, safi
));
9605 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
9606 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
9608 for (i
= 0; i
< PCOUNT_MAX
; i
++)
9609 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
9612 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
9613 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
9615 "Please report this bug, with the above command output\n");
9622 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
9623 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
9624 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
9625 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9629 BGP_INSTANCE_HELP_STR
9632 "Detailed information on TCP and BGP neighbor connections\n"
9633 "Neighbor to display information about\n"
9634 "Neighbor to display information about\n"
9635 "Neighbor on BGP configured interface\n"
9636 "Display detailed prefix count information\n"
9639 afi_t afi
= AFI_IP6
;
9640 safi_t safi
= SAFI_UNICAST
;
9643 struct bgp
*bgp
= NULL
;
9645 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9650 int uj
= use_json(argc
, argv
);
9654 argv_find(argv
, argc
, "neighbors", &idx
);
9655 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
9659 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
9662 #ifdef KEEP_OLD_VPN_COMMANDS
9663 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
9664 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
9665 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
9670 "Display information about all VPNv4 NLRIs\n"
9671 "Detailed information on TCP and BGP neighbor connections\n"
9672 "Neighbor to display information about\n"
9673 "Neighbor to display information about\n"
9674 "Neighbor on BGP configured interface\n"
9675 "Display detailed prefix count information\n"
9680 u_char uj
= use_json(argc
, argv
);
9682 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
9686 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
9689 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
9690 show_ip_bgp_vpn_all_route_prefix_cmd
,
9691 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
9696 "Display information about all VPNv4 NLRIs\n"
9697 "Network in the BGP routing table to display\n"
9698 "Network in the BGP routing table to display\n"
9702 char *network
= NULL
;
9703 struct bgp
*bgp
= bgp_get_default();
9705 vty_out(vty
, "Can't find default instance\n");
9709 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9710 network
= argv
[idx
]->arg
;
9711 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9712 network
= argv
[idx
]->arg
;
9714 vty_out(vty
, "Unable to figure out Network\n");
9718 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
9719 BGP_PATH_ALL
, use_json(argc
, argv
));
9721 #endif /* KEEP_OLD_VPN_COMMANDS */
9723 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
9724 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
9725 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
9731 "Display information about all EVPN NLRIs\n"
9732 "Network in the BGP routing table to display\n"
9733 "Network in the BGP routing table to display\n"
9737 char *network
= NULL
;
9739 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
9740 network
= argv
[idx
]->arg
;
9741 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
9742 network
= argv
[idx
]->arg
;
9744 vty_out(vty
, "Unable to figure out Network\n");
9747 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
9748 BGP_PATH_ALL
, use_json(argc
, argv
));
9751 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9752 safi_t safi
, int in
, const char *rmap_name
,
9753 u_char use_json
, json_object
*json
)
9755 struct bgp_table
*table
;
9756 struct bgp_adj_in
*ain
;
9757 struct bgp_adj_out
*adj
;
9758 unsigned long output_count
;
9759 unsigned long filtered_count
;
9760 struct bgp_node
*rn
;
9766 struct update_subgroup
*subgrp
;
9767 json_object
*json_scode
= NULL
;
9768 json_object
*json_ocode
= NULL
;
9769 json_object
*json_ar
= NULL
;
9770 struct peer_af
*paf
;
9773 json_scode
= json_object_new_object();
9774 json_ocode
= json_object_new_object();
9775 json_ar
= json_object_new_object();
9777 json_object_string_add(json_scode
, "suppressed", "s");
9778 json_object_string_add(json_scode
, "damped", "d");
9779 json_object_string_add(json_scode
, "history", "h");
9780 json_object_string_add(json_scode
, "valid", "*");
9781 json_object_string_add(json_scode
, "best", ">");
9782 json_object_string_add(json_scode
, "multipath", "=");
9783 json_object_string_add(json_scode
, "internal", "i");
9784 json_object_string_add(json_scode
, "ribFailure", "r");
9785 json_object_string_add(json_scode
, "stale", "S");
9786 json_object_string_add(json_scode
, "removed", "R");
9788 json_object_string_add(json_ocode
, "igp", "i");
9789 json_object_string_add(json_ocode
, "egp", "e");
9790 json_object_string_add(json_ocode
, "incomplete", "?");
9797 json_object_string_add(json
, "alert", "no BGP");
9798 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9799 json_object_free(json
);
9801 vty_out(vty
, "%% No bgp\n");
9805 table
= bgp
->rib
[afi
][safi
];
9807 output_count
= filtered_count
= 0;
9808 subgrp
= peer_subgroup(peer
, afi
, safi
);
9811 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
9813 json_object_int_add(json
, "bgpTableVersion",
9815 json_object_string_add(json
, "bgpLocalRouterId",
9816 inet_ntoa(bgp
->router_id
));
9817 json_object_object_add(json
, "bgpStatusCodes",
9819 json_object_object_add(json
, "bgpOriginCodes",
9821 json_object_string_add(json
,
9822 "bgpOriginatingDefaultNetwork",
9825 vty_out(vty
, "BGP table version is %" PRIu64
9826 ", local router ID is %s\n",
9827 table
->version
, inet_ntoa(bgp
->router_id
));
9828 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9829 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9831 vty_out(vty
, "Originating default network 0.0.0.0\n\n");
9836 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9838 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
9839 if (ain
->peer
!= peer
)
9843 json_object_int_add(
9844 json
, "bgpTableVersion",
9846 json_object_string_add(
9851 json_object_object_add(
9852 json
, "bgpStatusCodes",
9854 json_object_object_add(
9855 json
, "bgpOriginCodes",
9859 "BGP table version is 0, local router ID is %s\n",
9863 BGP_SHOW_SCODE_HEADER
);
9865 BGP_SHOW_OCODE_HEADER
);
9871 vty_out(vty
, BGP_SHOW_HEADER
);
9875 bgp_attr_dup(&attr
, ain
->attr
);
9876 if (bgp_input_modifier(peer
, &rn
->p
,
9880 route_vty_out_tmp(vty
, &rn
->p
,
9890 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
9891 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
9892 if (paf
->peer
!= peer
)
9897 json_object_int_add(
9901 json_object_string_add(
9906 json_object_object_add(
9910 json_object_object_add(
9916 "BGP table version is %" PRIu64
9917 ", local router ID is %s\n",
9922 BGP_SHOW_SCODE_HEADER
);
9924 BGP_SHOW_OCODE_HEADER
);
9937 bgp_attr_dup(&attr
, adj
->attr
);
9938 ret
= bgp_output_modifier(
9939 peer
, &rn
->p
, &attr
,
9940 afi
, safi
, rmap_name
);
9941 if (ret
!= RMAP_DENY
) {
9951 bgp_attr_undup(&attr
,
9958 json_object_object_add(json
, "advertisedRoutes", json_ar
);
9960 if (output_count
!= 0) {
9962 json_object_int_add(json
, "totalPrefixCounter",
9965 vty_out(vty
, "\nTotal number of prefixes %ld\n",
9969 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9970 json
, JSON_C_TO_STRING_PRETTY
));
9971 json_object_free(json
);
9975 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
9976 safi_t safi
, int in
, const char *rmap_name
,
9979 json_object
*json
= NULL
;
9982 json
= json_object_new_object();
9984 /* labeled-unicast routes live in the unicast table */
9985 if (safi
== SAFI_LABELED_UNICAST
)
9986 safi
= SAFI_UNICAST
;
9988 if (!peer
|| !peer
->afc
[afi
][safi
]) {
9990 json_object_string_add(
9992 "No such neighbor or address family");
9993 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
9994 json_object_free(json
);
9996 vty_out(vty
, "%% No such neighbor or address family\n");
10002 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10003 PEER_FLAG_SOFT_RECONFIG
)) {
10005 json_object_string_add(
10007 "Inbound soft reconfiguration not enabled");
10008 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10009 json_object_free(json
);
10012 "%% Inbound soft reconfiguration not enabled\n");
10014 return CMD_WARNING
;
10017 show_adj_route(vty
, peer
, afi
, safi
, in
, rmap_name
, use_json
, json
);
10019 return CMD_SUCCESS
;
10022 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10023 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10025 "neighbors <A.B.C.D|X:X::X:X|WORD> <received-routes|advertised-routes> [route-map WORD] [json]",
10029 BGP_INSTANCE_HELP_STR
10031 BGP_SAFI_WITH_LABEL_HELP_STR
10032 "Detailed information on TCP and BGP neighbor connections\n"
10033 "Neighbor to display information about\n"
10034 "Neighbor to display information about\n"
10035 "Neighbor on BGP configured interface\n"
10036 "Display the received routes from neighbor\n"
10037 "Display the routes advertised to a BGP neighbor\n"
10038 "Route-map to modify the attributes\n"
10039 "Name of the route map\n"
10042 afi_t afi
= AFI_IP6
;
10043 safi_t safi
= SAFI_UNICAST
;
10044 char *rmap_name
= NULL
;
10045 char *peerstr
= NULL
;
10047 struct bgp
*bgp
= NULL
;
10052 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10055 return CMD_WARNING
;
10057 int uj
= use_json(argc
, argv
);
10061 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10062 argv_find(argv
, argc
, "neighbors", &idx
);
10063 peerstr
= argv
[++idx
]->arg
;
10065 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10067 return CMD_WARNING
;
10069 if (argv_find(argv
, argc
, "received-routes", &idx
))
10071 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10073 if (argv_find(argv
, argc
, "route-map", &idx
))
10074 rmap_name
= argv
[++idx
]->arg
;
10076 return peer_adj_routes(vty
, peer
, afi
, safi
, rcvd
, rmap_name
, uj
);
10079 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10080 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10081 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10087 "Address Family modifier\n"
10088 "Detailed information on TCP and BGP neighbor connections\n"
10089 "Neighbor to display information about\n"
10090 "Neighbor to display information about\n"
10091 "Neighbor on BGP configured interface\n"
10092 "Display information received from a BGP neighbor\n"
10093 "Display the prefixlist filter\n"
10096 afi_t afi
= AFI_IP6
;
10097 safi_t safi
= SAFI_UNICAST
;
10098 char *peerstr
= NULL
;
10101 union sockunion su
;
10107 /* show [ip] bgp */
10108 if (argv_find(argv
, argc
, "ip", &idx
))
10110 /* [<ipv4|ipv6> [unicast]] */
10111 if (argv_find(argv
, argc
, "ipv4", &idx
))
10113 if (argv_find(argv
, argc
, "ipv6", &idx
))
10115 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10116 argv_find(argv
, argc
, "neighbors", &idx
);
10117 peerstr
= argv
[++idx
]->arg
;
10119 u_char uj
= use_json(argc
, argv
);
10121 ret
= str2sockunion(peerstr
, &su
);
10123 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10126 vty_out(vty
, "{}\n");
10129 "%% Malformed address or name: %s\n",
10131 return CMD_WARNING
;
10134 peer
= peer_lookup(NULL
, &su
);
10137 vty_out(vty
, "{}\n");
10139 vty_out(vty
, "No peer\n");
10140 return CMD_WARNING
;
10144 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10145 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10148 vty_out(vty
, "Address Family: %s\n",
10149 afi_safi_print(afi
, safi
));
10150 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10153 vty_out(vty
, "{}\n");
10155 vty_out(vty
, "No functional output\n");
10158 return CMD_SUCCESS
;
10161 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10162 afi_t afi
, safi_t safi
,
10163 enum bgp_show_type type
, u_char use_json
)
10165 /* labeled-unicast routes live in the unicast table */
10166 if (safi
== SAFI_LABELED_UNICAST
)
10167 safi
= SAFI_UNICAST
;
10169 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10171 json_object
*json_no
= NULL
;
10172 json_no
= json_object_new_object();
10173 json_object_string_add(
10174 json_no
, "warning",
10175 "No such neighbor or address family");
10176 vty_out(vty
, "%s\n",
10177 json_object_to_json_string(json_no
));
10178 json_object_free(json_no
);
10180 vty_out(vty
, "%% No such neighbor or address family\n");
10181 return CMD_WARNING
;
10184 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10187 DEFUN (show_ip_bgp_neighbor_routes
,
10188 show_ip_bgp_neighbor_routes_cmd
,
10189 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10190 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10194 BGP_INSTANCE_HELP_STR
10196 BGP_SAFI_WITH_LABEL_HELP_STR
10197 "Detailed information on TCP and BGP neighbor connections\n"
10198 "Neighbor to display information about\n"
10199 "Neighbor to display information about\n"
10200 "Neighbor on BGP configured interface\n"
10201 "Display flap statistics of the routes learned from neighbor\n"
10202 "Display the dampened routes received from neighbor\n"
10203 "Display routes learned from neighbor\n"
10206 char *peerstr
= NULL
;
10207 struct bgp
*bgp
= NULL
;
10208 afi_t afi
= AFI_IP6
;
10209 safi_t safi
= SAFI_UNICAST
;
10211 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10215 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10218 return CMD_WARNING
;
10220 int uj
= use_json(argc
, argv
);
10224 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10225 argv_find(argv
, argc
, "neighbors", &idx
);
10226 peerstr
= argv
[++idx
]->arg
;
10228 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10230 vty_out(vty
, "No such neighbor\n");
10231 return CMD_WARNING
;
10234 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10235 sh_type
= bgp_show_type_flap_neighbor
;
10236 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10237 sh_type
= bgp_show_type_damp_neighbor
;
10238 else if (argv_find(argv
, argc
, "routes", &idx
))
10239 sh_type
= bgp_show_type_neighbor
;
10241 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10244 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10246 struct bgp_distance
{
10247 /* Distance value for the IP source prefix. */
10250 /* Name of the access-list to be matched. */
10254 DEFUN (show_bgp_afi_vpn_rd_route
,
10255 show_bgp_afi_vpn_rd_route_cmd
,
10256 "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]",
10260 "Address Family modifier\n"
10261 "Display information for a route distinguisher\n"
10262 "Route Distinguisher\n"
10263 "Network in the BGP routing table to display\n"
10264 "Network in the BGP routing table to display\n"
10268 struct prefix_rd prd
;
10269 afi_t afi
= AFI_MAX
;
10272 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10273 vty_out(vty
, "%% Malformed Address Family\n");
10274 return CMD_WARNING
;
10277 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10279 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10280 return CMD_WARNING
;
10283 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10284 0, BGP_PATH_ALL
, use_json(argc
, argv
));
10287 static struct bgp_distance
*bgp_distance_new(void)
10289 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10292 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10294 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10297 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10298 const char *ip_str
, const char *access_list_str
)
10305 struct bgp_node
*rn
;
10306 struct bgp_distance
*bdistance
;
10308 afi
= bgp_node_afi(vty
);
10309 safi
= bgp_node_safi(vty
);
10311 ret
= str2prefix(ip_str
, &p
);
10313 vty_out(vty
, "Malformed prefix\n");
10314 return CMD_WARNING_CONFIG_FAILED
;
10317 distance
= atoi(distance_str
);
10319 /* Get BGP distance node. */
10320 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10322 bdistance
= rn
->info
;
10323 bgp_unlock_node(rn
);
10325 bdistance
= bgp_distance_new();
10326 rn
->info
= bdistance
;
10329 /* Set distance value. */
10330 bdistance
->distance
= distance
;
10332 /* Reset access-list configuration. */
10333 if (bdistance
->access_list
) {
10334 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10335 bdistance
->access_list
= NULL
;
10337 if (access_list_str
)
10338 bdistance
->access_list
=
10339 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
10341 return CMD_SUCCESS
;
10344 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
10345 const char *ip_str
, const char *access_list_str
)
10352 struct bgp_node
*rn
;
10353 struct bgp_distance
*bdistance
;
10355 afi
= bgp_node_afi(vty
);
10356 safi
= bgp_node_safi(vty
);
10358 ret
= str2prefix(ip_str
, &p
);
10360 vty_out(vty
, "Malformed prefix\n");
10361 return CMD_WARNING_CONFIG_FAILED
;
10364 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
10365 (struct prefix
*)&p
);
10367 vty_out(vty
, "Can't find specified prefix\n");
10368 return CMD_WARNING_CONFIG_FAILED
;
10371 bdistance
= rn
->info
;
10372 distance
= atoi(distance_str
);
10374 if (bdistance
->distance
!= distance
) {
10375 vty_out(vty
, "Distance does not match configured\n");
10376 return CMD_WARNING_CONFIG_FAILED
;
10379 if (bdistance
->access_list
)
10380 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
10381 bgp_distance_free(bdistance
);
10384 bgp_unlock_node(rn
);
10385 bgp_unlock_node(rn
);
10387 return CMD_SUCCESS
;
10390 /* Apply BGP information to distance method. */
10391 u_char
bgp_distance_apply(struct prefix
*p
, struct bgp_info
*rinfo
, afi_t afi
,
10392 safi_t safi
, struct bgp
*bgp
)
10394 struct bgp_node
*rn
;
10397 struct bgp_distance
*bdistance
;
10398 struct access_list
*alist
;
10399 struct bgp_static
*bgp_static
;
10404 peer
= rinfo
->peer
;
10406 /* Check source address. */
10407 sockunion2hostprefix(&peer
->su
, &q
);
10408 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
10410 bdistance
= rn
->info
;
10411 bgp_unlock_node(rn
);
10413 if (bdistance
->access_list
) {
10414 alist
= access_list_lookup(afi
, bdistance
->access_list
);
10416 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
10417 return bdistance
->distance
;
10419 return bdistance
->distance
;
10422 /* Backdoor check. */
10423 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
10425 bgp_static
= rn
->info
;
10426 bgp_unlock_node(rn
);
10428 if (bgp_static
->backdoor
) {
10429 if (bgp
->distance_local
[afi
][safi
])
10430 return bgp
->distance_local
[afi
][safi
];
10432 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10436 if (peer
->sort
== BGP_PEER_EBGP
) {
10437 if (bgp
->distance_ebgp
[afi
][safi
])
10438 return bgp
->distance_ebgp
[afi
][safi
];
10439 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
10441 if (bgp
->distance_ibgp
[afi
][safi
])
10442 return bgp
->distance_ibgp
[afi
][safi
];
10443 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
10447 DEFUN (bgp_distance
,
10449 "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
);
10457 int idx_number
= 2;
10458 int idx_number_2
= 3;
10459 int idx_number_3
= 4;
10463 afi
= bgp_node_afi(vty
);
10464 safi
= bgp_node_safi(vty
);
10466 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
10467 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
10468 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
10469 return CMD_SUCCESS
;
10472 DEFUN (no_bgp_distance
,
10473 no_bgp_distance_cmd
,
10474 "no distance bgp [(1-255) (1-255) (1-255)]",
10476 "Define an administrative distance\n"
10478 "Distance for routes external to the AS\n"
10479 "Distance for routes internal to the AS\n"
10480 "Distance for local routes\n")
10482 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10486 afi
= bgp_node_afi(vty
);
10487 safi
= bgp_node_safi(vty
);
10489 bgp
->distance_ebgp
[afi
][safi
] = 0;
10490 bgp
->distance_ibgp
[afi
][safi
] = 0;
10491 bgp
->distance_local
[afi
][safi
] = 0;
10492 return CMD_SUCCESS
;
10496 DEFUN (bgp_distance_source
,
10497 bgp_distance_source_cmd
,
10498 "distance (1-255) A.B.C.D/M",
10499 "Define an administrative distance\n"
10500 "Administrative distance\n"
10501 "IP source prefix\n")
10503 int idx_number
= 1;
10504 int idx_ipv4_prefixlen
= 2;
10505 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10506 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10507 return CMD_SUCCESS
;
10510 DEFUN (no_bgp_distance_source
,
10511 no_bgp_distance_source_cmd
,
10512 "no distance (1-255) A.B.C.D/M",
10514 "Define an administrative distance\n"
10515 "Administrative distance\n"
10516 "IP source prefix\n")
10518 int idx_number
= 2;
10519 int idx_ipv4_prefixlen
= 3;
10520 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10521 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
10522 return CMD_SUCCESS
;
10525 DEFUN (bgp_distance_source_access_list
,
10526 bgp_distance_source_access_list_cmd
,
10527 "distance (1-255) A.B.C.D/M WORD",
10528 "Define an administrative distance\n"
10529 "Administrative distance\n"
10530 "IP source prefix\n"
10531 "Access list name\n")
10533 int idx_number
= 1;
10534 int idx_ipv4_prefixlen
= 2;
10536 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
10537 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10538 return CMD_SUCCESS
;
10541 DEFUN (no_bgp_distance_source_access_list
,
10542 no_bgp_distance_source_access_list_cmd
,
10543 "no distance (1-255) A.B.C.D/M WORD",
10545 "Define an administrative distance\n"
10546 "Administrative distance\n"
10547 "IP source prefix\n"
10548 "Access list name\n")
10550 int idx_number
= 2;
10551 int idx_ipv4_prefixlen
= 3;
10553 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
10554 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
10555 return CMD_SUCCESS
;
10558 DEFUN (ipv6_bgp_distance_source
,
10559 ipv6_bgp_distance_source_cmd
,
10560 "distance (1-255) X:X::X:X/M",
10561 "Define an administrative distance\n"
10562 "Administrative distance\n"
10563 "IP source prefix\n")
10565 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
10566 return CMD_SUCCESS
;
10569 DEFUN (no_ipv6_bgp_distance_source
,
10570 no_ipv6_bgp_distance_source_cmd
,
10571 "no distance (1-255) X:X::X:X/M",
10573 "Define an administrative distance\n"
10574 "Administrative distance\n"
10575 "IP source prefix\n")
10577 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
10578 return CMD_SUCCESS
;
10581 DEFUN (ipv6_bgp_distance_source_access_list
,
10582 ipv6_bgp_distance_source_access_list_cmd
,
10583 "distance (1-255) X:X::X:X/M WORD",
10584 "Define an administrative distance\n"
10585 "Administrative distance\n"
10586 "IP source prefix\n"
10587 "Access list name\n")
10589 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
10590 return CMD_SUCCESS
;
10593 DEFUN (no_ipv6_bgp_distance_source_access_list
,
10594 no_ipv6_bgp_distance_source_access_list_cmd
,
10595 "no distance (1-255) X:X::X:X/M WORD",
10597 "Define an administrative distance\n"
10598 "Administrative distance\n"
10599 "IP source prefix\n"
10600 "Access list name\n")
10602 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
10603 return CMD_SUCCESS
;
10606 DEFUN (bgp_damp_set
,
10608 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10609 "BGP Specific commands\n"
10610 "Enable route-flap dampening\n"
10611 "Half-life time for the penalty\n"
10612 "Value to start reusing a route\n"
10613 "Value to start suppressing a route\n"
10614 "Maximum duration to suppress a stable route\n")
10616 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10617 int idx_half_life
= 2;
10619 int idx_suppress
= 4;
10620 int idx_max_suppress
= 5;
10621 int half
= DEFAULT_HALF_LIFE
* 60;
10622 int reuse
= DEFAULT_REUSE
;
10623 int suppress
= DEFAULT_SUPPRESS
;
10624 int max
= 4 * half
;
10627 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10628 reuse
= atoi(argv
[idx_reuse
]->arg
);
10629 suppress
= atoi(argv
[idx_suppress
]->arg
);
10630 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
10631 } else if (argc
== 3) {
10632 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
10636 if (suppress
< reuse
) {
10638 "Suppress value cannot be less than reuse value \n");
10642 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
10643 reuse
, suppress
, max
);
10646 DEFUN (bgp_damp_unset
,
10647 bgp_damp_unset_cmd
,
10648 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
10650 "BGP Specific commands\n"
10651 "Enable route-flap dampening\n"
10652 "Half-life time for the penalty\n"
10653 "Value to start reusing a route\n"
10654 "Value to start suppressing a route\n"
10655 "Maximum duration to suppress a stable route\n")
10657 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
10658 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
10661 /* Display specified route of BGP table. */
10662 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
10663 const char *ip_str
, afi_t afi
, safi_t safi
,
10664 struct prefix_rd
*prd
, int prefix_check
)
10667 struct prefix match
;
10668 struct bgp_node
*rn
;
10669 struct bgp_node
*rm
;
10670 struct bgp_info
*ri
;
10671 struct bgp_info
*ri_temp
;
10673 struct bgp_table
*table
;
10675 /* BGP structure lookup. */
10677 bgp
= bgp_lookup_by_name(view_name
);
10679 vty_out(vty
, "%% Can't find BGP instance %s\n",
10681 return CMD_WARNING
;
10684 bgp
= bgp_get_default();
10686 vty_out(vty
, "%% No BGP process is configured\n");
10687 return CMD_WARNING
;
10691 /* Check IP address argument. */
10692 ret
= str2prefix(ip_str
, &match
);
10694 vty_out(vty
, "%% address is malformed\n");
10695 return CMD_WARNING
;
10698 match
.family
= afi2family(afi
);
10700 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
10701 || (safi
== SAFI_EVPN
)) {
10702 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
10703 rn
= bgp_route_next(rn
)) {
10704 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
10706 if ((table
= rn
->info
) == NULL
)
10708 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
10712 || rm
->p
.prefixlen
== match
.prefixlen
) {
10715 if (ri
->extra
&& ri
->extra
->damp_info
) {
10716 ri_temp
= ri
->next
;
10717 bgp_damp_info_free(
10718 ri
->extra
->damp_info
,
10726 bgp_unlock_node(rm
);
10729 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
10732 || rn
->p
.prefixlen
== match
.prefixlen
) {
10735 if (ri
->extra
&& ri
->extra
->damp_info
) {
10736 ri_temp
= ri
->next
;
10737 bgp_damp_info_free(
10738 ri
->extra
->damp_info
,
10746 bgp_unlock_node(rn
);
10750 return CMD_SUCCESS
;
10753 DEFUN (clear_ip_bgp_dampening
,
10754 clear_ip_bgp_dampening_cmd
,
10755 "clear ip bgp dampening",
10759 "Clear route flap dampening information\n")
10761 bgp_damp_info_clean();
10762 return CMD_SUCCESS
;
10765 DEFUN (clear_ip_bgp_dampening_prefix
,
10766 clear_ip_bgp_dampening_prefix_cmd
,
10767 "clear ip bgp dampening A.B.C.D/M",
10771 "Clear route flap dampening information\n"
10774 int idx_ipv4_prefixlen
= 4;
10775 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
10776 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
10779 DEFUN (clear_ip_bgp_dampening_address
,
10780 clear_ip_bgp_dampening_address_cmd
,
10781 "clear ip bgp dampening A.B.C.D",
10785 "Clear route flap dampening information\n"
10786 "Network to clear damping information\n")
10789 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
10790 SAFI_UNICAST
, NULL
, 0);
10793 DEFUN (clear_ip_bgp_dampening_address_mask
,
10794 clear_ip_bgp_dampening_address_mask_cmd
,
10795 "clear ip bgp dampening A.B.C.D A.B.C.D",
10799 "Clear route flap dampening information\n"
10800 "Network to clear damping information\n"
10804 int idx_ipv4_2
= 5;
10806 char prefix_str
[BUFSIZ
];
10808 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
10811 vty_out(vty
, "%% Inconsistent address and mask\n");
10812 return CMD_WARNING
;
10815 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
10819 /* also used for encap safi */
10820 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
10821 afi_t afi
, safi_t safi
)
10823 struct bgp_node
*prn
;
10824 struct bgp_node
*rn
;
10825 struct bgp_table
*table
;
10827 struct prefix_rd
*prd
;
10828 struct bgp_static
*bgp_static
;
10829 mpls_label_t label
;
10830 char buf
[SU_ADDRSTRLEN
];
10831 char rdbuf
[RD_ADDRSTRLEN
];
10833 /* Network configuration. */
10834 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10835 prn
= bgp_route_next(prn
)) {
10836 if ((table
= prn
->info
) == NULL
)
10839 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10840 if ((bgp_static
= rn
->info
) == NULL
)
10844 prd
= (struct prefix_rd
*)&prn
->p
;
10846 /* "network" configuration display. */
10847 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
10848 label
= decode_label(&bgp_static
->label
);
10850 vty_out(vty
, " network %s/%d rd %s",
10851 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10853 p
->prefixlen
, rdbuf
);
10854 if (safi
== SAFI_MPLS_VPN
)
10855 vty_out(vty
, " label %u", label
);
10857 if (bgp_static
->rmap
.name
)
10858 vty_out(vty
, " route-map %s",
10859 bgp_static
->rmap
.name
);
10861 if (bgp_static
->backdoor
)
10862 vty_out(vty
, " backdoor");
10864 vty_out(vty
, "\n");
10869 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
10870 afi_t afi
, safi_t safi
)
10872 struct bgp_node
*prn
;
10873 struct bgp_node
*rn
;
10874 struct bgp_table
*table
;
10876 struct prefix_rd
*prd
;
10877 struct bgp_static
*bgp_static
;
10878 char buf
[PREFIX_STRLEN
];
10879 char buf2
[SU_ADDRSTRLEN
];
10880 char rdbuf
[RD_ADDRSTRLEN
];
10882 /* Network configuration. */
10883 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
10884 prn
= bgp_route_next(prn
)) {
10885 if ((table
= prn
->info
) == NULL
)
10888 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10889 if ((bgp_static
= rn
->info
) == NULL
)
10892 char *macrouter
= NULL
;
10895 if (bgp_static
->router_mac
)
10896 macrouter
= prefix_mac2str(
10897 bgp_static
->router_mac
, NULL
, 0);
10898 if (bgp_static
->eth_s_id
)
10899 esi
= esi2str(bgp_static
->eth_s_id
);
10901 prd
= (struct prefix_rd
*)&prn
->p
;
10903 /* "network" configuration display. */
10904 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
10905 if (p
->u
.prefix_evpn
.route_type
== 5) {
10906 char local_buf
[PREFIX_STRLEN
];
10907 uint8_t family
= IS_EVPN_PREFIX_IPADDR_V4((
10908 struct prefix_evpn
*)p
)
10911 inet_ntop(family
, &p
->u
.prefix_evpn
.ip
.ip
.addr
,
10912 local_buf
, PREFIX_STRLEN
);
10913 sprintf(buf
, "%s/%u", local_buf
,
10914 p
->u
.prefix_evpn
.ip_prefix_length
);
10916 prefix2str(p
, buf
, sizeof(buf
));
10919 if (bgp_static
->gatewayIp
.family
== AF_INET
10920 || bgp_static
->gatewayIp
.family
== AF_INET6
)
10921 inet_ntop(bgp_static
->gatewayIp
.family
,
10922 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
10925 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
10926 buf
, rdbuf
, p
->u
.prefix_evpn
.eth_tag
,
10927 decode_label(&bgp_static
->label
), esi
, buf2
,
10931 XFREE(MTYPE_TMP
, macrouter
);
10933 XFREE(MTYPE_TMP
, esi
);
10938 /* Configuration of static route announcement and aggregate
10940 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10943 struct bgp_node
*rn
;
10945 struct bgp_static
*bgp_static
;
10946 struct bgp_aggregate
*bgp_aggregate
;
10947 char buf
[SU_ADDRSTRLEN
];
10949 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
10950 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
10954 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
10955 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
10959 /* Network configuration. */
10960 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
10961 rn
= bgp_route_next(rn
)) {
10962 if ((bgp_static
= rn
->info
) == NULL
)
10967 /* "network" configuration display. */
10968 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
10969 u_int32_t destination
;
10970 struct in_addr netmask
;
10972 destination
= ntohl(p
->u
.prefix4
.s_addr
);
10973 masklen2ip(p
->prefixlen
, &netmask
);
10974 vty_out(vty
, " network %s",
10975 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10978 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
10979 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
10980 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
10981 || p
->u
.prefix4
.s_addr
== 0) {
10982 /* Natural mask is not display. */
10984 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
10986 vty_out(vty
, " network %s/%d",
10987 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
10992 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
10993 vty_out(vty
, " label-index %u",
10994 bgp_static
->label_index
);
10996 if (bgp_static
->rmap
.name
)
10997 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
10999 if (bgp_static
->backdoor
)
11000 vty_out(vty
, " backdoor");
11002 vty_out(vty
, "\n");
11005 /* Aggregate-address configuration. */
11006 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11007 rn
= bgp_route_next(rn
)) {
11008 if ((bgp_aggregate
= rn
->info
) == NULL
)
11013 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11014 struct in_addr netmask
;
11016 masklen2ip(p
->prefixlen
, &netmask
);
11017 vty_out(vty
, " aggregate-address %s %s",
11018 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11020 inet_ntoa(netmask
));
11022 vty_out(vty
, " aggregate-address %s/%d",
11023 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11028 if (bgp_aggregate
->as_set
)
11029 vty_out(vty
, " as-set");
11031 if (bgp_aggregate
->summary_only
)
11032 vty_out(vty
, " summary-only");
11034 vty_out(vty
, "\n");
11038 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11041 struct bgp_node
*rn
;
11042 struct bgp_distance
*bdistance
;
11044 /* Distance configuration. */
11045 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11046 && bgp
->distance_local
[afi
][safi
]
11047 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11048 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11049 || bgp
->distance_local
[afi
][safi
]
11050 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11051 vty_out(vty
, " distance bgp %d %d %d\n",
11052 bgp
->distance_ebgp
[afi
][safi
],
11053 bgp
->distance_ibgp
[afi
][safi
],
11054 bgp
->distance_local
[afi
][safi
]);
11057 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11058 rn
= bgp_route_next(rn
))
11059 if ((bdistance
= rn
->info
) != NULL
) {
11060 char buf
[PREFIX_STRLEN
];
11062 vty_out(vty
, " distance %d %s %s\n",
11063 bdistance
->distance
,
11064 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11065 bdistance
->access_list
? bdistance
->access_list
11070 /* Allocate routing table structure and install commands. */
11071 void bgp_route_init(void)
11076 /* Init BGP distance table. */
11077 FOREACH_AFI_SAFI (afi
, safi
)
11078 bgp_distance_table
[afi
][safi
] = bgp_table_init(afi
, safi
);
11080 /* IPv4 BGP commands. */
11081 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11082 install_element(BGP_NODE
, &bgp_network_cmd
);
11083 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11085 install_element(BGP_NODE
, &aggregate_address_cmd
);
11086 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11087 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11088 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11090 /* IPv4 unicast configuration. */
11091 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11092 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11093 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11095 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11096 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11097 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11098 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11100 /* IPv4 multicast configuration. */
11101 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11102 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11103 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11104 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11105 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11106 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11107 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11109 /* IPv4 labeled-unicast configuration. */
11110 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11111 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11112 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11113 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11114 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11116 install_element(VIEW_NODE
,
11117 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11118 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11119 install_element(VIEW_NODE
,
11120 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11121 #ifdef KEEP_OLD_VPN_COMMANDS
11122 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11123 #endif /* KEEP_OLD_VPN_COMMANDS */
11124 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11125 install_element(VIEW_NODE
,
11126 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11128 /* BGP dampening clear commands */
11129 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11130 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11132 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11133 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11136 install_element(ENABLE_NODE
,
11137 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11138 #ifdef KEEP_OLD_VPN_COMMANDS
11139 install_element(ENABLE_NODE
,
11140 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11141 #endif /* KEEP_OLD_VPN_COMMANDS */
11143 /* New config IPv6 BGP commands. */
11144 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11145 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11146 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11148 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11149 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11151 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11153 install_element(BGP_NODE
, &bgp_distance_cmd
);
11154 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11155 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11156 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11157 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11158 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11159 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11160 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11161 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11162 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11163 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11164 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11165 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11166 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11167 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11168 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11169 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11170 install_element(BGP_IPV4M_NODE
,
11171 &no_bgp_distance_source_access_list_cmd
);
11172 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11173 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11174 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11175 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11176 install_element(BGP_IPV6_NODE
,
11177 &ipv6_bgp_distance_source_access_list_cmd
);
11178 install_element(BGP_IPV6_NODE
,
11179 &no_ipv6_bgp_distance_source_access_list_cmd
);
11180 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11181 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11182 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11183 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11184 install_element(BGP_IPV6M_NODE
,
11185 &ipv6_bgp_distance_source_access_list_cmd
);
11186 install_element(BGP_IPV6M_NODE
,
11187 &no_ipv6_bgp_distance_source_access_list_cmd
);
11189 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11190 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11191 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11192 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11194 /* IPv4 Multicast Mode */
11195 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11196 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11198 /* Large Communities */
11199 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11200 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11203 void bgp_route_finish(void)
11208 FOREACH_AFI_SAFI (afi
, safi
) {
11209 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11210 bgp_distance_table
[afi
][safi
] = NULL
;