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"
41 #include "lib_errors.h"
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgpd/bgp_route.h"
46 #include "bgpd/bgp_attr.h"
47 #include "bgpd/bgp_debug.h"
48 #include "bgpd/bgp_errors.h"
49 #include "bgpd/bgp_aspath.h"
50 #include "bgpd/bgp_regex.h"
51 #include "bgpd/bgp_community.h"
52 #include "bgpd/bgp_ecommunity.h"
53 #include "bgpd/bgp_lcommunity.h"
54 #include "bgpd/bgp_clist.h"
55 #include "bgpd/bgp_packet.h"
56 #include "bgpd/bgp_filter.h"
57 #include "bgpd/bgp_fsm.h"
58 #include "bgpd/bgp_mplsvpn.h"
59 #include "bgpd/bgp_nexthop.h"
60 #include "bgpd/bgp_damp.h"
61 #include "bgpd/bgp_advertise.h"
62 #include "bgpd/bgp_zebra.h"
63 #include "bgpd/bgp_vty.h"
64 #include "bgpd/bgp_mpath.h"
65 #include "bgpd/bgp_nht.h"
66 #include "bgpd/bgp_updgrp.h"
67 #include "bgpd/bgp_label.h"
70 #include "bgpd/rfapi/rfapi_backend.h"
71 #include "bgpd/rfapi/vnc_import_bgp.h"
72 #include "bgpd/rfapi/vnc_export_bgp.h"
74 #include "bgpd/bgp_encap_types.h"
75 #include "bgpd/bgp_encap_tlv.h"
76 #include "bgpd/bgp_evpn.h"
77 #include "bgpd/bgp_evpn_vty.h"
78 #include "bgpd/bgp_flowspec.h"
79 #include "bgpd/bgp_flowspec_util.h"
80 #include "bgpd/bgp_pbr.h"
82 #ifndef VTYSH_EXTRACT_PL
83 #include "bgpd/bgp_route_clippy.c"
86 /* Extern from bgp_dump.c */
87 extern const char *bgp_origin_str
[];
88 extern const char *bgp_origin_long_str
[];
91 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
92 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
93 static const struct message bgp_pmsi_tnltype_str
[] = {
94 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
95 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
96 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
97 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
98 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
99 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
100 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
101 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
105 #define VRFID_NONE_STR "-"
107 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
108 safi_t safi
, struct prefix
*p
,
109 struct prefix_rd
*prd
)
112 struct bgp_node
*prn
= NULL
;
118 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
119 || (safi
== SAFI_EVPN
)) {
120 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
122 if (prn
->info
== NULL
)
123 prn
->info
= bgp_table_init(table
->bgp
, afi
, safi
);
125 bgp_unlock_node(prn
);
129 rn
= bgp_node_get(table
, p
);
131 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
132 || (safi
== SAFI_EVPN
))
138 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
139 safi_t safi
, struct prefix
*p
,
140 struct prefix_rd
*prd
)
143 struct bgp_node
*prn
= NULL
;
148 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
149 || (safi
== SAFI_EVPN
)) {
150 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
154 if (prn
->info
== NULL
) {
155 bgp_unlock_node(prn
);
162 rn
= bgp_node_lookup(table
, p
);
167 /* Allocate bgp_path_info_extra */
168 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
170 struct bgp_path_info_extra
*new;
171 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
172 sizeof(struct bgp_path_info_extra
));
173 new->label
[0] = MPLS_INVALID_LABEL
;
178 static void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
180 struct bgp_path_info_extra
*e
;
182 if (!extra
|| !*extra
)
187 bgp_damp_info_free(e
->damp_info
, 0);
191 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
194 /* FIXME: since multiple e may have the same e->parent
195 * and e->parent->net is holding a refcount for each
196 * of them, we need to do some fudging here.
198 * WARNING: if bpi->net->lock drops to 0, bpi may be
199 * freed as well (because bpi->net was holding the
200 * last reference to bpi) => write after free!
204 bpi
= bgp_path_info_lock(bpi
);
205 refcount
= bpi
->net
->lock
- 1;
206 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
209 bgp_path_info_unlock(bpi
);
211 bgp_path_info_unlock(e
->parent
);
216 bgp_unlock(e
->bgp_orig
);
218 if ((*extra
)->bgp_fs_pbr
)
219 list_delete(&((*extra
)->bgp_fs_pbr
));
220 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
225 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
226 * allocated if required.
228 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
231 pi
->extra
= bgp_path_info_extra_new();
235 /* Allocate new bgp info structure. */
236 struct bgp_path_info
*bgp_path_info_new(void)
238 return XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
241 /* Free bgp route information. */
242 static void bgp_path_info_free(struct bgp_path_info
*path
)
245 bgp_attr_unintern(&path
->attr
);
247 bgp_unlink_nexthop(path
);
248 bgp_path_info_extra_free(&path
->extra
);
249 bgp_path_info_mpath_free(&path
->mpath
);
251 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
253 XFREE(MTYPE_BGP_ROUTE
, path
);
256 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
262 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
264 assert(path
&& path
->lock
> 0);
267 if (path
->lock
== 0) {
269 zlog_debug ("%s: unlocked and freeing", __func__
);
270 zlog_backtrace (LOG_DEBUG
);
272 bgp_path_info_free(path
);
279 zlog_debug ("%s: unlocked to 1", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
287 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
289 struct bgp_path_info
*top
;
299 bgp_path_info_lock(pi
);
301 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
304 /* Do the actual removal of info from RIB, for use by bgp_process
305 completion callback *only* */
306 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
309 pi
->next
->prev
= pi
->prev
;
311 pi
->prev
->next
= pi
->next
;
315 bgp_path_info_mpath_dequeue(pi
);
316 bgp_path_info_unlock(pi
);
320 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
322 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
323 /* set of previous already took care of pcount */
324 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
327 /* undo the effects of a previous call to bgp_path_info_delete; typically
328 called when a route is deleted and then quickly re-added before the
329 deletion has been processed */
330 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
332 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
333 /* unset of previous already took care of pcount */
334 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
337 /* Adjust pcount as required */
338 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
340 struct bgp_table
*table
;
342 assert(rn
&& bgp_node_table(rn
));
343 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
345 table
= bgp_node_table(rn
);
347 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
350 if (!BGP_PATH_COUNTABLE(pi
)
351 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
353 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
355 /* slight hack, but more robust against errors. */
356 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
357 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
359 flog_err(EC_LIB_DEVELOPMENT
,
360 "Asked to decrement 0 prefix count for peer");
361 } else if (BGP_PATH_COUNTABLE(pi
)
362 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
363 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
364 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
368 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
369 struct bgp_path_info
*pi2
)
371 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
374 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
375 * This is here primarily to keep prefix-count in check.
377 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
380 SET_FLAG(pi
->flags
, flag
);
382 /* early bath if we know it's not a flag that changes countability state
384 if (!CHECK_FLAG(flag
,
385 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
388 bgp_pcount_adjust(rn
, pi
);
391 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
394 UNSET_FLAG(pi
->flags
, flag
);
396 /* early bath if we know it's not a flag that changes countability state
398 if (!CHECK_FLAG(flag
,
399 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
402 bgp_pcount_adjust(rn
, pi
);
405 /* Get MED value. If MED value is missing and "bgp bestpath
406 missing-as-worst" is specified, treat it as the worst value. */
407 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
409 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
412 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
419 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
421 if (pi
->addpath_rx_id
)
422 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
425 sprintf(buf
, "path %s", pi
->peer
->host
);
428 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
430 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
431 struct bgp_path_info
*exist
, int *paths_eq
,
432 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
433 char *pfx_buf
, afi_t afi
, safi_t safi
)
435 struct attr
*newattr
, *existattr
;
436 bgp_peer_sort_t new_sort
;
437 bgp_peer_sort_t exist_sort
;
443 uint32_t exist_weight
;
444 uint32_t newm
, existm
;
445 struct in_addr new_id
;
446 struct in_addr exist_id
;
449 int internal_as_route
;
452 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
453 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
455 uint32_t exist_mm_seq
;
463 zlog_debug("%s: new is NULL", pfx_buf
);
468 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
472 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
478 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
479 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
480 pfx_buf
, new_buf
, new->flags
, exist_buf
,
485 existattr
= exist
->attr
;
487 /* For EVPN routes, we cannot just go by local vs remote, we have to
488 * look at the MAC mobility sequence number, if present.
490 if (safi
== SAFI_EVPN
) {
491 /* This is an error condition described in RFC 7432 Section
493 * states that in this scenario "the PE MUST alert the operator"
495 * does not state what other action to take. In order to provide
497 * consistency in this scenario we are going to prefer the path
501 if (newattr
->sticky
!= existattr
->sticky
) {
503 prefix2str(&new->net
->p
, pfx_buf
,
505 * PREFIX2STR_BUFFER
);
506 bgp_path_info_path_with_addpath_rx_str(new,
508 bgp_path_info_path_with_addpath_rx_str(
512 if (newattr
->sticky
&& !existattr
->sticky
) {
515 "%s: %s wins over %s due to sticky MAC flag",
516 pfx_buf
, new_buf
, exist_buf
);
520 if (!newattr
->sticky
&& existattr
->sticky
) {
523 "%s: %s loses to %s due to sticky MAC flag",
524 pfx_buf
, new_buf
, exist_buf
);
529 new_mm_seq
= mac_mobility_seqnum(newattr
);
530 exist_mm_seq
= mac_mobility_seqnum(existattr
);
532 if (new_mm_seq
> exist_mm_seq
) {
535 "%s: %s wins over %s due to MM seq %u > %u",
536 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
541 if (new_mm_seq
< exist_mm_seq
) {
544 "%s: %s loses to %s due to MM seq %u < %u",
545 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
551 * if sequence numbers are the same path with the lowest IP
554 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
558 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
559 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
560 inet_ntoa(new->attr
->nexthop
));
566 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
567 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
568 inet_ntoa(new->attr
->nexthop
));
573 /* 1. Weight check. */
574 new_weight
= newattr
->weight
;
575 exist_weight
= existattr
->weight
;
577 if (new_weight
> exist_weight
) {
579 zlog_debug("%s: %s wins over %s due to weight %d > %d",
580 pfx_buf
, new_buf
, exist_buf
, new_weight
,
585 if (new_weight
< exist_weight
) {
587 zlog_debug("%s: %s loses to %s due to weight %d < %d",
588 pfx_buf
, new_buf
, exist_buf
, new_weight
,
593 /* 2. Local preference check. */
594 new_pref
= exist_pref
= bgp
->default_local_pref
;
596 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
597 new_pref
= newattr
->local_pref
;
598 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
599 exist_pref
= existattr
->local_pref
;
601 if (new_pref
> exist_pref
) {
604 "%s: %s wins over %s due to localpref %d > %d",
605 pfx_buf
, new_buf
, exist_buf
, new_pref
,
610 if (new_pref
< exist_pref
) {
613 "%s: %s loses to %s due to localpref %d < %d",
614 pfx_buf
, new_buf
, exist_buf
, new_pref
,
619 /* 3. Local route check. We prefer:
621 * - BGP_ROUTE_AGGREGATE
622 * - BGP_ROUTE_REDISTRIBUTE
624 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
625 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
628 "%s: %s wins over %s due to preferred BGP_ROUTE type",
629 pfx_buf
, new_buf
, exist_buf
);
633 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
634 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
637 "%s: %s loses to %s due to preferred BGP_ROUTE type",
638 pfx_buf
, new_buf
, exist_buf
);
642 /* 4. AS path length check. */
643 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
644 int exist_hops
= aspath_count_hops(existattr
->aspath
);
645 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
647 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
650 aspath_hops
= aspath_count_hops(newattr
->aspath
);
651 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
653 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
656 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
657 pfx_buf
, new_buf
, exist_buf
,
659 (exist_hops
+ exist_confeds
));
663 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
666 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
667 pfx_buf
, new_buf
, exist_buf
,
669 (exist_hops
+ exist_confeds
));
673 int newhops
= aspath_count_hops(newattr
->aspath
);
675 if (newhops
< exist_hops
) {
678 "%s: %s wins over %s due to aspath hopcount %d < %d",
679 pfx_buf
, new_buf
, exist_buf
,
680 newhops
, exist_hops
);
684 if (newhops
> exist_hops
) {
687 "%s: %s loses to %s due to aspath hopcount %d > %d",
688 pfx_buf
, new_buf
, exist_buf
,
689 newhops
, exist_hops
);
695 /* 5. Origin check. */
696 if (newattr
->origin
< existattr
->origin
) {
698 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
699 pfx_buf
, new_buf
, exist_buf
,
700 bgp_origin_long_str
[newattr
->origin
],
701 bgp_origin_long_str
[existattr
->origin
]);
705 if (newattr
->origin
> existattr
->origin
) {
707 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
708 pfx_buf
, new_buf
, exist_buf
,
709 bgp_origin_long_str
[newattr
->origin
],
710 bgp_origin_long_str
[existattr
->origin
]);
715 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
716 && aspath_count_hops(existattr
->aspath
) == 0);
717 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
718 && aspath_count_confeds(existattr
->aspath
) > 0
719 && aspath_count_hops(newattr
->aspath
) == 0
720 && aspath_count_hops(existattr
->aspath
) == 0);
722 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
723 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
724 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
725 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
726 || internal_as_route
) {
727 new_med
= bgp_med_value(new->attr
, bgp
);
728 exist_med
= bgp_med_value(exist
->attr
, bgp
);
730 if (new_med
< exist_med
) {
733 "%s: %s wins over %s due to MED %d < %d",
734 pfx_buf
, new_buf
, exist_buf
, new_med
,
739 if (new_med
> exist_med
) {
742 "%s: %s loses to %s due to MED %d > %d",
743 pfx_buf
, new_buf
, exist_buf
, new_med
,
749 /* 7. Peer type check. */
750 new_sort
= new->peer
->sort
;
751 exist_sort
= exist
->peer
->sort
;
753 if (new_sort
== BGP_PEER_EBGP
754 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
757 "%s: %s wins over %s due to eBGP peer > iBGP peer",
758 pfx_buf
, new_buf
, exist_buf
);
762 if (exist_sort
== BGP_PEER_EBGP
763 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
766 "%s: %s loses to %s due to iBGP peer < eBGP peer",
767 pfx_buf
, new_buf
, exist_buf
);
771 /* 8. IGP metric check. */
775 newm
= new->extra
->igpmetric
;
777 existm
= exist
->extra
->igpmetric
;
782 "%s: %s wins over %s due to IGP metric %d < %d",
783 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
790 "%s: %s loses to %s due to IGP metric %d > %d",
791 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
795 /* 9. Same IGP metric. Compare the cluster list length as
796 representative of IGP hops metric. Rewrite the metric value
797 pair (newm, existm) with the cluster list length. Prefer the
798 path with smaller cluster list length. */
799 if (newm
== existm
) {
800 if (peer_sort(new->peer
) == BGP_PEER_IBGP
801 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
802 && (mpath_cfg
== NULL
804 mpath_cfg
->ibgp_flags
,
805 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
806 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
807 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
812 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
813 pfx_buf
, new_buf
, exist_buf
,
821 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
822 pfx_buf
, new_buf
, exist_buf
,
829 /* 10. confed-external vs. confed-internal */
830 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
831 if (new_sort
== BGP_PEER_CONFED
832 && exist_sort
== BGP_PEER_IBGP
) {
835 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
836 pfx_buf
, new_buf
, exist_buf
);
840 if (exist_sort
== BGP_PEER_CONFED
841 && new_sort
== BGP_PEER_IBGP
) {
844 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
845 pfx_buf
, new_buf
, exist_buf
);
850 /* 11. Maximum path check. */
851 if (newm
== existm
) {
852 /* If one path has a label but the other does not, do not treat
853 * them as equals for multipath
855 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
857 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
860 "%s: %s and %s cannot be multipath, one has a label while the other does not",
861 pfx_buf
, new_buf
, exist_buf
);
862 } else if (bgp_flag_check(bgp
,
863 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
866 * For the two paths, all comparison steps till IGP
868 * have succeeded - including AS_PATH hop count. Since
870 * bestpath as-path multipath-relax' knob is on, we
872 * an exact match of AS_PATH. Thus, mark the paths are
874 * That will trigger both these paths to get into the
882 "%s: %s and %s are equal via multipath-relax",
883 pfx_buf
, new_buf
, exist_buf
);
884 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
885 if (aspath_cmp(new->attr
->aspath
,
886 exist
->attr
->aspath
)) {
891 "%s: %s and %s are equal via matching aspaths",
892 pfx_buf
, new_buf
, exist_buf
);
894 } else if (new->peer
->as
== exist
->peer
->as
) {
899 "%s: %s and %s are equal via same remote-as",
900 pfx_buf
, new_buf
, exist_buf
);
904 * TODO: If unequal cost ibgp multipath is enabled we can
905 * mark the paths as equal here instead of returning
910 "%s: %s wins over %s after IGP metric comparison",
911 pfx_buf
, new_buf
, exist_buf
);
914 "%s: %s loses to %s after IGP metric comparison",
915 pfx_buf
, new_buf
, exist_buf
);
920 /* 12. If both paths are external, prefer the path that was received
921 first (the oldest one). This step minimizes route-flap, since a
922 newer path won't displace an older one, even if it was the
923 preferred route based on the additional decision criteria below. */
924 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
925 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
926 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
929 "%s: %s wins over %s due to oldest external",
930 pfx_buf
, new_buf
, exist_buf
);
934 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
937 "%s: %s loses to %s due to oldest external",
938 pfx_buf
, new_buf
, exist_buf
);
943 /* 13. Router-ID comparision. */
944 /* If one of the paths is "stale", the corresponding peer router-id will
945 * be 0 and would always win over the other path. If originator id is
946 * used for the comparision, it will decide which path is better.
948 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
949 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
951 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
952 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
953 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
955 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
957 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
960 "%s: %s wins over %s due to Router-ID comparison",
961 pfx_buf
, new_buf
, exist_buf
);
965 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
968 "%s: %s loses to %s due to Router-ID comparison",
969 pfx_buf
, new_buf
, exist_buf
);
973 /* 14. Cluster length comparision. */
974 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
975 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
977 if (new_cluster
< exist_cluster
) {
980 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
981 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
986 if (new_cluster
> exist_cluster
) {
989 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
990 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
995 /* 15. Neighbor address comparision. */
996 /* Do this only if neither path is "stale" as stale paths do not have
997 * valid peer information (as the connection may or may not be up).
999 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1002 "%s: %s wins over %s due to latter path being STALE",
1003 pfx_buf
, new_buf
, exist_buf
);
1007 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1010 "%s: %s loses to %s due to former path being STALE",
1011 pfx_buf
, new_buf
, exist_buf
);
1015 /* locally configured routes to advertise do not have su_remote */
1016 if (new->peer
->su_remote
== NULL
)
1018 if (exist
->peer
->su_remote
== NULL
)
1021 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1026 "%s: %s loses to %s due to Neighor IP comparison",
1027 pfx_buf
, new_buf
, exist_buf
);
1034 "%s: %s wins over %s due to Neighor IP comparison",
1035 pfx_buf
, new_buf
, exist_buf
);
1040 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1041 pfx_buf
, new_buf
, exist_buf
);
1046 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1047 * is preferred, or 0 if they are the same (usually will only occur if
1048 * multipath is enabled
1049 * This version is compatible with */
1050 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1051 struct bgp_path_info
*exist
, char *pfx_buf
,
1052 afi_t afi
, safi_t safi
)
1056 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1070 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1071 struct attr
*attr
, afi_t afi
,
1074 struct bgp_filter
*filter
;
1076 filter
= &peer
->filter
[afi
][safi
];
1078 #define FILTER_EXIST_WARN(F, f, filter) \
1079 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1080 zlog_debug("%s: Could not find configured input %s-list %s!", \
1081 peer->host, #f, F##_IN_NAME(filter));
1083 if (DISTRIBUTE_IN_NAME(filter
)) {
1084 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1086 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1090 if (PREFIX_LIST_IN_NAME(filter
)) {
1091 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1093 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1097 if (FILTER_LIST_IN_NAME(filter
)) {
1098 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1100 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1105 return FILTER_PERMIT
;
1106 #undef FILTER_EXIST_WARN
1109 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1110 struct attr
*attr
, afi_t afi
,
1113 struct bgp_filter
*filter
;
1115 filter
= &peer
->filter
[afi
][safi
];
1117 #define FILTER_EXIST_WARN(F, f, filter) \
1118 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1119 zlog_debug("%s: Could not find configured output %s-list %s!", \
1120 peer->host, #f, F##_OUT_NAME(filter));
1122 if (DISTRIBUTE_OUT_NAME(filter
)) {
1123 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1125 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1129 if (PREFIX_LIST_OUT_NAME(filter
)) {
1130 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1132 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1137 if (FILTER_LIST_OUT_NAME(filter
)) {
1138 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1140 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1145 return FILTER_PERMIT
;
1146 #undef FILTER_EXIST_WARN
1149 /* If community attribute includes no_export then return 1. */
1150 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1152 if (attr
->community
) {
1153 /* NO_ADVERTISE check. */
1154 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1157 /* NO_EXPORT check. */
1158 if (peer
->sort
== BGP_PEER_EBGP
1159 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1162 /* NO_EXPORT_SUBCONFED check. */
1163 if (peer
->sort
== BGP_PEER_EBGP
1164 || peer
->sort
== BGP_PEER_CONFED
)
1165 if (community_include(attr
->community
,
1166 COMMUNITY_NO_EXPORT_SUBCONFED
))
1172 /* Route reflection loop check. */
1173 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1175 struct in_addr cluster_id
;
1177 if (attr
->cluster
) {
1178 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1179 cluster_id
= peer
->bgp
->cluster_id
;
1181 cluster_id
= peer
->bgp
->router_id
;
1183 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1189 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1190 struct attr
*attr
, afi_t afi
, safi_t safi
,
1191 const char *rmap_name
)
1193 struct bgp_filter
*filter
;
1194 struct bgp_path_info rmap_path
;
1195 route_map_result_t ret
;
1196 struct route_map
*rmap
= NULL
;
1198 filter
= &peer
->filter
[afi
][safi
];
1200 /* Apply default weight value. */
1201 if (peer
->weight
[afi
][safi
])
1202 attr
->weight
= peer
->weight
[afi
][safi
];
1205 rmap
= route_map_lookup_by_name(rmap_name
);
1210 if (ROUTE_MAP_IN_NAME(filter
)) {
1211 rmap
= ROUTE_MAP_IN(filter
);
1218 /* Route map apply. */
1220 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1221 /* Duplicate current value to new strucutre for modification. */
1222 rmap_path
.peer
= peer
;
1223 rmap_path
.attr
= attr
;
1225 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1227 /* Apply BGP route map to the attribute. */
1228 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1230 peer
->rmap_type
= 0;
1232 if (ret
== RMAP_DENYMATCH
)
1238 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1239 struct attr
*attr
, afi_t afi
, safi_t safi
,
1240 const char *rmap_name
)
1242 struct bgp_path_info rmap_path
;
1243 route_map_result_t ret
;
1244 struct route_map
*rmap
= NULL
;
1248 * So if we get to this point and have no rmap_name
1249 * we want to just show the output as it currently
1255 /* Apply default weight value. */
1256 if (peer
->weight
[afi
][safi
])
1257 attr
->weight
= peer
->weight
[afi
][safi
];
1259 rmap
= route_map_lookup_by_name(rmap_name
);
1262 * If we have a route map name and we do not find
1263 * the routemap that means we have an implicit
1269 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1270 /* Route map apply. */
1271 /* Duplicate current value to new strucutre for modification. */
1272 rmap_path
.peer
= peer
;
1273 rmap_path
.attr
= attr
;
1275 rmap_type
= peer
->rmap_type
;
1276 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1278 /* Apply BGP route map to the attribute. */
1279 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1281 peer
->rmap_type
= rmap_type
;
1283 if (ret
== RMAP_DENYMATCH
)
1285 * caller has multiple error paths with bgp_attr_flush()
1292 /* If this is an EBGP peer with remove-private-AS */
1293 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1294 struct peer
*peer
, struct attr
*attr
)
1296 if (peer
->sort
== BGP_PEER_EBGP
1297 && (peer_af_flag_check(peer
, afi
, safi
,
1298 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1299 || peer_af_flag_check(peer
, afi
, safi
,
1300 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1301 || peer_af_flag_check(peer
, afi
, safi
,
1302 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1303 || peer_af_flag_check(peer
, afi
, safi
,
1304 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1305 // Take action on the entire aspath
1306 if (peer_af_flag_check(peer
, afi
, safi
,
1307 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1308 || peer_af_flag_check(peer
, afi
, safi
,
1309 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1310 if (peer_af_flag_check(
1312 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1313 attr
->aspath
= aspath_replace_private_asns(
1314 attr
->aspath
, bgp
->as
);
1316 // The entire aspath consists of private ASNs so create
1318 else if (aspath_private_as_check(attr
->aspath
))
1319 attr
->aspath
= aspath_empty_get();
1321 // There are some public and some private ASNs, remove
1324 attr
->aspath
= aspath_remove_private_asns(
1328 // 'all' was not specified so the entire aspath must be private
1330 // for us to do anything
1331 else if (aspath_private_as_check(attr
->aspath
)) {
1332 if (peer_af_flag_check(
1334 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1335 attr
->aspath
= aspath_replace_private_asns(
1336 attr
->aspath
, bgp
->as
);
1338 attr
->aspath
= aspath_empty_get();
1343 /* If this is an EBGP peer with as-override */
1344 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1345 struct peer
*peer
, struct attr
*attr
)
1347 if (peer
->sort
== BGP_PEER_EBGP
1348 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1349 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1350 attr
->aspath
= aspath_replace_specific_asn(
1351 attr
->aspath
, peer
->as
, bgp
->as
);
1355 void bgp_attr_add_gshut_community(struct attr
*attr
)
1357 struct community
*old
;
1358 struct community
*new;
1359 struct community
*merge
;
1360 struct community
*gshut
;
1362 old
= attr
->community
;
1363 gshut
= community_str2com("graceful-shutdown");
1368 merge
= community_merge(community_dup(old
), gshut
);
1370 if (old
->refcnt
== 0)
1371 community_free(&old
);
1373 new = community_uniq_sort(merge
);
1374 community_free(&merge
);
1376 new = community_dup(gshut
);
1379 community_free(&gshut
);
1380 attr
->community
= new;
1381 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1383 /* When we add the graceful-shutdown community we must also
1384 * lower the local-preference */
1385 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1386 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1390 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1392 if (family
== AF_INET
) {
1393 attr
->nexthop
.s_addr
= 0;
1394 attr
->mp_nexthop_global_in
.s_addr
= 0;
1396 if (family
== AF_INET6
)
1397 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1398 if (family
== AF_EVPN
)
1399 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1402 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1403 struct update_subgroup
*subgrp
, struct prefix
*p
,
1406 struct bgp_filter
*filter
;
1409 struct peer
*onlypeer
;
1411 struct attr
*piattr
;
1412 char buf
[PREFIX_STRLEN
];
1418 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1420 if (DISABLE_BGP_ANNOUNCE
)
1423 afi
= SUBGRP_AFI(subgrp
);
1424 safi
= SUBGRP_SAFI(subgrp
);
1425 peer
= SUBGRP_PEER(subgrp
);
1427 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1428 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1431 filter
= &peer
->filter
[afi
][safi
];
1432 bgp
= SUBGRP_INST(subgrp
);
1433 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1437 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1438 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1439 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1442 * direct and direct_ext type routes originate internally even
1443 * though they can have peer pointers that reference other
1446 prefix2str(p
, buf
, PREFIX_STRLEN
);
1447 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1453 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1454 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1455 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1456 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1458 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1463 /* With addpath we may be asked to TX all kinds of paths so make sure
1465 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1466 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1467 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1471 /* If this is not the bestpath then check to see if there is an enabled
1473 * feature that requires us to advertise it */
1474 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1475 if (!bgp_addpath_tx_path(peer
, afi
, safi
, pi
)) {
1480 /* Aggregate-address suppress check. */
1481 if (pi
->extra
&& pi
->extra
->suppress
)
1482 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1487 * If we are doing VRF 2 VRF leaking via the import
1488 * statement, we want to prevent the route going
1489 * off box as that the RT and RD created are localy
1490 * significant and globaly useless.
1492 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1493 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1496 /* If it's labeled safi, make sure the route has a valid label. */
1497 if (safi
== SAFI_LABELED_UNICAST
) {
1498 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1499 if (!bgp_is_valid_label(&label
)) {
1500 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1501 zlog_debug("u%" PRIu64
":s%" PRIu64
1502 " %s/%d is filtered - no label (%p)",
1503 subgrp
->update_group
->id
, subgrp
->id
,
1504 inet_ntop(p
->family
, &p
->u
.prefix
,
1505 buf
, SU_ADDRSTRLEN
),
1506 p
->prefixlen
, &label
);
1511 /* Do not send back route to sender. */
1512 if (onlypeer
&& from
== onlypeer
) {
1516 /* Do not send the default route in the BGP table if the neighbor is
1517 * configured for default-originate */
1518 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1519 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1520 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1522 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1526 /* Transparency check. */
1527 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1528 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1533 /* If community is not disabled check the no-export and local. */
1534 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1535 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1537 "subgrpannouncecheck: community filter check fail");
1541 /* If the attribute has originator-id and it is same as remote
1543 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1544 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1545 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1547 "%s [Update:SEND] %s originator-id is same as "
1550 prefix2str(p
, buf
, sizeof(buf
)));
1554 /* ORF prefix-list filter check */
1555 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1556 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1557 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1558 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1559 if (peer
->orf_plist
[afi
][safi
]) {
1560 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1562 if (bgp_debug_update(NULL
, p
,
1563 subgrp
->update_group
, 0))
1565 "%s [Update:SEND] %s is filtered via ORF",
1573 /* Output filter check. */
1574 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1575 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1576 zlog_debug("%s [Update:SEND] %s is filtered",
1577 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1581 #ifdef BGP_SEND_ASPATH_CHECK
1582 /* AS path loop check. */
1583 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1584 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1586 "%s [Update:SEND] suppress announcement to peer AS %u "
1587 "that is part of AS path.",
1588 onlypeer
->host
, onlypeer
->as
);
1591 #endif /* BGP_SEND_ASPATH_CHECK */
1593 /* If we're a CONFED we need to loop check the CONFED ID too */
1594 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1595 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1596 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1598 "%s [Update:SEND] suppress announcement to peer AS %u"
1600 peer
->host
, bgp
->confed_id
);
1605 /* Route-Reflect check. */
1606 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1611 /* IBGP reflection check. */
1612 if (reflect
&& !samepeer_safe
) {
1613 /* A route from a Client peer. */
1614 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1615 PEER_FLAG_REFLECTOR_CLIENT
)) {
1616 /* Reflect to all the Non-Client peers and also to the
1617 Client peers other than the originator. Originator
1619 is already done. So there is noting to do. */
1620 /* no bgp client-to-client reflection check. */
1621 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1622 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1623 PEER_FLAG_REFLECTOR_CLIENT
))
1626 /* A route from a Non-client peer. Reflect to all other
1628 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1629 PEER_FLAG_REFLECTOR_CLIENT
))
1634 /* For modify attribute, copy it to temporary structure. */
1635 bgp_attr_dup(attr
, piattr
);
1637 /* If local-preference is not set. */
1638 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1639 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1640 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1641 attr
->local_pref
= bgp
->default_local_pref
;
1644 /* If originator-id is not set and the route is to be reflected,
1645 set the originator id */
1647 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1648 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1649 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1652 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1654 if (peer
->sort
== BGP_PEER_EBGP
1655 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1656 if (from
!= bgp
->peer_self
&& !transparent
1657 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1658 PEER_FLAG_MED_UNCHANGED
))
1660 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1663 /* Since the nexthop attribute can vary per peer, it is not explicitly
1665 * in announce check, only certain flags and length (or number of
1667 * -- for IPv6/MP_REACH) are set here in order to guide the update
1669 * code in setting the nexthop(s) on a per peer basis in
1671 * Typically, the source nexthop in the attribute is preserved but in
1673 * scenarios where we know it will always be overwritten, we reset the
1674 * nexthop to "0" in an attempt to achieve better Update packing. An
1675 * example of this is when a prefix from each of 2 IBGP peers needs to
1677 * announced to an EBGP peer (and they have the same attributes barring
1681 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1683 #define NEXTHOP_IS_V6 \
1684 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1685 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1686 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1687 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1689 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1691 * the peer (group) is configured to receive link-local nexthop
1693 * and it is available in the prefix OR we're not reflecting the route
1695 * the peer (group) to whom we're going to announce is on a shared
1697 * and this is either a self-originated route or the peer is EBGP.
1699 if (NEXTHOP_IS_V6
) {
1700 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1701 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1702 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1703 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1704 || (!reflect
&& peer
->shared_network
1705 && (from
== bgp
->peer_self
1706 || peer
->sort
== BGP_PEER_EBGP
))) {
1707 attr
->mp_nexthop_len
=
1708 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1711 /* Clear off link-local nexthop in source, whenever it is not
1713 * ensure more prefixes share the same attribute for
1716 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1717 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1718 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1721 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1722 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1724 /* Route map & unsuppress-map apply. */
1725 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1726 struct bgp_path_info rmap_path
;
1727 struct bgp_path_info_extra dummy_rmap_path_extra
;
1728 struct attr dummy_attr
;
1730 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1731 rmap_path
.peer
= peer
;
1732 rmap_path
.attr
= attr
;
1735 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1736 sizeof(struct bgp_path_info_extra
));
1737 rmap_path
.extra
= &dummy_rmap_path_extra
;
1740 /* don't confuse inbound and outbound setting */
1741 RESET_FLAG(attr
->rmap_change_flags
);
1744 * The route reflector is not allowed to modify the attributes
1745 * of the reflected IBGP routes unless explicitly allowed.
1747 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1748 && !bgp_flag_check(bgp
,
1749 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1750 bgp_attr_dup(&dummy_attr
, attr
);
1751 rmap_path
.attr
= &dummy_attr
;
1754 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1756 if (pi
->extra
&& pi
->extra
->suppress
)
1757 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1758 RMAP_BGP
, &rmap_path
);
1760 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1761 RMAP_BGP
, &rmap_path
);
1763 peer
->rmap_type
= 0;
1765 if (ret
== RMAP_DENYMATCH
) {
1766 bgp_attr_flush(attr
);
1771 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1772 if (peer
->sort
== BGP_PEER_IBGP
1773 || peer
->sort
== BGP_PEER_CONFED
) {
1774 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1775 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1777 bgp_attr_add_gshut_community(attr
);
1781 /* After route-map has been applied, we check to see if the nexthop to
1782 * be carried in the attribute (that is used for the announcement) can
1783 * be cleared off or not. We do this in all cases where we would be
1784 * setting the nexthop to "ourselves". For IPv6, we only need to
1786 * the global nexthop here; the link-local nexthop would have been
1788 * already, and if not, it is required by the update formation code.
1789 * Also see earlier comments in this function.
1792 * If route-map has performed some operation on the nexthop or the peer
1793 * configuration says to pass it unchanged, we cannot reset the nexthop
1794 * here, so only attempt to do it if these aren't true. Note that the
1795 * route-map handler itself might have cleared the nexthop, if for
1797 * it is configured as 'peer-address'.
1799 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1800 piattr
->rmap_change_flags
)
1802 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1803 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1804 /* We can reset the nexthop, if setting (or forcing) it to
1806 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1807 PEER_FLAG_NEXTHOP_SELF
)
1808 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1809 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1811 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1812 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1813 subgroup_announce_reset_nhop(
1814 (peer_cap_enhe(peer
, afi
, safi
)
1818 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1819 /* Can also reset the nexthop if announcing to EBGP, but
1821 * no peer in the subgroup is on a shared subnet.
1822 * Note: 3rd party nexthop currently implemented for
1825 if (!bgp_subgrp_multiaccess_check_v4(piattr
->nexthop
,
1827 subgroup_announce_reset_nhop(
1828 (peer_cap_enhe(peer
, afi
, safi
)
1832 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1834 * This flag is used for leaked vpn-vrf routes
1836 int family
= p
->family
;
1838 if (peer_cap_enhe(peer
, afi
, safi
))
1841 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1843 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1844 __func__
, family2str(family
));
1845 subgroup_announce_reset_nhop(family
, attr
);
1848 /* If IPv6/MP and nexthop does not have any override and happens
1850 * be a link-local address, reset it so that we don't pass along
1852 * source's link-local IPv6 address to recipients who may not be
1854 * the same interface.
1856 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1857 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1858 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1865 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1866 struct bgp_maxpaths_cfg
*mpath_cfg
,
1867 struct bgp_path_info_pair
*result
, afi_t afi
,
1870 struct bgp_path_info
*new_select
;
1871 struct bgp_path_info
*old_select
;
1872 struct bgp_path_info
*pi
;
1873 struct bgp_path_info
*pi1
;
1874 struct bgp_path_info
*pi2
;
1875 struct bgp_path_info
*nextpi
= NULL
;
1876 int paths_eq
, do_mpath
, debug
;
1877 struct list mp_list
;
1878 char pfx_buf
[PREFIX2STR_BUFFER
];
1879 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1881 bgp_mp_list_init(&mp_list
);
1883 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1885 debug
= bgp_debug_bestpath(&rn
->p
);
1888 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1890 /* bgp deterministic-med */
1892 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1894 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1895 for (pi1
= rn
->info
; pi1
; pi1
= pi1
->next
)
1896 bgp_path_info_unset_flag(rn
, pi1
,
1897 BGP_PATH_DMED_SELECTED
);
1899 for (pi1
= rn
->info
; pi1
; pi1
= pi1
->next
) {
1900 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1902 if (BGP_PATH_HOLDDOWN(pi1
))
1904 if (pi1
->peer
&& pi1
->peer
!= bgp
->peer_self
)
1905 if (pi1
->peer
->status
!= Established
)
1910 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
1911 if (CHECK_FLAG(pi2
->flags
,
1912 BGP_PATH_DMED_CHECK
))
1914 if (BGP_PATH_HOLDDOWN(pi2
))
1917 && pi2
->peer
!= bgp
->peer_self
1920 PEER_STATUS_NSF_WAIT
))
1921 if (pi2
->peer
->status
1925 if (!aspath_cmp_left(pi1
->attr
->aspath
,
1927 && !aspath_cmp_left_confed(
1932 if (bgp_path_info_cmp(
1933 bgp
, pi2
, new_select
,
1934 &paths_eq
, mpath_cfg
, debug
,
1935 pfx_buf
, afi
, safi
)) {
1936 bgp_path_info_unset_flag(
1938 BGP_PATH_DMED_SELECTED
);
1942 bgp_path_info_set_flag(
1943 rn
, pi2
, BGP_PATH_DMED_CHECK
);
1946 bgp_path_info_set_flag(rn
, new_select
,
1947 BGP_PATH_DMED_CHECK
);
1948 bgp_path_info_set_flag(rn
, new_select
,
1949 BGP_PATH_DMED_SELECTED
);
1952 bgp_path_info_path_with_addpath_rx_str(
1953 new_select
, path_buf
);
1954 zlog_debug("%s: %s is the bestpath from AS %u",
1956 aspath_get_first_as(
1957 new_select
->attr
->aspath
));
1962 /* Check old selected route and new selected route. */
1965 for (pi
= rn
->info
; (pi
!= NULL
) && (nextpi
= pi
->next
, 1);
1967 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
1970 if (BGP_PATH_HOLDDOWN(pi
)) {
1971 /* reap REMOVED routes, if needs be
1972 * selected route must stay for a while longer though
1974 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
1975 && (pi
!= old_select
))
1976 bgp_path_info_reap(rn
, pi
);
1979 zlog_debug("%s: pi %p in holddown", __func__
,
1985 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
1986 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
1987 if (pi
->peer
->status
!= Established
) {
1991 "%s: pi %p non self peer %s not estab state",
1992 __func__
, pi
, pi
->peer
->host
);
1997 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
1998 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
1999 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2001 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2005 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2007 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2008 debug
, pfx_buf
, afi
, safi
)) {
2013 /* Now that we know which path is the bestpath see if any of the other
2015 * qualify as multipaths
2019 bgp_path_info_path_with_addpath_rx_str(new_select
,
2022 sprintf(path_buf
, "NONE");
2024 "%s: After path selection, newbest is %s oldbest was %s",
2026 old_select
? old_select
->peer
->host
: "NONE");
2029 if (do_mpath
&& new_select
) {
2030 for (pi
= rn
->info
; (pi
!= NULL
) && (nextpi
= pi
->next
, 1);
2034 bgp_path_info_path_with_addpath_rx_str(
2037 if (pi
== new_select
) {
2040 "%s: %s is the bestpath, add to the multipath list",
2042 bgp_mp_list_add(&mp_list
, pi
);
2046 if (BGP_PATH_HOLDDOWN(pi
))
2049 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2050 && !CHECK_FLAG(pi
->peer
->sflags
,
2051 PEER_STATUS_NSF_WAIT
))
2052 if (pi
->peer
->status
!= Established
)
2055 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2058 "%s: %s has the same nexthop as the bestpath, skip it",
2063 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2064 mpath_cfg
, debug
, pfx_buf
, afi
, safi
);
2069 "%s: %s is equivalent to the bestpath, add to the multipath list",
2071 bgp_mp_list_add(&mp_list
, pi
);
2076 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2078 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2079 bgp_mp_list_clear(&mp_list
);
2081 result
->old
= old_select
;
2082 result
->new = new_select
;
2088 * A new route/change in bestpath of an existing route. Evaluate the path
2089 * for advertisement to the subgroup.
2091 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2092 struct bgp_path_info
*selected
,
2093 struct bgp_node
*rn
,
2094 uint32_t addpath_tx_id
)
2097 struct peer
*onlypeer
;
2103 afi
= SUBGRP_AFI(subgrp
);
2104 safi
= SUBGRP_SAFI(subgrp
);
2105 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2108 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2109 char buf_prefix
[PREFIX_STRLEN
];
2110 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2111 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2115 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2116 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2117 PEER_STATUS_ORF_WAIT_REFRESH
))
2120 memset(&attr
, 0, sizeof(struct attr
));
2121 /* It's initialized in bgp_announce_check() */
2123 /* Announcement to the subgroup. If the route is filtered withdraw it.
2126 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2127 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2129 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2130 selected
->addpath_tx_id
);
2133 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2135 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2142 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2143 * This is called at the end of route processing.
2145 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2147 struct bgp_path_info
*pi
;
2149 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2150 if (BGP_PATH_HOLDDOWN(pi
))
2152 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2153 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2158 * Has the route changed from the RIB's perspective? This is invoked only
2159 * if the route selection returns the same best route as earlier - to
2160 * determine if we need to update zebra or not.
2162 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2163 struct bgp_path_info
*selected
)
2165 struct bgp_path_info
*mpinfo
;
2167 /* If this is multipath, check all selected paths for any nexthop
2168 * change or attribute change. Some attribute changes (e.g., community)
2169 * aren't of relevance to the RIB, but we'll update zebra to ensure
2170 * we handle the case of BGP nexthop change. This is the behavior
2171 * when the best path has an attribute change anyway.
2173 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2174 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2178 * If this is multipath, check all selected paths for any nexthop change
2180 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2181 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2182 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2183 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2187 /* Nothing has changed from the RIB's perspective. */
2191 struct bgp_process_queue
{
2193 STAILQ_HEAD(, bgp_node
) pqueue
;
2194 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2196 unsigned int queued
;
2200 * old_select = The old best path
2201 * new_select = the new best path
2203 * if (!old_select && new_select)
2204 * We are sending new information on.
2206 * if (old_select && new_select) {
2207 * if (new_select != old_select)
2208 * We have a new best path send a change
2210 * We've received a update with new attributes that needs
2214 * if (old_select && !new_select)
2215 * We have no eligible route that we can announce or the rn
2218 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2219 afi_t afi
, safi_t safi
)
2221 struct bgp_path_info
*new_select
;
2222 struct bgp_path_info
*old_select
;
2223 struct bgp_path_info_pair old_and_new
;
2224 char pfx_buf
[PREFIX2STR_BUFFER
];
2227 /* Is it end of initial update? (after startup) */
2229 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2230 sizeof(bgp
->update_delay_zebra_resume_time
));
2232 bgp
->main_zebra_update_hold
= 0;
2233 FOREACH_AFI_SAFI (afi
, safi
) {
2234 if (bgp_fibupd_safi(safi
))
2235 bgp_zebra_announce_table(bgp
, afi
, safi
);
2237 bgp
->main_peers_update_hold
= 0;
2239 bgp_start_routeadv(bgp
);
2243 struct prefix
*p
= &rn
->p
;
2245 debug
= bgp_debug_bestpath(&rn
->p
);
2247 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2248 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2249 afi2str(afi
), safi2str(safi
));
2252 /* Best path selection. */
2253 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2255 old_select
= old_and_new
.old
;
2256 new_select
= old_and_new
.new;
2258 /* Do we need to allocate or free labels?
2259 * Right now, since we only deal with per-prefix labels, it is not
2260 * necessary to do this upon changes to best path except if the label
2263 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2266 || bgp_label_index_differs(new_select
, old_select
)
2267 || new_select
->sub_type
!= old_select
->sub_type
) {
2268 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2269 && new_select
->attr
->flag
2271 BGP_ATTR_PREFIX_SID
)
2272 && new_select
->attr
->label_index
2273 != BGP_INVALID_LABEL_INDEX
) {
2276 BGP_NODE_REGISTERED_FOR_LABEL
))
2277 bgp_unregister_for_label(rn
);
2278 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2280 bgp_set_valid_label(&rn
->local_label
);
2282 bgp_register_for_label(rn
, new_select
);
2284 } else if (CHECK_FLAG(rn
->flags
,
2285 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2286 bgp_unregister_for_label(rn
);
2288 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2289 bgp_unregister_for_label(rn
);
2293 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2295 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2296 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2297 old_select
, new_select
);
2300 /* If best route remains the same and this is not due to user-initiated
2301 * clear, see exactly what needs to be done.
2303 if (old_select
&& old_select
== new_select
2304 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2305 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2306 && !bgp
->addpath_tx_used
[afi
][safi
]) {
2307 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2309 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2310 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2312 if (bgp_fibupd_safi(safi
)
2313 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2315 if (new_select
->type
== ZEBRA_ROUTE_BGP
2316 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2317 || new_select
->sub_type
2318 == BGP_ROUTE_IMPORTED
))
2320 bgp_zebra_announce(rn
, p
, old_select
,
2324 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2325 bgp_zebra_clear_route_change_flags(rn
);
2327 /* If there is a change of interest to peers, reannounce the
2329 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2330 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2331 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2333 /* unicast routes must also be annouced to
2334 * labeled-unicast update-groups */
2335 if (safi
== SAFI_UNICAST
)
2336 group_announce_route(bgp
, afi
,
2337 SAFI_LABELED_UNICAST
, rn
,
2340 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2341 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2344 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2348 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2350 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2352 /* bestpath has changed; bump version */
2353 if (old_select
|| new_select
) {
2354 bgp_bump_version(rn
);
2356 if (!bgp
->t_rmap_def_originate_eval
) {
2360 update_group_refresh_default_originate_route_map
,
2361 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2362 &bgp
->t_rmap_def_originate_eval
);
2367 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2370 zlog_debug("%s: setting SELECTED flag", __func__
);
2371 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2372 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2373 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2377 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2378 if (old_select
!= new_select
) {
2380 vnc_import_bgp_exterior_del_route(bgp
, p
,
2382 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2385 vnc_import_bgp_exterior_add_route(bgp
, p
,
2387 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2393 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2395 /* unicast routes must also be annouced to labeled-unicast update-groups
2397 if (safi
== SAFI_UNICAST
)
2398 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2402 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2403 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2404 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2405 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2406 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2407 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2409 /* if this is an evpn imported type-5 prefix,
2410 * we need to withdraw the route first to clear
2411 * the nh neigh and the RMAC entry.
2414 is_route_parent_evpn(old_select
))
2415 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2417 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2419 /* Withdraw the route from the kernel. */
2420 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2421 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2422 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2423 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2425 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2429 /* advertise/withdraw type-5 routes */
2430 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2431 if (advertise_type5_routes(bgp
, afi
) && new_select
&&
2432 (!new_select
->extra
|| !new_select
->extra
->parent
)) {
2434 /* apply the route-map */
2435 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2438 ret
= route_map_apply(
2439 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2440 &rn
->p
, RMAP_BGP
, new_select
);
2441 if (ret
== RMAP_MATCH
)
2442 bgp_evpn_advertise_type5_route(
2443 bgp
, &rn
->p
, new_select
->attr
,
2446 bgp_evpn_advertise_type5_route(bgp
,
2452 } else if (advertise_type5_routes(bgp
, afi
) && old_select
&&
2453 (!old_select
->extra
|| !old_select
->extra
->parent
))
2454 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2457 /* Clear any route change flags. */
2458 bgp_zebra_clear_route_change_flags(rn
);
2460 /* Reap old select bgp_path_info, if it has been removed */
2461 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2462 bgp_path_info_reap(rn
, old_select
);
2464 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2468 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2470 struct bgp_process_queue
*pqnode
= data
;
2471 struct bgp
*bgp
= pqnode
->bgp
;
2472 struct bgp_table
*table
;
2473 struct bgp_node
*rn
;
2476 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2477 bgp_process_main_one(bgp
, NULL
, 0, 0);
2478 /* should always have dedicated wq call */
2479 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2483 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2484 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2485 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2486 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2487 table
= bgp_node_table(rn
);
2488 /* note, new RNs may be added as part of processing */
2489 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2491 bgp_unlock_node(rn
);
2492 bgp_table_unlock(table
);
2498 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2500 struct bgp_process_queue
*pqnode
= data
;
2502 bgp_unlock(pqnode
->bgp
);
2504 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2507 void bgp_process_queue_init(void)
2509 if (!bm
->process_main_queue
)
2510 bm
->process_main_queue
=
2511 work_queue_new(bm
->master
, "process_main_queue");
2513 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2514 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2515 bm
->process_main_queue
->spec
.max_retries
= 0;
2516 bm
->process_main_queue
->spec
.hold
= 50;
2517 /* Use a higher yield value of 50ms for main queue processing */
2518 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2521 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2523 struct bgp_process_queue
*pqnode
;
2525 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2526 sizeof(struct bgp_process_queue
));
2528 /* unlocked in bgp_processq_del */
2529 pqnode
->bgp
= bgp_lock(bgp
);
2530 STAILQ_INIT(&pqnode
->pqueue
);
2535 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2537 #define ARBITRARY_PROCESS_QLEN 10000
2538 struct work_queue
*wq
= bm
->process_main_queue
;
2539 struct bgp_process_queue
*pqnode
;
2540 int pqnode_reuse
= 0;
2542 /* already scheduled for processing? */
2543 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2549 /* Add route nodes to an existing work queue item until reaching the
2550 limit only if is from the same BGP view and it's not an EOIU marker
2552 if (work_queue_item_count(wq
)) {
2553 struct work_queue_item
*item
= work_queue_last_item(wq
);
2554 pqnode
= item
->data
;
2556 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2557 || pqnode
->bgp
!= bgp
2558 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2559 pqnode
= bgp_processq_alloc(bgp
);
2563 pqnode
= bgp_processq_alloc(bgp
);
2564 /* all unlocked in bgp_process_wq */
2565 bgp_table_lock(bgp_node_table(rn
));
2567 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2570 /* can't be enqueued twice */
2571 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2572 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2576 work_queue_add(wq
, pqnode
);
2581 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2583 struct bgp_process_queue
*pqnode
;
2585 if (bm
->process_main_queue
== NULL
)
2588 pqnode
= bgp_processq_alloc(bgp
);
2590 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2591 work_queue_add(bm
->process_main_queue
, pqnode
);
2594 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2598 peer
= THREAD_ARG(thread
);
2599 peer
->t_pmax_restart
= NULL
;
2601 if (bgp_debug_neighbor_events(peer
))
2603 "%s Maximum-prefix restart timer expired, restore peering",
2606 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2607 zlog_debug("%s: %s peer_clear failed",
2608 __PRETTY_FUNCTION__
, peer
->host
);
2613 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2617 iana_safi_t pkt_safi
;
2619 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2622 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2623 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2624 PEER_STATUS_PREFIX_LIMIT
)
2629 "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
2631 afi_safi_print(afi
, safi
), peer
->host
,
2632 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2633 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2635 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2636 PEER_FLAG_MAX_PREFIX_WARNING
))
2639 /* Convert AFI, SAFI to values for packet. */
2640 pkt_afi
= afi_int2iana(afi
);
2641 pkt_safi
= safi_int2iana(safi
);
2645 ndata
[0] = (pkt_afi
>> 8);
2647 ndata
[2] = pkt_safi
;
2648 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2649 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2650 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2651 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2653 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2654 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2655 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2659 /* Dynamic peers will just close their connection. */
2660 if (peer_dynamic_neighbor(peer
))
2663 /* restart timer start */
2664 if (peer
->pmax_restart
[afi
][safi
]) {
2665 peer
->v_pmax_restart
=
2666 peer
->pmax_restart
[afi
][safi
] * 60;
2668 if (bgp_debug_neighbor_events(peer
))
2670 "%s Maximum-prefix restart timer started for %d secs",
2671 peer
->host
, peer
->v_pmax_restart
);
2673 BGP_TIMER_ON(peer
->t_pmax_restart
,
2674 bgp_maximum_prefix_restart_timer
,
2675 peer
->v_pmax_restart
);
2680 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2681 PEER_STATUS_PREFIX_LIMIT
);
2683 if (peer
->pcount
[afi
][safi
]
2684 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2685 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2686 PEER_STATUS_PREFIX_THRESHOLD
)
2691 "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
2692 afi_safi_print(afi
, safi
), peer
->host
,
2693 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2694 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2695 PEER_STATUS_PREFIX_THRESHOLD
);
2697 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2698 PEER_STATUS_PREFIX_THRESHOLD
);
2702 /* Unconditionally remove the route from the RIB, without taking
2703 * damping into consideration (eg, because the session went down)
2705 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2706 struct peer
*peer
, afi_t afi
, safi_t safi
)
2708 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2710 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2711 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2713 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2716 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2717 struct peer
*peer
, afi_t afi
, safi_t safi
,
2718 struct prefix_rd
*prd
)
2720 /* apply dampening, if result is suppressed, we'll be retaining
2721 * the bgp_path_info in the RIB for historical reference.
2723 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2724 && peer
->sort
== BGP_PEER_EBGP
)
2725 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2726 == BGP_DAMP_SUPPRESSED
) {
2727 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2733 if (safi
== SAFI_MPLS_VPN
) {
2734 struct bgp_node
*prn
= NULL
;
2735 struct bgp_table
*table
= NULL
;
2737 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2738 (struct prefix
*)prd
);
2740 table
= (struct bgp_table
*)(prn
->info
);
2742 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2743 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2745 bgp_unlock_node(prn
);
2747 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2748 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2750 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2751 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2757 /* If this is an EVPN route, process for un-import. */
2758 if (safi
== SAFI_EVPN
)
2759 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2761 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2764 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2765 struct peer
*peer
, struct attr
*attr
,
2766 struct bgp_node
*rn
)
2768 struct bgp_path_info
*new;
2770 /* Make new BGP info. */
2771 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2773 new->instance
= instance
;
2774 new->sub_type
= sub_type
;
2777 new->uptime
= bgp_clock();
2779 new->addpath_tx_id
= ++peer
->bgp
->addpath_tx_id
;
2783 static void overlay_index_update(struct attr
*attr
,
2784 struct eth_segment_id
*eth_s_id
,
2785 union gw_addr
*gw_ip
)
2790 if (eth_s_id
== NULL
) {
2791 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2792 sizeof(struct eth_segment_id
));
2794 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2795 sizeof(struct eth_segment_id
));
2797 if (gw_ip
== NULL
) {
2798 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2800 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2801 sizeof(union gw_addr
));
2805 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2806 struct eth_segment_id
*eth_s_id
,
2807 union gw_addr
*gw_ip
)
2809 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2810 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2812 struct eth_segment_id esi
;
2816 if (afi
!= AFI_L2VPN
)
2819 memset(&temp
, 0, sizeof(temp
));
2820 path_eth_s_id
= &temp
.esi
;
2821 path_gw_ip
= &temp
.ip
;
2823 if (eth_s_id
== NULL
&& gw_ip
== NULL
)
2826 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2827 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2830 if (gw_ip
== NULL
) {
2831 memset(&temp
, 0, sizeof(temp
));
2832 path_gw_ip_remote
= &temp
.ip
;
2834 path_gw_ip_remote
= gw_ip
;
2836 if (eth_s_id
== NULL
) {
2837 memset(&temp
, 0, sizeof(temp
));
2838 path_eth_s_id_remote
= &temp
.esi
;
2840 path_eth_s_id_remote
= eth_s_id
;
2842 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2845 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2846 sizeof(struct eth_segment_id
));
2849 /* Check if received nexthop is valid or not. */
2850 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2855 /* Only validated for unicast and multicast currently. */
2856 /* Also valid for EVPN where the nexthop is an IP address. */
2857 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2860 /* If NEXT_HOP is present, validate it. */
2861 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2862 if (attr
->nexthop
.s_addr
== 0
2863 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2864 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2868 /* If MP_NEXTHOP is present, validate it. */
2869 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2870 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2871 * it is not an IPv6 link-local address.
2873 if (attr
->mp_nexthop_len
) {
2874 switch (attr
->mp_nexthop_len
) {
2875 case BGP_ATTR_NHLEN_IPV4
:
2876 case BGP_ATTR_NHLEN_VPNV4
:
2877 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2878 || IPV4_CLASS_DE(ntohl(
2879 attr
->mp_nexthop_global_in
.s_addr
))
2880 || bgp_nexthop_self(bgp
,
2881 attr
->mp_nexthop_global_in
));
2884 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
2885 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
2886 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
2887 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
2888 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
2889 || IN6_IS_ADDR_MULTICAST(
2890 &attr
->mp_nexthop_global
));
2902 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
2903 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
2904 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
2905 uint32_t num_labels
, int soft_reconfig
,
2906 struct bgp_route_evpn
*evpn
)
2909 int aspath_loop_count
= 0;
2910 struct bgp_node
*rn
;
2912 struct attr new_attr
;
2913 struct attr
*attr_new
;
2914 struct bgp_path_info
*pi
;
2915 struct bgp_path_info
*new;
2916 struct bgp_path_info_extra
*extra
;
2918 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
2920 int do_loop_check
= 1;
2921 int has_valid_label
= 0;
2923 int vnc_implicit_withdraw
= 0;
2927 memset(&new_attr
, 0, sizeof(struct attr
));
2928 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
2929 new_attr
.label
= MPLS_INVALID_LABEL
;
2932 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
2933 /* TODO: Check to see if we can get rid of "is_valid_label" */
2934 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
2935 has_valid_label
= (num_labels
> 0) ? 1 : 0;
2937 has_valid_label
= bgp_is_valid_label(label
);
2939 /* When peer's soft reconfiguration enabled. Record input packet in
2942 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
2943 && peer
!= bgp
->peer_self
)
2944 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
2946 /* Check previously received route. */
2947 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
2948 if (pi
->peer
== peer
&& pi
->type
== type
2949 && pi
->sub_type
== sub_type
2950 && pi
->addpath_rx_id
== addpath_id
)
2953 /* AS path local-as loop check. */
2954 if (peer
->change_local_as
) {
2955 if (peer
->allowas_in
[afi
][safi
])
2956 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
2957 else if (!CHECK_FLAG(peer
->flags
,
2958 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
2959 aspath_loop_count
= 1;
2961 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
2962 > aspath_loop_count
) {
2963 reason
= "as-path contains our own AS;";
2968 /* If the peer is configured for "allowas-in origin" and the last ASN in
2970 * as-path is our ASN then we do not need to call aspath_loop_check
2972 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
2973 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
2976 /* AS path loop check. */
2977 if (do_loop_check
) {
2978 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
2979 > peer
->allowas_in
[afi
][safi
]
2980 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
2981 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
2982 > peer
->allowas_in
[afi
][safi
])) {
2983 reason
= "as-path contains our own AS;";
2988 /* Route reflector originator ID check. */
2989 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
2990 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
2991 reason
= "originator is us;";
2995 /* Route reflector cluster ID check. */
2996 if (bgp_cluster_filter(peer
, attr
)) {
2997 reason
= "reflected from the same cluster;";
3001 /* Apply incoming filter. */
3002 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3007 bgp_attr_dup(&new_attr
, attr
);
3009 /* Apply incoming route-map.
3010 * NB: new_attr may now contain newly allocated values from route-map
3012 * commands, so we need bgp_attr_flush in the error paths, until we
3014 * the attr (which takes over the memory references) */
3015 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
)
3017 reason
= "route-map;";
3018 bgp_attr_flush(&new_attr
);
3022 if (peer
->sort
== BGP_PEER_EBGP
) {
3024 /* If we receive the graceful-shutdown community from an eBGP
3025 * peer we must lower local-preference */
3026 if (new_attr
.community
3027 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3028 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3029 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3031 /* If graceful-shutdown is configured then add the GSHUT
3032 * community to all paths received from eBGP peers */
3033 } else if (bgp_flag_check(peer
->bgp
,
3034 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3035 bgp_attr_add_gshut_community(&new_attr
);
3039 /* next hop check. */
3040 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3041 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3042 reason
= "martian or self next-hop;";
3043 bgp_attr_flush(&new_attr
);
3047 attr_new
= bgp_attr_intern(&new_attr
);
3049 /* If the update is implicit withdraw. */
3051 pi
->uptime
= bgp_clock();
3052 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3054 /* Same attribute comes in. */
3055 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3056 && attrhash_cmp(pi
->attr
, attr_new
)
3057 && (!has_valid_label
3058 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3059 num_labels
* sizeof(mpls_label_t
))
3061 && (overlay_index_equal(
3062 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3063 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3064 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3065 BGP_CONFIG_DAMPENING
)
3066 && peer
->sort
== BGP_PEER_EBGP
3067 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3068 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3069 bgp_debug_rdpfxpath2str(
3070 afi
, safi
, prd
, p
, label
,
3071 num_labels
, addpath_id
? 1 : 0,
3072 addpath_id
, pfx_buf
,
3074 zlog_debug("%s rcvd %s", peer
->host
,
3078 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3079 != BGP_DAMP_SUPPRESSED
) {
3080 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3082 bgp_process(bgp
, rn
, afi
, safi
);
3084 } else /* Duplicate - odd */
3086 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3087 if (!peer
->rcvd_attr_printed
) {
3089 "%s rcvd UPDATE w/ attr: %s",
3091 peer
->rcvd_attr_str
);
3092 peer
->rcvd_attr_printed
= 1;
3095 bgp_debug_rdpfxpath2str(
3096 afi
, safi
, prd
, p
, label
,
3097 num_labels
, addpath_id
? 1 : 0,
3098 addpath_id
, pfx_buf
,
3101 "%s rcvd %s...duplicate ignored",
3102 peer
->host
, pfx_buf
);
3105 /* graceful restart STALE flag unset. */
3106 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3107 bgp_path_info_unset_flag(
3108 rn
, pi
, BGP_PATH_STALE
);
3109 bgp_process(bgp
, rn
, afi
, safi
);
3113 bgp_unlock_node(rn
);
3114 bgp_attr_unintern(&attr_new
);
3119 /* Withdraw/Announce before we fully processed the withdraw */
3120 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3121 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3122 bgp_debug_rdpfxpath2str(
3123 afi
, safi
, prd
, p
, label
, num_labels
,
3124 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3127 "%s rcvd %s, flapped quicker than processing",
3128 peer
->host
, pfx_buf
);
3131 bgp_path_info_restore(rn
, pi
);
3134 /* Received Logging. */
3135 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3136 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3137 num_labels
, addpath_id
? 1 : 0,
3138 addpath_id
, pfx_buf
,
3140 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3143 /* graceful restart STALE flag unset. */
3144 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3145 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3147 /* The attribute is changed. */
3148 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3150 /* implicit withdraw, decrement aggregate and pcount here.
3151 * only if update is accepted, they'll increment below.
3153 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3155 /* Update bgp route dampening information. */
3156 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3157 && peer
->sort
== BGP_PEER_EBGP
) {
3158 /* This is implicit withdraw so we should update
3161 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3162 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3165 if (safi
== SAFI_MPLS_VPN
) {
3166 struct bgp_node
*prn
= NULL
;
3167 struct bgp_table
*table
= NULL
;
3169 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3170 (struct prefix
*)prd
);
3172 table
= (struct bgp_table
*)(prn
->info
);
3174 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3175 bgp
, prd
, table
, p
, pi
);
3177 bgp_unlock_node(prn
);
3179 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3180 && (safi
== SAFI_UNICAST
)) {
3181 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3183 * Implicit withdraw case.
3185 ++vnc_implicit_withdraw
;
3186 vnc_import_bgp_del_route(bgp
, p
, pi
);
3187 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3192 /* Special handling for EVPN update of an existing route. If the
3193 * extended community attribute has changed, we need to
3195 * the route using its existing extended community. It will be
3196 * subsequently processed for import with the new extended
3199 if (safi
== SAFI_EVPN
&& !same_attr
) {
3201 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3203 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3206 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3207 attr_new
->ecommunity
);
3209 if (bgp_debug_update(peer
, p
, NULL
, 1))
3211 "Change in EXT-COMM, existing %s new %s",
3213 pi
->attr
->ecommunity
),
3215 attr_new
->ecommunity
));
3216 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3222 /* Update to new attribute. */
3223 bgp_attr_unintern(&pi
->attr
);
3224 pi
->attr
= attr_new
;
3226 /* Update MPLS label */
3227 if (has_valid_label
) {
3228 extra
= bgp_path_info_extra_get(pi
);
3229 memcpy(&extra
->label
, label
,
3230 num_labels
* sizeof(mpls_label_t
));
3231 extra
->num_labels
= num_labels
;
3232 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3233 bgp_set_valid_label(&extra
->label
[0]);
3237 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3238 && (safi
== SAFI_UNICAST
)) {
3239 if (vnc_implicit_withdraw
) {
3241 * Add back the route with its new attributes
3243 * The route is still selected, until the route
3245 * queued by bgp_process actually runs. We have
3247 * update to the VNC side immediately to avoid
3249 * configuration changes (e.g., route-map
3251 * trigger re-importation of the entire RIB.
3253 vnc_import_bgp_add_route(bgp
, p
, pi
);
3254 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3258 /* Update Overlay Index */
3259 if (afi
== AFI_L2VPN
) {
3260 overlay_index_update(
3261 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3262 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3265 /* Update bgp route dampening information. */
3266 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3267 && peer
->sort
== BGP_PEER_EBGP
) {
3268 /* Now we do normal update dampening. */
3269 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3270 if (ret
== BGP_DAMP_SUPPRESSED
) {
3271 bgp_unlock_node(rn
);
3276 /* Nexthop reachability check - for unicast and
3277 * labeled-unicast.. */
3278 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3279 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3280 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3281 && !CHECK_FLAG(peer
->flags
,
3282 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3284 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3289 struct bgp
*bgp_nexthop
= bgp
;
3291 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3292 bgp_nexthop
= pi
->extra
->bgp_orig
;
3294 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3296 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3297 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3299 if (BGP_DEBUG(nht
, NHT
)) {
3300 char buf1
[INET6_ADDRSTRLEN
];
3302 (const void *)&attr_new
3304 buf1
, INET6_ADDRSTRLEN
);
3305 zlog_debug("%s(%s): NH unresolved",
3306 __FUNCTION__
, buf1
);
3308 bgp_path_info_unset_flag(rn
, pi
,
3312 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3315 if (safi
== SAFI_MPLS_VPN
) {
3316 struct bgp_node
*prn
= NULL
;
3317 struct bgp_table
*table
= NULL
;
3319 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3320 (struct prefix
*)prd
);
3322 table
= (struct bgp_table
*)(prn
->info
);
3324 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3325 bgp
, prd
, table
, p
, pi
);
3327 bgp_unlock_node(prn
);
3331 /* If this is an EVPN route and some attribute has changed,
3333 * route for import. If the extended community has changed, we
3335 * have done the un-import earlier and the import would result
3337 * route getting injected into appropriate L2 VNIs. If it is
3339 * some other attribute change, the import will result in
3341 * the attributes for the route in the VNI(s).
3343 if (safi
== SAFI_EVPN
&& !same_attr
)
3344 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3346 /* Process change. */
3347 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3349 bgp_process(bgp
, rn
, afi
, safi
);
3350 bgp_unlock_node(rn
);
3352 if (SAFI_UNICAST
== safi
3353 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3354 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3356 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3358 if ((SAFI_MPLS_VPN
== safi
)
3359 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3361 vpn_leak_to_vrf_update(bgp
, pi
);
3365 if (SAFI_MPLS_VPN
== safi
) {
3366 mpls_label_t label_decoded
= decode_label(label
);
3368 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3369 type
, sub_type
, &label_decoded
);
3371 if (SAFI_ENCAP
== safi
) {
3372 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3373 type
, sub_type
, NULL
);
3378 } // End of implicit withdraw
3380 /* Received Logging. */
3381 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3382 if (!peer
->rcvd_attr_printed
) {
3383 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3384 peer
->rcvd_attr_str
);
3385 peer
->rcvd_attr_printed
= 1;
3388 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3389 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3391 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3394 /* Make new BGP info. */
3395 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3397 /* Update MPLS label */
3398 if (has_valid_label
) {
3399 extra
= bgp_path_info_extra_get(new);
3400 memcpy(&extra
->label
, label
, num_labels
* sizeof(mpls_label_t
));
3401 extra
->num_labels
= num_labels
;
3402 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3403 bgp_set_valid_label(&extra
->label
[0]);
3406 /* Update Overlay Index */
3407 if (afi
== AFI_L2VPN
) {
3408 overlay_index_update(new->attr
,
3409 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3410 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3412 /* Nexthop reachability check. */
3413 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3414 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3415 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3416 && !CHECK_FLAG(peer
->flags
,
3417 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3418 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3423 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3424 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3425 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3427 if (BGP_DEBUG(nht
, NHT
)) {
3428 char buf1
[INET6_ADDRSTRLEN
];
3430 (const void *)&attr_new
->nexthop
,
3431 buf1
, INET6_ADDRSTRLEN
);
3432 zlog_debug("%s(%s): NH unresolved",
3433 __FUNCTION__
, buf1
);
3435 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3438 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3441 new->addpath_rx_id
= addpath_id
;
3443 /* Increment prefix */
3444 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3446 /* Register new BGP information. */
3447 bgp_path_info_add(rn
, new);
3449 /* route_node_get lock */
3450 bgp_unlock_node(rn
);
3453 if (safi
== SAFI_MPLS_VPN
) {
3454 struct bgp_node
*prn
= NULL
;
3455 struct bgp_table
*table
= NULL
;
3457 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3459 table
= (struct bgp_table
*)(prn
->info
);
3461 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3462 bgp
, prd
, table
, p
, new);
3464 bgp_unlock_node(prn
);
3468 /* If maximum prefix count is configured and current prefix
3470 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3473 /* If this is an EVPN route, process for import. */
3474 if (safi
== SAFI_EVPN
)
3475 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3477 /* Process change. */
3478 bgp_process(bgp
, rn
, afi
, safi
);
3480 if (SAFI_UNICAST
== safi
3481 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3482 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3483 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3485 if ((SAFI_MPLS_VPN
== safi
)
3486 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3488 vpn_leak_to_vrf_update(bgp
, new);
3491 if (SAFI_MPLS_VPN
== safi
) {
3492 mpls_label_t label_decoded
= decode_label(label
);
3494 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3495 sub_type
, &label_decoded
);
3497 if (SAFI_ENCAP
== safi
) {
3498 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3505 /* This BGP update is filtered. Log the reason then update BGP
3508 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3509 if (!peer
->rcvd_attr_printed
) {
3510 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3511 peer
->rcvd_attr_str
);
3512 peer
->rcvd_attr_printed
= 1;
3515 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3516 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3518 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3519 peer
->host
, pfx_buf
, reason
);
3523 /* If this is an EVPN route, un-import it as it is now filtered.
3525 if (safi
== SAFI_EVPN
)
3526 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3528 if (SAFI_UNICAST
== safi
3529 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3530 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3532 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3534 if ((SAFI_MPLS_VPN
== safi
)
3535 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3537 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3540 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3543 bgp_unlock_node(rn
);
3547 * Filtered update is treated as an implicit withdrawal (see
3549 * a few lines above)
3551 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3552 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3560 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3561 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3562 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3563 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3566 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3567 struct bgp_node
*rn
;
3568 struct bgp_path_info
*pi
;
3571 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3572 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3580 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3582 /* If peer is soft reconfiguration enabled. Record input packet for
3583 * further calculation.
3585 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3586 * routes that are filtered. This tanks out Quagga RS pretty badly due
3588 * the iteration over all RS clients.
3589 * Since we need to remove the entry from adj_in anyway, do that first
3591 * if there was no entry, we don't need to do anything more.
3593 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3594 && peer
!= bgp
->peer_self
)
3595 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3596 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3597 bgp_debug_rdpfxpath2str(
3598 afi
, safi
, prd
, p
, label
, num_labels
,
3599 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3602 "%s withdrawing route %s not in adj-in",
3603 peer
->host
, pfx_buf
);
3605 bgp_unlock_node(rn
);
3609 /* Lookup withdrawn route. */
3610 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
3611 if (pi
->peer
== peer
&& pi
->type
== type
3612 && pi
->sub_type
== sub_type
3613 && pi
->addpath_rx_id
== addpath_id
)
3617 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3618 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3619 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3621 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3625 /* Withdraw specified route from routing table. */
3626 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3627 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3628 if (SAFI_UNICAST
== safi
3629 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3630 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3631 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3633 if ((SAFI_MPLS_VPN
== safi
)
3634 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3636 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3638 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3639 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3640 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3642 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3645 /* Unlock bgp_node_get() lock. */
3646 bgp_unlock_node(rn
);
3651 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3654 struct update_subgroup
*subgrp
;
3655 subgrp
= peer_subgroup(peer
, afi
, safi
);
3656 subgroup_default_originate(subgrp
, withdraw
);
3661 * bgp_stop_announce_route_timer
3663 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3665 if (!paf
->t_announce_route
)
3668 THREAD_TIMER_OFF(paf
->t_announce_route
);
3672 * bgp_announce_route_timer_expired
3674 * Callback that is invoked when the route announcement timer for a
3677 static int bgp_announce_route_timer_expired(struct thread
*t
)
3679 struct peer_af
*paf
;
3682 paf
= THREAD_ARG(t
);
3685 if (peer
->status
!= Established
)
3688 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3691 peer_af_announce_route(paf
, 1);
3696 * bgp_announce_route
3698 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3700 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3702 struct peer_af
*paf
;
3703 struct update_subgroup
*subgrp
;
3705 paf
= peer_af_find(peer
, afi
, safi
);
3708 subgrp
= PAF_SUBGRP(paf
);
3711 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3712 * or a refresh has already been triggered.
3714 if (!subgrp
|| paf
->t_announce_route
)
3718 * Start a timer to stagger/delay the announce. This serves
3719 * two purposes - announcement can potentially be combined for
3720 * multiple peers and the announcement doesn't happen in the
3723 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3724 (subgrp
->peer_count
== 1)
3725 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3726 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3727 &paf
->t_announce_route
);
3731 * Announce routes from all AF tables to a peer.
3733 * This should ONLY be called when there is a need to refresh the
3734 * routes to the peer based on a policy change for this peer alone
3735 * or a route refresh request received from the peer.
3736 * The operation will result in splitting the peer from its existing
3737 * subgroups and putting it in new subgroups.
3739 void bgp_announce_route_all(struct peer
*peer
)
3744 FOREACH_AFI_SAFI (afi
, safi
)
3745 bgp_announce_route(peer
, afi
, safi
);
3748 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3749 struct bgp_table
*table
,
3750 struct prefix_rd
*prd
)
3753 struct bgp_node
*rn
;
3754 struct bgp_adj_in
*ain
;
3757 table
= peer
->bgp
->rib
[afi
][safi
];
3759 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3760 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3761 if (ain
->peer
!= peer
)
3764 struct bgp_path_info
*pi
= rn
->info
;
3765 uint32_t num_labels
= 0;
3766 mpls_label_t
*label_pnt
= NULL
;
3768 if (pi
&& pi
->extra
)
3769 num_labels
= pi
->extra
->num_labels
;
3771 label_pnt
= &pi
->extra
->label
[0];
3773 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3774 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3775 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3776 num_labels
, 1, NULL
);
3779 bgp_unlock_node(rn
);
3785 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3787 struct bgp_node
*rn
;
3788 struct bgp_table
*table
;
3790 if (peer
->status
!= Established
)
3793 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3794 && (safi
!= SAFI_EVPN
))
3795 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3797 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3798 rn
= bgp_route_next(rn
))
3799 if ((table
= rn
->info
) != NULL
) {
3800 struct prefix_rd prd
;
3801 prd
.family
= AF_UNSPEC
;
3803 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3805 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3811 struct bgp_clear_node_queue
{
3812 struct bgp_node
*rn
;
3815 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3817 struct bgp_clear_node_queue
*cnq
= data
;
3818 struct bgp_node
*rn
= cnq
->rn
;
3819 struct peer
*peer
= wq
->spec
.data
;
3820 struct bgp_path_info
*pi
;
3822 afi_t afi
= bgp_node_table(rn
)->afi
;
3823 safi_t safi
= bgp_node_table(rn
)->safi
;
3828 /* It is possible that we have multiple paths for a prefix from a peer
3829 * if that peer is using AddPath.
3831 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
3832 if (pi
->peer
!= peer
)
3835 /* graceful restart STALE flag set. */
3836 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
3837 && peer
->nsf
[afi
][safi
]
3838 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
3839 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
3840 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
3842 /* If this is an EVPN route, process for
3844 if (safi
== SAFI_EVPN
)
3845 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
3847 /* Handle withdraw for VRF route-leaking and L3VPN */
3848 if (SAFI_UNICAST
== safi
3849 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
3850 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3851 vpn_leak_from_vrf_withdraw(bgp_get_default(),
3854 if (SAFI_MPLS_VPN
== safi
&&
3855 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
3856 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3859 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3865 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
3867 struct bgp_clear_node_queue
*cnq
= data
;
3868 struct bgp_node
*rn
= cnq
->rn
;
3869 struct bgp_table
*table
= bgp_node_table(rn
);
3871 bgp_unlock_node(rn
);
3872 bgp_table_unlock(table
);
3873 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
3876 static void bgp_clear_node_complete(struct work_queue
*wq
)
3878 struct peer
*peer
= wq
->spec
.data
;
3880 /* Tickle FSM to start moving again */
3881 BGP_EVENT_ADD(peer
, Clearing_Completed
);
3883 peer_unlock(peer
); /* bgp_clear_route */
3886 static void bgp_clear_node_queue_init(struct peer
*peer
)
3888 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
3890 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
3891 #undef CLEAR_QUEUE_NAME_LEN
3893 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
3894 peer
->clear_node_queue
->spec
.hold
= 10;
3895 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
3896 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
3897 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
3898 peer
->clear_node_queue
->spec
.max_retries
= 0;
3900 /* we only 'lock' this peer reference when the queue is actually active
3902 peer
->clear_node_queue
->spec
.data
= peer
;
3905 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3906 struct bgp_table
*table
)
3908 struct bgp_node
*rn
;
3909 int force
= bm
->process_main_queue
? 0 : 1;
3912 table
= peer
->bgp
->rib
[afi
][safi
];
3914 /* If still no table => afi/safi isn't configured at all or smth. */
3918 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
3919 struct bgp_path_info
*pi
, *next
;
3920 struct bgp_adj_in
*ain
;
3921 struct bgp_adj_in
*ain_next
;
3923 /* XXX:TODO: This is suboptimal, every non-empty route_node is
3924 * queued for every clearing peer, regardless of whether it is
3925 * relevant to the peer at hand.
3927 * Overview: There are 3 different indices which need to be
3928 * scrubbed, potentially, when a peer is removed:
3930 * 1 peer's routes visible via the RIB (ie accepted routes)
3931 * 2 peer's routes visible by the (optional) peer's adj-in index
3932 * 3 other routes visible by the peer's adj-out index
3934 * 3 there is no hurry in scrubbing, once the struct peer is
3935 * removed from bgp->peer, we could just GC such deleted peer's
3936 * adj-outs at our leisure.
3938 * 1 and 2 must be 'scrubbed' in some way, at least made
3939 * invisible via RIB index before peer session is allowed to be
3940 * brought back up. So one needs to know when such a 'search' is
3945 * - there'd be a single global queue or a single RIB walker
3946 * - rather than tracking which route_nodes still need to be
3947 * examined on a peer basis, we'd track which peers still
3950 * Given that our per-peer prefix-counts now should be reliable,
3951 * this may actually be achievable. It doesn't seem to be a huge
3952 * problem at this time,
3954 * It is possible that we have multiple paths for a prefix from
3956 * if that peer is using AddPath.
3960 ain_next
= ain
->next
;
3962 if (ain
->peer
== peer
) {
3963 bgp_adj_in_remove(rn
, ain
);
3964 bgp_unlock_node(rn
);
3970 for (pi
= rn
->info
; pi
; pi
= next
) {
3972 if (pi
->peer
!= peer
)
3976 bgp_path_info_reap(rn
, pi
);
3978 struct bgp_clear_node_queue
*cnq
;
3980 /* both unlocked in bgp_clear_node_queue_del */
3981 bgp_table_lock(bgp_node_table(rn
));
3984 MTYPE_BGP_CLEAR_NODE_QUEUE
,
3985 sizeof(struct bgp_clear_node_queue
));
3987 work_queue_add(peer
->clear_node_queue
, cnq
);
3995 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3997 struct bgp_node
*rn
;
3998 struct bgp_table
*table
;
4000 if (peer
->clear_node_queue
== NULL
)
4001 bgp_clear_node_queue_init(peer
);
4003 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4004 * Idle until it receives a Clearing_Completed event. This protects
4005 * against peers which flap faster than we can we clear, which could
4008 * a) race with routes from the new session being installed before
4009 * clear_route_node visits the node (to delete the route of that
4011 * b) resource exhaustion, clear_route_node likely leads to an entry
4012 * on the process_main queue. Fast-flapping could cause that queue
4016 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4017 * the unlock will happen upon work-queue completion; other wise, the
4018 * unlock happens at the end of this function.
4020 if (!peer
->clear_node_queue
->thread
)
4023 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4024 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4026 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4027 rn
= bgp_route_next(rn
))
4028 if ((table
= rn
->info
) != NULL
)
4029 bgp_clear_route_table(peer
, afi
, safi
, table
);
4031 /* unlock if no nodes got added to the clear-node-queue. */
4032 if (!peer
->clear_node_queue
->thread
)
4036 void bgp_clear_route_all(struct peer
*peer
)
4041 FOREACH_AFI_SAFI (afi
, safi
)
4042 bgp_clear_route(peer
, afi
, safi
);
4045 rfapiProcessPeerDown(peer
);
4049 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4051 struct bgp_table
*table
;
4052 struct bgp_node
*rn
;
4053 struct bgp_adj_in
*ain
;
4054 struct bgp_adj_in
*ain_next
;
4056 table
= peer
->bgp
->rib
[afi
][safi
];
4058 /* It is possible that we have multiple paths for a prefix from a peer
4059 * if that peer is using AddPath.
4061 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4065 ain_next
= ain
->next
;
4067 if (ain
->peer
== peer
) {
4068 bgp_adj_in_remove(rn
, ain
);
4069 bgp_unlock_node(rn
);
4077 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4079 struct bgp_node
*rn
;
4080 struct bgp_path_info
*pi
;
4081 struct bgp_table
*table
;
4083 if (safi
== SAFI_MPLS_VPN
) {
4084 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4085 rn
= bgp_route_next(rn
)) {
4086 struct bgp_node
*rm
;
4088 /* look for neighbor in tables */
4089 if ((table
= rn
->info
) == NULL
)
4092 for (rm
= bgp_table_top(table
); rm
;
4093 rm
= bgp_route_next(rm
))
4094 for (pi
= rm
->info
; pi
; pi
= pi
->next
) {
4095 if (pi
->peer
!= peer
)
4097 if (!CHECK_FLAG(pi
->flags
,
4101 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4106 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4107 rn
= bgp_route_next(rn
))
4108 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
4109 if (pi
->peer
!= peer
)
4111 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4113 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4119 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4122 struct bgp_node
*rn
;
4123 struct bgp_path_info
*pi
;
4124 struct bgp_path_info
*next
;
4126 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4127 for (pi
= rn
->info
; pi
; pi
= next
) {
4129 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4130 && pi
->type
== ZEBRA_ROUTE_BGP
4131 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4132 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4133 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4135 if (bgp_fibupd_safi(safi
))
4136 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4138 bgp_path_info_reap(rn
, pi
);
4143 /* Delete all kernel routes. */
4144 void bgp_cleanup_routes(struct bgp
*bgp
)
4147 struct bgp_node
*rn
;
4149 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4150 if (afi
== AFI_L2VPN
)
4152 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4155 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4157 if (afi
!= AFI_L2VPN
) {
4159 safi
= SAFI_MPLS_VPN
;
4160 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4161 rn
= bgp_route_next(rn
)) {
4163 bgp_cleanup_table(bgp
,
4164 (struct bgp_table
*)(rn
->info
),
4166 bgp_table_finish((struct bgp_table
**)&(
4169 bgp_unlock_node(rn
);
4173 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4174 rn
= bgp_route_next(rn
)) {
4176 bgp_cleanup_table(bgp
,
4177 (struct bgp_table
*)(rn
->info
),
4179 bgp_table_finish((struct bgp_table
**)&(
4182 bgp_unlock_node(rn
);
4187 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4188 rn
= bgp_route_next(rn
)) {
4190 bgp_cleanup_table(bgp
,
4191 (struct bgp_table
*)(rn
->info
),
4193 bgp_table_finish((struct bgp_table
**)&(rn
->info
));
4195 bgp_unlock_node(rn
);
4200 void bgp_reset(void)
4203 bgp_zclient_reset();
4204 access_list_reset();
4205 prefix_list_reset();
4208 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4210 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4211 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4212 PEER_CAP_ADDPATH_AF_TX_RCV
));
4215 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4217 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4218 struct bgp_nlri
*packet
)
4227 int addpath_encoded
;
4228 uint32_t addpath_id
;
4231 lim
= pnt
+ packet
->length
;
4233 safi
= packet
->safi
;
4235 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4237 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4238 syntactic validity. If the field is syntactically incorrect,
4239 then the Error Subcode is set to Invalid Network Field. */
4240 for (; pnt
< lim
; pnt
+= psize
) {
4241 /* Clear prefix structure. */
4242 memset(&p
, 0, sizeof(struct prefix
));
4244 if (addpath_encoded
) {
4246 /* When packet overflow occurs return immediately. */
4247 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4250 addpath_id
= ntohl(*((uint32_t *)pnt
));
4251 pnt
+= BGP_ADDPATH_ID_LEN
;
4254 /* Fetch prefix length. */
4255 p
.prefixlen
= *pnt
++;
4256 /* afi/safi validity already verified by caller,
4257 * bgp_update_receive */
4258 p
.family
= afi2family(afi
);
4260 /* Prefix length check. */
4261 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4264 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4265 peer
->host
, p
.prefixlen
, packet
->afi
);
4269 /* Packet size overflow check. */
4270 psize
= PSIZE(p
.prefixlen
);
4272 /* When packet overflow occur return immediately. */
4273 if (pnt
+ psize
> lim
) {
4276 "%s [Error] Update packet error (prefix length %d overflows packet)",
4277 peer
->host
, p
.prefixlen
);
4281 /* Defensive coding, double-check the psize fits in a struct
4283 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4286 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4287 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4291 /* Fetch prefix from NLRI packet. */
4292 memcpy(p
.u
.val
, pnt
, psize
);
4294 /* Check address. */
4295 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4296 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4297 /* From RFC4271 Section 6.3:
4299 * If a prefix in the NLRI field is semantically
4301 * (e.g., an unexpected multicast IP address),
4303 * be logged locally, and the prefix SHOULD be
4308 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4309 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4314 /* Check address. */
4315 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4316 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4321 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4323 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4328 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4333 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4335 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4342 /* Normal process. */
4344 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4345 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4346 NULL
, NULL
, 0, 0, NULL
);
4348 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4349 safi
, ZEBRA_ROUTE_BGP
,
4350 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4353 /* Address family configuration mismatch or maximum-prefix count
4359 /* Packet length consistency check. */
4363 "%s [Error] Update packet error (prefix length mismatch with total length)",
4371 static struct bgp_static
*bgp_static_new(void)
4373 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4376 static void bgp_static_free(struct bgp_static
*bgp_static
)
4378 if (bgp_static
->rmap
.name
)
4379 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4380 if (bgp_static
->eth_s_id
)
4381 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4382 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4385 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4386 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4388 struct bgp_node
*rn
;
4389 struct bgp_path_info
*pi
;
4390 struct bgp_path_info
*new;
4391 struct bgp_path_info rmap_path
;
4393 struct attr
*attr_new
;
4396 int vnc_implicit_withdraw
= 0;
4403 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4405 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4407 attr
.nexthop
= bgp_static
->igpnexthop
;
4408 attr
.med
= bgp_static
->igpmetric
;
4409 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4411 if (bgp_static
->atomic
)
4412 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4414 /* Store label index, if required. */
4415 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4416 attr
.label_index
= bgp_static
->label_index
;
4417 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4420 /* Apply route-map. */
4421 if (bgp_static
->rmap
.name
) {
4422 struct attr attr_tmp
= attr
;
4424 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4425 rmap_path
.peer
= bgp
->peer_self
;
4426 rmap_path
.attr
= &attr_tmp
;
4428 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4430 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4433 bgp
->peer_self
->rmap_type
= 0;
4435 if (ret
== RMAP_DENYMATCH
) {
4436 /* Free uninterned attribute. */
4437 bgp_attr_flush(&attr_tmp
);
4439 /* Unintern original. */
4440 aspath_unintern(&attr
.aspath
);
4441 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4445 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4446 bgp_attr_add_gshut_community(&attr_tmp
);
4448 attr_new
= bgp_attr_intern(&attr_tmp
);
4451 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4452 bgp_attr_add_gshut_community(&attr
);
4454 attr_new
= bgp_attr_intern(&attr
);
4457 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4458 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4459 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4463 if (attrhash_cmp(pi
->attr
, attr_new
)
4464 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4465 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4466 bgp_unlock_node(rn
);
4467 bgp_attr_unintern(&attr_new
);
4468 aspath_unintern(&attr
.aspath
);
4471 /* The attribute is changed. */
4472 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4474 /* Rewrite BGP route information. */
4475 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4476 bgp_path_info_restore(rn
, pi
);
4478 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4480 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4481 && (safi
== SAFI_UNICAST
)) {
4482 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4484 * Implicit withdraw case.
4485 * We have to do this before pi is
4488 ++vnc_implicit_withdraw
;
4489 vnc_import_bgp_del_route(bgp
, p
, pi
);
4490 vnc_import_bgp_exterior_del_route(
4495 bgp_attr_unintern(&pi
->attr
);
4496 pi
->attr
= attr_new
;
4497 pi
->uptime
= bgp_clock();
4499 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4500 && (safi
== SAFI_UNICAST
)) {
4501 if (vnc_implicit_withdraw
) {
4502 vnc_import_bgp_add_route(bgp
, p
, pi
);
4503 vnc_import_bgp_exterior_add_route(
4509 /* Nexthop reachability check. */
4510 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4511 && (safi
== SAFI_UNICAST
4512 || safi
== SAFI_LABELED_UNICAST
)) {
4514 struct bgp
*bgp_nexthop
= bgp
;
4516 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4517 bgp_nexthop
= pi
->extra
->bgp_orig
;
4519 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4521 bgp_path_info_set_flag(rn
, pi
,
4524 if (BGP_DEBUG(nht
, NHT
)) {
4525 char buf1
[INET6_ADDRSTRLEN
];
4526 inet_ntop(p
->family
,
4530 "%s(%s): Route not in table, not advertising",
4531 __FUNCTION__
, buf1
);
4533 bgp_path_info_unset_flag(
4534 rn
, pi
, BGP_PATH_VALID
);
4537 /* Delete the NHT structure if any, if we're
4539 * enabling/disabling import check. We
4540 * deregister the route
4541 * from NHT to avoid overloading NHT and the
4542 * process interaction
4544 bgp_unlink_nexthop(pi
);
4545 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4547 /* Process change. */
4548 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4549 bgp_process(bgp
, rn
, afi
, safi
);
4551 if (SAFI_UNICAST
== safi
4552 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4554 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4555 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4559 bgp_unlock_node(rn
);
4560 aspath_unintern(&attr
.aspath
);
4565 /* Make new BGP info. */
4566 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4568 /* Nexthop reachability check. */
4569 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4570 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4571 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4572 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4574 if (BGP_DEBUG(nht
, NHT
)) {
4575 char buf1
[INET6_ADDRSTRLEN
];
4576 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4579 "%s(%s): Route not in table, not advertising",
4580 __FUNCTION__
, buf1
);
4582 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4585 /* Delete the NHT structure if any, if we're toggling between
4586 * enabling/disabling import check. We deregister the route
4587 * from NHT to avoid overloading NHT and the process interaction
4589 bgp_unlink_nexthop(new);
4591 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4594 /* Aggregate address increment. */
4595 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4597 /* Register new BGP information. */
4598 bgp_path_info_add(rn
, new);
4600 /* route_node_get lock */
4601 bgp_unlock_node(rn
);
4603 /* Process change. */
4604 bgp_process(bgp
, rn
, afi
, safi
);
4606 if (SAFI_UNICAST
== safi
4607 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4608 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4609 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4612 /* Unintern original. */
4613 aspath_unintern(&attr
.aspath
);
4616 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4619 struct bgp_node
*rn
;
4620 struct bgp_path_info
*pi
;
4622 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4624 /* Check selected route and self inserted route. */
4625 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4626 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4627 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4630 /* Withdraw static BGP route from routing table. */
4632 if (SAFI_UNICAST
== safi
4633 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4634 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4635 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4637 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4638 bgp_unlink_nexthop(pi
);
4639 bgp_path_info_delete(rn
, pi
);
4640 bgp_process(bgp
, rn
, afi
, safi
);
4643 /* Unlock bgp_node_lookup. */
4644 bgp_unlock_node(rn
);
4648 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4650 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4651 afi_t afi
, safi_t safi
,
4652 struct prefix_rd
*prd
)
4654 struct bgp_node
*rn
;
4655 struct bgp_path_info
*pi
;
4657 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4659 /* Check selected route and self inserted route. */
4660 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4661 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4662 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4665 /* Withdraw static BGP route from routing table. */
4668 rfapiProcessWithdraw(
4669 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4670 1); /* Kill, since it is an administrative change */
4672 if (SAFI_MPLS_VPN
== safi
4673 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4674 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4676 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4677 bgp_path_info_delete(rn
, pi
);
4678 bgp_process(bgp
, rn
, afi
, safi
);
4681 /* Unlock bgp_node_lookup. */
4682 bgp_unlock_node(rn
);
4685 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4686 struct bgp_static
*bgp_static
, afi_t afi
,
4689 struct bgp_node
*rn
;
4690 struct bgp_path_info
*new;
4691 struct attr
*attr_new
;
4692 struct attr attr
= {0};
4693 struct bgp_path_info
*pi
;
4695 mpls_label_t label
= 0;
4697 uint32_t num_labels
= 0;
4702 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4704 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4707 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4709 attr
.nexthop
= bgp_static
->igpnexthop
;
4710 attr
.med
= bgp_static
->igpmetric
;
4711 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4713 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4714 || (safi
== SAFI_ENCAP
)) {
4715 if (afi
== AFI_IP
) {
4716 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4717 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4720 if (afi
== AFI_L2VPN
) {
4721 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4723 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4724 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4725 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4726 sizeof(struct in6_addr
));
4727 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4728 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4729 struct bgp_encap_type_vxlan bet
;
4730 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4731 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4732 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4734 if (bgp_static
->router_mac
) {
4735 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4738 /* Apply route-map. */
4739 if (bgp_static
->rmap
.name
) {
4740 struct attr attr_tmp
= attr
;
4741 struct bgp_path_info rmap_path
;
4744 rmap_path
.peer
= bgp
->peer_self
;
4745 rmap_path
.attr
= &attr_tmp
;
4747 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4749 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4752 bgp
->peer_self
->rmap_type
= 0;
4754 if (ret
== RMAP_DENYMATCH
) {
4755 /* Free uninterned attribute. */
4756 bgp_attr_flush(&attr_tmp
);
4758 /* Unintern original. */
4759 aspath_unintern(&attr
.aspath
);
4760 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4765 attr_new
= bgp_attr_intern(&attr_tmp
);
4767 attr_new
= bgp_attr_intern(&attr
);
4770 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
4771 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4772 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4776 memset(&add
, 0, sizeof(union gw_addr
));
4777 if (attrhash_cmp(pi
->attr
, attr_new
)
4778 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4779 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4780 bgp_unlock_node(rn
);
4781 bgp_attr_unintern(&attr_new
);
4782 aspath_unintern(&attr
.aspath
);
4785 /* The attribute is changed. */
4786 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4788 /* Rewrite BGP route information. */
4789 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4790 bgp_path_info_restore(rn
, pi
);
4792 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4793 bgp_attr_unintern(&pi
->attr
);
4794 pi
->attr
= attr_new
;
4795 pi
->uptime
= bgp_clock();
4798 label
= decode_label(&pi
->extra
->label
[0]);
4801 /* Process change. */
4802 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4803 bgp_process(bgp
, rn
, afi
, safi
);
4805 if (SAFI_MPLS_VPN
== safi
4806 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4807 vpn_leak_to_vrf_update(bgp
, pi
);
4810 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
4811 pi
->attr
, afi
, safi
, pi
->type
,
4812 pi
->sub_type
, &label
);
4814 bgp_unlock_node(rn
);
4815 aspath_unintern(&attr
.aspath
);
4821 /* Make new BGP info. */
4822 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4824 SET_FLAG(new->flags
, BGP_PATH_VALID
);
4825 new->extra
= bgp_path_info_extra_new();
4827 new->extra
->label
[0] = bgp_static
->label
;
4828 new->extra
->num_labels
= num_labels
;
4831 label
= decode_label(&bgp_static
->label
);
4834 /* Aggregate address increment. */
4835 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4837 /* Register new BGP information. */
4838 bgp_path_info_add(rn
, new);
4839 /* route_node_get lock */
4840 bgp_unlock_node(rn
);
4842 /* Process change. */
4843 bgp_process(bgp
, rn
, afi
, safi
);
4845 if (SAFI_MPLS_VPN
== safi
4846 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4847 vpn_leak_to_vrf_update(bgp
, new);
4850 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
4851 safi
, new->type
, new->sub_type
, &label
);
4854 /* Unintern original. */
4855 aspath_unintern(&attr
.aspath
);
4858 /* Configure static BGP network. When user don't run zebra, static
4859 route should be installed as valid. */
4860 static int bgp_static_set(struct vty
*vty
, const char *negate
,
4861 const char *ip_str
, afi_t afi
, safi_t safi
,
4862 const char *rmap
, int backdoor
, uint32_t label_index
)
4864 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
4867 struct bgp_static
*bgp_static
;
4868 struct bgp_node
*rn
;
4869 uint8_t need_update
= 0;
4871 /* Convert IP prefix string to struct prefix. */
4872 ret
= str2prefix(ip_str
, &p
);
4874 vty_out(vty
, "%% Malformed prefix\n");
4875 return CMD_WARNING_CONFIG_FAILED
;
4877 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4878 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
4879 return CMD_WARNING_CONFIG_FAILED
;
4886 /* Set BGP static route configuration. */
4887 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
4890 vty_out(vty
, "%% Can't find static route specified\n");
4891 return CMD_WARNING_CONFIG_FAILED
;
4894 bgp_static
= bgp_static_get_node_info(rn
);
4896 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
4897 && (label_index
!= bgp_static
->label_index
)) {
4899 "%% label-index doesn't match static route\n");
4900 return CMD_WARNING_CONFIG_FAILED
;
4903 if ((rmap
&& bgp_static
->rmap
.name
)
4904 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
4906 "%% route-map name doesn't match static route\n");
4907 return CMD_WARNING_CONFIG_FAILED
;
4910 /* Update BGP RIB. */
4911 if (!bgp_static
->backdoor
)
4912 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4914 /* Clear configuration. */
4915 bgp_static_free(bgp_static
);
4916 bgp_static_set_node_info(rn
, NULL
);
4917 bgp_unlock_node(rn
);
4918 bgp_unlock_node(rn
);
4921 /* Set BGP static route configuration. */
4922 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
4924 bgp_static
= bgp_static_get_node_info(rn
);
4926 /* Configuration change. */
4927 /* Label index cannot be changed. */
4928 if (bgp_static
->label_index
!= label_index
) {
4929 vty_out(vty
, "%% cannot change label-index\n");
4930 return CMD_WARNING_CONFIG_FAILED
;
4933 /* Check previous routes are installed into BGP. */
4934 if (bgp_static
->valid
4935 && bgp_static
->backdoor
!= backdoor
)
4938 bgp_static
->backdoor
= backdoor
;
4941 if (bgp_static
->rmap
.name
)
4942 XFREE(MTYPE_ROUTE_MAP_NAME
,
4943 bgp_static
->rmap
.name
);
4944 bgp_static
->rmap
.name
=
4945 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4946 bgp_static
->rmap
.map
=
4947 route_map_lookup_by_name(rmap
);
4949 if (bgp_static
->rmap
.name
)
4950 XFREE(MTYPE_ROUTE_MAP_NAME
,
4951 bgp_static
->rmap
.name
);
4952 bgp_static
->rmap
.name
= NULL
;
4953 bgp_static
->rmap
.map
= NULL
;
4954 bgp_static
->valid
= 0;
4956 bgp_unlock_node(rn
);
4958 /* New configuration. */
4959 bgp_static
= bgp_static_new();
4960 bgp_static
->backdoor
= backdoor
;
4961 bgp_static
->valid
= 0;
4962 bgp_static
->igpmetric
= 0;
4963 bgp_static
->igpnexthop
.s_addr
= 0;
4964 bgp_static
->label_index
= label_index
;
4967 if (bgp_static
->rmap
.name
)
4968 XFREE(MTYPE_ROUTE_MAP_NAME
,
4969 bgp_static
->rmap
.name
);
4970 bgp_static
->rmap
.name
=
4971 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
4972 bgp_static
->rmap
.map
=
4973 route_map_lookup_by_name(rmap
);
4975 bgp_static_set_node_info(rn
, bgp_static
);
4978 bgp_static
->valid
= 1;
4980 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
4982 if (!bgp_static
->backdoor
)
4983 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
4989 void bgp_static_add(struct bgp
*bgp
)
4993 struct bgp_node
*rn
;
4994 struct bgp_node
*rm
;
4995 struct bgp_table
*table
;
4996 struct bgp_static
*bgp_static
;
4998 FOREACH_AFI_SAFI (afi
, safi
)
4999 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5000 rn
= bgp_route_next(rn
)) {
5001 if (rn
->info
== NULL
)
5004 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5005 || (safi
== SAFI_EVPN
)) {
5008 for (rm
= bgp_table_top(table
); rm
;
5009 rm
= bgp_route_next(rm
)) {
5011 bgp_static_get_node_info(rm
);
5012 bgp_static_update_safi(bgp
, &rm
->p
,
5017 bgp_static_update(bgp
, &rn
->p
,
5018 bgp_static_get_node_info(rn
),
5024 /* Called from bgp_delete(). Delete all static routes from the BGP
5026 void bgp_static_delete(struct bgp
*bgp
)
5030 struct bgp_node
*rn
;
5031 struct bgp_node
*rm
;
5032 struct bgp_table
*table
;
5033 struct bgp_static
*bgp_static
;
5035 FOREACH_AFI_SAFI (afi
, safi
)
5036 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5037 rn
= bgp_route_next(rn
)) {
5038 if (rn
->info
== NULL
)
5041 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5042 || (safi
== SAFI_EVPN
)) {
5045 for (rm
= bgp_table_top(table
); rm
;
5046 rm
= bgp_route_next(rm
)) {
5048 bgp_static_get_node_info(rm
);
5049 bgp_static_withdraw_safi(
5050 bgp
, &rm
->p
, AFI_IP
, safi
,
5051 (struct prefix_rd
*)&rn
->p
);
5052 bgp_static_free(bgp_static
);
5053 bgp_static_set_node_info(rn
, NULL
);
5054 bgp_unlock_node(rn
);
5057 bgp_static
= bgp_static_get_node_info(rn
);
5058 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5059 bgp_static_free(bgp_static
);
5060 bgp_static_set_node_info(rn
, NULL
);
5061 bgp_unlock_node(rn
);
5066 void bgp_static_redo_import_check(struct bgp
*bgp
)
5070 struct bgp_node
*rn
;
5071 struct bgp_node
*rm
;
5072 struct bgp_table
*table
;
5073 struct bgp_static
*bgp_static
;
5075 /* Use this flag to force reprocessing of the route */
5076 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5077 FOREACH_AFI_SAFI (afi
, safi
) {
5078 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5079 rn
= bgp_route_next(rn
)) {
5080 if (rn
->info
== NULL
)
5083 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5084 || (safi
== SAFI_EVPN
)) {
5087 for (rm
= bgp_table_top(table
); rm
;
5088 rm
= bgp_route_next(rm
)) {
5090 bgp_static_get_node_info(rm
);
5091 bgp_static_update_safi(bgp
, &rm
->p
,
5096 bgp_static
= bgp_static_get_node_info(rn
);
5097 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5102 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5105 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5108 struct bgp_table
*table
;
5109 struct bgp_node
*rn
;
5110 struct bgp_path_info
*pi
;
5112 table
= bgp
->rib
[afi
][safi
];
5113 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5114 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5115 if (pi
->peer
== bgp
->peer_self
5116 && ((pi
->type
== ZEBRA_ROUTE_BGP
5117 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5118 || (pi
->type
!= ZEBRA_ROUTE_BGP
5120 == BGP_ROUTE_REDISTRIBUTE
))) {
5121 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5123 bgp_unlink_nexthop(pi
);
5124 bgp_path_info_delete(rn
, pi
);
5125 bgp_process(bgp
, rn
, afi
, safi
);
5132 * Purge all networks and redistributed routes from routing table.
5133 * Invoked upon the instance going down.
5135 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5140 FOREACH_AFI_SAFI (afi
, safi
)
5141 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5146 * Currently this is used to set static routes for VPN and ENCAP.
5147 * I think it can probably be factored with bgp_static_set.
5149 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5150 const char *ip_str
, const char *rd_str
,
5151 const char *label_str
, const char *rmap_str
,
5152 int evpn_type
, const char *esi
, const char *gwip
,
5153 const char *ethtag
, const char *routermac
)
5155 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5158 struct prefix_rd prd
;
5159 struct bgp_node
*prn
;
5160 struct bgp_node
*rn
;
5161 struct bgp_table
*table
;
5162 struct bgp_static
*bgp_static
;
5163 mpls_label_t label
= MPLS_INVALID_LABEL
;
5164 struct prefix gw_ip
;
5166 /* validate ip prefix */
5167 ret
= str2prefix(ip_str
, &p
);
5169 vty_out(vty
, "%% Malformed prefix\n");
5170 return CMD_WARNING_CONFIG_FAILED
;
5173 if ((afi
== AFI_L2VPN
)
5174 && (bgp_build_evpn_prefix(evpn_type
,
5175 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5176 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5177 return CMD_WARNING_CONFIG_FAILED
;
5180 ret
= str2prefix_rd(rd_str
, &prd
);
5182 vty_out(vty
, "%% Malformed rd\n");
5183 return CMD_WARNING_CONFIG_FAILED
;
5187 unsigned long label_val
;
5188 label_val
= strtoul(label_str
, NULL
, 10);
5189 encode_label(label_val
, &label
);
5192 if (safi
== SAFI_EVPN
) {
5193 if (esi
&& str2esi(esi
, NULL
) == 0) {
5194 vty_out(vty
, "%% Malformed ESI\n");
5195 return CMD_WARNING_CONFIG_FAILED
;
5197 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5198 vty_out(vty
, "%% Malformed Router MAC\n");
5199 return CMD_WARNING_CONFIG_FAILED
;
5202 memset(&gw_ip
, 0, sizeof(struct prefix
));
5203 ret
= str2prefix(gwip
, &gw_ip
);
5205 vty_out(vty
, "%% Malformed GatewayIp\n");
5206 return CMD_WARNING_CONFIG_FAILED
;
5208 if ((gw_ip
.family
== AF_INET
5209 && is_evpn_prefix_ipaddr_v6(
5210 (struct prefix_evpn
*)&p
))
5211 || (gw_ip
.family
== AF_INET6
5212 && is_evpn_prefix_ipaddr_v4(
5213 (struct prefix_evpn
*)&p
))) {
5215 "%% GatewayIp family differs with IP prefix\n");
5216 return CMD_WARNING_CONFIG_FAILED
;
5220 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5221 if (prn
->info
== NULL
)
5222 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5224 bgp_unlock_node(prn
);
5227 rn
= bgp_node_get(table
, &p
);
5230 vty_out(vty
, "%% Same network configuration exists\n");
5231 bgp_unlock_node(rn
);
5233 /* New configuration. */
5234 bgp_static
= bgp_static_new();
5235 bgp_static
->backdoor
= 0;
5236 bgp_static
->valid
= 0;
5237 bgp_static
->igpmetric
= 0;
5238 bgp_static
->igpnexthop
.s_addr
= 0;
5239 bgp_static
->label
= label
;
5240 bgp_static
->prd
= prd
;
5243 if (bgp_static
->rmap
.name
)
5244 XFREE(MTYPE_ROUTE_MAP_NAME
,
5245 bgp_static
->rmap
.name
);
5246 bgp_static
->rmap
.name
=
5247 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5248 bgp_static
->rmap
.map
=
5249 route_map_lookup_by_name(rmap_str
);
5252 if (safi
== SAFI_EVPN
) {
5254 bgp_static
->eth_s_id
=
5256 sizeof(struct eth_segment_id
));
5257 str2esi(esi
, bgp_static
->eth_s_id
);
5260 bgp_static
->router_mac
=
5261 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5262 (void)prefix_str2mac(routermac
,
5263 bgp_static
->router_mac
);
5266 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5268 bgp_static_set_node_info(rn
, bgp_static
);
5270 bgp_static
->valid
= 1;
5271 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5277 /* Configure static BGP network. */
5278 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5279 const char *ip_str
, const char *rd_str
,
5280 const char *label_str
, int evpn_type
, const char *esi
,
5281 const char *gwip
, const char *ethtag
)
5283 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5286 struct prefix_rd prd
;
5287 struct bgp_node
*prn
;
5288 struct bgp_node
*rn
;
5289 struct bgp_table
*table
;
5290 struct bgp_static
*bgp_static
;
5291 mpls_label_t label
= MPLS_INVALID_LABEL
;
5293 /* Convert IP prefix string to struct prefix. */
5294 ret
= str2prefix(ip_str
, &p
);
5296 vty_out(vty
, "%% Malformed prefix\n");
5297 return CMD_WARNING_CONFIG_FAILED
;
5300 if ((afi
== AFI_L2VPN
)
5301 && (bgp_build_evpn_prefix(evpn_type
,
5302 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5303 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5304 return CMD_WARNING_CONFIG_FAILED
;
5306 ret
= str2prefix_rd(rd_str
, &prd
);
5308 vty_out(vty
, "%% Malformed rd\n");
5309 return CMD_WARNING_CONFIG_FAILED
;
5313 unsigned long label_val
;
5314 label_val
= strtoul(label_str
, NULL
, 10);
5315 encode_label(label_val
, &label
);
5318 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5319 if (prn
->info
== NULL
)
5320 prn
->info
= bgp_table_init(bgp
, afi
, safi
);
5322 bgp_unlock_node(prn
);
5325 rn
= bgp_node_lookup(table
, &p
);
5328 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5330 bgp_static
= bgp_static_get_node_info(rn
);
5331 bgp_static_free(bgp_static
);
5332 bgp_static_set_node_info(rn
, NULL
);
5333 bgp_unlock_node(rn
);
5334 bgp_unlock_node(rn
);
5336 vty_out(vty
, "%% Can't find the route\n");
5341 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5342 const char *rmap_name
)
5344 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5345 struct bgp_rmap
*rmap
;
5347 rmap
= &bgp
->table_map
[afi
][safi
];
5350 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5351 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5352 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5355 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5360 if (bgp_fibupd_safi(safi
))
5361 bgp_zebra_announce_table(bgp
, afi
, safi
);
5366 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5367 const char *rmap_name
)
5369 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5370 struct bgp_rmap
*rmap
;
5372 rmap
= &bgp
->table_map
[afi
][safi
];
5374 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5378 if (bgp_fibupd_safi(safi
))
5379 bgp_zebra_announce_table(bgp
, afi
, safi
);
5384 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5387 if (bgp
->table_map
[afi
][safi
].name
) {
5388 vty_out(vty
, " table-map %s\n",
5389 bgp
->table_map
[afi
][safi
].name
);
5393 DEFUN (bgp_table_map
,
5396 "BGP table to RIB route download filter\n"
5397 "Name of the route map\n")
5400 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5401 argv
[idx_word
]->arg
);
5403 DEFUN (no_bgp_table_map
,
5404 no_bgp_table_map_cmd
,
5405 "no table-map WORD",
5407 "BGP table to RIB route download filter\n"
5408 "Name of the route map\n")
5411 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5412 argv
[idx_word
]->arg
);
5418 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5419 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5420 backdoor$backdoor}]",
5422 "Specify a network to announce via BGP\n"
5427 "Route-map to modify the attributes\n"
5428 "Name of the route map\n"
5429 "Label index to associate with the prefix\n"
5430 "Label index value\n"
5431 "Specify a BGP backdoor route\n")
5433 char addr_prefix_str
[BUFSIZ
];
5438 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5441 vty_out(vty
, "%% Inconsistent address and mask\n");
5442 return CMD_WARNING_CONFIG_FAILED
;
5446 return bgp_static_set(
5447 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5448 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5449 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5452 DEFPY(ipv6_bgp_network
,
5453 ipv6_bgp_network_cmd
,
5454 "[no] network X:X::X:X/M$prefix \
5455 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5457 "Specify a network to announce via BGP\n"
5459 "Route-map to modify the attributes\n"
5460 "Name of the route map\n"
5461 "Label index to associate with the prefix\n"
5462 "Label index value\n")
5464 return bgp_static_set(
5465 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5466 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5469 /* Aggreagete address:
5471 advertise-map Set condition to advertise attribute
5472 as-set Generate AS set path information
5473 attribute-map Set attributes of aggregate
5474 route-map Set parameters of aggregate
5475 summary-only Filter more specific routes from updates
5476 suppress-map Conditionally filter more specific routes from updates
5479 struct bgp_aggregate
{
5480 /* Summary-only flag. */
5481 uint8_t summary_only
;
5483 /* AS set generation. */
5486 /* Route-map for aggregated route. */
5487 struct route_map
*map
;
5489 /* Suppress-count. */
5490 unsigned long count
;
5492 /* SAFI configuration. */
5496 static struct bgp_aggregate
*bgp_aggregate_new(void)
5498 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5501 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5503 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5506 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5507 struct aspath
*aspath
,
5508 struct community
*comm
,
5509 struct ecommunity
*ecomm
,
5510 struct lcommunity
*lcomm
)
5512 static struct aspath
*ae
= NULL
;
5515 ae
= aspath_empty();
5520 if (origin
!= pi
->attr
->origin
)
5523 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5526 if (!community_cmp(pi
->attr
->community
, comm
))
5529 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5532 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5535 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5541 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5542 struct prefix
*p
, uint8_t origin
,
5543 struct aspath
*aspath
,
5544 struct community
*community
,
5545 struct ecommunity
*ecommunity
,
5546 struct lcommunity
*lcommunity
,
5547 uint8_t atomic_aggregate
,
5548 struct bgp_aggregate
*aggregate
)
5550 struct bgp_node
*rn
;
5551 struct bgp_table
*table
;
5552 struct bgp_path_info
*pi
, *new;
5554 table
= bgp
->rib
[afi
][safi
];
5556 rn
= bgp_node_get(table
, p
);
5558 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
5559 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5560 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5563 if (aggregate
->count
> 0) {
5565 * If the aggregate information has not changed
5566 * no need to re-install it again.
5568 if (bgp_aggregate_info_same(rn
->info
, origin
, aspath
, community
,
5569 ecommunity
, lcommunity
)) {
5570 bgp_unlock_node(rn
);
5573 aspath_free(aspath
);
5575 community_free(&community
);
5577 ecommunity_free(&ecommunity
);
5579 lcommunity_free(&lcommunity
);
5585 * Mark the old as unusable
5588 bgp_path_info_delete(rn
, pi
);
5590 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5592 bgp_attr_aggregate_intern(bgp
, origin
, aspath
,
5593 community
, ecommunity
,
5598 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5600 bgp_path_info_add(rn
, new);
5601 bgp_process(bgp
, rn
, afi
, safi
);
5603 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
5604 if (pi
->peer
== bgp
->peer_self
5605 && pi
->type
== ZEBRA_ROUTE_BGP
5606 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5609 /* Withdraw static BGP route from routing table. */
5611 bgp_path_info_delete(rn
, pi
);
5612 bgp_process(bgp
, rn
, afi
, safi
);
5616 bgp_unlock_node(rn
);
5619 /* Update an aggregate as routes are added/removed from the BGP table */
5620 static void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5621 struct bgp_path_info
*pinew
, afi_t afi
,
5622 safi_t safi
, struct bgp_path_info
*del
,
5623 struct bgp_aggregate
*aggregate
)
5625 struct bgp_table
*table
;
5626 struct bgp_node
*top
;
5627 struct bgp_node
*rn
;
5629 struct aspath
*aspath
= NULL
;
5630 struct aspath
*asmerge
= NULL
;
5631 struct community
*community
= NULL
;
5632 struct community
*commerge
= NULL
;
5633 struct ecommunity
*ecommunity
= NULL
;
5634 struct ecommunity
*ecommerge
= NULL
;
5635 struct lcommunity
*lcommunity
= NULL
;
5636 struct lcommunity
*lcommerge
= NULL
;
5637 struct bgp_path_info
*pi
;
5638 unsigned long match
= 0;
5639 uint8_t atomic_aggregate
= 0;
5641 /* ORIGIN attribute: If at least one route among routes that are
5642 aggregated has ORIGIN with the value INCOMPLETE, then the
5643 aggregated route must have the ORIGIN attribute with the value
5644 INCOMPLETE. Otherwise, if at least one route among routes that
5645 are aggregated has ORIGIN with the value EGP, then the aggregated
5646 route must have the origin attribute with the value EGP. In all
5647 other case the value of the ORIGIN attribute of the aggregated
5648 route is INTERNAL. */
5649 origin
= BGP_ORIGIN_IGP
;
5651 table
= bgp
->rib
[afi
][safi
];
5653 top
= bgp_node_get(table
, p
);
5654 for (rn
= bgp_node_get(table
, p
); rn
;
5655 rn
= bgp_route_next_until(rn
, top
)) {
5656 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5661 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5662 if (BGP_PATH_HOLDDOWN(pi
))
5665 if (del
&& pi
== del
)
5669 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5670 atomic_aggregate
= 1;
5672 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5676 * summary-only aggregate route suppress
5677 * aggregated route announcements.
5679 if (aggregate
->summary_only
) {
5680 (bgp_path_info_extra_get(pi
))->suppress
++;
5681 bgp_path_info_set_flag(rn
, pi
,
5682 BGP_PATH_ATTR_CHANGED
);
5689 * If at least one route among routes that are
5690 * aggregated has ORIGIN with the value INCOMPLETE,
5691 * then the aggregated route MUST have the ORIGIN
5692 * attribute with the value INCOMPLETE. Otherwise, if
5693 * at least one route among routes that are aggregated
5694 * has ORIGIN with the value EGP, then the aggregated
5695 * route MUST have the ORIGIN attribute with the value
5698 if (origin
< pi
->attr
->origin
)
5699 origin
= pi
->attr
->origin
;
5701 if (!aggregate
->as_set
)
5705 * as-set aggregate route generate origin, as path,
5706 * and community aggregation.
5709 asmerge
= aspath_aggregate(aspath
,
5711 aspath_free(aspath
);
5714 aspath
= aspath_dup(pi
->attr
->aspath
);
5716 if (pi
->attr
->community
) {
5718 commerge
= community_merge(
5719 community
, pi
->attr
->community
);
5721 community_uniq_sort(commerge
);
5722 community_free(&commerge
);
5724 community
= community_dup(
5725 pi
->attr
->community
);
5728 if (pi
->attr
->ecommunity
) {
5730 ecommerge
= ecommunity_merge(
5732 pi
->attr
->ecommunity
);
5734 ecommunity_uniq_sort(ecommerge
);
5735 ecommunity_free(&ecommerge
);
5737 ecommunity
= ecommunity_dup(
5738 pi
->attr
->ecommunity
);
5741 if (pi
->attr
->lcommunity
) {
5743 lcommerge
= lcommunity_merge(
5745 pi
->attr
->lcommunity
);
5747 lcommunity_uniq_sort(lcommerge
);
5748 lcommunity_free(&lcommerge
);
5750 lcommunity
= lcommunity_dup(
5751 pi
->attr
->lcommunity
);
5755 bgp_process(bgp
, rn
, afi
, safi
);
5757 bgp_unlock_node(top
);
5762 if (aggregate
->summary_only
)
5763 (bgp_path_info_extra_get(pinew
))->suppress
++;
5765 if (origin
< pinew
->attr
->origin
)
5766 origin
= pinew
->attr
->origin
;
5768 if (aggregate
->as_set
) {
5770 asmerge
= aspath_aggregate(aspath
,
5771 pinew
->attr
->aspath
);
5772 aspath_free(aspath
);
5775 aspath
= aspath_dup(pinew
->attr
->aspath
);
5777 if (pinew
->attr
->community
) {
5779 commerge
= community_merge(
5781 pinew
->attr
->community
);
5783 community_uniq_sort(commerge
);
5784 community_free(&commerge
);
5786 community
= community_dup(
5787 pinew
->attr
->community
);
5790 if (pinew
->attr
->ecommunity
) {
5792 ecommerge
= ecommunity_merge(
5794 pinew
->attr
->ecommunity
);
5796 ecommunity_uniq_sort(ecommerge
);
5797 ecommunity_free(&ecommerge
);
5799 ecommunity
= ecommunity_dup(
5800 pinew
->attr
->ecommunity
);
5803 if (pinew
->attr
->lcommunity
) {
5805 lcommerge
= lcommunity_merge(
5807 pinew
->attr
->lcommunity
);
5809 lcommunity_uniq_sort(lcommerge
);
5810 lcommunity_free(&lcommerge
);
5812 lcommunity
= lcommunity_dup(
5813 pinew
->attr
->lcommunity
);
5818 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5819 ecommunity
, lcommunity
, atomic_aggregate
,
5822 if (aggregate
->count
== 0) {
5824 aspath_free(aspath
);
5826 community_free(&community
);
5828 ecommunity_free(&ecommunity
);
5830 lcommunity_free(&lcommunity
);
5834 static void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
5835 safi_t safi
, struct bgp_aggregate
*aggregate
)
5837 struct bgp_table
*table
;
5838 struct bgp_node
*top
;
5839 struct bgp_node
*rn
;
5840 struct bgp_path_info
*pi
;
5841 unsigned long match
;
5843 table
= bgp
->rib
[afi
][safi
];
5845 /* If routes exists below this node, generate aggregate routes. */
5846 top
= bgp_node_get(table
, p
);
5847 for (rn
= bgp_node_get(table
, p
); rn
;
5848 rn
= bgp_route_next_until(rn
, top
)) {
5849 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5853 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
5854 if (BGP_PATH_HOLDDOWN(pi
))
5857 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5860 if (aggregate
->summary_only
&& pi
->extra
) {
5861 pi
->extra
->suppress
--;
5863 if (pi
->extra
->suppress
== 0) {
5864 bgp_path_info_set_flag(
5865 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5872 /* If this node was suppressed, process the change. */
5874 bgp_process(bgp
, rn
, afi
, safi
);
5876 bgp_unlock_node(top
);
5879 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
5880 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
5882 struct bgp_node
*child
;
5883 struct bgp_node
*rn
;
5884 struct bgp_aggregate
*aggregate
;
5885 struct bgp_table
*table
;
5887 table
= bgp
->aggregate
[afi
][safi
];
5889 /* No aggregates configured. */
5890 if (bgp_table_top_nolock(table
) == NULL
)
5893 if (p
->prefixlen
== 0)
5896 if (BGP_PATH_HOLDDOWN(pi
))
5899 child
= bgp_node_get(table
, p
);
5901 /* Aggregate address configuration check. */
5902 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5903 aggregate
= bgp_aggregate_get_node_info(rn
);
5904 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5905 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5906 bgp_aggregate_route(bgp
, &rn
->p
, pi
, afi
, safi
, NULL
,
5910 bgp_unlock_node(child
);
5913 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
5914 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
5916 struct bgp_node
*child
;
5917 struct bgp_node
*rn
;
5918 struct bgp_aggregate
*aggregate
;
5919 struct bgp_table
*table
;
5921 table
= bgp
->aggregate
[afi
][safi
];
5923 /* No aggregates configured. */
5924 if (bgp_table_top_nolock(table
) == NULL
)
5927 if (p
->prefixlen
== 0)
5930 child
= bgp_node_get(table
, p
);
5932 /* Aggregate address configuration check. */
5933 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
5934 aggregate
= bgp_aggregate_get_node_info(rn
);
5935 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
5936 bgp_aggregate_delete(bgp
, &rn
->p
, afi
, safi
, aggregate
);
5937 bgp_aggregate_route(bgp
, &rn
->p
, NULL
, afi
, safi
, del
,
5941 bgp_unlock_node(child
);
5944 /* Aggregate route attribute. */
5945 #define AGGREGATE_SUMMARY_ONLY 1
5946 #define AGGREGATE_AS_SET 1
5948 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
5949 afi_t afi
, safi_t safi
)
5951 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5954 struct bgp_node
*rn
;
5955 struct bgp_aggregate
*aggregate
;
5957 /* Convert string to prefix structure. */
5958 ret
= str2prefix(prefix_str
, &p
);
5960 vty_out(vty
, "Malformed prefix\n");
5961 return CMD_WARNING_CONFIG_FAILED
;
5965 /* Old configuration check. */
5966 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
5969 "%% There is no aggregate-address configuration.\n");
5970 return CMD_WARNING_CONFIG_FAILED
;
5973 aggregate
= bgp_aggregate_get_node_info(rn
);
5974 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
5975 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
5976 NULL
, NULL
, 0, aggregate
);
5978 /* Unlock aggregate address configuration. */
5979 bgp_aggregate_set_node_info(rn
, NULL
);
5980 bgp_aggregate_free(aggregate
);
5981 bgp_unlock_node(rn
);
5982 bgp_unlock_node(rn
);
5987 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
5988 safi_t safi
, uint8_t summary_only
, uint8_t as_set
)
5990 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5993 struct bgp_node
*rn
;
5994 struct bgp_aggregate
*aggregate
;
5996 /* Convert string to prefix structure. */
5997 ret
= str2prefix(prefix_str
, &p
);
5999 vty_out(vty
, "Malformed prefix\n");
6000 return CMD_WARNING_CONFIG_FAILED
;
6004 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6005 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6006 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6008 return CMD_WARNING_CONFIG_FAILED
;
6011 /* Old configuration check. */
6012 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6015 vty_out(vty
, "There is already same aggregate network.\n");
6016 /* try to remove the old entry */
6017 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6019 vty_out(vty
, "Error deleting aggregate.\n");
6020 bgp_unlock_node(rn
);
6021 return CMD_WARNING_CONFIG_FAILED
;
6025 /* Make aggregate address structure. */
6026 aggregate
= bgp_aggregate_new();
6027 aggregate
->summary_only
= summary_only
;
6028 aggregate
->as_set
= as_set
;
6029 aggregate
->safi
= safi
;
6030 bgp_aggregate_set_node_info(rn
, aggregate
);
6032 /* Aggregate address insert into BGP routing table. */
6033 bgp_aggregate_route(bgp
, &p
, NULL
, afi
, safi
, NULL
, aggregate
);
6038 DEFUN (aggregate_address
,
6039 aggregate_address_cmd
,
6040 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6041 "Configure BGP aggregate entries\n"
6042 "Aggregate prefix\n"
6043 "Generate AS set path information\n"
6044 "Filter more specific routes from updates\n"
6045 "Filter more specific routes from updates\n"
6046 "Generate AS set path information\n")
6049 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6050 char *prefix
= argv
[idx
]->arg
;
6052 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6054 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6055 ? AGGREGATE_SUMMARY_ONLY
6058 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6059 summary_only
, as_set
);
6062 DEFUN (aggregate_address_mask
,
6063 aggregate_address_mask_cmd
,
6064 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6065 "Configure BGP aggregate entries\n"
6066 "Aggregate address\n"
6068 "Generate AS set path information\n"
6069 "Filter more specific routes from updates\n"
6070 "Filter more specific routes from updates\n"
6071 "Generate AS set path information\n")
6074 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6075 char *prefix
= argv
[idx
]->arg
;
6076 char *mask
= argv
[idx
+ 1]->arg
;
6078 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6080 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6081 ? AGGREGATE_SUMMARY_ONLY
6084 char prefix_str
[BUFSIZ
];
6085 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6088 vty_out(vty
, "%% Inconsistent address and mask\n");
6089 return CMD_WARNING_CONFIG_FAILED
;
6092 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6093 summary_only
, as_set
);
6096 DEFUN (no_aggregate_address
,
6097 no_aggregate_address_cmd
,
6098 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
6100 "Configure BGP aggregate entries\n"
6101 "Aggregate prefix\n"
6102 "Generate AS set path information\n"
6103 "Filter more specific routes from updates\n"
6104 "Filter more specific routes from updates\n"
6105 "Generate AS set path information\n")
6108 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6109 char *prefix
= argv
[idx
]->arg
;
6110 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6113 DEFUN (no_aggregate_address_mask
,
6114 no_aggregate_address_mask_cmd
,
6115 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
6117 "Configure BGP aggregate entries\n"
6118 "Aggregate address\n"
6120 "Generate AS set path information\n"
6121 "Filter more specific routes from updates\n"
6122 "Filter more specific routes from updates\n"
6123 "Generate AS set path information\n")
6126 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6127 char *prefix
= argv
[idx
]->arg
;
6128 char *mask
= argv
[idx
+ 1]->arg
;
6130 char prefix_str
[BUFSIZ
];
6131 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6134 vty_out(vty
, "%% Inconsistent address and mask\n");
6135 return CMD_WARNING_CONFIG_FAILED
;
6138 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6141 DEFUN (ipv6_aggregate_address
,
6142 ipv6_aggregate_address_cmd
,
6143 "aggregate-address X:X::X:X/M [summary-only]",
6144 "Configure BGP aggregate entries\n"
6145 "Aggregate prefix\n"
6146 "Filter more specific routes from updates\n")
6149 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6150 char *prefix
= argv
[idx
]->arg
;
6151 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6152 ? AGGREGATE_SUMMARY_ONLY
6154 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, sum_only
,
6158 DEFUN (no_ipv6_aggregate_address
,
6159 no_ipv6_aggregate_address_cmd
,
6160 "no aggregate-address X:X::X:X/M [summary-only]",
6162 "Configure BGP aggregate entries\n"
6163 "Aggregate prefix\n"
6164 "Filter more specific routes from updates\n")
6167 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6168 char *prefix
= argv
[idx
]->arg
;
6169 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6172 /* Redistribute route treatment. */
6173 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6174 const union g_addr
*nexthop
, ifindex_t ifindex
,
6175 enum nexthop_types_t nhtype
, uint32_t metric
,
6176 uint8_t type
, unsigned short instance
,
6179 struct bgp_path_info
*new;
6180 struct bgp_path_info
*bpi
;
6181 struct bgp_path_info rmap_path
;
6182 struct bgp_node
*bn
;
6184 struct attr
*new_attr
;
6187 struct bgp_redist
*red
;
6189 /* Make default attribute. */
6190 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6193 case NEXTHOP_TYPE_IFINDEX
:
6195 case NEXTHOP_TYPE_IPV4
:
6196 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6197 attr
.nexthop
= nexthop
->ipv4
;
6199 case NEXTHOP_TYPE_IPV6
:
6200 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6201 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6202 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6204 case NEXTHOP_TYPE_BLACKHOLE
:
6205 switch (p
->family
) {
6207 attr
.nexthop
.s_addr
= INADDR_ANY
;
6210 memset(&attr
.mp_nexthop_global
, 0,
6211 sizeof(attr
.mp_nexthop_global
));
6212 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6217 attr
.nh_ifindex
= ifindex
;
6220 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6223 afi
= family2afi(p
->family
);
6225 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6227 struct attr attr_new
;
6229 /* Copy attribute for modification. */
6230 bgp_attr_dup(&attr_new
, &attr
);
6232 if (red
->redist_metric_flag
)
6233 attr_new
.med
= red
->redist_metric
;
6235 /* Apply route-map. */
6236 if (red
->rmap
.name
) {
6237 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6238 rmap_path
.peer
= bgp
->peer_self
;
6239 rmap_path
.attr
= &attr_new
;
6241 SET_FLAG(bgp
->peer_self
->rmap_type
,
6242 PEER_RMAP_TYPE_REDISTRIBUTE
);
6244 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6247 bgp
->peer_self
->rmap_type
= 0;
6249 if (ret
== RMAP_DENYMATCH
) {
6250 /* Free uninterned attribute. */
6251 bgp_attr_flush(&attr_new
);
6253 /* Unintern original. */
6254 aspath_unintern(&attr
.aspath
);
6255 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6260 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6261 bgp_attr_add_gshut_community(&attr_new
);
6263 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6264 SAFI_UNICAST
, p
, NULL
);
6266 new_attr
= bgp_attr_intern(&attr_new
);
6268 for (bpi
= bn
->info
; bpi
; bpi
= bpi
->next
)
6269 if (bpi
->peer
== bgp
->peer_self
6270 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6274 /* Ensure the (source route) type is updated. */
6276 if (attrhash_cmp(bpi
->attr
, new_attr
)
6277 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6278 bgp_attr_unintern(&new_attr
);
6279 aspath_unintern(&attr
.aspath
);
6280 bgp_unlock_node(bn
);
6283 /* The attribute is changed. */
6284 bgp_path_info_set_flag(bn
, bpi
,
6285 BGP_PATH_ATTR_CHANGED
);
6287 /* Rewrite BGP route information. */
6288 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6289 bgp_path_info_restore(bn
, bpi
);
6291 bgp_aggregate_decrement(
6292 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6293 bgp_attr_unintern(&bpi
->attr
);
6294 bpi
->attr
= new_attr
;
6295 bpi
->uptime
= bgp_clock();
6297 /* Process change. */
6298 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6300 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6301 bgp_unlock_node(bn
);
6302 aspath_unintern(&attr
.aspath
);
6304 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6306 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6308 vpn_leak_from_vrf_update(
6309 bgp_get_default(), bgp
, bpi
);
6315 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6316 bgp
->peer_self
, new_attr
, bn
);
6317 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6319 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6320 bgp_path_info_add(bn
, new);
6321 bgp_unlock_node(bn
);
6322 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6324 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6325 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6327 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6331 /* Unintern original. */
6332 aspath_unintern(&attr
.aspath
);
6335 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6336 unsigned short instance
)
6339 struct bgp_node
*rn
;
6340 struct bgp_path_info
*pi
;
6341 struct bgp_redist
*red
;
6343 afi
= family2afi(p
->family
);
6345 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6347 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6348 SAFI_UNICAST
, p
, NULL
);
6350 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
6351 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6355 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6356 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6358 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6361 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6362 bgp_path_info_delete(rn
, pi
);
6363 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6365 bgp_unlock_node(rn
);
6369 /* Withdraw specified route type's route. */
6370 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6371 unsigned short instance
)
6373 struct bgp_node
*rn
;
6374 struct bgp_path_info
*pi
;
6375 struct bgp_table
*table
;
6377 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6379 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6380 for (pi
= rn
->info
; pi
; pi
= pi
->next
)
6381 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6382 && pi
->instance
== instance
)
6386 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6387 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6389 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6392 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6394 bgp_path_info_delete(rn
, pi
);
6395 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6400 /* Static function to display route. */
6401 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6408 if (p
->family
== AF_INET
) {
6412 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6415 json_object_string_add(json
, "prefix",
6416 inet_ntop(p
->family
,
6419 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6420 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6421 json_object_string_add(json
, "network", buf2
);
6423 } else if (p
->family
== AF_ETHERNET
) {
6424 prefix2str(p
, buf
, PREFIX_STRLEN
);
6425 len
= vty_out(vty
, "%s", buf
);
6426 } else if (p
->family
== AF_EVPN
) {
6430 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6433 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6434 } else if (p
->family
== AF_FLOWSPEC
) {
6435 route_vty_out_flowspec(vty
, p
, NULL
,
6437 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6438 NLRI_STRING_FORMAT_MIN
, json
);
6443 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6446 json_object_string_add(json
, "prefix",
6447 inet_ntop(p
->family
,
6450 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6451 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6452 json_object_string_add(json
, "network", buf2
);
6459 vty_out(vty
, "\n%*s", 20, " ");
6461 vty_out(vty
, "%*s", len
, " ");
6465 enum bgp_display_type
{
6469 /* Print the short form route status for a bgp_path_info */
6470 static void route_vty_short_status_out(struct vty
*vty
,
6471 struct bgp_path_info
*path
,
6472 json_object
*json_path
)
6476 /* Route status display. */
6477 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6478 json_object_boolean_true_add(json_path
, "removed");
6480 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6481 json_object_boolean_true_add(json_path
, "stale");
6483 if (path
->extra
&& path
->extra
->suppress
)
6484 json_object_boolean_true_add(json_path
, "suppressed");
6486 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6487 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6488 json_object_boolean_true_add(json_path
, "valid");
6491 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6492 json_object_boolean_true_add(json_path
, "history");
6494 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6495 json_object_boolean_true_add(json_path
, "damped");
6497 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6498 json_object_boolean_true_add(json_path
, "bestpath");
6500 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6501 json_object_boolean_true_add(json_path
, "multipath");
6503 /* Internal route. */
6504 if ((path
->peer
->as
)
6505 && (path
->peer
->as
== path
->peer
->local_as
))
6506 json_object_string_add(json_path
, "pathFrom",
6509 json_object_string_add(json_path
, "pathFrom",
6515 /* Route status display. */
6516 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
6518 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
6520 else if (path
->extra
&& path
->extra
->suppress
)
6522 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
6523 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6529 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
6531 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
6533 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
6535 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
6540 /* Internal route. */
6541 if (path
->peer
&& (path
->peer
->as
)
6542 && (path
->peer
->as
== path
->peer
->local_as
))
6548 /* called from terminal list command */
6549 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
6550 struct bgp_path_info
*path
, int display
, safi_t safi
,
6551 json_object
*json_paths
)
6554 json_object
*json_path
= NULL
;
6555 json_object
*json_nexthops
= NULL
;
6556 json_object
*json_nexthop_global
= NULL
;
6557 json_object
*json_nexthop_ll
= NULL
;
6558 char vrf_id_str
[VRF_NAMSIZ
] = {0};
6560 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
6561 bool nexthop_othervrf
= false;
6562 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
6563 const char *nexthop_vrfname
= "Default";
6566 json_path
= json_object_new_object();
6568 /* short status lead text */
6569 route_vty_short_status_out(vty
, path
, json_path
);
6572 /* print prefix and mask */
6574 route_vty_out_route(p
, vty
, json_path
);
6576 vty_out(vty
, "%*s", 17, " ");
6578 route_vty_out_route(p
, vty
, json_path
);
6581 /* Print attribute */
6585 json_object_array_add(json_paths
, json_path
);
6593 * If vrf id of nexthop is different from that of prefix,
6594 * set up printable string to append
6596 if (path
->extra
&& path
->extra
->bgp_orig
) {
6597 const char *self
= "";
6602 nexthop_othervrf
= true;
6603 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
6605 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
6606 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
6607 "@%s%s", VRFID_NONE_STR
, self
);
6609 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
6610 path
->extra
->bgp_orig
->vrf_id
, self
);
6612 if (path
->extra
->bgp_orig
->inst_type
6613 != BGP_INSTANCE_TYPE_DEFAULT
)
6615 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
6617 const char *self
= "";
6622 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
6626 * For ENCAP and EVPN routes, nexthop address family is not
6627 * neccessarily the same as the prefix address family.
6628 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
6629 * EVPN routes are also exchanged with a MP nexthop. Currently,
6631 * is only IPv4, the value will be present in either
6633 * attr->mp_nexthop_global_in
6635 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
6638 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
6642 sprintf(nexthop
, "%s",
6643 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
6647 sprintf(nexthop
, "%s",
6648 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
6652 sprintf(nexthop
, "?");
6657 json_nexthop_global
= json_object_new_object();
6659 json_object_string_add(json_nexthop_global
, "afi",
6660 (af
== AF_INET
) ? "ip" : "ipv6");
6661 json_object_string_add(json_nexthop_global
,
6662 (af
== AF_INET
) ? "ip" : "ipv6",
6664 json_object_boolean_true_add(json_nexthop_global
,
6667 vty_out(vty
, "%s%s", nexthop
, vrf_id_str
);
6668 } else if (safi
== SAFI_EVPN
) {
6670 json_nexthop_global
= json_object_new_object();
6672 json_object_string_add(json_nexthop_global
, "ip",
6673 inet_ntoa(attr
->nexthop
));
6674 json_object_string_add(json_nexthop_global
, "afi",
6676 json_object_boolean_true_add(json_nexthop_global
,
6679 vty_out(vty
, "%-16s%s", inet_ntoa(attr
->nexthop
),
6681 } else if (safi
== SAFI_FLOWSPEC
) {
6682 if (attr
->nexthop
.s_addr
!= 0) {
6684 json_nexthop_global
= json_object_new_object();
6685 json_object_string_add(
6686 json_nexthop_global
, "ip",
6687 inet_ntoa(attr
->nexthop
));
6688 json_object_string_add(json_nexthop_global
,
6690 json_object_boolean_true_add(
6691 json_nexthop_global
,
6694 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
6697 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6699 json_nexthop_global
= json_object_new_object();
6701 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
6702 json_object_string_add(
6703 json_nexthop_global
, "ip",
6704 inet_ntoa(attr
->mp_nexthop_global_in
));
6706 json_object_string_add(
6707 json_nexthop_global
, "ip",
6708 inet_ntoa(attr
->nexthop
));
6710 json_object_string_add(json_nexthop_global
, "afi",
6712 json_object_boolean_true_add(json_nexthop_global
,
6717 snprintf(buf
, sizeof(buf
), "%s%s",
6718 inet_ntoa(attr
->nexthop
), vrf_id_str
);
6719 vty_out(vty
, "%-16s", buf
);
6724 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6729 json_nexthop_global
= json_object_new_object();
6730 json_object_string_add(
6731 json_nexthop_global
, "ip",
6732 inet_ntop(AF_INET6
, &attr
->mp_nexthop_global
,
6734 json_object_string_add(json_nexthop_global
, "afi",
6736 json_object_string_add(json_nexthop_global
, "scope",
6739 /* We display both LL & GL if both have been
6741 if ((attr
->mp_nexthop_len
== 32)
6742 || (path
->peer
->conf_if
)) {
6743 json_nexthop_ll
= json_object_new_object();
6744 json_object_string_add(
6745 json_nexthop_ll
, "ip",
6747 &attr
->mp_nexthop_local
, buf
,
6749 json_object_string_add(json_nexthop_ll
, "afi",
6751 json_object_string_add(json_nexthop_ll
, "scope",
6754 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
6755 &attr
->mp_nexthop_local
)
6757 && !attr
->mp_nexthop_prefer_global
)
6758 json_object_boolean_true_add(
6759 json_nexthop_ll
, "used");
6761 json_object_boolean_true_add(
6762 json_nexthop_global
, "used");
6764 json_object_boolean_true_add(
6765 json_nexthop_global
, "used");
6767 /* Display LL if LL/Global both in table unless
6768 * prefer-global is set */
6769 if (((attr
->mp_nexthop_len
== 32)
6770 && !attr
->mp_nexthop_prefer_global
)
6771 || (path
->peer
->conf_if
)) {
6772 if (path
->peer
->conf_if
) {
6773 len
= vty_out(vty
, "%s",
6774 path
->peer
->conf_if
);
6775 len
= 16 - len
; /* len of IPv6
6781 vty_out(vty
, "\n%*s", 36, " ");
6783 vty_out(vty
, "%*s", len
, " ");
6789 &attr
->mp_nexthop_local
,
6795 vty_out(vty
, "\n%*s", 36, " ");
6797 vty_out(vty
, "%*s", len
, " ");
6803 &attr
->mp_nexthop_global
, buf
,
6809 vty_out(vty
, "\n%*s", 36, " ");
6811 vty_out(vty
, "%*s", len
, " ");
6817 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6821 * Adding "metric" field to match with corresponding
6822 * CLI. "med" will be deprecated in future.
6824 json_object_int_add(json_path
, "med", attr
->med
);
6825 json_object_int_add(json_path
, "metric", attr
->med
);
6827 vty_out(vty
, "%10u", attr
->med
);
6828 else if (!json_paths
)
6832 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
6836 * Adding "locPrf" field to match with corresponding
6837 * CLI. "localPref" will be deprecated in future.
6839 json_object_int_add(json_path
, "localpref",
6841 json_object_int_add(json_path
, "locPrf",
6844 vty_out(vty
, "%7u", attr
->local_pref
);
6845 else if (!json_paths
)
6849 json_object_int_add(json_path
, "weight", attr
->weight
);
6851 vty_out(vty
, "%7u ", attr
->weight
);
6855 json_object_string_add(
6856 json_path
, "peerId",
6857 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
6865 * Adding "path" field to match with corresponding
6866 * CLI. "aspath" will be deprecated in future.
6868 json_object_string_add(json_path
, "aspath",
6870 json_object_string_add(json_path
, "path",
6873 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
6878 json_object_string_add(json_path
, "origin",
6879 bgp_origin_long_str
[attr
->origin
]);
6881 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
6885 json_object_boolean_true_add(json_path
,
6886 "announceNexthopSelf");
6887 if (nexthop_othervrf
) {
6888 json_object_string_add(json_path
, "nhVrfName",
6891 json_object_int_add(json_path
, "nhVrfId",
6892 ((nexthop_vrfid
== VRF_UNKNOWN
)
6894 : (int)nexthop_vrfid
));
6899 if (json_nexthop_global
|| json_nexthop_ll
) {
6900 json_nexthops
= json_object_new_array();
6902 if (json_nexthop_global
)
6903 json_object_array_add(json_nexthops
,
6904 json_nexthop_global
);
6906 if (json_nexthop_ll
)
6907 json_object_array_add(json_nexthops
,
6910 json_object_object_add(json_path
, "nexthops",
6914 json_object_array_add(json_paths
, json_path
);
6918 /* prints an additional line, indented, with VNC info, if
6920 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
6921 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
6926 /* called from terminal list command */
6927 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
6928 safi_t safi
, bool use_json
, json_object
*json_ar
)
6930 json_object
*json_status
= NULL
;
6931 json_object
*json_net
= NULL
;
6934 /* Route status display. */
6936 json_status
= json_object_new_object();
6937 json_net
= json_object_new_object();
6944 /* print prefix and mask */
6946 json_object_string_add(
6947 json_net
, "addrPrefix",
6948 inet_ntop(p
->family
, &p
->u
.prefix
, buff
, BUFSIZ
));
6949 json_object_int_add(json_net
, "prefixLen", p
->prefixlen
);
6950 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6951 json_object_string_add(json_net
, "network", buf2
);
6953 route_vty_out_route(p
, vty
, NULL
);
6955 /* Print attribute */
6958 if (p
->family
== AF_INET
6959 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6960 || safi
== SAFI_EVPN
6961 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
6962 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
6963 || safi
== SAFI_EVPN
)
6964 json_object_string_add(
6965 json_net
, "nextHop",
6967 attr
->mp_nexthop_global_in
));
6969 json_object_string_add(
6970 json_net
, "nextHop",
6971 inet_ntoa(attr
->nexthop
));
6972 } else if (p
->family
== AF_INET6
6973 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
6976 json_object_string_add(
6977 json_net
, "nextHopGlobal",
6979 &attr
->mp_nexthop_global
, buf
,
6984 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
6985 json_object_int_add(json_net
, "metric",
6988 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
6991 * Adding "locPrf" field to match with
6992 * corresponding CLI. "localPref" will be
6993 * deprecated in future.
6995 json_object_int_add(json_net
, "localPref",
6997 json_object_int_add(json_net
, "locPrf",
7001 json_object_int_add(json_net
, "weight", attr
->weight
);
7007 * Adding "path" field to match with
7008 * corresponding CLI. "localPref" will be
7009 * deprecated in future.
7011 json_object_string_add(json_net
, "asPath",
7013 json_object_string_add(json_net
, "path",
7018 json_object_string_add(json_net
, "bgpOriginCode",
7019 bgp_origin_str
[attr
->origin
]);
7021 if (p
->family
== AF_INET
7022 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7023 || safi
== SAFI_EVPN
7024 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7025 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7026 || safi
== SAFI_EVPN
)
7027 vty_out(vty
, "%-16s",
7029 attr
->mp_nexthop_global_in
));
7031 vty_out(vty
, "%-16s",
7032 inet_ntoa(attr
->nexthop
));
7033 } else if (p
->family
== AF_INET6
7034 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7041 &attr
->mp_nexthop_global
, buf
,
7045 vty_out(vty
, "\n%*s", 36, " ");
7047 vty_out(vty
, "%*s", len
, " ");
7050 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7051 vty_out(vty
, "%10u", attr
->med
);
7055 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7056 vty_out(vty
, "%7u", attr
->local_pref
);
7060 vty_out(vty
, "%7u ", attr
->weight
);
7064 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7067 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7071 json_object_boolean_true_add(json_status
, "*");
7072 json_object_boolean_true_add(json_status
, ">");
7073 json_object_object_add(json_net
, "appliedStatusSymbols",
7075 char buf_cut
[BUFSIZ
];
7076 json_object_object_add(
7078 inet_ntop(p
->family
, &p
->u
.prefix
, buf_cut
, BUFSIZ
),
7084 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7085 struct bgp_path_info
*path
, int display
, safi_t safi
,
7088 json_object
*json_out
= NULL
;
7090 mpls_label_t label
= MPLS_INVALID_LABEL
;
7096 json_out
= json_object_new_object();
7098 /* short status lead text */
7099 route_vty_short_status_out(vty
, path
, json_out
);
7101 /* print prefix and mask */
7104 route_vty_out_route(p
, vty
, NULL
);
7106 vty_out(vty
, "%*s", 17, " ");
7109 /* Print attribute */
7112 if (((p
->family
== AF_INET
)
7113 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7114 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7115 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7116 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7117 || safi
== SAFI_EVPN
) {
7119 json_object_string_add(
7120 json_out
, "mpNexthopGlobalIn",
7122 attr
->mp_nexthop_global_in
));
7124 vty_out(vty
, "%-16s",
7126 attr
->mp_nexthop_global_in
));
7129 json_object_string_add(
7130 json_out
, "nexthop",
7131 inet_ntoa(attr
->nexthop
));
7133 vty_out(vty
, "%-16s",
7134 inet_ntoa(attr
->nexthop
));
7136 } else if (((p
->family
== AF_INET6
)
7137 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7138 || (safi
== SAFI_EVPN
7139 && BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7140 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7144 if (attr
->mp_nexthop_len
7145 == BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7147 json_object_string_add(
7148 json_out
, "mpNexthopGlobalIn",
7151 &attr
->mp_nexthop_global
,
7152 buf_a
, sizeof(buf_a
)));
7157 &attr
->mp_nexthop_global
,
7158 buf_a
, sizeof(buf_a
)));
7159 } else if (attr
->mp_nexthop_len
7160 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7163 &attr
->mp_nexthop_global
,
7164 buf_a
, sizeof(buf_a
));
7166 &attr
->mp_nexthop_local
,
7167 buf_b
, sizeof(buf_b
));
7168 sprintf(buf_c
, "%s(%s)", buf_a
, buf_b
);
7169 json_object_string_add(
7171 "mpNexthopGlobalLocal", buf_c
);
7173 vty_out(vty
, "%s(%s)",
7176 &attr
->mp_nexthop_global
,
7177 buf_a
, sizeof(buf_a
)),
7180 &attr
->mp_nexthop_local
,
7181 buf_b
, sizeof(buf_b
)));
7186 label
= decode_label(&path
->extra
->label
[0]);
7188 if (bgp_is_valid_label(&label
)) {
7190 json_object_int_add(json_out
, "notag", label
);
7191 json_object_array_add(json
, json_out
);
7193 vty_out(vty
, "notag/%d", label
);
7199 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7200 struct bgp_path_info
*path
, int display
,
7201 json_object
*json_paths
)
7205 json_object
*json_path
= NULL
;
7208 json_path
= json_object_new_object();
7213 /* short status lead text */
7214 route_vty_short_status_out(vty
, path
, json_path
);
7216 /* print prefix and mask */
7218 route_vty_out_route(p
, vty
, NULL
);
7220 vty_out(vty
, "%*s", 17, " ");
7222 /* Print attribute */
7226 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7230 vty_out(vty
, "%-16s",
7231 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7235 vty_out(vty
, "%s(%s)",
7236 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7238 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
,
7245 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7247 vty_out(vty
, "%s", str
);
7248 XFREE(MTYPE_TMP
, str
);
7250 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7252 inet_ntoa(attr
->evpn_overlay
.gw_ip
.ipv4
));
7253 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7256 &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7259 if (attr
->ecommunity
) {
7261 struct ecommunity_val
*routermac
= ecommunity_lookup(
7262 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7263 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7265 mac
= ecom_mac2str((char *)routermac
->val
);
7267 vty_out(vty
, "/%s", (char *)mac
);
7268 XFREE(MTYPE_TMP
, mac
);
7276 /* dampening route */
7277 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7278 struct bgp_path_info
*path
, int display
,
7279 safi_t safi
, bool use_json
, json_object
*json
)
7283 char timebuf
[BGP_UPTIME_LEN
];
7285 /* short status lead text */
7286 route_vty_short_status_out(vty
, path
, json
);
7288 /* print prefix and mask */
7291 route_vty_out_route(p
, vty
, NULL
);
7293 vty_out(vty
, "%*s", 17, " ");
7296 len
= vty_out(vty
, "%s", path
->peer
->host
);
7300 vty_out(vty
, "\n%*s", 34, " ");
7303 json_object_int_add(json
, "peerHost", len
);
7305 vty_out(vty
, "%*s", len
, " ");
7309 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7313 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7314 BGP_UPTIME_LEN
, use_json
,
7317 /* Print attribute */
7323 json_object_string_add(json
, "asPath",
7326 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7331 json_object_string_add(json
, "origin",
7332 bgp_origin_str
[attr
->origin
]);
7334 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7341 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7342 struct bgp_path_info
*path
, int display
,
7343 safi_t safi
, bool use_json
, json_object
*json
)
7346 struct bgp_damp_info
*bdi
;
7347 char timebuf
[BGP_UPTIME_LEN
];
7353 bdi
= path
->extra
->damp_info
;
7355 /* short status lead text */
7356 route_vty_short_status_out(vty
, path
, json
);
7358 /* print prefix and mask */
7361 route_vty_out_route(p
, vty
, NULL
);
7363 vty_out(vty
, "%*s", 17, " ");
7366 len
= vty_out(vty
, "%s", path
->peer
->host
);
7370 vty_out(vty
, "\n%*s", 33, " ");
7373 json_object_int_add(json
, "peerHost", len
);
7375 vty_out(vty
, "%*s", len
, " ");
7378 len
= vty_out(vty
, "%d", bdi
->flap
);
7385 json_object_int_add(json
, "bdiFlap", len
);
7387 vty_out(vty
, "%*s", len
, " ");
7391 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
7394 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
7395 BGP_UPTIME_LEN
, 0, NULL
));
7397 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
7398 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7400 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7401 BGP_UPTIME_LEN
, use_json
, json
);
7404 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7409 vty_out(vty
, "%*s ", 8, " ");
7412 /* Print attribute */
7418 json_object_string_add(json
, "asPath",
7421 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7426 json_object_string_add(json
, "origin",
7427 bgp_origin_str
[attr
->origin
]);
7429 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7435 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
7436 int *first
, const char *header
,
7437 json_object
*json_adv_to
)
7439 char buf1
[INET6_ADDRSTRLEN
];
7440 json_object
*json_peer
= NULL
;
7443 /* 'advertised-to' is a dictionary of peers we have advertised
7445 * prefix too. The key is the peer's IP or swpX, the value is
7447 * hostname if we know it and "" if not.
7449 json_peer
= json_object_new_object();
7452 json_object_string_add(json_peer
, "hostname",
7456 json_object_object_add(json_adv_to
, peer
->conf_if
,
7459 json_object_object_add(
7461 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
7465 vty_out(vty
, "%s", header
);
7470 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
7472 vty_out(vty
, " %s(%s)", peer
->hostname
,
7475 vty_out(vty
, " %s(%s)", peer
->hostname
,
7476 sockunion2str(&peer
->su
, buf1
,
7480 vty_out(vty
, " %s", peer
->conf_if
);
7483 sockunion2str(&peer
->su
, buf1
,
7489 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
, struct prefix
*p
,
7490 struct bgp_path_info
*path
, afi_t afi
, safi_t safi
,
7491 json_object
*json_paths
)
7493 char buf
[INET6_ADDRSTRLEN
];
7495 char buf2
[EVPN_ROUTE_STRLEN
];
7497 int sockunion_vty_out(struct vty
*, union sockunion
*);
7499 json_object
*json_bestpath
= NULL
;
7500 json_object
*json_cluster_list
= NULL
;
7501 json_object
*json_cluster_list_list
= NULL
;
7502 json_object
*json_ext_community
= NULL
;
7503 json_object
*json_last_update
= NULL
;
7504 json_object
*json_pmsi
= NULL
;
7505 json_object
*json_nexthop_global
= NULL
;
7506 json_object
*json_nexthop_ll
= NULL
;
7507 json_object
*json_nexthops
= NULL
;
7508 json_object
*json_path
= NULL
;
7509 json_object
*json_peer
= NULL
;
7510 json_object
*json_string
= NULL
;
7511 json_object
*json_adv_to
= NULL
;
7513 struct listnode
*node
, *nnode
;
7515 int addpath_capable
;
7517 unsigned int first_as
;
7519 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7522 json_path
= json_object_new_object();
7523 json_peer
= json_object_new_object();
7524 json_nexthop_global
= json_object_new_object();
7527 if (!json_paths
&& safi
== SAFI_EVPN
) {
7530 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf2
, sizeof(buf2
));
7531 vty_out(vty
, " Route %s", buf2
);
7533 if (path
->extra
&& path
->extra
->num_labels
) {
7534 bgp_evpn_label2str(path
->extra
->label
,
7535 path
->extra
->num_labels
, tag_buf
,
7537 vty_out(vty
, " VNI %s", tag_buf
);
7540 if (path
->extra
&& path
->extra
->parent
) {
7541 struct bgp_path_info
*parent_ri
;
7542 struct bgp_node
*rn
, *prn
;
7544 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
7545 rn
= parent_ri
->net
;
7546 if (rn
&& rn
->prn
) {
7548 vty_out(vty
, " Imported from %s:%s\n",
7550 (struct prefix_rd
*)&prn
->p
,
7551 buf1
, sizeof(buf1
)),
7560 /* Line1 display AS-path, Aggregator */
7563 if (!attr
->aspath
->json
)
7564 aspath_str_update(attr
->aspath
, true);
7565 json_object_lock(attr
->aspath
->json
);
7566 json_object_object_add(json_path
, "aspath",
7567 attr
->aspath
->json
);
7569 if (attr
->aspath
->segments
)
7570 aspath_print_vty(vty
, " %s",
7573 vty_out(vty
, " Local");
7577 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
7579 json_object_boolean_true_add(json_path
,
7582 vty_out(vty
, ", (removed)");
7585 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
7587 json_object_boolean_true_add(json_path
,
7590 vty_out(vty
, ", (stale)");
7593 if (CHECK_FLAG(attr
->flag
,
7594 ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
7596 json_object_int_add(json_path
, "aggregatorAs",
7597 attr
->aggregator_as
);
7598 json_object_string_add(
7599 json_path
, "aggregatorId",
7600 inet_ntoa(attr
->aggregator_addr
));
7602 vty_out(vty
, ", (aggregated by %u %s)",
7603 attr
->aggregator_as
,
7604 inet_ntoa(attr
->aggregator_addr
));
7608 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7609 PEER_FLAG_REFLECTOR_CLIENT
)) {
7611 json_object_boolean_true_add(
7612 json_path
, "rxedFromRrClient");
7614 vty_out(vty
, ", (Received from a RR-client)");
7617 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
7618 PEER_FLAG_RSERVER_CLIENT
)) {
7620 json_object_boolean_true_add(
7621 json_path
, "rxedFromRsClient");
7623 vty_out(vty
, ", (Received from a RS-client)");
7626 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7628 json_object_boolean_true_add(
7629 json_path
, "dampeningHistoryEntry");
7631 vty_out(vty
, ", (history entry)");
7632 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
7634 json_object_boolean_true_add(
7635 json_path
, "dampeningSuppressed");
7637 vty_out(vty
, ", (suppressed due to dampening)");
7643 /* Line2 display Next-hop, Neighbor, Router-id */
7644 /* Display the nexthop */
7645 if ((p
->family
== AF_INET
|| p
->family
== AF_ETHERNET
7646 || p
->family
== AF_EVPN
)
7647 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7648 || safi
== SAFI_EVPN
7649 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7650 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7651 || safi
== SAFI_EVPN
) {
7653 json_object_string_add(
7654 json_nexthop_global
, "ip",
7656 attr
->mp_nexthop_global_in
));
7660 attr
->mp_nexthop_global_in
));
7663 json_object_string_add(
7664 json_nexthop_global
, "ip",
7665 inet_ntoa(attr
->nexthop
));
7668 inet_ntoa(attr
->nexthop
));
7672 json_object_string_add(json_nexthop_global
,
7676 json_object_string_add(
7677 json_nexthop_global
, "ip",
7679 &attr
->mp_nexthop_global
, buf
,
7681 json_object_string_add(json_nexthop_global
,
7683 json_object_string_add(json_nexthop_global
,
7688 &attr
->mp_nexthop_global
, buf
,
7693 /* Display the IGP cost or 'inaccessible' */
7694 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7696 json_object_boolean_false_add(
7697 json_nexthop_global
, "accessible");
7699 vty_out(vty
, " (inaccessible)");
7701 if (path
->extra
&& path
->extra
->igpmetric
) {
7703 json_object_int_add(
7704 json_nexthop_global
, "metric",
7705 path
->extra
->igpmetric
);
7707 vty_out(vty
, " (metric %u)",
7708 path
->extra
->igpmetric
);
7711 /* IGP cost is 0, display this only for json */
7714 json_object_int_add(json_nexthop_global
,
7719 json_object_boolean_true_add(
7720 json_nexthop_global
, "accessible");
7723 /* Display peer "from" output */
7724 /* This path was originated locally */
7725 if (path
->peer
== bgp
->peer_self
) {
7727 if (safi
== SAFI_EVPN
7728 || (p
->family
== AF_INET
7729 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7731 json_object_string_add(
7732 json_peer
, "peerId", "0.0.0.0");
7734 vty_out(vty
, " from 0.0.0.0 ");
7737 json_object_string_add(json_peer
,
7740 vty_out(vty
, " from :: ");
7744 json_object_string_add(
7745 json_peer
, "routerId",
7746 inet_ntoa(bgp
->router_id
));
7748 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
7751 /* We RXed this path from one of our peers */
7755 json_object_string_add(
7756 json_peer
, "peerId",
7757 sockunion2str(&path
->peer
->su
, buf
,
7759 json_object_string_add(
7760 json_peer
, "routerId",
7762 &path
->peer
->remote_id
, buf1
,
7765 if (path
->peer
->hostname
)
7766 json_object_string_add(
7767 json_peer
, "hostname",
7768 path
->peer
->hostname
);
7770 if (path
->peer
->domainname
)
7771 json_object_string_add(
7772 json_peer
, "domainname",
7773 path
->peer
->domainname
);
7775 if (path
->peer
->conf_if
)
7776 json_object_string_add(
7777 json_peer
, "interface",
7778 path
->peer
->conf_if
);
7780 if (path
->peer
->conf_if
) {
7781 if (path
->peer
->hostname
7784 BGP_FLAG_SHOW_HOSTNAME
))
7785 vty_out(vty
, " from %s(%s)",
7786 path
->peer
->hostname
,
7787 path
->peer
->conf_if
);
7789 vty_out(vty
, " from %s",
7790 path
->peer
->conf_if
);
7792 if (path
->peer
->hostname
7795 BGP_FLAG_SHOW_HOSTNAME
))
7796 vty_out(vty
, " from %s(%s)",
7797 path
->peer
->hostname
,
7800 vty_out(vty
, " from %s",
7808 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
7809 vty_out(vty
, " (%s)",
7810 inet_ntoa(attr
->originator_id
));
7812 vty_out(vty
, " (%s)",
7815 &path
->peer
->remote_id
,
7816 buf1
, sizeof(buf1
)));
7821 * Note when vrfid of nexthop is different from that of prefix
7823 if (path
->extra
&& path
->extra
->bgp_orig
) {
7824 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7829 if (path
->extra
->bgp_orig
->inst_type
7830 == BGP_INSTANCE_TYPE_DEFAULT
)
7834 vn
= path
->extra
->bgp_orig
->name
;
7836 json_object_string_add(json_path
, "nhVrfName",
7839 if (nexthop_vrfid
== VRF_UNKNOWN
) {
7840 json_object_int_add(json_path
,
7843 json_object_int_add(json_path
,
7844 "nhVrfId", (int)nexthop_vrfid
);
7847 if (nexthop_vrfid
== VRF_UNKNOWN
)
7848 vty_out(vty
, " vrf ?");
7850 vty_out(vty
, " vrf %u", nexthop_vrfid
);
7856 json_object_boolean_true_add(json_path
,
7857 "announceNexthopSelf");
7859 vty_out(vty
, " announce-nh-self");
7866 /* display the link-local nexthop */
7867 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7869 json_nexthop_ll
= json_object_new_object();
7870 json_object_string_add(
7871 json_nexthop_ll
, "ip",
7873 &attr
->mp_nexthop_local
, buf
,
7875 json_object_string_add(json_nexthop_ll
, "afi",
7877 json_object_string_add(json_nexthop_ll
, "scope",
7880 json_object_boolean_true_add(json_nexthop_ll
,
7883 if (!attr
->mp_nexthop_prefer_global
)
7884 json_object_boolean_true_add(
7885 json_nexthop_ll
, "used");
7887 json_object_boolean_true_add(
7888 json_nexthop_global
, "used");
7890 vty_out(vty
, " (%s) %s\n",
7892 &attr
->mp_nexthop_local
, buf
,
7894 attr
->mp_nexthop_prefer_global
7899 /* If we do not have a link-local nexthop then we must flag the
7903 json_object_boolean_true_add(
7904 json_nexthop_global
, "used");
7907 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
7908 * Int/Ext/Local, Atomic, best */
7910 json_object_string_add(
7911 json_path
, "origin",
7912 bgp_origin_long_str
[attr
->origin
]);
7914 vty_out(vty
, " Origin %s",
7915 bgp_origin_long_str
[attr
->origin
]);
7917 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
7921 * Adding "metric" field to match with
7922 * corresponding CLI. "med" will be
7923 * deprecated in future.
7925 json_object_int_add(json_path
, "med",
7927 json_object_int_add(json_path
, "metric",
7930 vty_out(vty
, ", metric %u", attr
->med
);
7933 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7935 json_object_int_add(json_path
, "localpref",
7938 vty_out(vty
, ", localpref %u",
7942 if (attr
->weight
!= 0) {
7944 json_object_int_add(json_path
, "weight",
7947 vty_out(vty
, ", weight %u", attr
->weight
);
7950 if (attr
->tag
!= 0) {
7952 json_object_int_add(json_path
, "tag",
7955 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
,
7959 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
7961 json_object_boolean_false_add(json_path
,
7964 vty_out(vty
, ", invalid");
7965 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
7967 json_object_boolean_true_add(json_path
,
7970 vty_out(vty
, ", valid");
7973 if (path
->peer
!= bgp
->peer_self
) {
7974 if (path
->peer
->as
== path
->peer
->local_as
) {
7975 if (CHECK_FLAG(bgp
->config
,
7976 BGP_CONFIG_CONFEDERATION
)) {
7978 json_object_string_add(
7983 ", confed-internal");
7986 json_object_string_add(
7990 vty_out(vty
, ", internal");
7993 if (bgp_confederation_peers_check(
7994 bgp
, path
->peer
->as
)) {
7996 json_object_string_add(
8001 ", confed-external");
8004 json_object_string_add(
8008 vty_out(vty
, ", external");
8011 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8013 json_object_boolean_true_add(json_path
,
8015 json_object_boolean_true_add(json_path
,
8018 vty_out(vty
, ", aggregated, local");
8020 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8022 json_object_boolean_true_add(json_path
,
8025 vty_out(vty
, ", sourced");
8028 json_object_boolean_true_add(json_path
,
8030 json_object_boolean_true_add(json_path
,
8033 vty_out(vty
, ", sourced, local");
8037 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8039 json_object_boolean_true_add(json_path
,
8042 vty_out(vty
, ", atomic-aggregate");
8045 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8046 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8047 && bgp_path_info_mpath_count(path
))) {
8049 json_object_boolean_true_add(json_path
,
8052 vty_out(vty
, ", multipath");
8055 // Mark the bestpath(s)
8056 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8057 first_as
= aspath_get_first_as(attr
->aspath
);
8062 json_object_new_object();
8063 json_object_int_add(json_bestpath
,
8064 "bestpathFromAs", first_as
);
8067 vty_out(vty
, ", bestpath-from-AS %u",
8071 ", bestpath-from-AS Local");
8075 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8079 json_object_new_object();
8080 json_object_boolean_true_add(json_bestpath
,
8083 vty_out(vty
, ", best");
8087 json_object_object_add(json_path
, "bestpath",
8093 /* Line 4 display Community */
8094 if (attr
->community
) {
8096 if (!attr
->community
->json
)
8097 community_str(attr
->community
, true);
8098 json_object_lock(attr
->community
->json
);
8099 json_object_object_add(json_path
, "community",
8100 attr
->community
->json
);
8102 vty_out(vty
, " Community: %s\n",
8103 attr
->community
->str
);
8107 /* Line 5 display Extended-community */
8108 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8110 json_ext_community
= json_object_new_object();
8111 json_object_string_add(json_ext_community
,
8113 attr
->ecommunity
->str
);
8114 json_object_object_add(json_path
,
8115 "extendedCommunity",
8116 json_ext_community
);
8118 vty_out(vty
, " Extended Community: %s\n",
8119 attr
->ecommunity
->str
);
8123 /* Line 6 display Large community */
8124 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8126 if (!attr
->lcommunity
->json
)
8127 lcommunity_str(attr
->lcommunity
, true);
8128 json_object_lock(attr
->lcommunity
->json
);
8129 json_object_object_add(json_path
,
8131 attr
->lcommunity
->json
);
8133 vty_out(vty
, " Large Community: %s\n",
8134 attr
->lcommunity
->str
);
8138 /* Line 7 display Originator, Cluster-id */
8139 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8140 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8142 & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8144 json_object_string_add(
8145 json_path
, "originatorId",
8146 inet_ntoa(attr
->originator_id
));
8148 vty_out(vty
, " Originator: %s",
8149 inet_ntoa(attr
->originator_id
));
8152 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8157 json_object_new_object();
8158 json_cluster_list_list
=
8159 json_object_new_array();
8162 i
< attr
->cluster
->length
/ 4;
8164 json_string
= json_object_new_string(
8168 json_object_array_add(
8169 json_cluster_list_list
,
8173 /* struct cluster_list does not have
8175 * aspath and community do. Add this
8178 json_object_string_add(json_cluster_list,
8179 "string", attr->cluster->str);
8181 json_object_object_add(
8182 json_cluster_list
, "list",
8183 json_cluster_list_list
);
8184 json_object_object_add(
8185 json_path
, "clusterList",
8188 vty_out(vty
, ", Cluster list: ");
8191 i
< attr
->cluster
->length
/ 4;
8205 if (path
->extra
&& path
->extra
->damp_info
)
8206 bgp_damp_info_vty(vty
, path
, json_path
);
8209 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8210 && safi
!= SAFI_EVPN
) {
8211 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8214 json_object_int_add(json_path
, "remoteLabel",
8217 vty_out(vty
, " Remote label: %d\n", label
);
8221 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8223 json_object_int_add(json_path
, "labelIndex",
8226 vty_out(vty
, " Label Index: %d\n",
8230 /* Line 8 display Addpath IDs */
8231 if (path
->addpath_rx_id
|| path
->addpath_tx_id
) {
8233 json_object_int_add(json_path
, "addpathRxId",
8234 path
->addpath_rx_id
);
8235 json_object_int_add(json_path
, "addpathTxId",
8236 path
->addpath_tx_id
);
8238 vty_out(vty
, " AddPath ID: RX %u, TX %u\n",
8239 path
->addpath_rx_id
,
8240 path
->addpath_tx_id
);
8244 /* If we used addpath to TX a non-bestpath we need to display
8245 * "Advertised to" on a path-by-path basis */
8246 if (bgp
->addpath_tx_used
[afi
][safi
]) {
8249 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8251 bgp_addpath_encode_tx(peer
, afi
, safi
);
8252 has_adj
= bgp_adj_out_lookup(
8253 peer
, path
->net
, path
->addpath_tx_id
);
8255 if ((addpath_capable
&& has_adj
)
8256 || (!addpath_capable
&& has_adj
8257 && CHECK_FLAG(path
->flags
,
8258 BGP_PATH_SELECTED
))) {
8259 if (json_path
&& !json_adv_to
)
8261 json_object_new_object();
8263 route_vty_out_advertised_to(
8272 json_object_object_add(json_path
,
8283 /* Line 9 display Uptime */
8284 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8286 json_last_update
= json_object_new_object();
8287 json_object_int_add(json_last_update
, "epoch", tbuf
);
8288 json_object_string_add(json_last_update
, "string",
8290 json_object_object_add(json_path
, "lastUpdate",
8293 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8295 /* Line 10 display PMSI tunnel attribute, if present */
8296 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8297 const char *str
= lookup_msg(bgp_pmsi_tnltype_str
,
8298 attr
->pmsi_tnl_type
,
8299 PMSI_TNLTYPE_STR_DEFAULT
);
8302 json_pmsi
= json_object_new_object();
8303 json_object_string_add(json_pmsi
,
8305 json_object_object_add(json_path
, "pmsi",
8308 vty_out(vty
, " PMSI Tunnel Type: %s\n",
8314 /* We've constructed the json object for this path, add it to the json
8318 if (json_nexthop_global
|| json_nexthop_ll
) {
8319 json_nexthops
= json_object_new_array();
8321 if (json_nexthop_global
)
8322 json_object_array_add(json_nexthops
,
8323 json_nexthop_global
);
8325 if (json_nexthop_ll
)
8326 json_object_array_add(json_nexthops
,
8329 json_object_object_add(json_path
, "nexthops",
8333 json_object_object_add(json_path
, "peer", json_peer
);
8334 json_object_array_add(json_paths
, json_path
);
8339 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
8340 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
8341 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
8343 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
8344 const char *prefix_list_str
, afi_t afi
,
8345 safi_t safi
, enum bgp_show_type type
);
8346 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
8347 const char *filter
, afi_t afi
, safi_t safi
,
8348 enum bgp_show_type type
);
8349 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
8350 const char *rmap_str
, afi_t afi
, safi_t safi
,
8351 enum bgp_show_type type
);
8352 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
8353 const char *com
, int exact
, afi_t afi
,
8355 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
8356 const char *prefix
, afi_t afi
, safi_t safi
,
8357 enum bgp_show_type type
);
8358 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
8359 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
8360 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
8361 const char *comstr
, int exact
, afi_t afi
,
8362 safi_t safi
, bool use_json
);
8365 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8366 struct bgp_table
*table
, enum bgp_show_type type
,
8367 void *output_arg
, bool use_json
, char *rd
,
8368 int is_last
, unsigned long *output_cum
,
8369 unsigned long *total_cum
,
8370 unsigned long *json_header_depth
)
8372 struct bgp_path_info
*pi
;
8373 struct bgp_node
*rn
;
8376 unsigned long output_count
= 0;
8377 unsigned long total_count
= 0;
8380 json_object
*json_paths
= NULL
;
8383 if (output_cum
&& *output_cum
!= 0)
8386 if (use_json
&& !*json_header_depth
) {
8388 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
8389 ",\n \"routerId\": \"%s\",\n \"routes\": { ",
8390 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
8391 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
8394 table
->version
, inet_ntoa(bgp
->router_id
));
8395 *json_header_depth
= 2;
8397 vty_out(vty
, " \"routeDistinguishers\" : {");
8398 ++*json_header_depth
;
8402 if (use_json
&& rd
) {
8403 vty_out(vty
, " \"%s\" : { ", rd
);
8406 /* Start processing of routes. */
8407 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
8408 if (rn
->info
== NULL
)
8413 json_paths
= json_object_new_array();
8417 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
8419 if (type
== bgp_show_type_flap_statistics
8420 || type
== bgp_show_type_flap_neighbor
8421 || type
== bgp_show_type_dampend_paths
8422 || type
== bgp_show_type_damp_neighbor
) {
8423 if (!(pi
->extra
&& pi
->extra
->damp_info
))
8426 if (type
== bgp_show_type_regexp
) {
8427 regex_t
*regex
= output_arg
;
8429 if (bgp_regexec(regex
, pi
->attr
->aspath
)
8433 if (type
== bgp_show_type_prefix_list
) {
8434 struct prefix_list
*plist
= output_arg
;
8436 if (prefix_list_apply(plist
, &rn
->p
)
8440 if (type
== bgp_show_type_filter_list
) {
8441 struct as_list
*as_list
= output_arg
;
8443 if (as_list_apply(as_list
, pi
->attr
->aspath
)
8444 != AS_FILTER_PERMIT
)
8447 if (type
== bgp_show_type_route_map
) {
8448 struct route_map
*rmap
= output_arg
;
8449 struct bgp_path_info path
;
8450 struct attr dummy_attr
;
8453 bgp_attr_dup(&dummy_attr
, pi
->attr
);
8455 path
.peer
= pi
->peer
;
8456 path
.attr
= &dummy_attr
;
8458 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
8460 if (ret
== RMAP_DENYMATCH
)
8463 if (type
== bgp_show_type_neighbor
8464 || type
== bgp_show_type_flap_neighbor
8465 || type
== bgp_show_type_damp_neighbor
) {
8466 union sockunion
*su
= output_arg
;
8468 if (pi
->peer
== NULL
8469 || pi
->peer
->su_remote
== NULL
8470 || !sockunion_same(pi
->peer
->su_remote
, su
))
8473 if (type
== bgp_show_type_cidr_only
) {
8474 uint32_t destination
;
8476 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
8477 if (IN_CLASSC(destination
)
8478 && rn
->p
.prefixlen
== 24)
8480 if (IN_CLASSB(destination
)
8481 && rn
->p
.prefixlen
== 16)
8483 if (IN_CLASSA(destination
)
8484 && rn
->p
.prefixlen
== 8)
8487 if (type
== bgp_show_type_prefix_longer
) {
8489 if (!prefix_match(p
, &rn
->p
))
8492 if (type
== bgp_show_type_community_all
) {
8493 if (!pi
->attr
->community
)
8496 if (type
== bgp_show_type_community
) {
8497 struct community
*com
= output_arg
;
8499 if (!pi
->attr
->community
8500 || !community_match(pi
->attr
->community
,
8504 if (type
== bgp_show_type_community_exact
) {
8505 struct community
*com
= output_arg
;
8507 if (!pi
->attr
->community
8508 || !community_cmp(pi
->attr
->community
, com
))
8511 if (type
== bgp_show_type_community_list
) {
8512 struct community_list
*list
= output_arg
;
8514 if (!community_list_match(pi
->attr
->community
,
8518 if (type
== bgp_show_type_community_list_exact
) {
8519 struct community_list
*list
= output_arg
;
8521 if (!community_list_exact_match(
8522 pi
->attr
->community
, list
))
8525 if (type
== bgp_show_type_lcommunity
) {
8526 struct lcommunity
*lcom
= output_arg
;
8528 if (!pi
->attr
->lcommunity
8529 || !lcommunity_match(pi
->attr
->lcommunity
,
8533 if (type
== bgp_show_type_lcommunity_list
) {
8534 struct community_list
*list
= output_arg
;
8536 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
8540 if (type
== bgp_show_type_lcommunity_all
) {
8541 if (!pi
->attr
->lcommunity
)
8544 if (type
== bgp_show_type_dampend_paths
8545 || type
== bgp_show_type_damp_neighbor
) {
8546 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
8547 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
8551 if (!use_json
&& header
) {
8552 vty_out(vty
, "BGP table version is %" PRIu64
8553 ", local router ID is %s, vrf id ",
8555 inet_ntoa(bgp
->router_id
));
8556 if (bgp
->vrf_id
== VRF_UNKNOWN
)
8557 vty_out(vty
, "%s", VRFID_NONE_STR
);
8559 vty_out(vty
, "%u", bgp
->vrf_id
);
8561 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
8562 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
8563 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
8564 if (type
== bgp_show_type_dampend_paths
8565 || type
== bgp_show_type_damp_neighbor
)
8566 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
8567 else if (type
== bgp_show_type_flap_statistics
8568 || type
== bgp_show_type_flap_neighbor
)
8569 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
8571 vty_out(vty
, BGP_SHOW_HEADER
);
8574 if (rd
!= NULL
&& !display
&& !output_count
) {
8577 "Route Distinguisher: %s\n",
8580 if (type
== bgp_show_type_dampend_paths
8581 || type
== bgp_show_type_damp_neighbor
)
8582 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
8583 safi
, use_json
, json_paths
);
8584 else if (type
== bgp_show_type_flap_statistics
8585 || type
== bgp_show_type_flap_neighbor
)
8586 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
8587 safi
, use_json
, json_paths
);
8589 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
8601 if (p
->family
== AF_FLOWSPEC
) {
8602 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
8604 bgp_fs_nlri_get_string((unsigned char *)
8605 p
->u
.prefix_flowspec
.ptr
,
8606 p
->u
.prefix_flowspec
8609 NLRI_STRING_FORMAT_MIN
,
8612 vty_out(vty
, "\"%s/%d\": ",
8614 p
->u
.prefix_flowspec
.prefixlen
);
8616 vty_out(vty
, ",\"%s/%d\": ",
8618 p
->u
.prefix_flowspec
.prefixlen
);
8620 prefix2str(p
, buf2
, sizeof(buf2
));
8622 vty_out(vty
, "\"%s\": ", buf2
);
8624 vty_out(vty
, ",\"%s\": ", buf2
);
8627 json_object_to_json_string(json_paths
));
8628 json_object_free(json_paths
);
8635 output_count
+= *output_cum
;
8636 *output_cum
= output_count
;
8639 total_count
+= *total_cum
;
8640 *total_cum
= total_count
;
8644 vty_out(vty
, " }%s ", (is_last
? "" : ","));
8648 for (i
= 0; i
< *json_header_depth
; ++i
)
8649 vty_out(vty
, " } ");
8653 /* No route is displayed */
8654 if (output_count
== 0) {
8655 if (type
== bgp_show_type_normal
)
8657 "No BGP prefixes displayed, %ld exist\n",
8661 "\nDisplayed %ld routes and %ld total paths\n",
8662 output_count
, total_count
);
8669 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
8670 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
8671 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8673 struct bgp_node
*rn
, *next
;
8674 unsigned long output_cum
= 0;
8675 unsigned long total_cum
= 0;
8676 unsigned long json_header_depth
= 0;
8679 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
8681 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
8682 next
= bgp_route_next(rn
);
8683 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
8685 if (rn
->info
!= NULL
) {
8686 struct prefix_rd prd
;
8687 char rd
[RD_ADDRSTRLEN
];
8689 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
8690 prefix_rd2str(&prd
, rd
, sizeof(rd
));
8691 bgp_show_table(vty
, bgp
, safi
, rn
->info
, type
,
8692 output_arg
, use_json
, rd
, next
== NULL
,
8693 &output_cum
, &total_cum
,
8694 &json_header_depth
);
8700 if (output_cum
== 0)
8701 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
8705 "\nDisplayed %ld routes and %ld total paths\n",
8706 output_cum
, total_cum
);
8710 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
8711 enum bgp_show_type type
, void *output_arg
, bool use_json
)
8713 struct bgp_table
*table
;
8714 unsigned long json_header_depth
= 0;
8717 bgp
= bgp_get_default();
8722 vty_out(vty
, "No BGP process is configured\n");
8724 vty_out(vty
, "{}\n");
8728 table
= bgp
->rib
[afi
][safi
];
8729 /* use MPLS and ENCAP specific shows until they are merged */
8730 if (safi
== SAFI_MPLS_VPN
) {
8731 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
8732 output_arg
, use_json
);
8735 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
8736 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
8737 output_arg
, use_json
,
8740 /* labeled-unicast routes live in the unicast table */
8741 else if (safi
== SAFI_LABELED_UNICAST
)
8742 safi
= SAFI_UNICAST
;
8744 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
8745 NULL
, 1, NULL
, NULL
, &json_header_depth
);
8748 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
8749 safi_t safi
, bool use_json
)
8751 struct listnode
*node
, *nnode
;
8754 bool route_output
= false;
8757 vty_out(vty
, "{\n");
8759 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
8760 route_output
= true;
8763 vty_out(vty
, ",\n");
8767 vty_out(vty
, "\"%s\":",
8768 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8772 vty_out(vty
, "\nInstance %s:\n",
8773 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
8777 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
8782 vty_out(vty
, "}\n");
8783 else if (!route_output
)
8784 vty_out(vty
, "%% BGP instance not found\n");
8787 /* Header of detailed BGP route information */
8788 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
8789 struct bgp_node
*rn
, struct prefix_rd
*prd
,
8790 afi_t afi
, safi_t safi
, json_object
*json
)
8792 struct bgp_path_info
*pi
;
8795 struct listnode
*node
, *nnode
;
8796 char buf1
[RD_ADDRSTRLEN
];
8797 char buf2
[INET6_ADDRSTRLEN
];
8798 char buf3
[EVPN_ROUTE_STRLEN
];
8799 char prefix_str
[BUFSIZ
];
8804 int route_filter_translated_v4
= 0;
8805 int route_filter_v4
= 0;
8806 int route_filter_translated_v6
= 0;
8807 int route_filter_v6
= 0;
8810 int accept_own_nexthop
= 0;
8813 int no_advertise
= 0;
8817 int has_valid_label
= 0;
8818 mpls_label_t label
= 0;
8819 json_object
*json_adv_to
= NULL
;
8822 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
8824 if (has_valid_label
)
8825 label
= label_pton(&rn
->local_label
);
8828 if (has_valid_label
)
8829 json_object_int_add(json
, "localLabel", label
);
8831 json_object_string_add(
8833 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
8835 if (safi
== SAFI_EVPN
)
8836 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
8837 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
8840 bgp_evpn_route2str((struct prefix_evpn
*)p
,
8841 buf3
, sizeof(buf3
)));
8843 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
8844 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
8845 ? prefix_rd2str(prd
, buf1
,
8848 safi
== SAFI_MPLS_VPN
? ":" : "",
8849 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
8853 if (has_valid_label
)
8854 vty_out(vty
, "Local label: %d\n", label
);
8855 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
8856 vty_out(vty
, "not allocated\n");
8859 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
8861 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
8863 if (pi
->extra
&& pi
->extra
->suppress
)
8866 if (pi
->attr
->community
== NULL
)
8869 no_advertise
+= community_include(
8870 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
8871 no_export
+= community_include(pi
->attr
->community
,
8872 COMMUNITY_NO_EXPORT
);
8873 local_as
+= community_include(pi
->attr
->community
,
8874 COMMUNITY_LOCAL_AS
);
8875 accept_own
+= community_include(pi
->attr
->community
,
8876 COMMUNITY_ACCEPT_OWN
);
8877 route_filter_translated_v4
+= community_include(
8878 pi
->attr
->community
,
8879 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
8880 route_filter_translated_v6
+= community_include(
8881 pi
->attr
->community
,
8882 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
8883 route_filter_v4
+= community_include(
8884 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
8885 route_filter_v6
+= community_include(
8886 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
8887 llgr_stale
+= community_include(pi
->attr
->community
,
8888 COMMUNITY_LLGR_STALE
);
8889 no_llgr
+= community_include(pi
->attr
->community
,
8891 accept_own_nexthop
+=
8892 community_include(pi
->attr
->community
,
8893 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
8894 blackhole
+= community_include(pi
->attr
->community
,
8895 COMMUNITY_BLACKHOLE
);
8896 no_peer
+= community_include(pi
->attr
->community
,
8902 vty_out(vty
, "Paths: (%d available", count
);
8904 vty_out(vty
, ", best #%d", best
);
8905 if (safi
== SAFI_UNICAST
)
8906 vty_out(vty
, ", table %s",
8908 == BGP_INSTANCE_TYPE_DEFAULT
)
8912 vty_out(vty
, ", no best path");
8916 ", accept own local route exported and imported in different VRF");
8917 else if (route_filter_translated_v4
)
8919 ", mark translated RTs for VPNv4 route filtering");
8920 else if (route_filter_v4
)
8922 ", attach RT as-is for VPNv4 route filtering");
8923 else if (route_filter_translated_v6
)
8925 ", mark translated RTs for VPNv6 route filtering");
8926 else if (route_filter_v6
)
8928 ", attach RT as-is for VPNv6 route filtering");
8929 else if (llgr_stale
)
8931 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
8934 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
8935 else if (accept_own_nexthop
)
8937 ", accept local nexthop");
8939 vty_out(vty
, ", inform peer to blackhole prefix");
8941 vty_out(vty
, ", not advertised to EBGP peer");
8942 else if (no_advertise
)
8943 vty_out(vty
, ", not advertised to any peer");
8945 vty_out(vty
, ", not advertised outside local AS");
8948 ", inform EBGP peer not to advertise to their EBGP peers");
8952 ", Advertisements suppressed by an aggregate.");
8953 vty_out(vty
, ")\n");
8956 /* If we are not using addpath then we can display Advertised to and
8958 * show what peers we advertised the bestpath to. If we are using
8960 * though then we must display Advertised to on a path-by-path basis. */
8961 if (!bgp
->addpath_tx_used
[afi
][safi
]) {
8962 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8963 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
8964 if (json
&& !json_adv_to
)
8965 json_adv_to
= json_object_new_object();
8967 route_vty_out_advertised_to(
8969 " Advertised to non peer-group peers:\n ",
8976 json_object_object_add(json
, "advertisedTo",
8981 vty_out(vty
, " Not advertised to any peer");
8987 /* Display specified route of BGP table. */
8988 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
8989 struct bgp_table
*rib
, const char *ip_str
,
8990 afi_t afi
, safi_t safi
,
8991 struct prefix_rd
*prd
, int prefix_check
,
8992 enum bgp_path_type pathtype
, bool use_json
)
8997 struct prefix match
;
8998 struct bgp_node
*rn
;
8999 struct bgp_node
*rm
;
9000 struct bgp_path_info
*pi
;
9001 struct bgp_table
*table
;
9002 json_object
*json
= NULL
;
9003 json_object
*json_paths
= NULL
;
9005 /* Check IP address argument. */
9006 ret
= str2prefix(ip_str
, &match
);
9008 vty_out(vty
, "address is malformed\n");
9012 match
.family
= afi2family(afi
);
9015 json
= json_object_new_object();
9016 json_paths
= json_object_new_array();
9019 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
) {
9020 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9021 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9024 if ((table
= rn
->info
) == NULL
)
9029 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9033 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9034 bgp_unlock_node(rm
);
9038 for (pi
= rm
->info
; pi
; pi
= pi
->next
) {
9040 route_vty_out_detail_header(
9042 (struct prefix_rd
*)&rn
->p
,
9043 AFI_IP
, safi
, json
);
9048 if (pathtype
== BGP_PATH_SHOW_ALL
9049 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9050 && CHECK_FLAG(pi
->flags
,
9052 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9053 && (CHECK_FLAG(pi
->flags
,
9055 || CHECK_FLAG(pi
->flags
,
9056 BGP_PATH_SELECTED
))))
9057 route_vty_out_detail(vty
, bgp
, &rm
->p
,
9062 bgp_unlock_node(rm
);
9064 } else if (safi
== SAFI_FLOWSPEC
) {
9065 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9066 &match
, prefix_check
,
9073 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9075 || rn
->p
.prefixlen
== match
.prefixlen
) {
9076 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
9078 route_vty_out_detail_header(
9079 vty
, bgp
, rn
, NULL
, afi
,
9085 if (pathtype
== BGP_PATH_SHOW_ALL
9087 == BGP_PATH_SHOW_BESTPATH
9092 == BGP_PATH_SHOW_MULTIPATH
9098 BGP_PATH_SELECTED
))))
9099 route_vty_out_detail(
9100 vty
, bgp
, &rn
->p
, pi
,
9101 afi
, safi
, json_paths
);
9105 bgp_unlock_node(rn
);
9111 json_object_object_add(json
, "paths", json_paths
);
9113 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9114 json
, JSON_C_TO_STRING_PRETTY
));
9115 json_object_free(json
);
9118 vty_out(vty
, "%% Network not in table\n");
9126 /* Display specified route of Main RIB */
9127 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9128 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9129 int prefix_check
, enum bgp_path_type pathtype
,
9133 bgp
= bgp_get_default();
9136 vty_out(vty
, "No BGP process is configured\n");
9138 vty_out(vty
, "{}\n");
9143 /* labeled-unicast routes live in the unicast table */
9144 if (safi
== SAFI_LABELED_UNICAST
)
9145 safi
= SAFI_UNICAST
;
9147 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9148 afi
, safi
, prd
, prefix_check
, pathtype
,
9152 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9153 struct cmd_token
**argv
, afi_t afi
, safi_t safi
,
9156 struct lcommunity
*lcom
;
9162 b
= buffer_new(1024);
9163 for (i
= 0; i
< argc
; i
++) {
9165 buffer_putc(b
, ' ');
9167 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9169 buffer_putstr(b
, argv
[i
]->arg
);
9173 buffer_putc(b
, '\0');
9175 str
= buffer_getstr(b
);
9178 lcom
= lcommunity_str2com(str
);
9179 XFREE(MTYPE_TMP
, str
);
9181 vty_out(vty
, "%% Large-community malformed\n");
9185 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity
, lcom
,
9189 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9190 const char *lcom
, afi_t afi
, safi_t safi
,
9193 struct community_list
*list
;
9195 list
= community_list_lookup(bgp_clist
, lcom
,
9196 LARGE_COMMUNITY_LIST_MASTER
);
9198 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9203 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_lcommunity_list
,
9207 DEFUN (show_ip_bgp_large_community_list
,
9208 show_ip_bgp_large_community_list_cmd
,
9209 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [json]",
9213 BGP_INSTANCE_HELP_STR
9215 BGP_SAFI_WITH_LABEL_HELP_STR
9216 "Display routes matching the large-community-list\n"
9217 "large-community-list number\n"
9218 "large-community-list name\n"
9222 afi_t afi
= AFI_IP6
;
9223 safi_t safi
= SAFI_UNICAST
;
9226 if (argv_find(argv
, argc
, "ip", &idx
))
9228 if (argv_find(argv
, argc
, "view", &idx
)
9229 || argv_find(argv
, argc
, "vrf", &idx
))
9230 vrf
= argv
[++idx
]->arg
;
9231 if (argv_find(argv
, argc
, "ipv4", &idx
)
9232 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9233 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9234 if (argv_find(argv
, argc
, "unicast", &idx
)
9235 || argv_find(argv
, argc
, "multicast", &idx
))
9236 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9239 bool uj
= use_json(argc
, argv
);
9241 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9243 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9247 argv_find(argv
, argc
, "large-community-list", &idx
);
9248 return bgp_show_lcommunity_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
, safi
,
9251 DEFUN (show_ip_bgp_large_community
,
9252 show_ip_bgp_large_community_cmd
,
9253 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [AA:BB:CC] [json]",
9257 BGP_INSTANCE_HELP_STR
9259 BGP_SAFI_WITH_LABEL_HELP_STR
9260 "Display routes matching the large-communities\n"
9261 "List of large-community numbers\n"
9265 afi_t afi
= AFI_IP6
;
9266 safi_t safi
= SAFI_UNICAST
;
9269 if (argv_find(argv
, argc
, "ip", &idx
))
9271 if (argv_find(argv
, argc
, "view", &idx
)
9272 || argv_find(argv
, argc
, "vrf", &idx
))
9273 vrf
= argv
[++idx
]->arg
;
9274 if (argv_find(argv
, argc
, "ipv4", &idx
)
9275 || argv_find(argv
, argc
, "ipv6", &idx
)) {
9276 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
9277 if (argv_find(argv
, argc
, "unicast", &idx
)
9278 || argv_find(argv
, argc
, "multicast", &idx
))
9279 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
9282 bool uj
= use_json(argc
, argv
);
9284 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
9286 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
9290 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
))
9291 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
, afi
, safi
, uj
);
9293 return bgp_show(vty
, bgp
, afi
, safi
,
9294 bgp_show_type_lcommunity_all
, NULL
, uj
);
9297 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9301 /* BGP route print out function without JSON */
9304 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9305 <dampening <parameters>\
9310 |community-list <(1-500)|WORD> [exact-match]\
9311 |A.B.C.D/M longer-prefixes\
9312 |X:X::X:X/M longer-prefixes\
9317 BGP_INSTANCE_HELP_STR
9319 BGP_SAFI_WITH_LABEL_HELP_STR
9320 "Display detailed information about dampening\n"
9321 "Display detail of configured dampening parameters\n"
9322 "Display routes matching the route-map\n"
9323 "A route-map to match on\n"
9324 "Display routes conforming to the prefix-list\n"
9325 "Prefix-list name\n"
9326 "Display routes conforming to the filter-list\n"
9327 "Regular expression access list name\n"
9328 "BGP RIB advertisement statistics\n"
9329 "Display routes matching the community-list\n"
9330 "community-list number\n"
9331 "community-list name\n"
9332 "Exact match of the communities\n"
9334 "Display route and more specific routes\n"
9336 "Display route and more specific routes\n")
9338 afi_t afi
= AFI_IP6
;
9339 safi_t safi
= SAFI_UNICAST
;
9340 int exact_match
= 0;
9341 struct bgp
*bgp
= NULL
;
9344 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9349 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9350 if (argv_find(argv
, argc
, "parameters", &idx
))
9351 return bgp_show_dampening_parameters(vty
, afi
, safi
);
9354 if (argv_find(argv
, argc
, "prefix-list", &idx
))
9355 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9356 safi
, bgp_show_type_prefix_list
);
9358 if (argv_find(argv
, argc
, "filter-list", &idx
))
9359 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9360 safi
, bgp_show_type_filter_list
);
9362 if (argv_find(argv
, argc
, "statistics", &idx
))
9363 return bgp_table_stats(vty
, bgp
, afi
, safi
);
9365 if (argv_find(argv
, argc
, "route-map", &idx
))
9366 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
9367 safi
, bgp_show_type_route_map
);
9369 if (argv_find(argv
, argc
, "community-list", &idx
)) {
9370 const char *clist_number_or_name
= argv
[++idx
]->arg
;
9371 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
9373 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
9374 exact_match
, afi
, safi
);
9377 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9378 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9379 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
9381 bgp_show_type_prefix_longer
);
9386 /* BGP route print out function with JSON */
9387 DEFUN (show_ip_bgp_json
,
9388 show_ip_bgp_json_cmd
,
9389 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
9391 |dampening <flap-statistics|dampened-paths>\
9392 |community [AA:NN|local-AS|no-advertise|no-export\
9393 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
9394 |accept-own|accept-own-nexthop|route-filter-v6\
9395 |route-filter-v4|route-filter-translated-v6\
9396 |route-filter-translated-v4] [exact-match]\
9401 BGP_INSTANCE_HELP_STR
9403 BGP_SAFI_WITH_LABEL_HELP_STR
9404 "Display only routes with non-natural netmasks\n"
9405 "Display detailed information about dampening\n"
9406 "Display flap statistics of routes\n"
9407 "Display paths suppressed due to dampening\n"
9408 "Display routes matching the communities\n"
9410 "Do not send outside local AS (well-known community)\n"
9411 "Do not advertise to any peer (well-known community)\n"
9412 "Do not export to next AS (well-known community)\n"
9413 "Graceful shutdown (well-known community)\n"
9414 "Do not export to any peer (well-known community)\n"
9415 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
9416 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
9417 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
9418 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
9419 "Should accept VPN route with local nexthop (well-known community)\n"
9420 "RT VPNv6 route filtering (well-known community)\n"
9421 "RT VPNv4 route filtering (well-known community)\n"
9422 "RT translated VPNv6 route filtering (well-known community)\n"
9423 "RT translated VPNv4 route filtering (well-known community)\n"
9424 "Exact match of the communities\n"
9427 afi_t afi
= AFI_IP6
;
9428 safi_t safi
= SAFI_UNICAST
;
9429 enum bgp_show_type sh_type
= bgp_show_type_normal
;
9430 struct bgp
*bgp
= NULL
;
9432 int exact_match
= 0;
9433 bool uj
= use_json(argc
, argv
);
9438 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9443 if (argv_find(argv
, argc
, "cidr-only", &idx
))
9444 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
9447 if (argv_find(argv
, argc
, "dampening", &idx
)) {
9448 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
9449 return bgp_show(vty
, bgp
, afi
, safi
,
9450 bgp_show_type_dampend_paths
, NULL
, uj
);
9451 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
9452 return bgp_show(vty
, bgp
, afi
, safi
,
9453 bgp_show_type_flap_statistics
, NULL
,
9457 if (argv_find(argv
, argc
, "community", &idx
)) {
9458 char *maybecomm
= idx
+ 1 < argc
? argv
[idx
+ 1]->text
: NULL
;
9459 char *community
= NULL
;
9461 if (maybecomm
&& !strmatch(maybecomm
, "json")
9462 && !strmatch(maybecomm
, "exact-match"))
9463 community
= maybecomm
;
9465 if (argv_find(argv
, argc
, "exact-match", &idx
))
9469 return bgp_show_community(vty
, bgp
, community
,
9470 exact_match
, afi
, safi
, uj
);
9472 return (bgp_show(vty
, bgp
, afi
, safi
,
9473 bgp_show_type_community_all
, NULL
,
9477 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
9480 DEFUN (show_ip_bgp_route
,
9481 show_ip_bgp_route_cmd
,
9482 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
9483 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
9487 BGP_INSTANCE_HELP_STR
9489 BGP_SAFI_WITH_LABEL_HELP_STR
9490 "Network in the BGP routing table to display\n"
9492 "Network in the BGP routing table to display\n"
9494 "Display only the bestpath\n"
9495 "Display only multipaths\n"
9498 int prefix_check
= 0;
9500 afi_t afi
= AFI_IP6
;
9501 safi_t safi
= SAFI_UNICAST
;
9502 char *prefix
= NULL
;
9503 struct bgp
*bgp
= NULL
;
9504 enum bgp_path_type path_type
;
9505 bool uj
= use_json(argc
, argv
);
9509 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9516 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
9520 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
9521 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
9522 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
9524 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
9525 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
9528 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
9529 && afi
!= AFI_IP6
) {
9531 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
9534 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
9537 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
9541 prefix
= argv
[idx
]->arg
;
9543 /* [<bestpath|multipath>] */
9544 if (argv_find(argv
, argc
, "bestpath", &idx
))
9545 path_type
= BGP_PATH_SHOW_BESTPATH
;
9546 else if (argv_find(argv
, argc
, "multipath", &idx
))
9547 path_type
= BGP_PATH_SHOW_MULTIPATH
;
9549 path_type
= BGP_PATH_SHOW_ALL
;
9551 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
9555 DEFUN (show_ip_bgp_regexp
,
9556 show_ip_bgp_regexp_cmd
,
9557 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
9561 BGP_INSTANCE_HELP_STR
9563 BGP_SAFI_WITH_LABEL_HELP_STR
9564 "Display routes matching the AS path regular expression\n"
9565 "A regular-expression to match the BGP AS paths\n")
9567 afi_t afi
= AFI_IP6
;
9568 safi_t safi
= SAFI_UNICAST
;
9569 struct bgp
*bgp
= NULL
;
9572 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9577 // get index of regex
9578 argv_find(argv
, argc
, "regexp", &idx
);
9581 char *regstr
= argv_concat(argv
, argc
, idx
);
9582 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
9583 bgp_show_type_regexp
);
9584 XFREE(MTYPE_TMP
, regstr
);
9588 DEFUN (show_ip_bgp_instance_all
,
9589 show_ip_bgp_instance_all_cmd
,
9590 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
9594 BGP_INSTANCE_ALL_HELP_STR
9596 BGP_SAFI_WITH_LABEL_HELP_STR
9600 safi_t safi
= SAFI_UNICAST
;
9601 struct bgp
*bgp
= NULL
;
9603 bool uj
= use_json(argc
, argv
);
9608 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
9613 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
9617 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9618 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
9623 regex
= bgp_regcomp(regstr
);
9625 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
9629 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
9630 bgp_regex_free(regex
);
9634 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9635 const char *prefix_list_str
, afi_t afi
,
9636 safi_t safi
, enum bgp_show_type type
)
9638 struct prefix_list
*plist
;
9640 plist
= prefix_list_lookup(afi
, prefix_list_str
);
9641 if (plist
== NULL
) {
9642 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
9647 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
9650 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9651 const char *filter
, afi_t afi
, safi_t safi
,
9652 enum bgp_show_type type
)
9654 struct as_list
*as_list
;
9656 as_list
= as_list_lookup(filter
);
9657 if (as_list
== NULL
) {
9658 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
9663 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
9666 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9667 const char *rmap_str
, afi_t afi
, safi_t safi
,
9668 enum bgp_show_type type
)
9670 struct route_map
*rmap
;
9672 rmap
= route_map_lookup_by_name(rmap_str
);
9674 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
9678 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
9681 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9682 const char *comstr
, int exact
, afi_t afi
,
9683 safi_t safi
, bool use_json
)
9685 struct community
*com
;
9688 com
= community_str2com(comstr
);
9690 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
9694 ret
= bgp_show(vty
, bgp
, afi
, safi
,
9695 (exact
? bgp_show_type_community_exact
9696 : bgp_show_type_community
),
9698 community_free(&com
);
9703 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9704 const char *com
, int exact
, afi_t afi
,
9707 struct community_list
*list
;
9709 list
= community_list_lookup(bgp_clist
, com
, COMMUNITY_LIST_MASTER
);
9711 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
9715 return bgp_show(vty
, bgp
, afi
, safi
,
9716 (exact
? bgp_show_type_community_list_exact
9717 : bgp_show_type_community_list
),
9721 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9722 const char *prefix
, afi_t afi
, safi_t safi
,
9723 enum bgp_show_type type
)
9730 ret
= str2prefix(prefix
, p
);
9732 vty_out(vty
, "%% Malformed Prefix\n");
9736 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
9741 static struct peer
*peer_lookup_in_view(struct vty
*vty
, struct bgp
*bgp
,
9742 const char *ip_str
, bool use_json
)
9748 /* Get peer sockunion. */
9749 ret
= str2sockunion(ip_str
, &su
);
9751 peer
= peer_lookup_by_conf_if(bgp
, ip_str
);
9753 peer
= peer_lookup_by_hostname(bgp
, ip_str
);
9757 json_object
*json_no
= NULL
;
9758 json_no
= json_object_new_object();
9759 json_object_string_add(
9761 "malformedAddressOrName",
9763 vty_out(vty
, "%s\n",
9764 json_object_to_json_string_ext(
9766 JSON_C_TO_STRING_PRETTY
));
9767 json_object_free(json_no
);
9770 "%% Malformed address or name: %s\n",
9778 /* Peer structure lookup. */
9779 peer
= peer_lookup(bgp
, &su
);
9782 json_object
*json_no
= NULL
;
9783 json_no
= json_object_new_object();
9784 json_object_string_add(json_no
, "warning",
9785 "No such neighbor in this view/vrf");
9786 vty_out(vty
, "%s\n",
9787 json_object_to_json_string_ext(
9788 json_no
, JSON_C_TO_STRING_PRETTY
));
9789 json_object_free(json_no
);
9791 vty_out(vty
, "No such neighbor in this view/vrf\n");
9799 BGP_STATS_MAXBITLEN
= 0,
9803 BGP_STATS_UNAGGREGATEABLE
,
9804 BGP_STATS_MAX_AGGREGATEABLE
,
9805 BGP_STATS_AGGREGATES
,
9807 BGP_STATS_ASPATH_COUNT
,
9808 BGP_STATS_ASPATH_MAXHOPS
,
9809 BGP_STATS_ASPATH_TOTHOPS
,
9810 BGP_STATS_ASPATH_MAXSIZE
,
9811 BGP_STATS_ASPATH_TOTSIZE
,
9812 BGP_STATS_ASN_HIGHEST
,
9816 static const char *table_stats_strs
[] = {
9817 [BGP_STATS_PREFIXES
] = "Total Prefixes",
9818 [BGP_STATS_TOTPLEN
] = "Average prefix length",
9819 [BGP_STATS_RIB
] = "Total Advertisements",
9820 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
9821 [BGP_STATS_MAX_AGGREGATEABLE
] =
9822 "Maximum aggregateable prefixes",
9823 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
9824 [BGP_STATS_SPACE
] = "Address space advertised",
9825 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
9826 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
9827 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
9828 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
9829 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
9830 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
9831 [BGP_STATS_MAX
] = NULL
,
9834 struct bgp_table_stats
{
9835 struct bgp_table
*table
;
9836 unsigned long long counts
[BGP_STATS_MAX
];
9841 #define TALLY_SIGFIG 100000
9842 static unsigned long
9843 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
9845 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
9846 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
9847 unsigned long ret
= newtot
/ count
;
9849 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
9856 static int bgp_table_stats_walker(struct thread
*t
)
9858 struct bgp_node
*rn
;
9859 struct bgp_node
*top
;
9860 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
9861 unsigned int space
= 0;
9863 if (!(top
= bgp_table_top(ts
->table
)))
9866 switch (top
->p
.family
) {
9868 space
= IPV4_MAX_BITLEN
;
9871 space
= IPV6_MAX_BITLEN
;
9875 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
9877 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
9878 struct bgp_path_info
*pi
;
9879 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
9880 unsigned int pinum
= 0;
9888 ts
->counts
[BGP_STATS_PREFIXES
]++;
9889 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
9892 ts
->counts
[BGP_STATS_AVGPLEN
]
9893 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
9894 ts
->counts
[BGP_STATS_AVGPLEN
],
9898 /* check if the prefix is included by any other announcements */
9899 while (prn
&& !prn
->info
)
9900 prn
= bgp_node_parent_nolock(prn
);
9902 if (prn
== NULL
|| prn
== top
) {
9903 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
9904 /* announced address space */
9907 pow(2.0, space
- rn
->p
.prefixlen
);
9908 } else if (prn
->info
)
9909 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
9911 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
9913 ts
->counts
[BGP_STATS_RIB
]++;
9916 && (CHECK_FLAG(pi
->attr
->flag
,
9918 BGP_ATTR_ATOMIC_AGGREGATE
))))
9919 ts
->counts
[BGP_STATS_AGGREGATES
]++;
9922 if (pi
->attr
&& pi
->attr
->aspath
) {
9924 aspath_count_hops(pi
->attr
->aspath
);
9926 aspath_size(pi
->attr
->aspath
);
9927 as_t highest
= aspath_highest(pi
->attr
->aspath
);
9929 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
9931 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
9932 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] =
9935 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
9936 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] =
9939 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
9940 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
9942 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
9943 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9944 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
9946 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
9947 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
9948 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
9951 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
9952 ts
->counts
[BGP_STATS_ASN_HIGHEST
] =
9960 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
9963 struct bgp_table_stats ts
;
9966 if (!bgp
->rib
[afi
][safi
]) {
9967 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
9972 vty_out(vty
, "BGP %s RIB statistics\n", afi_safi_print(afi
, safi
));
9974 /* labeled-unicast routes live in the unicast table */
9975 if (safi
== SAFI_LABELED_UNICAST
)
9976 safi
= SAFI_UNICAST
;
9978 memset(&ts
, 0, sizeof(ts
));
9979 ts
.table
= bgp
->rib
[afi
][safi
];
9980 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
9982 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
9983 if (!table_stats_strs
[i
])
9988 case BGP_STATS_ASPATH_AVGHOPS
:
9989 case BGP_STATS_ASPATH_AVGSIZE
:
9990 case BGP_STATS_AVGPLEN
:
9991 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
9992 vty_out (vty
, "%12.2f",
9993 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
9996 case BGP_STATS_ASPATH_TOTHOPS
:
9997 case BGP_STATS_ASPATH_TOTSIZE
:
9998 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
9999 vty_out(vty
, "%12.2f",
10001 ? (float)ts
.counts
[i
]
10003 [BGP_STATS_ASPATH_COUNT
]
10006 case BGP_STATS_TOTPLEN
:
10007 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10008 vty_out(vty
, "%12.2f",
10010 ? (float)ts
.counts
[i
]
10012 [BGP_STATS_PREFIXES
]
10015 case BGP_STATS_SPACE
:
10016 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10017 vty_out(vty
, "%12g\n", ts
.total_space
);
10019 if (afi
== AFI_IP6
) {
10020 vty_out(vty
, "%30s: ", "/32 equivalent ");
10021 vty_out(vty
, "%12g\n",
10022 ts
.total_space
* pow(2.0, -128 + 32));
10023 vty_out(vty
, "%30s: ", "/48 equivalent ");
10024 vty_out(vty
, "%12g\n",
10025 ts
.total_space
* pow(2.0, -128 + 48));
10027 vty_out(vty
, "%30s: ", "% announced ");
10028 vty_out(vty
, "%12.2f\n",
10029 ts
.total_space
* 100. * pow(2.0, -32));
10030 vty_out(vty
, "%30s: ", "/8 equivalent ");
10031 vty_out(vty
, "%12.2f\n",
10032 ts
.total_space
* pow(2.0, -32 + 8));
10033 vty_out(vty
, "%30s: ", "/24 equivalent ");
10034 vty_out(vty
, "%12.2f\n",
10035 ts
.total_space
* pow(2.0, -32 + 24));
10039 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10040 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10043 vty_out(vty
, "\n");
10045 return CMD_SUCCESS
;
10057 PCOUNT_PFCNT
, /* the figure we display to users */
10061 static const char *pcount_strs
[] = {
10062 [PCOUNT_ADJ_IN
] = "Adj-in",
10063 [PCOUNT_DAMPED
] = "Damped",
10064 [PCOUNT_REMOVED
] = "Removed",
10065 [PCOUNT_HISTORY
] = "History",
10066 [PCOUNT_STALE
] = "Stale",
10067 [PCOUNT_VALID
] = "Valid",
10068 [PCOUNT_ALL
] = "All RIB",
10069 [PCOUNT_COUNTED
] = "PfxCt counted",
10070 [PCOUNT_PFCNT
] = "Useable",
10071 [PCOUNT_MAX
] = NULL
,
10074 struct peer_pcounts
{
10075 unsigned int count
[PCOUNT_MAX
];
10076 const struct peer
*peer
;
10077 const struct bgp_table
*table
;
10080 static int bgp_peer_count_walker(struct thread
*t
)
10082 struct bgp_node
*rn
;
10083 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10084 const struct peer
*peer
= pc
->peer
;
10086 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10087 struct bgp_adj_in
*ain
;
10088 struct bgp_path_info
*pi
;
10090 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10091 if (ain
->peer
== peer
)
10092 pc
->count
[PCOUNT_ADJ_IN
]++;
10094 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
10095 if (pi
->peer
!= peer
)
10098 pc
->count
[PCOUNT_ALL
]++;
10100 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10101 pc
->count
[PCOUNT_DAMPED
]++;
10102 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10103 pc
->count
[PCOUNT_HISTORY
]++;
10104 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10105 pc
->count
[PCOUNT_REMOVED
]++;
10106 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10107 pc
->count
[PCOUNT_STALE
]++;
10108 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10109 pc
->count
[PCOUNT_VALID
]++;
10110 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10111 pc
->count
[PCOUNT_PFCNT
]++;
10113 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10114 pc
->count
[PCOUNT_COUNTED
]++;
10115 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10117 EC_LIB_DEVELOPMENT
,
10118 "Attempting to count but flags say it is unusable");
10120 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10122 EC_LIB_DEVELOPMENT
,
10123 "Not counted but flags say we should");
10130 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10131 safi_t safi
, bool use_json
)
10133 struct peer_pcounts pcounts
= {.peer
= peer
};
10135 json_object
*json
= NULL
;
10136 json_object
*json_loop
= NULL
;
10139 json
= json_object_new_object();
10140 json_loop
= json_object_new_object();
10143 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10144 || !peer
->bgp
->rib
[afi
][safi
]) {
10146 json_object_string_add(
10148 "No such neighbor or address family");
10149 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10150 json_object_free(json
);
10152 vty_out(vty
, "%% No such neighbor or address family\n");
10154 return CMD_WARNING
;
10157 memset(&pcounts
, 0, sizeof(pcounts
));
10158 pcounts
.peer
= peer
;
10159 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10161 /* in-place call via thread subsystem so as to record execution time
10162 * stats for the thread-walk (i.e. ensure this can't be blamed on
10163 * on just vty_read()).
10165 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10168 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10169 json_object_string_add(json
, "multiProtocol",
10170 afi_safi_print(afi
, safi
));
10171 json_object_int_add(json
, "pfxCounter",
10172 peer
->pcount
[afi
][safi
]);
10174 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10175 json_object_int_add(json_loop
, pcount_strs
[i
],
10178 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10180 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10181 json_object_string_add(json
, "pfxctDriftFor",
10183 json_object_string_add(
10184 json
, "recommended",
10185 "Please report this bug, with the above command output");
10187 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10188 json
, JSON_C_TO_STRING_PRETTY
));
10189 json_object_free(json
);
10193 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10194 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10195 peer
->hostname
, peer
->host
,
10196 afi_safi_print(afi
, safi
));
10198 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10199 afi_safi_print(afi
, safi
));
10202 vty_out(vty
, "PfxCt: %ld\n", peer
->pcount
[afi
][safi
]);
10203 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10205 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10206 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10209 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10210 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10212 "Please report this bug, with the above command output\n");
10216 return CMD_SUCCESS
;
10219 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10220 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10221 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10222 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10226 BGP_INSTANCE_HELP_STR
10229 "Detailed information on TCP and BGP neighbor connections\n"
10230 "Neighbor to display information about\n"
10231 "Neighbor to display information about\n"
10232 "Neighbor on BGP configured interface\n"
10233 "Display detailed prefix count information\n"
10236 afi_t afi
= AFI_IP6
;
10237 safi_t safi
= SAFI_UNICAST
;
10240 struct bgp
*bgp
= NULL
;
10241 bool uj
= use_json(argc
, argv
);
10246 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10249 return CMD_WARNING
;
10251 argv_find(argv
, argc
, "neighbors", &idx
);
10252 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
10254 return CMD_WARNING
;
10256 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_UNICAST
, uj
);
10259 #ifdef KEEP_OLD_VPN_COMMANDS
10260 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
10261 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
10262 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10267 "Display information about all VPNv4 NLRIs\n"
10268 "Detailed information on TCP and BGP neighbor connections\n"
10269 "Neighbor to display information about\n"
10270 "Neighbor to display information about\n"
10271 "Neighbor on BGP configured interface\n"
10272 "Display detailed prefix count information\n"
10277 bool uj
= use_json(argc
, argv
);
10279 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
10281 return CMD_WARNING
;
10283 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
10286 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
10287 show_ip_bgp_vpn_all_route_prefix_cmd
,
10288 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
10293 "Display information about all VPNv4 NLRIs\n"
10294 "Network in the BGP routing table to display\n"
10295 "Network in the BGP routing table to display\n"
10299 char *network
= NULL
;
10300 struct bgp
*bgp
= bgp_get_default();
10302 vty_out(vty
, "Can't find default instance\n");
10303 return CMD_WARNING
;
10306 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10307 network
= argv
[idx
]->arg
;
10308 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10309 network
= argv
[idx
]->arg
;
10311 vty_out(vty
, "Unable to figure out Network\n");
10312 return CMD_WARNING
;
10315 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
10316 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10318 #endif /* KEEP_OLD_VPN_COMMANDS */
10320 DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix
,
10321 show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
,
10322 "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
10328 "Display information about all EVPN NLRIs\n"
10329 "Network in the BGP routing table to display\n"
10330 "Network in the BGP routing table to display\n"
10334 char *network
= NULL
;
10336 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
10337 network
= argv
[idx
]->arg
;
10338 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
10339 network
= argv
[idx
]->arg
;
10341 vty_out(vty
, "Unable to figure out Network\n");
10342 return CMD_WARNING
;
10344 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
, 0,
10345 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10348 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10349 safi_t safi
, enum bgp_show_adj_route_type type
,
10350 const char *rmap_name
, bool use_json
,
10353 struct bgp_table
*table
;
10354 struct bgp_adj_in
*ain
;
10355 struct bgp_adj_out
*adj
;
10356 unsigned long output_count
;
10357 unsigned long filtered_count
;
10358 struct bgp_node
*rn
;
10364 struct update_subgroup
*subgrp
;
10365 json_object
*json_scode
= NULL
;
10366 json_object
*json_ocode
= NULL
;
10367 json_object
*json_ar
= NULL
;
10368 struct peer_af
*paf
;
10369 bool route_filtered
;
10372 json_scode
= json_object_new_object();
10373 json_ocode
= json_object_new_object();
10374 json_ar
= json_object_new_object();
10376 json_object_string_add(json_scode
, "suppressed", "s");
10377 json_object_string_add(json_scode
, "damped", "d");
10378 json_object_string_add(json_scode
, "history", "h");
10379 json_object_string_add(json_scode
, "valid", "*");
10380 json_object_string_add(json_scode
, "best", ">");
10381 json_object_string_add(json_scode
, "multipath", "=");
10382 json_object_string_add(json_scode
, "internal", "i");
10383 json_object_string_add(json_scode
, "ribFailure", "r");
10384 json_object_string_add(json_scode
, "stale", "S");
10385 json_object_string_add(json_scode
, "removed", "R");
10387 json_object_string_add(json_ocode
, "igp", "i");
10388 json_object_string_add(json_ocode
, "egp", "e");
10389 json_object_string_add(json_ocode
, "incomplete", "?");
10396 json_object_string_add(json
, "alert", "no BGP");
10397 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10398 json_object_free(json
);
10400 vty_out(vty
, "%% No bgp\n");
10404 table
= bgp
->rib
[afi
][safi
];
10406 output_count
= filtered_count
= 0;
10407 subgrp
= peer_subgroup(peer
, afi
, safi
);
10409 if (type
== bgp_show_adj_route_advertised
&& subgrp
10410 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
10412 json_object_int_add(json
, "bgpTableVersion",
10414 json_object_string_add(json
, "bgpLocalRouterId",
10415 inet_ntoa(bgp
->router_id
));
10416 json_object_object_add(json
, "bgpStatusCodes",
10418 json_object_object_add(json
, "bgpOriginCodes",
10420 json_object_string_add(
10421 json
, "bgpOriginatingDefaultNetwork",
10422 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10424 vty_out(vty
, "BGP table version is %" PRIu64
10425 ", local router ID is %s, vrf id ",
10426 table
->version
, inet_ntoa(bgp
->router_id
));
10427 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10428 vty_out(vty
, "%s", VRFID_NONE_STR
);
10430 vty_out(vty
, "%u", bgp
->vrf_id
);
10431 vty_out(vty
, "\n");
10432 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
10433 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
10434 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
10436 vty_out(vty
, "Originating default network %s\n\n",
10437 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
10442 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
10443 if (type
== bgp_show_adj_route_received
10444 || type
== bgp_show_adj_route_filtered
) {
10445 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
10446 if (ain
->peer
!= peer
|| !ain
->attr
)
10451 json_object_int_add(
10452 json
, "bgpTableVersion",
10454 json_object_string_add(
10456 "bgpLocalRouterId",
10459 json_object_object_add(
10460 json
, "bgpStatusCodes",
10462 json_object_object_add(
10463 json
, "bgpOriginCodes",
10467 "BGP table version is 0, local router ID is %s, vrf id ",
10470 if (bgp
->vrf_id
== VRF_UNKNOWN
)
10476 vty_out(vty
, "\n");
10478 BGP_SHOW_SCODE_HEADER
);
10480 BGP_SHOW_NCODE_HEADER
);
10482 BGP_SHOW_OCODE_HEADER
);
10488 vty_out(vty
, BGP_SHOW_HEADER
);
10492 bgp_attr_dup(&attr
, ain
->attr
);
10493 route_filtered
= false;
10495 /* Filter prefix using distribute list,
10496 * filter list or prefix list
10498 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
10499 safi
)) == FILTER_DENY
)
10500 route_filtered
= true;
10502 /* Filter prefix using route-map */
10503 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
10504 afi
, safi
, rmap_name
);
10506 if (type
== bgp_show_adj_route_filtered
&&
10507 !route_filtered
&& ret
!= RMAP_DENY
) {
10508 bgp_attr_undup(&attr
, ain
->attr
);
10512 if (type
== bgp_show_adj_route_received
&&
10513 (route_filtered
|| ret
== RMAP_DENY
))
10516 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
10517 use_json
, json_ar
);
10518 bgp_attr_undup(&attr
, ain
->attr
);
10521 } else if (type
== bgp_show_adj_route_advertised
) {
10522 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
10523 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
10524 if (paf
->peer
!= peer
|| !adj
->attr
)
10529 json_object_int_add(
10533 json_object_string_add(
10535 "bgpLocalRouterId",
10538 json_object_object_add(
10542 json_object_object_add(
10548 "BGP table version is %" PRIu64
10549 ", local router ID is %s, vrf id ",
10562 vty_out(vty
, "\n");
10564 BGP_SHOW_SCODE_HEADER
);
10566 BGP_SHOW_NCODE_HEADER
);
10568 BGP_SHOW_OCODE_HEADER
);
10579 bgp_attr_dup(&attr
, adj
->attr
);
10580 ret
= bgp_output_modifier(
10581 peer
, &rn
->p
, &attr
, afi
, safi
,
10584 if (ret
!= RMAP_DENY
) {
10585 route_vty_out_tmp(vty
, &rn
->p
,
10594 bgp_attr_undup(&attr
, adj
->attr
);
10600 json_object_object_add(json
, "advertisedRoutes", json_ar
);
10601 json_object_int_add(json
, "totalPrefixCounter", output_count
);
10602 json_object_int_add(json
, "filteredPrefixCounter",
10605 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10606 json
, JSON_C_TO_STRING_PRETTY
));
10607 json_object_free(json
);
10608 } else if (output_count
> 0) {
10609 if (filtered_count
> 0)
10611 "\nTotal number of prefixes %ld (%ld filtered)\n",
10612 output_count
, filtered_count
);
10614 vty_out(vty
, "\nTotal number of prefixes %ld\n",
10619 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10620 safi_t safi
, enum bgp_show_adj_route_type type
,
10621 const char *rmap_name
, bool use_json
)
10623 json_object
*json
= NULL
;
10626 json
= json_object_new_object();
10628 /* labeled-unicast routes live in the unicast table */
10629 if (safi
== SAFI_LABELED_UNICAST
)
10630 safi
= SAFI_UNICAST
;
10632 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10634 json_object_string_add(
10636 "No such neighbor or address family");
10637 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10638 json_object_free(json
);
10640 vty_out(vty
, "%% No such neighbor or address family\n");
10642 return CMD_WARNING
;
10645 if ((type
== bgp_show_adj_route_received
10646 || type
== bgp_show_adj_route_filtered
)
10647 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
10648 PEER_FLAG_SOFT_RECONFIG
)) {
10650 json_object_string_add(
10652 "Inbound soft reconfiguration not enabled");
10653 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10654 json_object_free(json
);
10657 "%% Inbound soft reconfiguration not enabled\n");
10659 return CMD_WARNING
;
10662 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
10664 return CMD_SUCCESS
;
10667 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
10668 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
10669 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10670 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
10674 BGP_INSTANCE_HELP_STR
10676 BGP_SAFI_WITH_LABEL_HELP_STR
10677 "Detailed information on TCP and BGP neighbor connections\n"
10678 "Neighbor to display information about\n"
10679 "Neighbor to display information about\n"
10680 "Neighbor on BGP configured interface\n"
10681 "Display the routes advertised to a BGP neighbor\n"
10682 "Display the received routes from neighbor\n"
10683 "Display the filtered routes received from neighbor\n"
10684 "Route-map to modify the attributes\n"
10685 "Name of the route map\n"
10688 afi_t afi
= AFI_IP6
;
10689 safi_t safi
= SAFI_UNICAST
;
10690 char *rmap_name
= NULL
;
10691 char *peerstr
= NULL
;
10692 struct bgp
*bgp
= NULL
;
10694 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
10696 bool uj
= use_json(argc
, argv
);
10701 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10704 return CMD_WARNING
;
10706 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10707 argv_find(argv
, argc
, "neighbors", &idx
);
10708 peerstr
= argv
[++idx
]->arg
;
10710 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10712 return CMD_WARNING
;
10714 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
10715 type
= bgp_show_adj_route_advertised
;
10716 else if (argv_find(argv
, argc
, "received-routes", &idx
))
10717 type
= bgp_show_adj_route_received
;
10718 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
10719 type
= bgp_show_adj_route_filtered
;
10721 if (argv_find(argv
, argc
, "route-map", &idx
))
10722 rmap_name
= argv
[++idx
]->arg
;
10724 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
10727 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
10728 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
10729 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
10735 "Address Family modifier\n"
10736 "Detailed information on TCP and BGP neighbor connections\n"
10737 "Neighbor to display information about\n"
10738 "Neighbor to display information about\n"
10739 "Neighbor on BGP configured interface\n"
10740 "Display information received from a BGP neighbor\n"
10741 "Display the prefixlist filter\n"
10744 afi_t afi
= AFI_IP6
;
10745 safi_t safi
= SAFI_UNICAST
;
10746 char *peerstr
= NULL
;
10749 union sockunion su
;
10755 /* show [ip] bgp */
10756 if (argv_find(argv
, argc
, "ip", &idx
))
10758 /* [<ipv4|ipv6> [unicast]] */
10759 if (argv_find(argv
, argc
, "ipv4", &idx
))
10761 if (argv_find(argv
, argc
, "ipv6", &idx
))
10763 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10764 argv_find(argv
, argc
, "neighbors", &idx
);
10765 peerstr
= argv
[++idx
]->arg
;
10767 bool uj
= use_json(argc
, argv
);
10769 ret
= str2sockunion(peerstr
, &su
);
10771 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
10774 vty_out(vty
, "{}\n");
10777 "%% Malformed address or name: %s\n",
10779 return CMD_WARNING
;
10782 peer
= peer_lookup(NULL
, &su
);
10785 vty_out(vty
, "{}\n");
10787 vty_out(vty
, "No peer\n");
10788 return CMD_WARNING
;
10792 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
10793 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
10796 vty_out(vty
, "Address Family: %s\n",
10797 afi_safi_print(afi
, safi
));
10798 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
10801 vty_out(vty
, "{}\n");
10803 vty_out(vty
, "No functional output\n");
10806 return CMD_SUCCESS
;
10809 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
10810 afi_t afi
, safi_t safi
,
10811 enum bgp_show_type type
, bool use_json
)
10813 /* labeled-unicast routes live in the unicast table */
10814 if (safi
== SAFI_LABELED_UNICAST
)
10815 safi
= SAFI_UNICAST
;
10817 if (!peer
|| !peer
->afc
[afi
][safi
]) {
10819 json_object
*json_no
= NULL
;
10820 json_no
= json_object_new_object();
10821 json_object_string_add(
10822 json_no
, "warning",
10823 "No such neighbor or address family");
10824 vty_out(vty
, "%s\n",
10825 json_object_to_json_string(json_no
));
10826 json_object_free(json_no
);
10828 vty_out(vty
, "%% No such neighbor or address family\n");
10829 return CMD_WARNING
;
10832 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
10835 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
10836 show_ip_bgp_flowspec_routes_detailed_cmd
,
10837 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
10841 BGP_INSTANCE_HELP_STR
10844 "Detailed information on flowspec entries\n"
10847 afi_t afi
= AFI_IP
;
10848 safi_t safi
= SAFI_UNICAST
;
10849 struct bgp
*bgp
= NULL
;
10851 bool uj
= use_json(argc
, argv
);
10856 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10859 return CMD_WARNING
;
10861 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
10864 DEFUN (show_ip_bgp_neighbor_routes
,
10865 show_ip_bgp_neighbor_routes_cmd
,
10866 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
10867 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
10871 BGP_INSTANCE_HELP_STR
10873 BGP_SAFI_WITH_LABEL_HELP_STR
10874 "Detailed information on TCP and BGP neighbor connections\n"
10875 "Neighbor to display information about\n"
10876 "Neighbor to display information about\n"
10877 "Neighbor on BGP configured interface\n"
10878 "Display flap statistics of the routes learned from neighbor\n"
10879 "Display the dampened routes received from neighbor\n"
10880 "Display routes learned from neighbor\n"
10883 char *peerstr
= NULL
;
10884 struct bgp
*bgp
= NULL
;
10885 afi_t afi
= AFI_IP6
;
10886 safi_t safi
= SAFI_UNICAST
;
10888 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
10890 bool uj
= use_json(argc
, argv
);
10895 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10898 return CMD_WARNING
;
10900 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
10901 argv_find(argv
, argc
, "neighbors", &idx
);
10902 peerstr
= argv
[++idx
]->arg
;
10904 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
10906 return CMD_WARNING
;
10908 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10909 sh_type
= bgp_show_type_flap_neighbor
;
10910 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
10911 sh_type
= bgp_show_type_damp_neighbor
;
10912 else if (argv_find(argv
, argc
, "routes", &idx
))
10913 sh_type
= bgp_show_type_neighbor
;
10915 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
10918 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
10920 struct bgp_distance
{
10921 /* Distance value for the IP source prefix. */
10924 /* Name of the access-list to be matched. */
10928 DEFUN (show_bgp_afi_vpn_rd_route
,
10929 show_bgp_afi_vpn_rd_route_cmd
,
10930 "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]",
10934 "Address Family modifier\n"
10935 "Display information for a route distinguisher\n"
10936 "Route Distinguisher\n"
10937 "Network in the BGP routing table to display\n"
10938 "Network in the BGP routing table to display\n"
10942 struct prefix_rd prd
;
10943 afi_t afi
= AFI_MAX
;
10946 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
10947 vty_out(vty
, "%% Malformed Address Family\n");
10948 return CMD_WARNING
;
10951 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
10953 vty_out(vty
, "%% Malformed Route Distinguisher\n");
10954 return CMD_WARNING
;
10957 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
10958 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
10961 static struct bgp_distance
*bgp_distance_new(void)
10963 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
10966 static void bgp_distance_free(struct bgp_distance
*bdistance
)
10968 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
10971 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
10972 const char *ip_str
, const char *access_list_str
)
10979 struct bgp_node
*rn
;
10980 struct bgp_distance
*bdistance
;
10982 afi
= bgp_node_afi(vty
);
10983 safi
= bgp_node_safi(vty
);
10985 ret
= str2prefix(ip_str
, &p
);
10987 vty_out(vty
, "Malformed prefix\n");
10988 return CMD_WARNING_CONFIG_FAILED
;
10991 distance
= atoi(distance_str
);
10993 /* Get BGP distance node. */
10994 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
10995 bdistance
= bgp_distance_get_node(rn
);
10997 bgp_unlock_node(rn
);
10999 bdistance
= bgp_distance_new();
11000 bgp_distance_set_node_info(rn
, bdistance
);
11003 /* Set distance value. */
11004 bdistance
->distance
= distance
;
11006 /* Reset access-list configuration. */
11007 if (bdistance
->access_list
) {
11008 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11009 bdistance
->access_list
= NULL
;
11011 if (access_list_str
)
11012 bdistance
->access_list
=
11013 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11015 return CMD_SUCCESS
;
11018 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11019 const char *ip_str
, const char *access_list_str
)
11026 struct bgp_node
*rn
;
11027 struct bgp_distance
*bdistance
;
11029 afi
= bgp_node_afi(vty
);
11030 safi
= bgp_node_safi(vty
);
11032 ret
= str2prefix(ip_str
, &p
);
11034 vty_out(vty
, "Malformed prefix\n");
11035 return CMD_WARNING_CONFIG_FAILED
;
11038 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11039 (struct prefix
*)&p
);
11041 vty_out(vty
, "Can't find specified prefix\n");
11042 return CMD_WARNING_CONFIG_FAILED
;
11045 bdistance
= bgp_distance_get_node(rn
);
11046 distance
= atoi(distance_str
);
11048 if (bdistance
->distance
!= distance
) {
11049 vty_out(vty
, "Distance does not match configured\n");
11050 return CMD_WARNING_CONFIG_FAILED
;
11053 if (bdistance
->access_list
)
11054 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11055 bgp_distance_free(bdistance
);
11058 bgp_unlock_node(rn
);
11059 bgp_unlock_node(rn
);
11061 return CMD_SUCCESS
;
11064 /* Apply BGP information to distance method. */
11065 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11066 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11068 struct bgp_node
*rn
;
11071 struct bgp_distance
*bdistance
;
11072 struct access_list
*alist
;
11073 struct bgp_static
*bgp_static
;
11078 peer
= pinfo
->peer
;
11080 /* Check source address. */
11081 sockunion2hostprefix(&peer
->su
, &q
);
11082 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11084 bdistance
= bgp_distance_get_node(rn
);
11085 bgp_unlock_node(rn
);
11087 if (bdistance
->access_list
) {
11088 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11090 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11091 return bdistance
->distance
;
11093 return bdistance
->distance
;
11096 /* Backdoor check. */
11097 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11099 bgp_static
= bgp_static_get_node_info(rn
);
11100 bgp_unlock_node(rn
);
11102 if (bgp_static
->backdoor
) {
11103 if (bgp
->distance_local
[afi
][safi
])
11104 return bgp
->distance_local
[afi
][safi
];
11106 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11110 if (peer
->sort
== BGP_PEER_EBGP
) {
11111 if (bgp
->distance_ebgp
[afi
][safi
])
11112 return bgp
->distance_ebgp
[afi
][safi
];
11113 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11115 if (bgp
->distance_ibgp
[afi
][safi
])
11116 return bgp
->distance_ibgp
[afi
][safi
];
11117 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11121 DEFUN (bgp_distance
,
11123 "distance bgp (1-255) (1-255) (1-255)",
11124 "Define an administrative distance\n"
11126 "Distance for routes external to the AS\n"
11127 "Distance for routes internal to the AS\n"
11128 "Distance for local routes\n")
11130 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11131 int idx_number
= 2;
11132 int idx_number_2
= 3;
11133 int idx_number_3
= 4;
11137 afi
= bgp_node_afi(vty
);
11138 safi
= bgp_node_safi(vty
);
11140 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11141 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11142 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11143 return CMD_SUCCESS
;
11146 DEFUN (no_bgp_distance
,
11147 no_bgp_distance_cmd
,
11148 "no distance bgp [(1-255) (1-255) (1-255)]",
11150 "Define an administrative distance\n"
11152 "Distance for routes external to the AS\n"
11153 "Distance for routes internal to the AS\n"
11154 "Distance for local routes\n")
11156 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11160 afi
= bgp_node_afi(vty
);
11161 safi
= bgp_node_safi(vty
);
11163 bgp
->distance_ebgp
[afi
][safi
] = 0;
11164 bgp
->distance_ibgp
[afi
][safi
] = 0;
11165 bgp
->distance_local
[afi
][safi
] = 0;
11166 return CMD_SUCCESS
;
11170 DEFUN (bgp_distance_source
,
11171 bgp_distance_source_cmd
,
11172 "distance (1-255) A.B.C.D/M",
11173 "Define an administrative distance\n"
11174 "Administrative distance\n"
11175 "IP source prefix\n")
11177 int idx_number
= 1;
11178 int idx_ipv4_prefixlen
= 2;
11179 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11180 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11181 return CMD_SUCCESS
;
11184 DEFUN (no_bgp_distance_source
,
11185 no_bgp_distance_source_cmd
,
11186 "no distance (1-255) A.B.C.D/M",
11188 "Define an administrative distance\n"
11189 "Administrative distance\n"
11190 "IP source prefix\n")
11192 int idx_number
= 2;
11193 int idx_ipv4_prefixlen
= 3;
11194 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11195 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11196 return CMD_SUCCESS
;
11199 DEFUN (bgp_distance_source_access_list
,
11200 bgp_distance_source_access_list_cmd
,
11201 "distance (1-255) A.B.C.D/M WORD",
11202 "Define an administrative distance\n"
11203 "Administrative distance\n"
11204 "IP source prefix\n"
11205 "Access list name\n")
11207 int idx_number
= 1;
11208 int idx_ipv4_prefixlen
= 2;
11210 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11211 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11212 return CMD_SUCCESS
;
11215 DEFUN (no_bgp_distance_source_access_list
,
11216 no_bgp_distance_source_access_list_cmd
,
11217 "no distance (1-255) A.B.C.D/M WORD",
11219 "Define an administrative distance\n"
11220 "Administrative distance\n"
11221 "IP source prefix\n"
11222 "Access list name\n")
11224 int idx_number
= 2;
11225 int idx_ipv4_prefixlen
= 3;
11227 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
11228 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
11229 return CMD_SUCCESS
;
11232 DEFUN (ipv6_bgp_distance_source
,
11233 ipv6_bgp_distance_source_cmd
,
11234 "distance (1-255) X:X::X:X/M",
11235 "Define an administrative distance\n"
11236 "Administrative distance\n"
11237 "IP source prefix\n")
11239 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
11240 return CMD_SUCCESS
;
11243 DEFUN (no_ipv6_bgp_distance_source
,
11244 no_ipv6_bgp_distance_source_cmd
,
11245 "no distance (1-255) X:X::X:X/M",
11247 "Define an administrative distance\n"
11248 "Administrative distance\n"
11249 "IP source prefix\n")
11251 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
11252 return CMD_SUCCESS
;
11255 DEFUN (ipv6_bgp_distance_source_access_list
,
11256 ipv6_bgp_distance_source_access_list_cmd
,
11257 "distance (1-255) X:X::X:X/M WORD",
11258 "Define an administrative distance\n"
11259 "Administrative distance\n"
11260 "IP source prefix\n"
11261 "Access list name\n")
11263 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
11264 return CMD_SUCCESS
;
11267 DEFUN (no_ipv6_bgp_distance_source_access_list
,
11268 no_ipv6_bgp_distance_source_access_list_cmd
,
11269 "no distance (1-255) X:X::X:X/M WORD",
11271 "Define an administrative distance\n"
11272 "Administrative distance\n"
11273 "IP source prefix\n"
11274 "Access list name\n")
11276 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
11277 return CMD_SUCCESS
;
11280 DEFUN (bgp_damp_set
,
11282 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11283 "BGP Specific commands\n"
11284 "Enable route-flap dampening\n"
11285 "Half-life time for the penalty\n"
11286 "Value to start reusing a route\n"
11287 "Value to start suppressing a route\n"
11288 "Maximum duration to suppress a stable route\n")
11290 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11291 int idx_half_life
= 2;
11293 int idx_suppress
= 4;
11294 int idx_max_suppress
= 5;
11295 int half
= DEFAULT_HALF_LIFE
* 60;
11296 int reuse
= DEFAULT_REUSE
;
11297 int suppress
= DEFAULT_SUPPRESS
;
11298 int max
= 4 * half
;
11301 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11302 reuse
= atoi(argv
[idx_reuse
]->arg
);
11303 suppress
= atoi(argv
[idx_suppress
]->arg
);
11304 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
11305 } else if (argc
== 3) {
11306 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
11310 if (suppress
< reuse
) {
11312 "Suppress value cannot be less than reuse value \n");
11316 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
11317 reuse
, suppress
, max
);
11320 DEFUN (bgp_damp_unset
,
11321 bgp_damp_unset_cmd
,
11322 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
11324 "BGP Specific commands\n"
11325 "Enable route-flap dampening\n"
11326 "Half-life time for the penalty\n"
11327 "Value to start reusing a route\n"
11328 "Value to start suppressing a route\n"
11329 "Maximum duration to suppress a stable route\n")
11331 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11332 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
11335 /* Display specified route of BGP table. */
11336 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
11337 const char *ip_str
, afi_t afi
, safi_t safi
,
11338 struct prefix_rd
*prd
, int prefix_check
)
11341 struct prefix match
;
11342 struct bgp_node
*rn
;
11343 struct bgp_node
*rm
;
11344 struct bgp_path_info
*pi
;
11345 struct bgp_path_info
*pi_temp
;
11347 struct bgp_table
*table
;
11349 /* BGP structure lookup. */
11351 bgp
= bgp_lookup_by_name(view_name
);
11353 vty_out(vty
, "%% Can't find BGP instance %s\n",
11355 return CMD_WARNING
;
11358 bgp
= bgp_get_default();
11360 vty_out(vty
, "%% No BGP process is configured\n");
11361 return CMD_WARNING
;
11365 /* Check IP address argument. */
11366 ret
= str2prefix(ip_str
, &match
);
11368 vty_out(vty
, "%% address is malformed\n");
11369 return CMD_WARNING
;
11372 match
.family
= afi2family(afi
);
11374 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
11375 || (safi
== SAFI_EVPN
)) {
11376 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
11377 rn
= bgp_route_next(rn
)) {
11378 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
11380 if ((table
= rn
->info
) == NULL
)
11382 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
11386 || rm
->p
.prefixlen
== match
.prefixlen
) {
11389 if (pi
->extra
&& pi
->extra
->damp_info
) {
11390 pi_temp
= pi
->next
;
11391 bgp_damp_info_free(
11392 pi
->extra
->damp_info
,
11400 bgp_unlock_node(rm
);
11403 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
11406 || rn
->p
.prefixlen
== match
.prefixlen
) {
11409 if (pi
->extra
&& pi
->extra
->damp_info
) {
11410 pi_temp
= pi
->next
;
11411 bgp_damp_info_free(
11412 pi
->extra
->damp_info
,
11420 bgp_unlock_node(rn
);
11424 return CMD_SUCCESS
;
11427 DEFUN (clear_ip_bgp_dampening
,
11428 clear_ip_bgp_dampening_cmd
,
11429 "clear ip bgp dampening",
11433 "Clear route flap dampening information\n")
11435 bgp_damp_info_clean();
11436 return CMD_SUCCESS
;
11439 DEFUN (clear_ip_bgp_dampening_prefix
,
11440 clear_ip_bgp_dampening_prefix_cmd
,
11441 "clear ip bgp dampening A.B.C.D/M",
11445 "Clear route flap dampening information\n"
11448 int idx_ipv4_prefixlen
= 4;
11449 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
11450 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
11453 DEFUN (clear_ip_bgp_dampening_address
,
11454 clear_ip_bgp_dampening_address_cmd
,
11455 "clear ip bgp dampening A.B.C.D",
11459 "Clear route flap dampening information\n"
11460 "Network to clear damping information\n")
11463 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
11464 SAFI_UNICAST
, NULL
, 0);
11467 DEFUN (clear_ip_bgp_dampening_address_mask
,
11468 clear_ip_bgp_dampening_address_mask_cmd
,
11469 "clear ip bgp dampening A.B.C.D A.B.C.D",
11473 "Clear route flap dampening information\n"
11474 "Network to clear damping information\n"
11478 int idx_ipv4_2
= 5;
11480 char prefix_str
[BUFSIZ
];
11482 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
11485 vty_out(vty
, "%% Inconsistent address and mask\n");
11486 return CMD_WARNING
;
11489 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
11493 static void show_bgp_peerhash_entry(struct hash_backet
*backet
, void *arg
)
11495 struct vty
*vty
= arg
;
11496 struct peer
*peer
= backet
->data
;
11497 char buf
[SU_ADDRSTRLEN
];
11499 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
11500 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
11503 DEFUN (show_bgp_peerhash
,
11504 show_bgp_peerhash_cmd
,
11505 "show bgp peerhash",
11508 "Display information about the BGP peerhash\n")
11510 struct list
*instances
= bm
->bgp
;
11511 struct listnode
*node
;
11514 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
11515 vty_out(vty
, "BGP: %s\n", bgp
->name
);
11516 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
11520 return CMD_SUCCESS
;
11523 /* also used for encap safi */
11524 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
11525 afi_t afi
, safi_t safi
)
11527 struct bgp_node
*prn
;
11528 struct bgp_node
*rn
;
11529 struct bgp_table
*table
;
11531 struct prefix_rd
*prd
;
11532 struct bgp_static
*bgp_static
;
11533 mpls_label_t label
;
11534 char buf
[SU_ADDRSTRLEN
];
11535 char rdbuf
[RD_ADDRSTRLEN
];
11537 /* Network configuration. */
11538 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11539 prn
= bgp_route_next(prn
)) {
11540 if ((table
= prn
->info
) == NULL
)
11543 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11544 bgp_static
= bgp_static_get_node_info(rn
);
11545 if (bgp_static
== NULL
)
11549 prd
= (struct prefix_rd
*)&prn
->p
;
11551 /* "network" configuration display. */
11552 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11553 label
= decode_label(&bgp_static
->label
);
11555 vty_out(vty
, " network %s/%d rd %s",
11556 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11558 p
->prefixlen
, rdbuf
);
11559 if (safi
== SAFI_MPLS_VPN
)
11560 vty_out(vty
, " label %u", label
);
11562 if (bgp_static
->rmap
.name
)
11563 vty_out(vty
, " route-map %s",
11564 bgp_static
->rmap
.name
);
11566 if (bgp_static
->backdoor
)
11567 vty_out(vty
, " backdoor");
11569 vty_out(vty
, "\n");
11574 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
11575 afi_t afi
, safi_t safi
)
11577 struct bgp_node
*prn
;
11578 struct bgp_node
*rn
;
11579 struct bgp_table
*table
;
11581 struct prefix_rd
*prd
;
11582 struct bgp_static
*bgp_static
;
11583 char buf
[PREFIX_STRLEN
* 2];
11584 char buf2
[SU_ADDRSTRLEN
];
11585 char rdbuf
[RD_ADDRSTRLEN
];
11587 /* Network configuration. */
11588 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
11589 prn
= bgp_route_next(prn
)) {
11590 if ((table
= prn
->info
) == NULL
)
11593 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11594 bgp_static
= bgp_static_get_node_info(rn
);
11595 if (bgp_static
== NULL
)
11598 char *macrouter
= NULL
;
11601 if (bgp_static
->router_mac
)
11602 macrouter
= prefix_mac2str(
11603 bgp_static
->router_mac
, NULL
, 0);
11604 if (bgp_static
->eth_s_id
)
11605 esi
= esi2str(bgp_static
->eth_s_id
);
11607 prd
= (struct prefix_rd
*)&prn
->p
;
11609 /* "network" configuration display. */
11610 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
11611 if (p
->u
.prefix_evpn
.route_type
== 5) {
11612 char local_buf
[PREFIX_STRLEN
];
11613 uint8_t family
= is_evpn_prefix_ipaddr_v4((
11614 struct prefix_evpn
*)p
)
11618 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
11619 local_buf
, PREFIX_STRLEN
);
11620 sprintf(buf
, "%s/%u", local_buf
,
11621 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
11623 prefix2str(p
, buf
, sizeof(buf
));
11626 if (bgp_static
->gatewayIp
.family
== AF_INET
11627 || bgp_static
->gatewayIp
.family
== AF_INET6
)
11628 inet_ntop(bgp_static
->gatewayIp
.family
,
11629 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
11632 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
11634 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
11635 decode_label(&bgp_static
->label
), esi
, buf2
,
11639 XFREE(MTYPE_TMP
, macrouter
);
11641 XFREE(MTYPE_TMP
, esi
);
11646 /* Configuration of static route announcement and aggregate
11648 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11651 struct bgp_node
*rn
;
11653 struct bgp_static
*bgp_static
;
11654 struct bgp_aggregate
*bgp_aggregate
;
11655 char buf
[SU_ADDRSTRLEN
];
11657 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
11658 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
11662 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
11663 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
11667 /* Network configuration. */
11668 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
11669 rn
= bgp_route_next(rn
)) {
11670 bgp_static
= bgp_static_get_node_info(rn
);
11671 if (bgp_static
== NULL
)
11676 /* "network" configuration display. */
11677 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11678 uint32_t destination
;
11679 struct in_addr netmask
;
11681 destination
= ntohl(p
->u
.prefix4
.s_addr
);
11682 masklen2ip(p
->prefixlen
, &netmask
);
11683 vty_out(vty
, " network %s",
11684 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11687 if ((IN_CLASSC(destination
) && p
->prefixlen
== 24)
11688 || (IN_CLASSB(destination
) && p
->prefixlen
== 16)
11689 || (IN_CLASSA(destination
) && p
->prefixlen
== 8)
11690 || p
->u
.prefix4
.s_addr
== 0) {
11691 /* Natural mask is not display. */
11693 vty_out(vty
, " mask %s", inet_ntoa(netmask
));
11695 vty_out(vty
, " network %s/%d",
11696 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11701 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
11702 vty_out(vty
, " label-index %u",
11703 bgp_static
->label_index
);
11705 if (bgp_static
->rmap
.name
)
11706 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
11708 if (bgp_static
->backdoor
)
11709 vty_out(vty
, " backdoor");
11711 vty_out(vty
, "\n");
11714 /* Aggregate-address configuration. */
11715 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
11716 rn
= bgp_route_next(rn
)) {
11717 bgp_aggregate
= bgp_aggregate_get_node_info(rn
);
11718 if (bgp_aggregate
== NULL
)
11723 if (bgp_option_check(BGP_OPT_CONFIG_CISCO
) && afi
== AFI_IP
) {
11724 struct in_addr netmask
;
11726 masklen2ip(p
->prefixlen
, &netmask
);
11727 vty_out(vty
, " aggregate-address %s %s",
11728 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11730 inet_ntoa(netmask
));
11732 vty_out(vty
, " aggregate-address %s/%d",
11733 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
11738 if (bgp_aggregate
->as_set
)
11739 vty_out(vty
, " as-set");
11741 if (bgp_aggregate
->summary_only
)
11742 vty_out(vty
, " summary-only");
11744 vty_out(vty
, "\n");
11748 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
11751 struct bgp_node
*rn
;
11752 struct bgp_distance
*bdistance
;
11754 /* Distance configuration. */
11755 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
11756 && bgp
->distance_local
[afi
][safi
]
11757 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
11758 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
11759 || bgp
->distance_local
[afi
][safi
]
11760 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
11761 vty_out(vty
, " distance bgp %d %d %d\n",
11762 bgp
->distance_ebgp
[afi
][safi
],
11763 bgp
->distance_ibgp
[afi
][safi
],
11764 bgp
->distance_local
[afi
][safi
]);
11767 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
11768 rn
= bgp_route_next(rn
)) {
11769 bdistance
= bgp_distance_get_node(rn
);
11770 if (bdistance
!= NULL
) {
11771 char buf
[PREFIX_STRLEN
];
11773 vty_out(vty
, " distance %d %s %s\n",
11774 bdistance
->distance
,
11775 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
11776 bdistance
->access_list
? bdistance
->access_list
11782 /* Allocate routing table structure and install commands. */
11783 void bgp_route_init(void)
11788 /* Init BGP distance table. */
11789 FOREACH_AFI_SAFI (afi
, safi
)
11790 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
11792 /* IPv4 BGP commands. */
11793 install_element(BGP_NODE
, &bgp_table_map_cmd
);
11794 install_element(BGP_NODE
, &bgp_network_cmd
);
11795 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
11797 install_element(BGP_NODE
, &aggregate_address_cmd
);
11798 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
11799 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
11800 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
11802 /* IPv4 unicast configuration. */
11803 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
11804 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
11805 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
11807 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
11808 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
11809 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
11810 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
11812 /* IPv4 multicast configuration. */
11813 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
11814 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
11815 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
11816 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
11817 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
11818 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
11819 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
11821 /* IPv4 labeled-unicast configuration. */
11822 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
11823 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
11824 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
11825 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
11826 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
11828 install_element(VIEW_NODE
,
11829 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
11830 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
11831 install_element(VIEW_NODE
,
11832 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
11833 #ifdef KEEP_OLD_VPN_COMMANDS
11834 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
11835 #endif /* KEEP_OLD_VPN_COMMANDS */
11836 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
11837 install_element(VIEW_NODE
,
11838 &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd
);
11840 /* BGP dampening clear commands */
11841 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
11842 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
11844 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
11845 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
11848 install_element(ENABLE_NODE
,
11849 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
11850 #ifdef KEEP_OLD_VPN_COMMANDS
11851 install_element(ENABLE_NODE
,
11852 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
11853 #endif /* KEEP_OLD_VPN_COMMANDS */
11855 /* New config IPv6 BGP commands. */
11856 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
11857 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
11858 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
11860 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
11861 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
11863 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
11865 install_element(BGP_NODE
, &bgp_distance_cmd
);
11866 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
11867 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
11868 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
11869 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
11870 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
11871 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
11872 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
11873 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
11874 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
11875 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
11876 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
11877 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
11878 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
11879 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
11880 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
11881 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
11882 install_element(BGP_IPV4M_NODE
,
11883 &no_bgp_distance_source_access_list_cmd
);
11884 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
11885 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
11886 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
11887 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11888 install_element(BGP_IPV6_NODE
,
11889 &ipv6_bgp_distance_source_access_list_cmd
);
11890 install_element(BGP_IPV6_NODE
,
11891 &no_ipv6_bgp_distance_source_access_list_cmd
);
11892 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
11893 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
11894 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
11895 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
11896 install_element(BGP_IPV6M_NODE
,
11897 &ipv6_bgp_distance_source_access_list_cmd
);
11898 install_element(BGP_IPV6M_NODE
,
11899 &no_ipv6_bgp_distance_source_access_list_cmd
);
11901 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
11902 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
11903 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
11904 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
11906 /* IPv4 Multicast Mode */
11907 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
11908 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
11910 /* Large Communities */
11911 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
11912 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
11914 /* show bgp ipv4 flowspec detailed */
11915 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
11917 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
11920 void bgp_route_finish(void)
11925 FOREACH_AFI_SAFI (afi
, safi
) {
11926 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
11927 bgp_distance_table
[afi
][safi
] = NULL
;