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
35 #include "sockunion.h"
38 #include "workqueue.h"
42 #include "lib_errors.h"
44 #include "bgpd/bgpd.h"
45 #include "bgpd/bgp_table.h"
46 #include "bgpd/bgp_route.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_debug.h"
49 #include "bgpd/bgp_errors.h"
50 #include "bgpd/bgp_aspath.h"
51 #include "bgpd/bgp_regex.h"
52 #include "bgpd/bgp_community.h"
53 #include "bgpd/bgp_ecommunity.h"
54 #include "bgpd/bgp_lcommunity.h"
55 #include "bgpd/bgp_clist.h"
56 #include "bgpd/bgp_packet.h"
57 #include "bgpd/bgp_filter.h"
58 #include "bgpd/bgp_fsm.h"
59 #include "bgpd/bgp_mplsvpn.h"
60 #include "bgpd/bgp_nexthop.h"
61 #include "bgpd/bgp_damp.h"
62 #include "bgpd/bgp_advertise.h"
63 #include "bgpd/bgp_zebra.h"
64 #include "bgpd/bgp_vty.h"
65 #include "bgpd/bgp_mpath.h"
66 #include "bgpd/bgp_nht.h"
67 #include "bgpd/bgp_updgrp.h"
68 #include "bgpd/bgp_label.h"
69 #include "bgpd/bgp_addpath.h"
70 #include "bgpd/bgp_mac.h"
73 #include "bgpd/rfapi/rfapi_backend.h"
74 #include "bgpd/rfapi/vnc_import_bgp.h"
75 #include "bgpd/rfapi/vnc_export_bgp.h"
77 #include "bgpd/bgp_encap_types.h"
78 #include "bgpd/bgp_encap_tlv.h"
79 #include "bgpd/bgp_evpn.h"
80 #include "bgpd/bgp_evpn_vty.h"
81 #include "bgpd/bgp_flowspec.h"
82 #include "bgpd/bgp_flowspec_util.h"
83 #include "bgpd/bgp_pbr.h"
85 #ifndef VTYSH_EXTRACT_PL
86 #include "bgpd/bgp_route_clippy.c"
89 /* Extern from bgp_dump.c */
90 extern const char *bgp_origin_str
[];
91 extern const char *bgp_origin_long_str
[];
94 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
95 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
96 static const struct message bgp_pmsi_tnltype_str
[] = {
97 {PMSI_TNLTYPE_NO_INFO
, PMSI_TNLTYPE_STR_NO_INFO
},
98 {PMSI_TNLTYPE_RSVP_TE_P2MP
, "RSVP-TE P2MP"},
99 {PMSI_TNLTYPE_MLDP_P2MP
, "mLDP P2MP"},
100 {PMSI_TNLTYPE_PIM_SSM
, "PIM-SSM"},
101 {PMSI_TNLTYPE_PIM_SM
, "PIM-SM"},
102 {PMSI_TNLTYPE_PIM_BIDIR
, "PIM-BIDIR"},
103 {PMSI_TNLTYPE_INGR_REPL
, "Ingress Replication"},
104 {PMSI_TNLTYPE_MLDP_MP2MP
, "mLDP MP2MP"},
108 #define VRFID_NONE_STR "-"
110 DEFINE_HOOK(bgp_process
,
111 (struct bgp
*bgp
, afi_t afi
, safi_t safi
,
112 struct bgp_node
*bn
, struct peer
*peer
, bool withdraw
),
113 (bgp
, afi
, safi
, bn
, peer
, withdraw
))
116 struct bgp_node
*bgp_afi_node_get(struct bgp_table
*table
, afi_t afi
,
117 safi_t safi
, struct prefix
*p
,
118 struct prefix_rd
*prd
)
121 struct bgp_node
*prn
= NULL
;
127 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
128 || (safi
== SAFI_EVPN
)) {
129 prn
= bgp_node_get(table
, (struct prefix
*)prd
);
131 if (!bgp_node_has_bgp_path_info_data(prn
))
132 bgp_node_set_bgp_table_info(
133 prn
, bgp_table_init(table
->bgp
, afi
, safi
));
135 bgp_unlock_node(prn
);
136 table
= bgp_node_get_bgp_table_info(prn
);
139 rn
= bgp_node_get(table
, p
);
141 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
142 || (safi
== SAFI_EVPN
))
148 struct bgp_node
*bgp_afi_node_lookup(struct bgp_table
*table
, afi_t afi
,
149 safi_t safi
, struct prefix
*p
,
150 struct prefix_rd
*prd
)
153 struct bgp_node
*prn
= NULL
;
158 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
159 || (safi
== SAFI_EVPN
)) {
160 prn
= bgp_node_lookup(table
, (struct prefix
*)prd
);
164 if (!bgp_node_has_bgp_path_info_data(prn
)) {
165 bgp_unlock_node(prn
);
169 table
= bgp_node_get_bgp_table_info(prn
);
172 rn
= bgp_node_lookup(table
, p
);
177 /* Allocate bgp_path_info_extra */
178 static struct bgp_path_info_extra
*bgp_path_info_extra_new(void)
180 struct bgp_path_info_extra
*new;
181 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA
,
182 sizeof(struct bgp_path_info_extra
));
183 new->label
[0] = MPLS_INVALID_LABEL
;
185 new->bgp_fs_pbr
= NULL
;
186 new->bgp_fs_iprule
= NULL
;
190 void bgp_path_info_extra_free(struct bgp_path_info_extra
**extra
)
192 struct bgp_path_info_extra
*e
;
194 if (!extra
|| !*extra
)
199 bgp_damp_info_free(e
->damp_info
, 0);
203 struct bgp_path_info
*bpi
= (struct bgp_path_info
*)e
->parent
;
206 /* FIXME: since multiple e may have the same e->parent
207 * and e->parent->net is holding a refcount for each
208 * of them, we need to do some fudging here.
210 * WARNING: if bpi->net->lock drops to 0, bpi may be
211 * freed as well (because bpi->net was holding the
212 * last reference to bpi) => write after free!
216 bpi
= bgp_path_info_lock(bpi
);
217 refcount
= bpi
->net
->lock
- 1;
218 bgp_unlock_node((struct bgp_node
*)bpi
->net
);
221 bgp_path_info_unlock(bpi
);
223 bgp_path_info_unlock(e
->parent
);
228 bgp_unlock(e
->bgp_orig
);
230 if ((*extra
)->bgp_fs_iprule
)
231 list_delete(&((*extra
)->bgp_fs_iprule
));
232 if ((*extra
)->bgp_fs_pbr
)
233 list_delete(&((*extra
)->bgp_fs_pbr
));
234 XFREE(MTYPE_BGP_ROUTE_EXTRA
, *extra
);
239 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
242 struct bgp_path_info_extra
*bgp_path_info_extra_get(struct bgp_path_info
*pi
)
245 pi
->extra
= bgp_path_info_extra_new();
249 /* Free bgp route information. */
250 static void bgp_path_info_free(struct bgp_path_info
*path
)
252 bgp_attr_unintern(&path
->attr
);
254 bgp_unlink_nexthop(path
);
255 bgp_path_info_extra_free(&path
->extra
);
256 bgp_path_info_mpath_free(&path
->mpath
);
258 bgp_addpath_free_info_data(&path
->tx_addpath
,
259 &path
->net
->tx_addpath
);
261 peer_unlock(path
->peer
); /* bgp_path_info peer reference */
263 XFREE(MTYPE_BGP_ROUTE
, path
);
266 struct bgp_path_info
*bgp_path_info_lock(struct bgp_path_info
*path
)
272 struct bgp_path_info
*bgp_path_info_unlock(struct bgp_path_info
*path
)
274 assert(path
&& path
->lock
> 0);
277 if (path
->lock
== 0) {
279 zlog_debug ("%s: unlocked and freeing", __func__
);
280 zlog_backtrace (LOG_DEBUG
);
282 bgp_path_info_free(path
);
289 zlog_debug ("%s: unlocked to 1", __func__
);
290 zlog_backtrace (LOG_DEBUG
);
297 void bgp_path_info_add(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
299 struct bgp_path_info
*top
;
301 top
= bgp_node_get_bgp_path_info(rn
);
307 bgp_node_set_bgp_path_info(rn
, pi
);
309 bgp_path_info_lock(pi
);
311 peer_lock(pi
->peer
); /* bgp_path_info peer reference */
314 /* Do the actual removal of info from RIB, for use by bgp_process
315 completion callback *only* */
316 void bgp_path_info_reap(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
319 pi
->next
->prev
= pi
->prev
;
321 pi
->prev
->next
= pi
->next
;
323 bgp_node_set_bgp_path_info(rn
, pi
->next
);
325 bgp_path_info_mpath_dequeue(pi
);
326 bgp_path_info_unlock(pi
);
330 void bgp_path_info_delete(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
332 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_REMOVED
);
333 /* set of previous already took care of pcount */
334 UNSET_FLAG(pi
->flags
, BGP_PATH_VALID
);
337 /* undo the effects of a previous call to bgp_path_info_delete; typically
338 called when a route is deleted and then quickly re-added before the
339 deletion has been processed */
340 void bgp_path_info_restore(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
342 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_REMOVED
);
343 /* unset of previous already took care of pcount */
344 SET_FLAG(pi
->flags
, BGP_PATH_VALID
);
347 /* Adjust pcount as required */
348 static void bgp_pcount_adjust(struct bgp_node
*rn
, struct bgp_path_info
*pi
)
350 struct bgp_table
*table
;
352 assert(rn
&& bgp_node_table(rn
));
353 assert(pi
&& pi
->peer
&& pi
->peer
->bgp
);
355 table
= bgp_node_table(rn
);
357 if (pi
->peer
== pi
->peer
->bgp
->peer_self
)
360 if (!BGP_PATH_COUNTABLE(pi
)
361 && CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
363 UNSET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
365 /* slight hack, but more robust against errors. */
366 if (pi
->peer
->pcount
[table
->afi
][table
->safi
])
367 pi
->peer
->pcount
[table
->afi
][table
->safi
]--;
369 flog_err(EC_LIB_DEVELOPMENT
,
370 "Asked to decrement 0 prefix count for peer");
371 } else if (BGP_PATH_COUNTABLE(pi
)
372 && !CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
373 SET_FLAG(pi
->flags
, BGP_PATH_COUNTED
);
374 pi
->peer
->pcount
[table
->afi
][table
->safi
]++;
378 static int bgp_label_index_differs(struct bgp_path_info
*pi1
,
379 struct bgp_path_info
*pi2
)
381 return (!(pi1
->attr
->label_index
== pi2
->attr
->label_index
));
384 /* Set/unset bgp_path_info flags, adjusting any other state as needed.
385 * This is here primarily to keep prefix-count in check.
387 void bgp_path_info_set_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
390 SET_FLAG(pi
->flags
, flag
);
392 /* early bath if we know it's not a flag that changes countability state
394 if (!CHECK_FLAG(flag
,
395 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
398 bgp_pcount_adjust(rn
, pi
);
401 void bgp_path_info_unset_flag(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
404 UNSET_FLAG(pi
->flags
, flag
);
406 /* early bath if we know it's not a flag that changes countability state
408 if (!CHECK_FLAG(flag
,
409 BGP_PATH_VALID
| BGP_PATH_HISTORY
| BGP_PATH_REMOVED
))
412 bgp_pcount_adjust(rn
, pi
);
415 /* Get MED value. If MED value is missing and "bgp bestpath
416 missing-as-worst" is specified, treat it as the worst value. */
417 static uint32_t bgp_med_value(struct attr
*attr
, struct bgp
*bgp
)
419 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
422 if (bgp_flag_check(bgp
, BGP_FLAG_MED_MISSING_AS_WORST
))
429 void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info
*pi
, char *buf
)
431 if (pi
->addpath_rx_id
)
432 sprintf(buf
, "path %s (addpath rxid %d)", pi
->peer
->host
,
435 sprintf(buf
, "path %s", pi
->peer
->host
);
438 /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
440 static int bgp_path_info_cmp(struct bgp
*bgp
, struct bgp_path_info
*new,
441 struct bgp_path_info
*exist
, int *paths_eq
,
442 struct bgp_maxpaths_cfg
*mpath_cfg
, int debug
,
443 char *pfx_buf
, afi_t afi
, safi_t safi
,
444 enum bgp_path_selection_reason
*reason
)
446 struct attr
*newattr
, *existattr
;
447 bgp_peer_sort_t new_sort
;
448 bgp_peer_sort_t exist_sort
;
454 uint32_t exist_weight
;
455 uint32_t newm
, existm
;
456 struct in_addr new_id
;
457 struct in_addr exist_id
;
460 int internal_as_route
;
463 char new_buf
[PATH_ADDPATH_STR_BUFFER
];
464 char exist_buf
[PATH_ADDPATH_STR_BUFFER
];
466 uint32_t exist_mm_seq
;
473 *reason
= bgp_path_selection_none
;
475 zlog_debug("%s: new is NULL", pfx_buf
);
480 bgp_path_info_path_with_addpath_rx_str(new, new_buf
);
483 *reason
= bgp_path_selection_first
;
485 zlog_debug("%s: %s is the initial bestpath", pfx_buf
,
491 bgp_path_info_path_with_addpath_rx_str(exist
, exist_buf
);
492 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
493 pfx_buf
, new_buf
, new->flags
, exist_buf
,
498 existattr
= exist
->attr
;
500 /* For EVPN routes, we cannot just go by local vs remote, we have to
501 * look at the MAC mobility sequence number, if present.
503 if (safi
== SAFI_EVPN
) {
504 /* This is an error condition described in RFC 7432 Section
506 * states that in this scenario "the PE MUST alert the operator"
508 * does not state what other action to take. In order to provide
510 * consistency in this scenario we are going to prefer the path
514 if (newattr
->sticky
!= existattr
->sticky
) {
516 prefix2str(&new->net
->p
, pfx_buf
,
518 * PREFIX2STR_BUFFER
);
519 bgp_path_info_path_with_addpath_rx_str(new,
521 bgp_path_info_path_with_addpath_rx_str(
525 if (newattr
->sticky
&& !existattr
->sticky
) {
526 *reason
= bgp_path_selection_evpn_sticky_mac
;
529 "%s: %s wins over %s due to sticky MAC flag",
530 pfx_buf
, new_buf
, exist_buf
);
534 if (!newattr
->sticky
&& existattr
->sticky
) {
535 *reason
= bgp_path_selection_evpn_sticky_mac
;
538 "%s: %s loses to %s due to sticky MAC flag",
539 pfx_buf
, new_buf
, exist_buf
);
544 new_mm_seq
= mac_mobility_seqnum(newattr
);
545 exist_mm_seq
= mac_mobility_seqnum(existattr
);
547 if (new_mm_seq
> exist_mm_seq
) {
548 *reason
= bgp_path_selection_evpn_seq
;
551 "%s: %s wins over %s due to MM seq %u > %u",
552 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
557 if (new_mm_seq
< exist_mm_seq
) {
558 *reason
= bgp_path_selection_evpn_seq
;
561 "%s: %s loses to %s due to MM seq %u < %u",
562 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
568 * if sequence numbers are the same path with the lowest IP
571 nh_cmp
= bgp_path_info_nexthop_cmp(new, exist
);
573 *reason
= bgp_path_selection_evpn_lower_ip
;
576 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
577 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
578 inet_ntoa(new->attr
->nexthop
));
582 *reason
= bgp_path_selection_evpn_lower_ip
;
585 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
586 pfx_buf
, new_buf
, exist_buf
, new_mm_seq
,
587 inet_ntoa(new->attr
->nexthop
));
592 /* 1. Weight check. */
593 new_weight
= newattr
->weight
;
594 exist_weight
= existattr
->weight
;
596 if (new_weight
> exist_weight
) {
597 *reason
= bgp_path_selection_weight
;
599 zlog_debug("%s: %s wins over %s due to weight %d > %d",
600 pfx_buf
, new_buf
, exist_buf
, new_weight
,
605 if (new_weight
< exist_weight
) {
606 *reason
= bgp_path_selection_weight
;
608 zlog_debug("%s: %s loses to %s due to weight %d < %d",
609 pfx_buf
, new_buf
, exist_buf
, new_weight
,
614 /* 2. Local preference check. */
615 new_pref
= exist_pref
= bgp
->default_local_pref
;
617 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
618 new_pref
= newattr
->local_pref
;
619 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
620 exist_pref
= existattr
->local_pref
;
622 if (new_pref
> exist_pref
) {
623 *reason
= bgp_path_selection_local_pref
;
626 "%s: %s wins over %s due to localpref %d > %d",
627 pfx_buf
, new_buf
, exist_buf
, new_pref
,
632 if (new_pref
< exist_pref
) {
633 *reason
= bgp_path_selection_local_pref
;
636 "%s: %s loses to %s due to localpref %d < %d",
637 pfx_buf
, new_buf
, exist_buf
, new_pref
,
642 /* 3. Local route check. We prefer:
644 * - BGP_ROUTE_AGGREGATE
645 * - BGP_ROUTE_REDISTRIBUTE
647 if (!(new->sub_type
== BGP_ROUTE_NORMAL
||
648 new->sub_type
== BGP_ROUTE_IMPORTED
)) {
649 *reason
= bgp_path_selection_local_route
;
652 "%s: %s wins over %s due to preferred BGP_ROUTE type",
653 pfx_buf
, new_buf
, exist_buf
);
657 if (!(exist
->sub_type
== BGP_ROUTE_NORMAL
||
658 exist
->sub_type
== BGP_ROUTE_IMPORTED
)) {
659 *reason
= bgp_path_selection_local_route
;
662 "%s: %s loses to %s due to preferred BGP_ROUTE type",
663 pfx_buf
, new_buf
, exist_buf
);
667 /* 4. AS path length check. */
668 if (!bgp_flag_check(bgp
, BGP_FLAG_ASPATH_IGNORE
)) {
669 int exist_hops
= aspath_count_hops(existattr
->aspath
);
670 int exist_confeds
= aspath_count_confeds(existattr
->aspath
);
672 if (bgp_flag_check(bgp
, BGP_FLAG_ASPATH_CONFED
)) {
675 aspath_hops
= aspath_count_hops(newattr
->aspath
);
676 aspath_hops
+= aspath_count_confeds(newattr
->aspath
);
678 if (aspath_hops
< (exist_hops
+ exist_confeds
)) {
679 *reason
= bgp_path_selection_confed_as_path
;
682 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
683 pfx_buf
, new_buf
, exist_buf
,
685 (exist_hops
+ exist_confeds
));
689 if (aspath_hops
> (exist_hops
+ exist_confeds
)) {
690 *reason
= bgp_path_selection_confed_as_path
;
693 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
694 pfx_buf
, new_buf
, exist_buf
,
696 (exist_hops
+ exist_confeds
));
700 int newhops
= aspath_count_hops(newattr
->aspath
);
702 if (newhops
< exist_hops
) {
703 *reason
= bgp_path_selection_as_path
;
706 "%s: %s wins over %s due to aspath hopcount %d < %d",
707 pfx_buf
, new_buf
, exist_buf
,
708 newhops
, exist_hops
);
712 if (newhops
> exist_hops
) {
713 *reason
= bgp_path_selection_as_path
;
716 "%s: %s loses to %s due to aspath hopcount %d > %d",
717 pfx_buf
, new_buf
, exist_buf
,
718 newhops
, exist_hops
);
724 /* 5. Origin check. */
725 if (newattr
->origin
< existattr
->origin
) {
726 *reason
= bgp_path_selection_origin
;
728 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
729 pfx_buf
, new_buf
, exist_buf
,
730 bgp_origin_long_str
[newattr
->origin
],
731 bgp_origin_long_str
[existattr
->origin
]);
735 if (newattr
->origin
> existattr
->origin
) {
736 *reason
= bgp_path_selection_origin
;
738 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
739 pfx_buf
, new_buf
, exist_buf
,
740 bgp_origin_long_str
[newattr
->origin
],
741 bgp_origin_long_str
[existattr
->origin
]);
746 internal_as_route
= (aspath_count_hops(newattr
->aspath
) == 0
747 && aspath_count_hops(existattr
->aspath
) == 0);
748 confed_as_route
= (aspath_count_confeds(newattr
->aspath
) > 0
749 && aspath_count_confeds(existattr
->aspath
) > 0
750 && aspath_count_hops(newattr
->aspath
) == 0
751 && aspath_count_hops(existattr
->aspath
) == 0);
753 if (bgp_flag_check(bgp
, BGP_FLAG_ALWAYS_COMPARE_MED
)
754 || (bgp_flag_check(bgp
, BGP_FLAG_MED_CONFED
) && confed_as_route
)
755 || aspath_cmp_left(newattr
->aspath
, existattr
->aspath
)
756 || aspath_cmp_left_confed(newattr
->aspath
, existattr
->aspath
)
757 || internal_as_route
) {
758 new_med
= bgp_med_value(new->attr
, bgp
);
759 exist_med
= bgp_med_value(exist
->attr
, bgp
);
761 if (new_med
< exist_med
) {
762 *reason
= bgp_path_selection_med
;
765 "%s: %s wins over %s due to MED %d < %d",
766 pfx_buf
, new_buf
, exist_buf
, new_med
,
771 if (new_med
> exist_med
) {
772 *reason
= bgp_path_selection_med
;
775 "%s: %s loses to %s due to MED %d > %d",
776 pfx_buf
, new_buf
, exist_buf
, new_med
,
782 /* 7. Peer type check. */
783 new_sort
= new->peer
->sort
;
784 exist_sort
= exist
->peer
->sort
;
786 if (new_sort
== BGP_PEER_EBGP
787 && (exist_sort
== BGP_PEER_IBGP
|| exist_sort
== BGP_PEER_CONFED
)) {
788 *reason
= bgp_path_selection_peer
;
791 "%s: %s wins over %s due to eBGP peer > iBGP peer",
792 pfx_buf
, new_buf
, exist_buf
);
796 if (exist_sort
== BGP_PEER_EBGP
797 && (new_sort
== BGP_PEER_IBGP
|| new_sort
== BGP_PEER_CONFED
)) {
798 *reason
= bgp_path_selection_peer
;
801 "%s: %s loses to %s due to iBGP peer < eBGP peer",
802 pfx_buf
, new_buf
, exist_buf
);
806 /* 8. IGP metric check. */
810 newm
= new->extra
->igpmetric
;
812 existm
= exist
->extra
->igpmetric
;
817 "%s: %s wins over %s due to IGP metric %d < %d",
818 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
825 "%s: %s loses to %s due to IGP metric %d > %d",
826 pfx_buf
, new_buf
, exist_buf
, newm
, existm
);
830 /* 9. Same IGP metric. Compare the cluster list length as
831 representative of IGP hops metric. Rewrite the metric value
832 pair (newm, existm) with the cluster list length. Prefer the
833 path with smaller cluster list length. */
834 if (newm
== existm
) {
835 if (peer_sort(new->peer
) == BGP_PEER_IBGP
836 && peer_sort(exist
->peer
) == BGP_PEER_IBGP
837 && (mpath_cfg
== NULL
839 mpath_cfg
->ibgp_flags
,
840 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN
))) {
841 newm
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
842 existm
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
847 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
848 pfx_buf
, new_buf
, exist_buf
,
856 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
857 pfx_buf
, new_buf
, exist_buf
,
864 /* 10. confed-external vs. confed-internal */
865 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
866 if (new_sort
== BGP_PEER_CONFED
867 && exist_sort
== BGP_PEER_IBGP
) {
868 *reason
= bgp_path_selection_confed
;
871 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
872 pfx_buf
, new_buf
, exist_buf
);
876 if (exist_sort
== BGP_PEER_CONFED
877 && new_sort
== BGP_PEER_IBGP
) {
878 *reason
= bgp_path_selection_confed
;
881 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
882 pfx_buf
, new_buf
, exist_buf
);
887 /* 11. Maximum path check. */
888 if (newm
== existm
) {
889 /* If one path has a label but the other does not, do not treat
890 * them as equals for multipath
892 if ((new->extra
&&bgp_is_valid_label(&new->extra
->label
[0]))
894 && bgp_is_valid_label(&exist
->extra
->label
[0]))) {
897 "%s: %s and %s cannot be multipath, one has a label while the other does not",
898 pfx_buf
, new_buf
, exist_buf
);
899 } else if (bgp_flag_check(bgp
,
900 BGP_FLAG_ASPATH_MULTIPATH_RELAX
)) {
903 * For the two paths, all comparison steps till IGP
905 * have succeeded - including AS_PATH hop count. Since
907 * bestpath as-path multipath-relax' knob is on, we
909 * an exact match of AS_PATH. Thus, mark the paths are
911 * That will trigger both these paths to get into the
919 "%s: %s and %s are equal via multipath-relax",
920 pfx_buf
, new_buf
, exist_buf
);
921 } else if (new->peer
->sort
== BGP_PEER_IBGP
) {
922 if (aspath_cmp(new->attr
->aspath
,
923 exist
->attr
->aspath
)) {
928 "%s: %s and %s are equal via matching aspaths",
929 pfx_buf
, new_buf
, exist_buf
);
931 } else if (new->peer
->as
== exist
->peer
->as
) {
936 "%s: %s and %s are equal via same remote-as",
937 pfx_buf
, new_buf
, exist_buf
);
941 * TODO: If unequal cost ibgp multipath is enabled we can
942 * mark the paths as equal here instead of returning
947 "%s: %s wins over %s after IGP metric comparison",
948 pfx_buf
, new_buf
, exist_buf
);
951 "%s: %s loses to %s after IGP metric comparison",
952 pfx_buf
, new_buf
, exist_buf
);
954 *reason
= bgp_path_selection_igp_metric
;
958 /* 12. If both paths are external, prefer the path that was received
959 first (the oldest one). This step minimizes route-flap, since a
960 newer path won't displace an older one, even if it was the
961 preferred route based on the additional decision criteria below. */
962 if (!bgp_flag_check(bgp
, BGP_FLAG_COMPARE_ROUTER_ID
)
963 && new_sort
== BGP_PEER_EBGP
&& exist_sort
== BGP_PEER_EBGP
) {
964 if (CHECK_FLAG(new->flags
, BGP_PATH_SELECTED
)) {
965 *reason
= bgp_path_selection_older
;
968 "%s: %s wins over %s due to oldest external",
969 pfx_buf
, new_buf
, exist_buf
);
973 if (CHECK_FLAG(exist
->flags
, BGP_PATH_SELECTED
)) {
974 *reason
= bgp_path_selection_older
;
977 "%s: %s loses to %s due to oldest external",
978 pfx_buf
, new_buf
, exist_buf
);
983 /* 13. Router-ID comparision. */
984 /* If one of the paths is "stale", the corresponding peer router-id will
985 * be 0 and would always win over the other path. If originator id is
986 * used for the comparision, it will decide which path is better.
988 if (newattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
989 new_id
.s_addr
= newattr
->originator_id
.s_addr
;
991 new_id
.s_addr
= new->peer
->remote_id
.s_addr
;
992 if (existattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
993 exist_id
.s_addr
= existattr
->originator_id
.s_addr
;
995 exist_id
.s_addr
= exist
->peer
->remote_id
.s_addr
;
997 if (ntohl(new_id
.s_addr
) < ntohl(exist_id
.s_addr
)) {
998 *reason
= bgp_path_selection_router_id
;
1001 "%s: %s wins over %s due to Router-ID comparison",
1002 pfx_buf
, new_buf
, exist_buf
);
1006 if (ntohl(new_id
.s_addr
) > ntohl(exist_id
.s_addr
)) {
1007 *reason
= bgp_path_selection_router_id
;
1010 "%s: %s loses to %s due to Router-ID comparison",
1011 pfx_buf
, new_buf
, exist_buf
);
1015 /* 14. Cluster length comparision. */
1016 new_cluster
= BGP_CLUSTER_LIST_LENGTH(new->attr
);
1017 exist_cluster
= BGP_CLUSTER_LIST_LENGTH(exist
->attr
);
1019 if (new_cluster
< exist_cluster
) {
1020 *reason
= bgp_path_selection_cluster_length
;
1023 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1024 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1029 if (new_cluster
> exist_cluster
) {
1030 *reason
= bgp_path_selection_cluster_length
;
1033 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1034 pfx_buf
, new_buf
, exist_buf
, new_cluster
,
1039 /* 15. Neighbor address comparision. */
1040 /* Do this only if neither path is "stale" as stale paths do not have
1041 * valid peer information (as the connection may or may not be up).
1043 if (CHECK_FLAG(exist
->flags
, BGP_PATH_STALE
)) {
1044 *reason
= bgp_path_selection_stale
;
1047 "%s: %s wins over %s due to latter path being STALE",
1048 pfx_buf
, new_buf
, exist_buf
);
1052 if (CHECK_FLAG(new->flags
, BGP_PATH_STALE
)) {
1053 *reason
= bgp_path_selection_stale
;
1056 "%s: %s loses to %s due to former path being STALE",
1057 pfx_buf
, new_buf
, exist_buf
);
1061 /* locally configured routes to advertise do not have su_remote */
1062 if (new->peer
->su_remote
== NULL
) {
1063 *reason
= bgp_path_selection_local_configured
;
1066 if (exist
->peer
->su_remote
== NULL
) {
1067 *reason
= bgp_path_selection_local_configured
;
1071 ret
= sockunion_cmp(new->peer
->su_remote
, exist
->peer
->su_remote
);
1074 *reason
= bgp_path_selection_neighbor_ip
;
1077 "%s: %s loses to %s due to Neighor IP comparison",
1078 pfx_buf
, new_buf
, exist_buf
);
1083 *reason
= bgp_path_selection_neighbor_ip
;
1086 "%s: %s wins over %s due to Neighor IP comparison",
1087 pfx_buf
, new_buf
, exist_buf
);
1091 *reason
= bgp_path_selection_default
;
1093 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1094 pfx_buf
, new_buf
, exist_buf
);
1099 /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1100 * is preferred, or 0 if they are the same (usually will only occur if
1101 * multipath is enabled
1102 * This version is compatible with */
1103 int bgp_path_info_cmp_compatible(struct bgp
*bgp
, struct bgp_path_info
*new,
1104 struct bgp_path_info
*exist
, char *pfx_buf
,
1105 afi_t afi
, safi_t safi
,
1106 enum bgp_path_selection_reason
*reason
)
1110 ret
= bgp_path_info_cmp(bgp
, new, exist
, &paths_eq
, NULL
, 0, pfx_buf
,
1124 static enum filter_type
bgp_input_filter(struct peer
*peer
, struct prefix
*p
,
1125 struct attr
*attr
, afi_t afi
,
1128 struct bgp_filter
*filter
;
1130 filter
= &peer
->filter
[afi
][safi
];
1132 #define FILTER_EXIST_WARN(F, f, filter) \
1133 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
1134 zlog_debug("%s: Could not find configured input %s-list %s!", \
1135 peer->host, #f, F##_IN_NAME(filter));
1137 if (DISTRIBUTE_IN_NAME(filter
)) {
1138 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1140 if (access_list_apply(DISTRIBUTE_IN(filter
), p
) == FILTER_DENY
)
1144 if (PREFIX_LIST_IN_NAME(filter
)) {
1145 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1147 if (prefix_list_apply(PREFIX_LIST_IN(filter
), p
) == PREFIX_DENY
)
1151 if (FILTER_LIST_IN_NAME(filter
)) {
1152 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1154 if (as_list_apply(FILTER_LIST_IN(filter
), attr
->aspath
)
1159 return FILTER_PERMIT
;
1160 #undef FILTER_EXIST_WARN
1163 static enum filter_type
bgp_output_filter(struct peer
*peer
, struct prefix
*p
,
1164 struct attr
*attr
, afi_t afi
,
1167 struct bgp_filter
*filter
;
1169 filter
= &peer
->filter
[afi
][safi
];
1171 #define FILTER_EXIST_WARN(F, f, filter) \
1172 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
1173 zlog_debug("%s: Could not find configured output %s-list %s!", \
1174 peer->host, #f, F##_OUT_NAME(filter));
1176 if (DISTRIBUTE_OUT_NAME(filter
)) {
1177 FILTER_EXIST_WARN(DISTRIBUTE
, distribute
, filter
);
1179 if (access_list_apply(DISTRIBUTE_OUT(filter
), p
) == FILTER_DENY
)
1183 if (PREFIX_LIST_OUT_NAME(filter
)) {
1184 FILTER_EXIST_WARN(PREFIX_LIST
, prefix
, filter
);
1186 if (prefix_list_apply(PREFIX_LIST_OUT(filter
), p
)
1191 if (FILTER_LIST_OUT_NAME(filter
)) {
1192 FILTER_EXIST_WARN(FILTER_LIST
, as
, filter
);
1194 if (as_list_apply(FILTER_LIST_OUT(filter
), attr
->aspath
)
1199 return FILTER_PERMIT
;
1200 #undef FILTER_EXIST_WARN
1203 /* If community attribute includes no_export then return 1. */
1204 static int bgp_community_filter(struct peer
*peer
, struct attr
*attr
)
1206 if (attr
->community
) {
1207 /* NO_ADVERTISE check. */
1208 if (community_include(attr
->community
, COMMUNITY_NO_ADVERTISE
))
1211 /* NO_EXPORT check. */
1212 if (peer
->sort
== BGP_PEER_EBGP
1213 && community_include(attr
->community
, COMMUNITY_NO_EXPORT
))
1216 /* NO_EXPORT_SUBCONFED check. */
1217 if (peer
->sort
== BGP_PEER_EBGP
1218 || peer
->sort
== BGP_PEER_CONFED
)
1219 if (community_include(attr
->community
,
1220 COMMUNITY_NO_EXPORT_SUBCONFED
))
1226 /* Route reflection loop check. */
1227 static int bgp_cluster_filter(struct peer
*peer
, struct attr
*attr
)
1229 struct in_addr cluster_id
;
1231 if (attr
->cluster
) {
1232 if (peer
->bgp
->config
& BGP_CONFIG_CLUSTER_ID
)
1233 cluster_id
= peer
->bgp
->cluster_id
;
1235 cluster_id
= peer
->bgp
->router_id
;
1237 if (cluster_loop_check(attr
->cluster
, cluster_id
))
1243 static int bgp_input_modifier(struct peer
*peer
, struct prefix
*p
,
1244 struct attr
*attr
, afi_t afi
, safi_t safi
,
1245 const char *rmap_name
, mpls_label_t
*label
,
1246 uint32_t num_labels
)
1248 struct bgp_filter
*filter
;
1249 struct bgp_path_info rmap_path
= { 0 };
1250 struct bgp_path_info_extra extra
= { 0 };
1251 route_map_result_t ret
;
1252 struct route_map
*rmap
= NULL
;
1254 filter
= &peer
->filter
[afi
][safi
];
1256 /* Apply default weight value. */
1257 if (peer
->weight
[afi
][safi
])
1258 attr
->weight
= peer
->weight
[afi
][safi
];
1261 rmap
= route_map_lookup_by_name(rmap_name
);
1266 if (ROUTE_MAP_IN_NAME(filter
)) {
1267 rmap
= ROUTE_MAP_IN(filter
);
1274 /* Route map apply. */
1276 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1277 /* Duplicate current value to new strucutre for modification. */
1278 rmap_path
.peer
= peer
;
1279 rmap_path
.attr
= attr
;
1280 rmap_path
.extra
= &extra
;
1281 extra
.num_labels
= num_labels
;
1282 if (label
&& num_labels
&& num_labels
<= BGP_MAX_LABELS
)
1283 memcpy(extra
.label
, label
,
1284 num_labels
* sizeof(mpls_label_t
));
1286 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_IN
);
1288 /* Apply BGP route map to the attribute. */
1289 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1291 peer
->rmap_type
= 0;
1293 if (ret
== RMAP_DENYMATCH
)
1299 static int bgp_output_modifier(struct peer
*peer
, struct prefix
*p
,
1300 struct attr
*attr
, afi_t afi
, safi_t safi
,
1301 const char *rmap_name
)
1303 struct bgp_path_info rmap_path
;
1304 route_map_result_t ret
;
1305 struct route_map
*rmap
= NULL
;
1309 * So if we get to this point and have no rmap_name
1310 * we want to just show the output as it currently
1316 /* Apply default weight value. */
1317 if (peer
->weight
[afi
][safi
])
1318 attr
->weight
= peer
->weight
[afi
][safi
];
1320 rmap
= route_map_lookup_by_name(rmap_name
);
1323 * If we have a route map name and we do not find
1324 * the routemap that means we have an implicit
1330 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1331 /* Route map apply. */
1332 /* Duplicate current value to new strucutre for modification. */
1333 rmap_path
.peer
= peer
;
1334 rmap_path
.attr
= attr
;
1336 rmap_type
= peer
->rmap_type
;
1337 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1339 /* Apply BGP route map to the attribute. */
1340 ret
= route_map_apply(rmap
, p
, RMAP_BGP
, &rmap_path
);
1342 peer
->rmap_type
= rmap_type
;
1344 if (ret
== RMAP_DENYMATCH
)
1346 * caller has multiple error paths with bgp_attr_flush()
1353 /* If this is an EBGP peer with remove-private-AS */
1354 static void bgp_peer_remove_private_as(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1355 struct peer
*peer
, struct attr
*attr
)
1357 if (peer
->sort
== BGP_PEER_EBGP
1358 && (peer_af_flag_check(peer
, afi
, safi
,
1359 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1360 || peer_af_flag_check(peer
, afi
, safi
,
1361 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
)
1362 || peer_af_flag_check(peer
, afi
, safi
,
1363 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)
1364 || peer_af_flag_check(peer
, afi
, safi
,
1365 PEER_FLAG_REMOVE_PRIVATE_AS
))) {
1366 // Take action on the entire aspath
1367 if (peer_af_flag_check(peer
, afi
, safi
,
1368 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
)
1369 || peer_af_flag_check(peer
, afi
, safi
,
1370 PEER_FLAG_REMOVE_PRIVATE_AS_ALL
)) {
1371 if (peer_af_flag_check(
1373 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE
))
1374 attr
->aspath
= aspath_replace_private_asns(
1375 attr
->aspath
, bgp
->as
, peer
->as
);
1377 // The entire aspath consists of private ASNs so create
1379 else if (aspath_private_as_check(attr
->aspath
))
1380 attr
->aspath
= aspath_empty_get();
1382 // There are some public and some private ASNs, remove
1385 attr
->aspath
= aspath_remove_private_asns(
1386 attr
->aspath
, peer
->as
);
1389 // 'all' was not specified so the entire aspath must be private
1391 // for us to do anything
1392 else if (aspath_private_as_check(attr
->aspath
)) {
1393 if (peer_af_flag_check(
1395 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE
))
1396 attr
->aspath
= aspath_replace_private_asns(
1397 attr
->aspath
, bgp
->as
, peer
->as
);
1399 attr
->aspath
= aspath_empty_get();
1404 /* If this is an EBGP peer with as-override */
1405 static void bgp_peer_as_override(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
1406 struct peer
*peer
, struct attr
*attr
)
1408 if (peer
->sort
== BGP_PEER_EBGP
1409 && peer_af_flag_check(peer
, afi
, safi
, PEER_FLAG_AS_OVERRIDE
)) {
1410 if (aspath_single_asn_check(attr
->aspath
, peer
->as
))
1411 attr
->aspath
= aspath_replace_specific_asn(
1412 attr
->aspath
, peer
->as
, bgp
->as
);
1416 void bgp_attr_add_gshut_community(struct attr
*attr
)
1418 struct community
*old
;
1419 struct community
*new;
1420 struct community
*merge
;
1421 struct community
*gshut
;
1423 old
= attr
->community
;
1424 gshut
= community_str2com("graceful-shutdown");
1429 merge
= community_merge(community_dup(old
), gshut
);
1431 if (old
->refcnt
== 0)
1432 community_free(&old
);
1434 new = community_uniq_sort(merge
);
1435 community_free(&merge
);
1437 new = community_dup(gshut
);
1440 community_free(&gshut
);
1441 attr
->community
= new;
1442 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES
);
1444 /* When we add the graceful-shutdown community we must also
1445 * lower the local-preference */
1446 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1447 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1451 static void subgroup_announce_reset_nhop(uint8_t family
, struct attr
*attr
)
1453 if (family
== AF_INET
) {
1454 attr
->nexthop
.s_addr
= 0;
1455 attr
->mp_nexthop_global_in
.s_addr
= 0;
1457 if (family
== AF_INET6
)
1458 memset(&attr
->mp_nexthop_global
, 0, IPV6_MAX_BYTELEN
);
1459 if (family
== AF_EVPN
)
1460 memset(&attr
->mp_nexthop_global_in
, 0, BGP_ATTR_NHLEN_IPV4
);
1463 int subgroup_announce_check(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
1464 struct update_subgroup
*subgrp
, struct prefix
*p
,
1467 struct bgp_filter
*filter
;
1470 struct peer
*onlypeer
;
1472 struct attr
*piattr
;
1473 char buf
[PREFIX_STRLEN
];
1474 route_map_result_t ret
;
1479 int samepeer_safe
= 0; /* for synthetic mplsvpns routes */
1481 if (DISABLE_BGP_ANNOUNCE
)
1484 afi
= SUBGRP_AFI(subgrp
);
1485 safi
= SUBGRP_SAFI(subgrp
);
1486 peer
= SUBGRP_PEER(subgrp
);
1488 if (CHECK_FLAG(peer
->flags
, PEER_FLAG_LONESOUL
))
1489 onlypeer
= SUBGRP_PFIRST(subgrp
)->peer
;
1492 filter
= &peer
->filter
[afi
][safi
];
1493 bgp
= SUBGRP_INST(subgrp
);
1494 piattr
= bgp_path_info_mpath_count(pi
) ? bgp_path_info_mpath_attr(pi
)
1498 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
)) && (safi
== SAFI_MPLS_VPN
)
1499 && ((pi
->type
== ZEBRA_ROUTE_BGP_DIRECT
)
1500 || (pi
->type
== ZEBRA_ROUTE_BGP_DIRECT_EXT
))) {
1503 * direct and direct_ext type routes originate internally even
1504 * though they can have peer pointers that reference other
1507 prefix2str(p
, buf
, PREFIX_STRLEN
);
1508 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1514 if (((afi
== AFI_IP
) || (afi
== AFI_IP6
))
1515 && ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_UNICAST
))
1516 && (pi
->type
== ZEBRA_ROUTE_BGP
)
1517 && (pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
1519 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1524 /* With addpath we may be asked to TX all kinds of paths so make sure
1526 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
)
1527 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)
1528 || CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
1532 /* If this is not the bestpath then check to see if there is an enabled
1534 * feature that requires us to advertise it */
1535 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
1536 if (!bgp_addpath_tx_path(peer
->addpath_type
[afi
][safi
], pi
)) {
1541 /* Aggregate-address suppress check. */
1542 if (pi
->extra
&& pi
->extra
->suppress
)
1543 if (!UNSUPPRESS_MAP_NAME(filter
)) {
1548 * If we are doing VRF 2 VRF leaking via the import
1549 * statement, we want to prevent the route going
1550 * off box as that the RT and RD created are localy
1551 * significant and globaly useless.
1553 if (safi
== SAFI_MPLS_VPN
&& pi
->extra
&& pi
->extra
->num_labels
1554 && pi
->extra
->label
[0] == BGP_PREVENT_VRF_2_VRF_LEAK
)
1557 /* If it's labeled safi, make sure the route has a valid label. */
1558 if (safi
== SAFI_LABELED_UNICAST
) {
1559 mpls_label_t label
= bgp_adv_label(rn
, pi
, peer
, afi
, safi
);
1560 if (!bgp_is_valid_label(&label
)) {
1561 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1562 zlog_debug("u%" PRIu64
":s%" PRIu64
1563 " %s/%d is filtered - no label (%p)",
1564 subgrp
->update_group
->id
, subgrp
->id
,
1565 inet_ntop(p
->family
, &p
->u
.prefix
,
1566 buf
, SU_ADDRSTRLEN
),
1567 p
->prefixlen
, &label
);
1572 /* Do not send back route to sender. */
1573 if (onlypeer
&& from
== onlypeer
) {
1577 /* Do not send the default route in the BGP table if the neighbor is
1578 * configured for default-originate */
1579 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1580 PEER_FLAG_DEFAULT_ORIGINATE
)) {
1581 if (p
->family
== AF_INET
&& p
->u
.prefix4
.s_addr
== INADDR_ANY
)
1583 else if (p
->family
== AF_INET6
&& p
->prefixlen
== 0)
1587 /* Transparency check. */
1588 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
)
1589 && CHECK_FLAG(from
->af_flags
[afi
][safi
], PEER_FLAG_RSERVER_CLIENT
))
1594 /* If community is not disabled check the no-export and local. */
1595 if (!transparent
&& bgp_community_filter(peer
, piattr
)) {
1596 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1598 "subgrpannouncecheck: community filter check fail");
1602 /* If the attribute has originator-id and it is same as remote
1604 if (onlypeer
&& piattr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
1605 && (IPV4_ADDR_SAME(&onlypeer
->remote_id
, &piattr
->originator_id
))) {
1606 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1608 "%s [Update:SEND] %s originator-id is same as "
1611 prefix2str(p
, buf
, sizeof(buf
)));
1615 /* ORF prefix-list filter check */
1616 if (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_RM_ADV
)
1617 && (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ORF_PREFIX_SM_RCV
)
1618 || CHECK_FLAG(peer
->af_cap
[afi
][safi
],
1619 PEER_CAP_ORF_PREFIX_SM_OLD_RCV
)))
1620 if (peer
->orf_plist
[afi
][safi
]) {
1621 if (prefix_list_apply(peer
->orf_plist
[afi
][safi
], p
)
1623 if (bgp_debug_update(NULL
, p
,
1624 subgrp
->update_group
, 0))
1626 "%s [Update:SEND] %s is filtered via ORF",
1634 /* Output filter check. */
1635 if (bgp_output_filter(peer
, p
, piattr
, afi
, safi
) == FILTER_DENY
) {
1636 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1637 zlog_debug("%s [Update:SEND] %s is filtered",
1638 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1642 #ifdef BGP_SEND_ASPATH_CHECK
1643 /* AS path loop check. */
1644 if (onlypeer
&& aspath_loop_check(piattr
->aspath
, onlypeer
->as
)) {
1645 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1647 "%s [Update:SEND] suppress announcement to peer AS %u "
1648 "that is part of AS path.",
1649 onlypeer
->host
, onlypeer
->as
);
1652 #endif /* BGP_SEND_ASPATH_CHECK */
1654 /* If we're a CONFED we need to loop check the CONFED ID too */
1655 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1656 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1657 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1659 "%s [Update:SEND] suppress announcement to peer AS %u"
1661 peer
->host
, bgp
->confed_id
);
1666 /* Route-Reflect check. */
1667 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1672 /* IBGP reflection check. */
1673 if (reflect
&& !samepeer_safe
) {
1674 /* A route from a Client peer. */
1675 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1676 PEER_FLAG_REFLECTOR_CLIENT
)) {
1677 /* Reflect to all the Non-Client peers and also to the
1678 Client peers other than the originator. Originator
1680 is already done. So there is noting to do. */
1681 /* no bgp client-to-client reflection check. */
1682 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1683 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1684 PEER_FLAG_REFLECTOR_CLIENT
))
1687 /* A route from a Non-client peer. Reflect to all other
1689 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1690 PEER_FLAG_REFLECTOR_CLIENT
))
1695 /* For modify attribute, copy it to temporary structure. */
1696 bgp_attr_dup(attr
, piattr
);
1698 /* If local-preference is not set. */
1699 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1700 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1701 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1702 attr
->local_pref
= bgp
->default_local_pref
;
1705 /* If originator-id is not set and the route is to be reflected,
1706 set the originator id */
1708 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1709 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1710 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1713 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1715 if (peer
->sort
== BGP_PEER_EBGP
1716 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1717 if (from
!= bgp
->peer_self
&& !transparent
1718 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1719 PEER_FLAG_MED_UNCHANGED
))
1721 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1724 /* Since the nexthop attribute can vary per peer, it is not explicitly
1726 * in announce check, only certain flags and length (or number of
1728 * -- for IPv6/MP_REACH) are set here in order to guide the update
1730 * code in setting the nexthop(s) on a per peer basis in
1732 * Typically, the source nexthop in the attribute is preserved but in
1734 * scenarios where we know it will always be overwritten, we reset the
1735 * nexthop to "0" in an attempt to achieve better Update packing. An
1736 * example of this is when a prefix from each of 2 IBGP peers needs to
1738 * announced to an EBGP peer (and they have the same attributes barring
1742 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1744 #define NEXTHOP_IS_V6 \
1745 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1746 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1747 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1748 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1750 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1752 * the peer (group) is configured to receive link-local nexthop
1754 * and it is available in the prefix OR we're not reflecting the route
1756 * the peer (group) to whom we're going to announce is on a shared
1758 * and this is either a self-originated route or the peer is EBGP.
1760 if (NEXTHOP_IS_V6
) {
1761 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1762 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1763 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1764 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1765 || (!reflect
&& peer
->shared_network
1766 && (from
== bgp
->peer_self
1767 || peer
->sort
== BGP_PEER_EBGP
))) {
1768 attr
->mp_nexthop_len
=
1769 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1772 /* Clear off link-local nexthop in source, whenever it is not
1774 * ensure more prefixes share the same attribute for
1777 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1778 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1779 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1782 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1783 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1785 /* Route map & unsuppress-map apply. */
1786 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1787 struct bgp_path_info rmap_path
= {0};
1788 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1789 struct attr dummy_attr
= {0};
1791 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1792 rmap_path
.peer
= peer
;
1793 rmap_path
.attr
= attr
;
1796 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1797 sizeof(struct bgp_path_info_extra
));
1798 rmap_path
.extra
= &dummy_rmap_path_extra
;
1801 /* don't confuse inbound and outbound setting */
1802 RESET_FLAG(attr
->rmap_change_flags
);
1805 * The route reflector is not allowed to modify the attributes
1806 * of the reflected IBGP routes unless explicitly allowed.
1808 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1809 && !bgp_flag_check(bgp
,
1810 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1811 bgp_attr_dup(&dummy_attr
, attr
);
1812 rmap_path
.attr
= &dummy_attr
;
1815 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1817 if (pi
->extra
&& pi
->extra
->suppress
)
1818 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1819 RMAP_BGP
, &rmap_path
);
1821 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1822 RMAP_BGP
, &rmap_path
);
1824 peer
->rmap_type
= 0;
1826 if (ret
== RMAP_DENYMATCH
) {
1827 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1828 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1829 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1831 bgp_attr_flush(attr
);
1836 /* RFC 8212 to prevent route leaks.
1837 * This specification intends to improve this situation by requiring the
1838 * explicit configuration of both BGP Import and Export Policies for any
1839 * External BGP (EBGP) session such as customers, peers, or
1840 * confederation boundaries for all enabled address families. Through
1841 * codification of the aforementioned requirement, operators will
1842 * benefit from consistent behavior across different BGP
1845 if (peer
->bgp
->ebgp_requires_policy
1846 == DEFAULT_EBGP_POLICY_ENABLED
)
1847 if (!bgp_outbound_policy_exists(peer
, filter
))
1850 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1851 if (peer
->sort
== BGP_PEER_IBGP
1852 || peer
->sort
== BGP_PEER_CONFED
) {
1853 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1854 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1856 bgp_attr_add_gshut_community(attr
);
1860 /* After route-map has been applied, we check to see if the nexthop to
1861 * be carried in the attribute (that is used for the announcement) can
1862 * be cleared off or not. We do this in all cases where we would be
1863 * setting the nexthop to "ourselves". For IPv6, we only need to
1865 * the global nexthop here; the link-local nexthop would have been
1867 * already, and if not, it is required by the update formation code.
1868 * Also see earlier comments in this function.
1871 * If route-map has performed some operation on the nexthop or the peer
1872 * configuration says to pass it unchanged, we cannot reset the nexthop
1873 * here, so only attempt to do it if these aren't true. Note that the
1874 * route-map handler itself might have cleared the nexthop, if for
1876 * it is configured as 'peer-address'.
1878 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1879 piattr
->rmap_change_flags
)
1881 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1882 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1883 /* We can reset the nexthop, if setting (or forcing) it to
1885 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1886 PEER_FLAG_NEXTHOP_SELF
)
1887 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1888 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1890 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1891 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1892 subgroup_announce_reset_nhop(
1893 (peer_cap_enhe(peer
, afi
, safi
)
1897 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1898 /* Can also reset the nexthop if announcing to EBGP, but
1900 * no peer in the subgroup is on a shared subnet.
1901 * Note: 3rd party nexthop currently implemented for
1904 if ((p
->family
== AF_INET
) &&
1905 (!bgp_subgrp_multiaccess_check_v4(
1908 subgroup_announce_reset_nhop(
1909 (peer_cap_enhe(peer
, afi
, safi
)
1914 if ((p
->family
== AF_INET6
) &&
1915 (!bgp_subgrp_multiaccess_check_v6(
1916 piattr
->mp_nexthop_global
,
1918 subgroup_announce_reset_nhop(
1919 (peer_cap_enhe(peer
, afi
, safi
)
1926 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1928 * This flag is used for leaked vpn-vrf routes
1930 int family
= p
->family
;
1932 if (peer_cap_enhe(peer
, afi
, safi
))
1935 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1937 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1938 __func__
, family2str(family
));
1939 subgroup_announce_reset_nhop(family
, attr
);
1942 /* If IPv6/MP and nexthop does not have any override and happens
1944 * be a link-local address, reset it so that we don't pass along
1946 * source's link-local IPv6 address to recipients who may not be
1948 * the same interface.
1950 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1951 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1952 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1959 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1960 struct bgp_maxpaths_cfg
*mpath_cfg
,
1961 struct bgp_path_info_pair
*result
, afi_t afi
,
1964 struct bgp_path_info
*new_select
;
1965 struct bgp_path_info
*old_select
;
1966 struct bgp_path_info
*pi
;
1967 struct bgp_path_info
*pi1
;
1968 struct bgp_path_info
*pi2
;
1969 struct bgp_path_info
*nextpi
= NULL
;
1970 int paths_eq
, do_mpath
, debug
;
1971 struct list mp_list
;
1972 char pfx_buf
[PREFIX2STR_BUFFER
];
1973 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1975 bgp_mp_list_init(&mp_list
);
1977 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1979 debug
= bgp_debug_bestpath(&rn
->p
);
1982 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1984 /* bgp deterministic-med */
1986 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1988 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1989 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1991 bgp_path_info_unset_flag(rn
, pi1
,
1992 BGP_PATH_DMED_SELECTED
);
1994 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1996 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
1998 if (BGP_PATH_HOLDDOWN(pi1
))
2000 if (pi1
->peer
!= bgp
->peer_self
)
2001 if (pi1
->peer
->status
!= Established
)
2006 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2007 if (CHECK_FLAG(pi2
->flags
,
2008 BGP_PATH_DMED_CHECK
))
2010 if (BGP_PATH_HOLDDOWN(pi2
))
2012 if (pi2
->peer
!= bgp
->peer_self
2015 PEER_STATUS_NSF_WAIT
))
2016 if (pi2
->peer
->status
2020 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2022 && !aspath_cmp_left_confed(
2027 if (bgp_path_info_cmp(
2028 bgp
, pi2
, new_select
,
2029 &paths_eq
, mpath_cfg
, debug
,
2032 bgp_path_info_unset_flag(
2034 BGP_PATH_DMED_SELECTED
);
2038 bgp_path_info_set_flag(
2039 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2042 bgp_path_info_set_flag(rn
, new_select
,
2043 BGP_PATH_DMED_CHECK
);
2044 bgp_path_info_set_flag(rn
, new_select
,
2045 BGP_PATH_DMED_SELECTED
);
2048 bgp_path_info_path_with_addpath_rx_str(
2049 new_select
, path_buf
);
2050 zlog_debug("%s: %s is the bestpath from AS %u",
2052 aspath_get_first_as(
2053 new_select
->attr
->aspath
));
2058 /* Check old selected route and new selected route. */
2061 for (pi
= bgp_node_get_bgp_path_info(rn
);
2062 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2063 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2066 if (BGP_PATH_HOLDDOWN(pi
)) {
2067 /* reap REMOVED routes, if needs be
2068 * selected route must stay for a while longer though
2070 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2071 && (pi
!= old_select
))
2072 bgp_path_info_reap(rn
, pi
);
2075 zlog_debug("%s: pi %p in holddown", __func__
,
2081 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2082 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2083 if (pi
->peer
->status
!= Established
) {
2087 "%s: pi %p non self peer %s not estab state",
2088 __func__
, pi
, pi
->peer
->host
);
2093 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2094 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2095 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2097 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2101 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2103 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2104 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2109 /* Now that we know which path is the bestpath see if any of the other
2111 * qualify as multipaths
2115 bgp_path_info_path_with_addpath_rx_str(new_select
,
2118 sprintf(path_buf
, "NONE");
2120 "%s: After path selection, newbest is %s oldbest was %s",
2122 old_select
? old_select
->peer
->host
: "NONE");
2125 if (do_mpath
&& new_select
) {
2126 for (pi
= bgp_node_get_bgp_path_info(rn
);
2127 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2130 bgp_path_info_path_with_addpath_rx_str(
2133 if (pi
== new_select
) {
2136 "%s: %s is the bestpath, add to the multipath list",
2138 bgp_mp_list_add(&mp_list
, pi
);
2142 if (BGP_PATH_HOLDDOWN(pi
))
2145 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2146 && !CHECK_FLAG(pi
->peer
->sflags
,
2147 PEER_STATUS_NSF_WAIT
))
2148 if (pi
->peer
->status
!= Established
)
2151 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2154 "%s: %s has the same nexthop as the bestpath, skip it",
2159 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2160 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2166 "%s: %s is equivalent to the bestpath, add to the multipath list",
2168 bgp_mp_list_add(&mp_list
, pi
);
2173 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2175 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2176 bgp_mp_list_clear(&mp_list
);
2178 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2180 result
->old
= old_select
;
2181 result
->new = new_select
;
2187 * A new route/change in bestpath of an existing route. Evaluate the path
2188 * for advertisement to the subgroup.
2190 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2191 struct bgp_path_info
*selected
,
2192 struct bgp_node
*rn
,
2193 uint32_t addpath_tx_id
)
2196 struct peer
*onlypeer
;
2202 afi
= SUBGRP_AFI(subgrp
);
2203 safi
= SUBGRP_SAFI(subgrp
);
2204 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2207 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2208 char buf_prefix
[PREFIX_STRLEN
];
2209 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2210 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2214 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2215 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2216 PEER_STATUS_ORF_WAIT_REFRESH
))
2219 memset(&attr
, 0, sizeof(struct attr
));
2220 /* It's initialized in bgp_announce_check() */
2222 /* Announcement to the subgroup. If the route is filtered withdraw it.
2225 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2226 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2228 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2232 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2234 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2241 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2242 * This is called at the end of route processing.
2244 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2246 struct bgp_path_info
*pi
;
2248 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2249 if (BGP_PATH_HOLDDOWN(pi
))
2251 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2252 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2257 * Has the route changed from the RIB's perspective? This is invoked only
2258 * if the route selection returns the same best route as earlier - to
2259 * determine if we need to update zebra or not.
2261 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2262 struct bgp_path_info
*selected
)
2264 struct bgp_path_info
*mpinfo
;
2266 /* If this is multipath, check all selected paths for any nexthop
2267 * change or attribute change. Some attribute changes (e.g., community)
2268 * aren't of relevance to the RIB, but we'll update zebra to ensure
2269 * we handle the case of BGP nexthop change. This is the behavior
2270 * when the best path has an attribute change anyway.
2272 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2273 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2277 * If this is multipath, check all selected paths for any nexthop change
2279 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2280 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2281 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2282 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2286 /* Nothing has changed from the RIB's perspective. */
2290 struct bgp_process_queue
{
2292 STAILQ_HEAD(, bgp_node
) pqueue
;
2293 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2295 unsigned int queued
;
2299 * old_select = The old best path
2300 * new_select = the new best path
2302 * if (!old_select && new_select)
2303 * We are sending new information on.
2305 * if (old_select && new_select) {
2306 * if (new_select != old_select)
2307 * We have a new best path send a change
2309 * We've received a update with new attributes that needs
2313 * if (old_select && !new_select)
2314 * We have no eligible route that we can announce or the rn
2317 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2318 afi_t afi
, safi_t safi
)
2320 struct bgp_path_info
*new_select
;
2321 struct bgp_path_info
*old_select
;
2322 struct bgp_path_info_pair old_and_new
;
2323 char pfx_buf
[PREFIX2STR_BUFFER
];
2326 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2328 debug
= bgp_debug_bestpath(&rn
->p
);
2330 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2332 "%s: bgp delete in progress, ignoring event, p=%s",
2337 /* Is it end of initial update? (after startup) */
2339 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2340 sizeof(bgp
->update_delay_zebra_resume_time
));
2342 bgp
->main_zebra_update_hold
= 0;
2343 FOREACH_AFI_SAFI (afi
, safi
) {
2344 if (bgp_fibupd_safi(safi
))
2345 bgp_zebra_announce_table(bgp
, afi
, safi
);
2347 bgp
->main_peers_update_hold
= 0;
2349 bgp_start_routeadv(bgp
);
2353 struct prefix
*p
= &rn
->p
;
2355 debug
= bgp_debug_bestpath(&rn
->p
);
2357 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2358 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2359 afi2str(afi
), safi2str(safi
));
2362 /* Best path selection. */
2363 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2365 old_select
= old_and_new
.old
;
2366 new_select
= old_and_new
.new;
2368 /* Do we need to allocate or free labels?
2369 * Right now, since we only deal with per-prefix labels, it is not
2370 * necessary to do this upon changes to best path. Exceptions:
2371 * - label index has changed -> recalculate resulting label
2372 * - path_info sub_type changed -> switch to/from implicit-null
2373 * - no valid label (due to removed static label binding) -> get new one
2375 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2378 || bgp_label_index_differs(new_select
, old_select
)
2379 || new_select
->sub_type
!= old_select
->sub_type
2380 || !bgp_is_valid_label(&rn
->local_label
)) {
2381 /* Enforced penultimate hop popping:
2382 * implicit-null for local routes, aggregate
2383 * and redistributed routes
2385 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2386 || new_select
->sub_type
2387 == BGP_ROUTE_AGGREGATE
2388 || new_select
->sub_type
2389 == BGP_ROUTE_REDISTRIBUTE
) {
2392 BGP_NODE_REGISTERED_FOR_LABEL
))
2393 bgp_unregister_for_label(rn
);
2394 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2396 bgp_set_valid_label(&rn
->local_label
);
2398 bgp_register_for_label(rn
, new_select
);
2400 } else if (CHECK_FLAG(rn
->flags
,
2401 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2402 bgp_unregister_for_label(rn
);
2404 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2405 bgp_unregister_for_label(rn
);
2409 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2411 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2412 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2413 old_select
, new_select
);
2416 /* If best route remains the same and this is not due to user-initiated
2417 * clear, see exactly what needs to be done.
2419 if (old_select
&& old_select
== new_select
2420 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2421 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2422 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2423 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2425 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2426 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2428 if (bgp_fibupd_safi(safi
)
2429 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2431 if (new_select
->type
== ZEBRA_ROUTE_BGP
2432 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2433 || new_select
->sub_type
2434 == BGP_ROUTE_IMPORTED
))
2436 bgp_zebra_announce(rn
, p
, old_select
,
2440 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2441 bgp_zebra_clear_route_change_flags(rn
);
2443 /* If there is a change of interest to peers, reannounce the
2445 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2446 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2447 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2449 /* unicast routes must also be annouced to
2450 * labeled-unicast update-groups */
2451 if (safi
== SAFI_UNICAST
)
2452 group_announce_route(bgp
, afi
,
2453 SAFI_LABELED_UNICAST
, rn
,
2456 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2457 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2460 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2464 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2466 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2468 /* bestpath has changed; bump version */
2469 if (old_select
|| new_select
) {
2470 bgp_bump_version(rn
);
2472 if (!bgp
->t_rmap_def_originate_eval
) {
2476 update_group_refresh_default_originate_route_map
,
2477 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2478 &bgp
->t_rmap_def_originate_eval
);
2483 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2486 zlog_debug("%s: setting SELECTED flag", __func__
);
2487 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2488 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2489 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2493 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2494 if (old_select
!= new_select
) {
2496 vnc_import_bgp_exterior_del_route(bgp
, p
,
2498 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2501 vnc_import_bgp_exterior_add_route(bgp
, p
,
2503 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2509 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2511 /* unicast routes must also be annouced to labeled-unicast update-groups
2513 if (safi
== SAFI_UNICAST
)
2514 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2518 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2519 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2520 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2521 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2522 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2523 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2525 /* if this is an evpn imported type-5 prefix,
2526 * we need to withdraw the route first to clear
2527 * the nh neigh and the RMAC entry.
2530 is_route_parent_evpn(old_select
))
2531 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2533 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2535 /* Withdraw the route from the kernel. */
2536 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2537 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2538 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2539 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2541 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2545 /* advertise/withdraw type-5 routes */
2546 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2547 if (advertise_type5_routes(bgp
, afi
) &&
2549 is_route_injectable_into_evpn(new_select
)) {
2551 /* apply the route-map */
2552 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2553 route_map_result_t ret
;
2555 ret
= route_map_apply(
2556 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2557 &rn
->p
, RMAP_BGP
, new_select
);
2558 if (ret
== RMAP_PERMITMATCH
)
2559 bgp_evpn_advertise_type5_route(
2560 bgp
, &rn
->p
, new_select
->attr
,
2563 bgp_evpn_withdraw_type5_route(
2564 bgp
, &rn
->p
, afi
, safi
);
2566 bgp_evpn_advertise_type5_route(bgp
,
2572 } else if (advertise_type5_routes(bgp
, afi
) &&
2574 is_route_injectable_into_evpn(old_select
))
2575 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2578 /* Clear any route change flags. */
2579 bgp_zebra_clear_route_change_flags(rn
);
2581 /* Reap old select bgp_path_info, if it has been removed */
2582 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2583 bgp_path_info_reap(rn
, old_select
);
2585 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2589 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2591 struct bgp_process_queue
*pqnode
= data
;
2592 struct bgp
*bgp
= pqnode
->bgp
;
2593 struct bgp_table
*table
;
2594 struct bgp_node
*rn
;
2597 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2598 bgp_process_main_one(bgp
, NULL
, 0, 0);
2599 /* should always have dedicated wq call */
2600 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2604 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2605 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2606 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2607 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2608 table
= bgp_node_table(rn
);
2609 /* note, new RNs may be added as part of processing */
2610 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2612 bgp_unlock_node(rn
);
2613 bgp_table_unlock(table
);
2619 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2621 struct bgp_process_queue
*pqnode
= data
;
2623 bgp_unlock(pqnode
->bgp
);
2625 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2628 void bgp_process_queue_init(void)
2630 if (!bm
->process_main_queue
)
2631 bm
->process_main_queue
=
2632 work_queue_new(bm
->master
, "process_main_queue");
2634 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2635 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2636 bm
->process_main_queue
->spec
.max_retries
= 0;
2637 bm
->process_main_queue
->spec
.hold
= 50;
2638 /* Use a higher yield value of 50ms for main queue processing */
2639 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2642 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2644 struct bgp_process_queue
*pqnode
;
2646 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2647 sizeof(struct bgp_process_queue
));
2649 /* unlocked in bgp_processq_del */
2650 pqnode
->bgp
= bgp_lock(bgp
);
2651 STAILQ_INIT(&pqnode
->pqueue
);
2656 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2658 #define ARBITRARY_PROCESS_QLEN 10000
2659 struct work_queue
*wq
= bm
->process_main_queue
;
2660 struct bgp_process_queue
*pqnode
;
2661 int pqnode_reuse
= 0;
2663 /* already scheduled for processing? */
2664 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2670 /* Add route nodes to an existing work queue item until reaching the
2671 limit only if is from the same BGP view and it's not an EOIU marker
2673 if (work_queue_item_count(wq
)) {
2674 struct work_queue_item
*item
= work_queue_last_item(wq
);
2675 pqnode
= item
->data
;
2677 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2678 || pqnode
->bgp
!= bgp
2679 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2680 pqnode
= bgp_processq_alloc(bgp
);
2684 pqnode
= bgp_processq_alloc(bgp
);
2685 /* all unlocked in bgp_process_wq */
2686 bgp_table_lock(bgp_node_table(rn
));
2688 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2691 /* can't be enqueued twice */
2692 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2693 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2697 work_queue_add(wq
, pqnode
);
2702 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2704 struct bgp_process_queue
*pqnode
;
2706 if (bm
->process_main_queue
== NULL
)
2709 pqnode
= bgp_processq_alloc(bgp
);
2711 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2712 work_queue_add(bm
->process_main_queue
, pqnode
);
2715 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2719 peer
= THREAD_ARG(thread
);
2720 peer
->t_pmax_restart
= NULL
;
2722 if (bgp_debug_neighbor_events(peer
))
2724 "%s Maximum-prefix restart timer expired, restore peering",
2727 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2728 zlog_debug("%s: %s peer_clear failed",
2729 __PRETTY_FUNCTION__
, peer
->host
);
2734 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2738 iana_safi_t pkt_safi
;
2740 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2743 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2744 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2745 PEER_STATUS_PREFIX_LIMIT
)
2750 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2751 " exceed, limit %" PRIu32
,
2752 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2753 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2754 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2756 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2757 PEER_FLAG_MAX_PREFIX_WARNING
))
2760 /* Convert AFI, SAFI to values for packet. */
2761 pkt_afi
= afi_int2iana(afi
);
2762 pkt_safi
= safi_int2iana(safi
);
2766 ndata
[0] = (pkt_afi
>> 8);
2768 ndata
[2] = pkt_safi
;
2769 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2770 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2771 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2772 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2774 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2775 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2776 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2780 /* Dynamic peers will just close their connection. */
2781 if (peer_dynamic_neighbor(peer
))
2784 /* restart timer start */
2785 if (peer
->pmax_restart
[afi
][safi
]) {
2786 peer
->v_pmax_restart
=
2787 peer
->pmax_restart
[afi
][safi
] * 60;
2789 if (bgp_debug_neighbor_events(peer
))
2791 "%s Maximum-prefix restart timer started for %d secs",
2792 peer
->host
, peer
->v_pmax_restart
);
2794 BGP_TIMER_ON(peer
->t_pmax_restart
,
2795 bgp_maximum_prefix_restart_timer
,
2796 peer
->v_pmax_restart
);
2801 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2802 PEER_STATUS_PREFIX_LIMIT
);
2804 if (peer
->pcount
[afi
][safi
]
2805 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2806 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2807 PEER_STATUS_PREFIX_THRESHOLD
)
2812 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2814 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2815 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2816 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2817 PEER_STATUS_PREFIX_THRESHOLD
);
2819 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2820 PEER_STATUS_PREFIX_THRESHOLD
);
2824 /* Unconditionally remove the route from the RIB, without taking
2825 * damping into consideration (eg, because the session went down)
2827 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2828 struct peer
*peer
, afi_t afi
, safi_t safi
)
2830 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2832 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2833 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2835 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
2837 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2840 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2841 struct peer
*peer
, afi_t afi
, safi_t safi
,
2842 struct prefix_rd
*prd
)
2844 /* apply dampening, if result is suppressed, we'll be retaining
2845 * the bgp_path_info in the RIB for historical reference.
2847 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2848 && peer
->sort
== BGP_PEER_EBGP
)
2849 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2850 == BGP_DAMP_SUPPRESSED
) {
2851 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2857 if (safi
== SAFI_MPLS_VPN
) {
2858 struct bgp_node
*prn
= NULL
;
2859 struct bgp_table
*table
= NULL
;
2861 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2862 (struct prefix
*)prd
);
2863 if (bgp_node_has_bgp_path_info_data(prn
)) {
2864 table
= bgp_node_get_bgp_table_info(prn
);
2866 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2867 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2869 bgp_unlock_node(prn
);
2871 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2872 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2874 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2875 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2881 /* If this is an EVPN route, process for un-import. */
2882 if (safi
== SAFI_EVPN
)
2883 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2885 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2888 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2889 struct peer
*peer
, struct attr
*attr
,
2890 struct bgp_node
*rn
)
2892 struct bgp_path_info
*new;
2894 /* Make new BGP info. */
2895 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2897 new->instance
= instance
;
2898 new->sub_type
= sub_type
;
2901 new->uptime
= bgp_clock();
2906 static void overlay_index_update(struct attr
*attr
,
2907 struct eth_segment_id
*eth_s_id
,
2908 union gw_addr
*gw_ip
)
2913 if (eth_s_id
== NULL
) {
2914 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2915 sizeof(struct eth_segment_id
));
2917 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2918 sizeof(struct eth_segment_id
));
2920 if (gw_ip
== NULL
) {
2921 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2923 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2924 sizeof(union gw_addr
));
2928 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2929 struct eth_segment_id
*eth_s_id
,
2930 union gw_addr
*gw_ip
)
2932 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2933 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2935 struct eth_segment_id esi
;
2939 if (afi
!= AFI_L2VPN
)
2942 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2943 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2945 if (gw_ip
== NULL
) {
2946 memset(&temp
, 0, sizeof(temp
));
2947 path_gw_ip_remote
= &temp
.ip
;
2949 path_gw_ip_remote
= gw_ip
;
2951 if (eth_s_id
== NULL
) {
2952 memset(&temp
, 0, sizeof(temp
));
2953 path_eth_s_id_remote
= &temp
.esi
;
2955 path_eth_s_id_remote
= eth_s_id
;
2957 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2960 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2961 sizeof(struct eth_segment_id
));
2964 /* Check if received nexthop is valid or not. */
2965 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2970 /* Only validated for unicast and multicast currently. */
2971 /* Also valid for EVPN where the nexthop is an IP address. */
2972 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2975 /* If NEXT_HOP is present, validate it. */
2976 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2977 if (attr
->nexthop
.s_addr
== 0
2978 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2979 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2983 /* If MP_NEXTHOP is present, validate it. */
2984 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2985 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2986 * it is not an IPv6 link-local address.
2988 if (attr
->mp_nexthop_len
) {
2989 switch (attr
->mp_nexthop_len
) {
2990 case BGP_ATTR_NHLEN_IPV4
:
2991 case BGP_ATTR_NHLEN_VPNV4
:
2992 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2993 || IPV4_CLASS_DE(ntohl(
2994 attr
->mp_nexthop_global_in
.s_addr
))
2995 || bgp_nexthop_self(bgp
,
2996 attr
->mp_nexthop_global_in
));
2999 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3000 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3001 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3002 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3003 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3004 || IN6_IS_ADDR_MULTICAST(
3005 &attr
->mp_nexthop_global
));
3017 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3018 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3019 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3020 uint32_t num_labels
, int soft_reconfig
,
3021 struct bgp_route_evpn
*evpn
)
3024 int aspath_loop_count
= 0;
3025 struct bgp_node
*rn
;
3027 struct attr new_attr
;
3028 struct attr
*attr_new
;
3029 struct bgp_path_info
*pi
;
3030 struct bgp_path_info
*new;
3031 struct bgp_path_info_extra
*extra
;
3033 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3035 int do_loop_check
= 1;
3036 int has_valid_label
= 0;
3038 int vnc_implicit_withdraw
= 0;
3042 memset(&new_attr
, 0, sizeof(struct attr
));
3043 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3044 new_attr
.label
= MPLS_INVALID_LABEL
;
3047 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3048 /* TODO: Check to see if we can get rid of "is_valid_label" */
3049 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3050 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3052 has_valid_label
= bgp_is_valid_label(label
);
3054 /* When peer's soft reconfiguration enabled. Record input packet in
3057 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3058 && peer
!= bgp
->peer_self
)
3059 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3061 /* Check previously received route. */
3062 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3063 if (pi
->peer
== peer
&& pi
->type
== type
3064 && pi
->sub_type
== sub_type
3065 && pi
->addpath_rx_id
== addpath_id
)
3068 /* AS path local-as loop check. */
3069 if (peer
->change_local_as
) {
3070 if (peer
->allowas_in
[afi
][safi
])
3071 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3072 else if (!CHECK_FLAG(peer
->flags
,
3073 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3074 aspath_loop_count
= 1;
3076 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3077 > aspath_loop_count
) {
3078 peer
->stat_pfx_aspath_loop
++;
3079 reason
= "as-path contains our own AS;";
3084 /* If the peer is configured for "allowas-in origin" and the last ASN in
3086 * as-path is our ASN then we do not need to call aspath_loop_check
3088 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3089 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3092 /* AS path loop check. */
3093 if (do_loop_check
) {
3094 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3095 > peer
->allowas_in
[afi
][safi
]
3096 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3097 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3098 > peer
->allowas_in
[afi
][safi
])) {
3099 peer
->stat_pfx_aspath_loop
++;
3100 reason
= "as-path contains our own AS;";
3105 /* Route reflector originator ID check. */
3106 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3107 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3108 peer
->stat_pfx_originator_loop
++;
3109 reason
= "originator is us;";
3113 /* Route reflector cluster ID check. */
3114 if (bgp_cluster_filter(peer
, attr
)) {
3115 peer
->stat_pfx_cluster_loop
++;
3116 reason
= "reflected from the same cluster;";
3120 /* Apply incoming filter. */
3121 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3122 peer
->stat_pfx_filter
++;
3127 /* RFC 8212 to prevent route leaks.
3128 * This specification intends to improve this situation by requiring the
3129 * explicit configuration of both BGP Import and Export Policies for any
3130 * External BGP (EBGP) session such as customers, peers, or
3131 * confederation boundaries for all enabled address families. Through
3132 * codification of the aforementioned requirement, operators will
3133 * benefit from consistent behavior across different BGP
3136 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3137 if (!bgp_inbound_policy_exists(peer
,
3138 &peer
->filter
[afi
][safi
])) {
3139 reason
= "inbound policy missing";
3143 bgp_attr_dup(&new_attr
, attr
);
3145 /* Apply incoming route-map.
3146 * NB: new_attr may now contain newly allocated values from route-map
3148 * commands, so we need bgp_attr_flush in the error paths, until we
3150 * the attr (which takes over the memory references) */
3151 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3152 label
, num_labels
) == RMAP_DENY
) {
3153 peer
->stat_pfx_filter
++;
3154 reason
= "route-map;";
3155 bgp_attr_flush(&new_attr
);
3159 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3160 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3161 /* remove from RIB previous entry */
3162 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3165 if (peer
->sort
== BGP_PEER_EBGP
) {
3167 /* If we receive the graceful-shutdown community from an eBGP
3168 * peer we must lower local-preference */
3169 if (new_attr
.community
3170 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3171 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3172 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3174 /* If graceful-shutdown is configured then add the GSHUT
3175 * community to all paths received from eBGP peers */
3176 } else if (bgp_flag_check(peer
->bgp
,
3177 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3178 bgp_attr_add_gshut_community(&new_attr
);
3182 /* next hop check. */
3183 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3184 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3185 peer
->stat_pfx_nh_invalid
++;
3186 reason
= "martian or self next-hop;";
3187 bgp_attr_flush(&new_attr
);
3191 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3192 peer
->stat_pfx_nh_invalid
++;
3193 reason
= "self mac;";
3197 attr_new
= bgp_attr_intern(&new_attr
);
3199 /* If the update is implicit withdraw. */
3201 pi
->uptime
= bgp_clock();
3202 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3204 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3206 /* Same attribute comes in. */
3207 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3208 && attrhash_cmp(pi
->attr
, attr_new
)
3209 && (!has_valid_label
3210 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3211 num_labels
* sizeof(mpls_label_t
))
3213 && (overlay_index_equal(
3214 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3215 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3216 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3217 BGP_CONFIG_DAMPENING
)
3218 && peer
->sort
== BGP_PEER_EBGP
3219 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3220 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3221 bgp_debug_rdpfxpath2str(
3222 afi
, safi
, prd
, p
, label
,
3223 num_labels
, addpath_id
? 1 : 0,
3224 addpath_id
, pfx_buf
,
3226 zlog_debug("%s rcvd %s", peer
->host
,
3230 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3231 != BGP_DAMP_SUPPRESSED
) {
3232 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3234 bgp_process(bgp
, rn
, afi
, safi
);
3236 } else /* Duplicate - odd */
3238 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3239 if (!peer
->rcvd_attr_printed
) {
3241 "%s rcvd UPDATE w/ attr: %s",
3243 peer
->rcvd_attr_str
);
3244 peer
->rcvd_attr_printed
= 1;
3247 bgp_debug_rdpfxpath2str(
3248 afi
, safi
, prd
, p
, label
,
3249 num_labels
, addpath_id
? 1 : 0,
3250 addpath_id
, pfx_buf
,
3253 "%s rcvd %s...duplicate ignored",
3254 peer
->host
, pfx_buf
);
3257 /* graceful restart STALE flag unset. */
3258 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3259 bgp_path_info_unset_flag(
3260 rn
, pi
, BGP_PATH_STALE
);
3261 bgp_process(bgp
, rn
, afi
, safi
);
3265 bgp_unlock_node(rn
);
3266 bgp_attr_unintern(&attr_new
);
3271 /* Withdraw/Announce before we fully processed the withdraw */
3272 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3273 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3274 bgp_debug_rdpfxpath2str(
3275 afi
, safi
, prd
, p
, label
, num_labels
,
3276 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3279 "%s rcvd %s, flapped quicker than processing",
3280 peer
->host
, pfx_buf
);
3283 bgp_path_info_restore(rn
, pi
);
3286 /* Received Logging. */
3287 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3288 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3289 num_labels
, addpath_id
? 1 : 0,
3290 addpath_id
, pfx_buf
,
3292 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3295 /* graceful restart STALE flag unset. */
3296 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3297 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3299 /* The attribute is changed. */
3300 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3302 /* implicit withdraw, decrement aggregate and pcount here.
3303 * only if update is accepted, they'll increment below.
3305 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3307 /* Update bgp route dampening information. */
3308 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3309 && peer
->sort
== BGP_PEER_EBGP
) {
3310 /* This is implicit withdraw so we should update
3313 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3314 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3317 if (safi
== SAFI_MPLS_VPN
) {
3318 struct bgp_node
*prn
= NULL
;
3319 struct bgp_table
*table
= NULL
;
3321 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3322 (struct prefix
*)prd
);
3323 if (bgp_node_has_bgp_path_info_data(prn
)) {
3324 table
= bgp_node_get_bgp_table_info(prn
);
3326 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3327 bgp
, prd
, table
, p
, pi
);
3329 bgp_unlock_node(prn
);
3331 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3332 && (safi
== SAFI_UNICAST
)) {
3333 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3335 * Implicit withdraw case.
3337 ++vnc_implicit_withdraw
;
3338 vnc_import_bgp_del_route(bgp
, p
, pi
);
3339 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3344 /* Special handling for EVPN update of an existing route. If the
3345 * extended community attribute has changed, we need to
3347 * the route using its existing extended community. It will be
3348 * subsequently processed for import with the new extended
3351 if (safi
== SAFI_EVPN
&& !same_attr
) {
3353 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3355 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3358 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3359 attr_new
->ecommunity
);
3361 if (bgp_debug_update(peer
, p
, NULL
, 1))
3363 "Change in EXT-COMM, existing %s new %s",
3365 pi
->attr
->ecommunity
),
3367 attr_new
->ecommunity
));
3368 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3374 /* Update to new attribute. */
3375 bgp_attr_unintern(&pi
->attr
);
3376 pi
->attr
= attr_new
;
3378 /* Update MPLS label */
3379 if (has_valid_label
) {
3380 extra
= bgp_path_info_extra_get(pi
);
3381 if (extra
->label
!= label
) {
3382 memcpy(&extra
->label
, label
,
3383 num_labels
* sizeof(mpls_label_t
));
3384 extra
->num_labels
= num_labels
;
3386 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3387 bgp_set_valid_label(&extra
->label
[0]);
3391 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3392 && (safi
== SAFI_UNICAST
)) {
3393 if (vnc_implicit_withdraw
) {
3395 * Add back the route with its new attributes
3397 * The route is still selected, until the route
3399 * queued by bgp_process actually runs. We have
3401 * update to the VNC side immediately to avoid
3403 * configuration changes (e.g., route-map
3405 * trigger re-importation of the entire RIB.
3407 vnc_import_bgp_add_route(bgp
, p
, pi
);
3408 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3412 /* Update Overlay Index */
3413 if (afi
== AFI_L2VPN
) {
3414 overlay_index_update(
3415 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3416 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3419 /* Update bgp route dampening information. */
3420 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3421 && peer
->sort
== BGP_PEER_EBGP
) {
3422 /* Now we do normal update dampening. */
3423 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3424 if (ret
== BGP_DAMP_SUPPRESSED
) {
3425 bgp_unlock_node(rn
);
3430 /* Nexthop reachability check - for unicast and
3431 * labeled-unicast.. */
3432 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3433 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3434 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3435 && !CHECK_FLAG(peer
->flags
,
3436 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3438 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3443 struct bgp
*bgp_nexthop
= bgp
;
3445 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3446 bgp_nexthop
= pi
->extra
->bgp_orig
;
3448 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3450 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3451 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3453 if (BGP_DEBUG(nht
, NHT
)) {
3454 char buf1
[INET6_ADDRSTRLEN
];
3456 (const void *)&attr_new
3458 buf1
, INET6_ADDRSTRLEN
);
3459 zlog_debug("%s(%s): NH unresolved",
3460 __FUNCTION__
, buf1
);
3462 bgp_path_info_unset_flag(rn
, pi
,
3466 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3469 if (safi
== SAFI_MPLS_VPN
) {
3470 struct bgp_node
*prn
= NULL
;
3471 struct bgp_table
*table
= NULL
;
3473 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3474 (struct prefix
*)prd
);
3475 if (bgp_node_has_bgp_path_info_data(prn
)) {
3476 table
= bgp_node_get_bgp_table_info(prn
);
3478 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3479 bgp
, prd
, table
, p
, pi
);
3481 bgp_unlock_node(prn
);
3485 /* If this is an EVPN route and some attribute has changed,
3487 * route for import. If the extended community has changed, we
3489 * have done the un-import earlier and the import would result
3491 * route getting injected into appropriate L2 VNIs. If it is
3493 * some other attribute change, the import will result in
3495 * the attributes for the route in the VNI(s).
3497 if (safi
== SAFI_EVPN
&& !same_attr
)
3498 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3500 /* Process change. */
3501 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3503 bgp_process(bgp
, rn
, afi
, safi
);
3504 bgp_unlock_node(rn
);
3506 if (SAFI_UNICAST
== safi
3507 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3508 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3510 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3512 if ((SAFI_MPLS_VPN
== safi
)
3513 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3515 vpn_leak_to_vrf_update(bgp
, pi
);
3519 if (SAFI_MPLS_VPN
== safi
) {
3520 mpls_label_t label_decoded
= decode_label(label
);
3522 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3523 type
, sub_type
, &label_decoded
);
3525 if (SAFI_ENCAP
== safi
) {
3526 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3527 type
, sub_type
, NULL
);
3532 } // End of implicit withdraw
3534 /* Received Logging. */
3535 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3536 if (!peer
->rcvd_attr_printed
) {
3537 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3538 peer
->rcvd_attr_str
);
3539 peer
->rcvd_attr_printed
= 1;
3542 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3543 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3545 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3548 /* Make new BGP info. */
3549 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3551 /* Update MPLS label */
3552 if (has_valid_label
) {
3553 extra
= bgp_path_info_extra_get(new);
3554 if (extra
->label
!= label
) {
3555 memcpy(&extra
->label
, label
,
3556 num_labels
* sizeof(mpls_label_t
));
3557 extra
->num_labels
= num_labels
;
3559 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3560 bgp_set_valid_label(&extra
->label
[0]);
3563 /* Update Overlay Index */
3564 if (afi
== AFI_L2VPN
) {
3565 overlay_index_update(new->attr
,
3566 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3567 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3569 /* Nexthop reachability check. */
3570 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3571 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3572 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3573 && !CHECK_FLAG(peer
->flags
,
3574 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3575 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3580 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3581 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3582 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3584 if (BGP_DEBUG(nht
, NHT
)) {
3585 char buf1
[INET6_ADDRSTRLEN
];
3587 (const void *)&attr_new
->nexthop
,
3588 buf1
, INET6_ADDRSTRLEN
);
3589 zlog_debug("%s(%s): NH unresolved",
3590 __FUNCTION__
, buf1
);
3592 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3595 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3598 new->addpath_rx_id
= addpath_id
;
3600 /* Increment prefix */
3601 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3603 /* Register new BGP information. */
3604 bgp_path_info_add(rn
, new);
3606 /* route_node_get lock */
3607 bgp_unlock_node(rn
);
3610 if (safi
== SAFI_MPLS_VPN
) {
3611 struct bgp_node
*prn
= NULL
;
3612 struct bgp_table
*table
= NULL
;
3614 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3615 if (bgp_node_has_bgp_path_info_data(prn
)) {
3616 table
= bgp_node_get_bgp_table_info(prn
);
3618 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3619 bgp
, prd
, table
, p
, new);
3621 bgp_unlock_node(prn
);
3625 /* If maximum prefix count is configured and current prefix
3627 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3630 /* If this is an EVPN route, process for import. */
3631 if (safi
== SAFI_EVPN
)
3632 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3634 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3636 /* Process change. */
3637 bgp_process(bgp
, rn
, afi
, safi
);
3639 if (SAFI_UNICAST
== safi
3640 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3641 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3642 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3644 if ((SAFI_MPLS_VPN
== safi
)
3645 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3647 vpn_leak_to_vrf_update(bgp
, new);
3650 if (SAFI_MPLS_VPN
== safi
) {
3651 mpls_label_t label_decoded
= decode_label(label
);
3653 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3654 sub_type
, &label_decoded
);
3656 if (SAFI_ENCAP
== safi
) {
3657 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3664 /* This BGP update is filtered. Log the reason then update BGP
3667 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3669 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3670 if (!peer
->rcvd_attr_printed
) {
3671 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3672 peer
->rcvd_attr_str
);
3673 peer
->rcvd_attr_printed
= 1;
3676 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3677 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3679 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3680 peer
->host
, pfx_buf
, reason
);
3684 /* If this is an EVPN route, un-import it as it is now filtered.
3686 if (safi
== SAFI_EVPN
)
3687 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3689 if (SAFI_UNICAST
== safi
3690 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3691 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3693 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3695 if ((SAFI_MPLS_VPN
== safi
)
3696 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3698 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3701 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3704 bgp_unlock_node(rn
);
3708 * Filtered update is treated as an implicit withdrawal (see
3710 * a few lines above)
3712 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3713 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3721 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3722 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3723 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3724 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3727 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3728 struct bgp_node
*rn
;
3729 struct bgp_path_info
*pi
;
3732 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3733 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3741 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3743 /* If peer is soft reconfiguration enabled. Record input packet for
3744 * further calculation.
3746 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3747 * routes that are filtered. This tanks out Quagga RS pretty badly due
3749 * the iteration over all RS clients.
3750 * Since we need to remove the entry from adj_in anyway, do that first
3752 * if there was no entry, we don't need to do anything more.
3754 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3755 && peer
!= bgp
->peer_self
)
3756 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3757 peer
->stat_pfx_dup_withdraw
++;
3759 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3760 bgp_debug_rdpfxpath2str(
3761 afi
, safi
, prd
, p
, label
, num_labels
,
3762 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3765 "%s withdrawing route %s not in adj-in",
3766 peer
->host
, pfx_buf
);
3768 bgp_unlock_node(rn
);
3772 /* Lookup withdrawn route. */
3773 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3774 if (pi
->peer
== peer
&& pi
->type
== type
3775 && pi
->sub_type
== sub_type
3776 && pi
->addpath_rx_id
== addpath_id
)
3780 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3781 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3782 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3784 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3788 /* Withdraw specified route from routing table. */
3789 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3790 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3791 if (SAFI_UNICAST
== safi
3792 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3793 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3794 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3796 if ((SAFI_MPLS_VPN
== safi
)
3797 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3799 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3801 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3802 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3803 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3805 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3808 /* Unlock bgp_node_get() lock. */
3809 bgp_unlock_node(rn
);
3814 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3817 struct update_subgroup
*subgrp
;
3818 subgrp
= peer_subgroup(peer
, afi
, safi
);
3819 subgroup_default_originate(subgrp
, withdraw
);
3824 * bgp_stop_announce_route_timer
3826 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3828 if (!paf
->t_announce_route
)
3831 THREAD_TIMER_OFF(paf
->t_announce_route
);
3835 * bgp_announce_route_timer_expired
3837 * Callback that is invoked when the route announcement timer for a
3840 static int bgp_announce_route_timer_expired(struct thread
*t
)
3842 struct peer_af
*paf
;
3845 paf
= THREAD_ARG(t
);
3848 if (peer
->status
!= Established
)
3851 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3854 peer_af_announce_route(paf
, 1);
3859 * bgp_announce_route
3861 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3863 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3865 struct peer_af
*paf
;
3866 struct update_subgroup
*subgrp
;
3868 paf
= peer_af_find(peer
, afi
, safi
);
3871 subgrp
= PAF_SUBGRP(paf
);
3874 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3875 * or a refresh has already been triggered.
3877 if (!subgrp
|| paf
->t_announce_route
)
3881 * Start a timer to stagger/delay the announce. This serves
3882 * two purposes - announcement can potentially be combined for
3883 * multiple peers and the announcement doesn't happen in the
3886 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3887 (subgrp
->peer_count
== 1)
3888 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3889 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3890 &paf
->t_announce_route
);
3894 * Announce routes from all AF tables to a peer.
3896 * This should ONLY be called when there is a need to refresh the
3897 * routes to the peer based on a policy change for this peer alone
3898 * or a route refresh request received from the peer.
3899 * The operation will result in splitting the peer from its existing
3900 * subgroups and putting it in new subgroups.
3902 void bgp_announce_route_all(struct peer
*peer
)
3907 FOREACH_AFI_SAFI (afi
, safi
)
3908 bgp_announce_route(peer
, afi
, safi
);
3911 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3912 struct bgp_table
*table
,
3913 struct prefix_rd
*prd
)
3916 struct bgp_node
*rn
;
3917 struct bgp_adj_in
*ain
;
3920 table
= peer
->bgp
->rib
[afi
][safi
];
3922 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3923 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3924 if (ain
->peer
!= peer
)
3927 struct bgp_path_info
*pi
;
3928 uint32_t num_labels
= 0;
3929 mpls_label_t
*label_pnt
= NULL
;
3930 struct bgp_route_evpn evpn
;
3932 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3934 if (pi
->peer
== peer
)
3937 if (pi
&& pi
->extra
)
3938 num_labels
= pi
->extra
->num_labels
;
3940 label_pnt
= &pi
->extra
->label
[0];
3942 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3945 memset(&evpn
, 0, sizeof(evpn
));
3947 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3948 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3949 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3950 num_labels
, 1, &evpn
);
3953 bgp_unlock_node(rn
);
3959 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3961 struct bgp_node
*rn
;
3962 struct bgp_table
*table
;
3964 if (peer
->status
!= Established
)
3967 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3968 && (safi
!= SAFI_EVPN
))
3969 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3971 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3972 rn
= bgp_route_next(rn
)) {
3973 table
= bgp_node_get_bgp_table_info(rn
);
3974 if (table
!= NULL
) {
3975 struct prefix_rd prd
;
3977 prd
.family
= AF_UNSPEC
;
3979 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3981 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3988 struct bgp_clear_node_queue
{
3989 struct bgp_node
*rn
;
3992 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3994 struct bgp_clear_node_queue
*cnq
= data
;
3995 struct bgp_node
*rn
= cnq
->rn
;
3996 struct peer
*peer
= wq
->spec
.data
;
3997 struct bgp_path_info
*pi
;
3999 afi_t afi
= bgp_node_table(rn
)->afi
;
4000 safi_t safi
= bgp_node_table(rn
)->safi
;
4005 /* It is possible that we have multiple paths for a prefix from a peer
4006 * if that peer is using AddPath.
4008 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4009 if (pi
->peer
!= peer
)
4012 /* graceful restart STALE flag set. */
4013 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4014 && peer
->nsf
[afi
][safi
]
4015 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4016 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4017 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4019 /* If this is an EVPN route, process for
4021 if (safi
== SAFI_EVPN
)
4022 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4024 /* Handle withdraw for VRF route-leaking and L3VPN */
4025 if (SAFI_UNICAST
== safi
4026 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4027 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4028 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4031 if (SAFI_MPLS_VPN
== safi
&&
4032 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4033 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4036 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4042 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4044 struct bgp_clear_node_queue
*cnq
= data
;
4045 struct bgp_node
*rn
= cnq
->rn
;
4046 struct bgp_table
*table
= bgp_node_table(rn
);
4048 bgp_unlock_node(rn
);
4049 bgp_table_unlock(table
);
4050 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4053 static void bgp_clear_node_complete(struct work_queue
*wq
)
4055 struct peer
*peer
= wq
->spec
.data
;
4057 /* Tickle FSM to start moving again */
4058 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4060 peer_unlock(peer
); /* bgp_clear_route */
4063 static void bgp_clear_node_queue_init(struct peer
*peer
)
4065 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4067 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4068 #undef CLEAR_QUEUE_NAME_LEN
4070 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4071 peer
->clear_node_queue
->spec
.hold
= 10;
4072 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4073 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4074 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4075 peer
->clear_node_queue
->spec
.max_retries
= 0;
4077 /* we only 'lock' this peer reference when the queue is actually active
4079 peer
->clear_node_queue
->spec
.data
= peer
;
4082 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4083 struct bgp_table
*table
)
4085 struct bgp_node
*rn
;
4086 int force
= bm
->process_main_queue
? 0 : 1;
4089 table
= peer
->bgp
->rib
[afi
][safi
];
4091 /* If still no table => afi/safi isn't configured at all or smth. */
4095 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4096 struct bgp_path_info
*pi
, *next
;
4097 struct bgp_adj_in
*ain
;
4098 struct bgp_adj_in
*ain_next
;
4100 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4101 * queued for every clearing peer, regardless of whether it is
4102 * relevant to the peer at hand.
4104 * Overview: There are 3 different indices which need to be
4105 * scrubbed, potentially, when a peer is removed:
4107 * 1 peer's routes visible via the RIB (ie accepted routes)
4108 * 2 peer's routes visible by the (optional) peer's adj-in index
4109 * 3 other routes visible by the peer's adj-out index
4111 * 3 there is no hurry in scrubbing, once the struct peer is
4112 * removed from bgp->peer, we could just GC such deleted peer's
4113 * adj-outs at our leisure.
4115 * 1 and 2 must be 'scrubbed' in some way, at least made
4116 * invisible via RIB index before peer session is allowed to be
4117 * brought back up. So one needs to know when such a 'search' is
4122 * - there'd be a single global queue or a single RIB walker
4123 * - rather than tracking which route_nodes still need to be
4124 * examined on a peer basis, we'd track which peers still
4127 * Given that our per-peer prefix-counts now should be reliable,
4128 * this may actually be achievable. It doesn't seem to be a huge
4129 * problem at this time,
4131 * It is possible that we have multiple paths for a prefix from
4133 * if that peer is using AddPath.
4137 ain_next
= ain
->next
;
4139 if (ain
->peer
== peer
) {
4140 bgp_adj_in_remove(rn
, ain
);
4141 bgp_unlock_node(rn
);
4147 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4149 if (pi
->peer
!= peer
)
4153 bgp_path_info_reap(rn
, pi
);
4155 struct bgp_clear_node_queue
*cnq
;
4157 /* both unlocked in bgp_clear_node_queue_del */
4158 bgp_table_lock(bgp_node_table(rn
));
4161 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4162 sizeof(struct bgp_clear_node_queue
));
4164 work_queue_add(peer
->clear_node_queue
, cnq
);
4172 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4174 struct bgp_node
*rn
;
4175 struct bgp_table
*table
;
4177 if (peer
->clear_node_queue
== NULL
)
4178 bgp_clear_node_queue_init(peer
);
4180 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4181 * Idle until it receives a Clearing_Completed event. This protects
4182 * against peers which flap faster than we can we clear, which could
4185 * a) race with routes from the new session being installed before
4186 * clear_route_node visits the node (to delete the route of that
4188 * b) resource exhaustion, clear_route_node likely leads to an entry
4189 * on the process_main queue. Fast-flapping could cause that queue
4193 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4194 * the unlock will happen upon work-queue completion; other wise, the
4195 * unlock happens at the end of this function.
4197 if (!peer
->clear_node_queue
->thread
)
4200 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4201 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4203 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4204 rn
= bgp_route_next(rn
)) {
4205 table
= bgp_node_get_bgp_table_info(rn
);
4209 bgp_clear_route_table(peer
, afi
, safi
, table
);
4212 /* unlock if no nodes got added to the clear-node-queue. */
4213 if (!peer
->clear_node_queue
->thread
)
4217 void bgp_clear_route_all(struct peer
*peer
)
4222 FOREACH_AFI_SAFI (afi
, safi
)
4223 bgp_clear_route(peer
, afi
, safi
);
4226 rfapiProcessPeerDown(peer
);
4230 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4232 struct bgp_table
*table
;
4233 struct bgp_node
*rn
;
4234 struct bgp_adj_in
*ain
;
4235 struct bgp_adj_in
*ain_next
;
4237 table
= peer
->bgp
->rib
[afi
][safi
];
4239 /* It is possible that we have multiple paths for a prefix from a peer
4240 * if that peer is using AddPath.
4242 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4246 ain_next
= ain
->next
;
4248 if (ain
->peer
== peer
) {
4249 bgp_adj_in_remove(rn
, ain
);
4250 bgp_unlock_node(rn
);
4258 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4260 struct bgp_node
*rn
;
4261 struct bgp_path_info
*pi
;
4262 struct bgp_table
*table
;
4264 if (safi
== SAFI_MPLS_VPN
) {
4265 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4266 rn
= bgp_route_next(rn
)) {
4267 struct bgp_node
*rm
;
4269 /* look for neighbor in tables */
4270 table
= bgp_node_get_bgp_table_info(rn
);
4274 for (rm
= bgp_table_top(table
); rm
;
4275 rm
= bgp_route_next(rm
))
4276 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4278 if (pi
->peer
!= peer
)
4280 if (!CHECK_FLAG(pi
->flags
,
4284 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4289 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4290 rn
= bgp_route_next(rn
))
4291 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4293 if (pi
->peer
!= peer
)
4295 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4297 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4303 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4305 if (peer
->sort
== BGP_PEER_EBGP
4306 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4307 || FILTER_LIST_OUT_NAME(filter
)
4308 || DISTRIBUTE_OUT_NAME(filter
)))
4313 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4315 if (peer
->sort
== BGP_PEER_EBGP
4316 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4317 || FILTER_LIST_IN_NAME(filter
)
4318 || DISTRIBUTE_IN_NAME(filter
)))
4323 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4326 struct bgp_node
*rn
;
4327 struct bgp_path_info
*pi
;
4328 struct bgp_path_info
*next
;
4330 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4331 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4334 /* Unimport EVPN routes from VRFs */
4335 if (safi
== SAFI_EVPN
)
4336 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4340 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4341 && pi
->type
== ZEBRA_ROUTE_BGP
4342 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4343 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4344 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4346 if (bgp_fibupd_safi(safi
))
4347 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4349 bgp_path_info_reap(rn
, pi
);
4354 /* Delete all kernel routes. */
4355 void bgp_cleanup_routes(struct bgp
*bgp
)
4358 struct bgp_node
*rn
;
4359 struct bgp_table
*table
;
4361 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4362 if (afi
== AFI_L2VPN
)
4364 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4367 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4369 if (afi
!= AFI_L2VPN
) {
4371 safi
= SAFI_MPLS_VPN
;
4372 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4373 rn
= bgp_route_next(rn
)) {
4374 table
= bgp_node_get_bgp_table_info(rn
);
4375 if (table
!= NULL
) {
4376 bgp_cleanup_table(bgp
, table
, safi
);
4377 bgp_table_finish(&table
);
4378 bgp_node_set_bgp_table_info(rn
, NULL
);
4379 bgp_unlock_node(rn
);
4383 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4384 rn
= bgp_route_next(rn
)) {
4385 table
= bgp_node_get_bgp_table_info(rn
);
4386 if (table
!= NULL
) {
4387 bgp_cleanup_table(bgp
, table
, safi
);
4388 bgp_table_finish(&table
);
4389 bgp_node_set_bgp_table_info(rn
, NULL
);
4390 bgp_unlock_node(rn
);
4395 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4396 rn
= bgp_route_next(rn
)) {
4397 table
= bgp_node_get_bgp_table_info(rn
);
4398 if (table
!= NULL
) {
4399 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4400 bgp_table_finish(&table
);
4401 bgp_node_set_bgp_table_info(rn
, NULL
);
4402 bgp_unlock_node(rn
);
4407 void bgp_reset(void)
4410 bgp_zclient_reset();
4411 access_list_reset();
4412 prefix_list_reset();
4415 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4417 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4418 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4419 PEER_CAP_ADDPATH_AF_TX_RCV
));
4422 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4424 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4425 struct bgp_nlri
*packet
)
4434 int addpath_encoded
;
4435 uint32_t addpath_id
;
4438 lim
= pnt
+ packet
->length
;
4440 safi
= packet
->safi
;
4442 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4444 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4445 syntactic validity. If the field is syntactically incorrect,
4446 then the Error Subcode is set to Invalid Network Field. */
4447 for (; pnt
< lim
; pnt
+= psize
) {
4448 /* Clear prefix structure. */
4449 memset(&p
, 0, sizeof(struct prefix
));
4451 if (addpath_encoded
) {
4453 /* When packet overflow occurs return immediately. */
4454 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4455 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4457 addpath_id
= ntohl(*((uint32_t *)pnt
));
4458 pnt
+= BGP_ADDPATH_ID_LEN
;
4461 /* Fetch prefix length. */
4462 p
.prefixlen
= *pnt
++;
4463 /* afi/safi validity already verified by caller,
4464 * bgp_update_receive */
4465 p
.family
= afi2family(afi
);
4467 /* Prefix length check. */
4468 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4471 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4472 peer
->host
, p
.prefixlen
, packet
->afi
);
4473 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4476 /* Packet size overflow check. */
4477 psize
= PSIZE(p
.prefixlen
);
4479 /* When packet overflow occur return immediately. */
4480 if (pnt
+ psize
> lim
) {
4483 "%s [Error] Update packet error (prefix length %d overflows packet)",
4484 peer
->host
, p
.prefixlen
);
4485 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4488 /* Defensive coding, double-check the psize fits in a struct
4490 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4493 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4494 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4495 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4498 /* Fetch prefix from NLRI packet. */
4499 memcpy(p
.u
.val
, pnt
, psize
);
4501 /* Check address. */
4502 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4503 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4504 /* From RFC4271 Section 6.3:
4506 * If a prefix in the NLRI field is semantically
4508 * (e.g., an unexpected multicast IP address),
4510 * be logged locally, and the prefix SHOULD be
4515 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4516 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4521 /* Check address. */
4522 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4523 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4528 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4530 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4535 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4540 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4542 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4549 /* Normal process. */
4551 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4552 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4553 NULL
, NULL
, 0, 0, NULL
);
4555 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4556 safi
, ZEBRA_ROUTE_BGP
,
4557 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4560 /* Do not send BGP notification twice when maximum-prefix count
4562 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4563 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4565 /* Address family configuration mismatch. */
4567 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4570 /* Packet length consistency check. */
4574 "%s [Error] Update packet error (prefix length mismatch with total length)",
4576 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4579 return BGP_NLRI_PARSE_OK
;
4582 static struct bgp_static
*bgp_static_new(void)
4584 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4587 static void bgp_static_free(struct bgp_static
*bgp_static
)
4589 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4590 route_map_counter_decrement(bgp_static
->rmap
.map
);
4592 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4593 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4596 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4597 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4599 struct bgp_node
*rn
;
4600 struct bgp_path_info
*pi
;
4601 struct bgp_path_info
*new;
4602 struct bgp_path_info rmap_path
;
4604 struct attr
*attr_new
;
4605 route_map_result_t ret
;
4607 int vnc_implicit_withdraw
= 0;
4614 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4616 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4618 attr
.nexthop
= bgp_static
->igpnexthop
;
4619 attr
.med
= bgp_static
->igpmetric
;
4620 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4622 if (bgp_static
->atomic
)
4623 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4625 /* Store label index, if required. */
4626 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4627 attr
.label_index
= bgp_static
->label_index
;
4628 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4631 /* Apply route-map. */
4632 if (bgp_static
->rmap
.name
) {
4633 struct attr attr_tmp
= attr
;
4635 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4636 rmap_path
.peer
= bgp
->peer_self
;
4637 rmap_path
.attr
= &attr_tmp
;
4639 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4641 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4644 bgp
->peer_self
->rmap_type
= 0;
4646 if (ret
== RMAP_DENYMATCH
) {
4647 /* Free uninterned attribute. */
4648 bgp_attr_flush(&attr_tmp
);
4650 /* Unintern original. */
4651 aspath_unintern(&attr
.aspath
);
4652 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4656 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4657 bgp_attr_add_gshut_community(&attr_tmp
);
4659 attr_new
= bgp_attr_intern(&attr_tmp
);
4662 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4663 bgp_attr_add_gshut_community(&attr
);
4665 attr_new
= bgp_attr_intern(&attr
);
4668 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4669 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4670 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4674 if (attrhash_cmp(pi
->attr
, attr_new
)
4675 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4676 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4677 bgp_unlock_node(rn
);
4678 bgp_attr_unintern(&attr_new
);
4679 aspath_unintern(&attr
.aspath
);
4682 /* The attribute is changed. */
4683 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4685 /* Rewrite BGP route information. */
4686 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4687 bgp_path_info_restore(rn
, pi
);
4689 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4691 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4692 && (safi
== SAFI_UNICAST
)) {
4693 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4695 * Implicit withdraw case.
4696 * We have to do this before pi is
4699 ++vnc_implicit_withdraw
;
4700 vnc_import_bgp_del_route(bgp
, p
, pi
);
4701 vnc_import_bgp_exterior_del_route(
4706 bgp_attr_unintern(&pi
->attr
);
4707 pi
->attr
= attr_new
;
4708 pi
->uptime
= bgp_clock();
4710 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4711 && (safi
== SAFI_UNICAST
)) {
4712 if (vnc_implicit_withdraw
) {
4713 vnc_import_bgp_add_route(bgp
, p
, pi
);
4714 vnc_import_bgp_exterior_add_route(
4720 /* Nexthop reachability check. */
4721 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4722 && (safi
== SAFI_UNICAST
4723 || safi
== SAFI_LABELED_UNICAST
)) {
4725 struct bgp
*bgp_nexthop
= bgp
;
4727 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4728 bgp_nexthop
= pi
->extra
->bgp_orig
;
4730 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4732 bgp_path_info_set_flag(rn
, pi
,
4735 if (BGP_DEBUG(nht
, NHT
)) {
4736 char buf1
[INET6_ADDRSTRLEN
];
4737 inet_ntop(p
->family
,
4741 "%s(%s): Route not in table, not advertising",
4742 __FUNCTION__
, buf1
);
4744 bgp_path_info_unset_flag(
4745 rn
, pi
, BGP_PATH_VALID
);
4748 /* Delete the NHT structure if any, if we're
4750 * enabling/disabling import check. We
4751 * deregister the route
4752 * from NHT to avoid overloading NHT and the
4753 * process interaction
4755 bgp_unlink_nexthop(pi
);
4756 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4758 /* Process change. */
4759 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4760 bgp_process(bgp
, rn
, afi
, safi
);
4762 if (SAFI_UNICAST
== safi
4763 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4765 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4766 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4770 bgp_unlock_node(rn
);
4771 aspath_unintern(&attr
.aspath
);
4776 /* Make new BGP info. */
4777 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4779 /* Nexthop reachability check. */
4780 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4781 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4782 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4783 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4785 if (BGP_DEBUG(nht
, NHT
)) {
4786 char buf1
[INET6_ADDRSTRLEN
];
4787 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4790 "%s(%s): Route not in table, not advertising",
4791 __FUNCTION__
, buf1
);
4793 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4796 /* Delete the NHT structure if any, if we're toggling between
4797 * enabling/disabling import check. We deregister the route
4798 * from NHT to avoid overloading NHT and the process interaction
4800 bgp_unlink_nexthop(new);
4802 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4805 /* Aggregate address increment. */
4806 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4808 /* Register new BGP information. */
4809 bgp_path_info_add(rn
, new);
4811 /* route_node_get lock */
4812 bgp_unlock_node(rn
);
4814 /* Process change. */
4815 bgp_process(bgp
, rn
, afi
, safi
);
4817 if (SAFI_UNICAST
== safi
4818 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4819 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4820 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4823 /* Unintern original. */
4824 aspath_unintern(&attr
.aspath
);
4827 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4830 struct bgp_node
*rn
;
4831 struct bgp_path_info
*pi
;
4833 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4835 /* Check selected route and self inserted route. */
4836 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4837 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4838 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4841 /* Withdraw static BGP route from routing table. */
4843 if (SAFI_UNICAST
== safi
4844 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4845 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4846 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4848 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4849 bgp_unlink_nexthop(pi
);
4850 bgp_path_info_delete(rn
, pi
);
4851 bgp_process(bgp
, rn
, afi
, safi
);
4854 /* Unlock bgp_node_lookup. */
4855 bgp_unlock_node(rn
);
4859 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4861 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4862 afi_t afi
, safi_t safi
,
4863 struct prefix_rd
*prd
)
4865 struct bgp_node
*rn
;
4866 struct bgp_path_info
*pi
;
4868 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4870 /* Check selected route and self inserted route. */
4871 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4872 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4873 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4876 /* Withdraw static BGP route from routing table. */
4879 rfapiProcessWithdraw(
4880 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4881 1); /* Kill, since it is an administrative change */
4883 if (SAFI_MPLS_VPN
== safi
4884 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4885 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4887 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4888 bgp_path_info_delete(rn
, pi
);
4889 bgp_process(bgp
, rn
, afi
, safi
);
4892 /* Unlock bgp_node_lookup. */
4893 bgp_unlock_node(rn
);
4896 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4897 struct bgp_static
*bgp_static
, afi_t afi
,
4900 struct bgp_node
*rn
;
4901 struct bgp_path_info
*new;
4902 struct attr
*attr_new
;
4903 struct attr attr
= {0};
4904 struct bgp_path_info
*pi
;
4906 mpls_label_t label
= 0;
4908 uint32_t num_labels
= 0;
4913 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4915 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4918 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4920 attr
.nexthop
= bgp_static
->igpnexthop
;
4921 attr
.med
= bgp_static
->igpmetric
;
4922 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4924 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4925 || (safi
== SAFI_ENCAP
)) {
4926 if (afi
== AFI_IP
) {
4927 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4928 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4931 if (afi
== AFI_L2VPN
) {
4932 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4934 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4935 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4936 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4937 sizeof(struct in6_addr
));
4938 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4939 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4940 struct bgp_encap_type_vxlan bet
;
4941 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4942 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4943 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4945 if (bgp_static
->router_mac
) {
4946 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4949 /* Apply route-map. */
4950 if (bgp_static
->rmap
.name
) {
4951 struct attr attr_tmp
= attr
;
4952 struct bgp_path_info rmap_path
;
4953 route_map_result_t ret
;
4955 rmap_path
.peer
= bgp
->peer_self
;
4956 rmap_path
.attr
= &attr_tmp
;
4958 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4960 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4963 bgp
->peer_self
->rmap_type
= 0;
4965 if (ret
== RMAP_DENYMATCH
) {
4966 /* Free uninterned attribute. */
4967 bgp_attr_flush(&attr_tmp
);
4969 /* Unintern original. */
4970 aspath_unintern(&attr
.aspath
);
4971 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4976 attr_new
= bgp_attr_intern(&attr_tmp
);
4978 attr_new
= bgp_attr_intern(&attr
);
4981 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4982 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4983 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4987 memset(&add
, 0, sizeof(union gw_addr
));
4988 if (attrhash_cmp(pi
->attr
, attr_new
)
4989 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4990 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4991 bgp_unlock_node(rn
);
4992 bgp_attr_unintern(&attr_new
);
4993 aspath_unintern(&attr
.aspath
);
4996 /* The attribute is changed. */
4997 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4999 /* Rewrite BGP route information. */
5000 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5001 bgp_path_info_restore(rn
, pi
);
5003 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5004 bgp_attr_unintern(&pi
->attr
);
5005 pi
->attr
= attr_new
;
5006 pi
->uptime
= bgp_clock();
5009 label
= decode_label(&pi
->extra
->label
[0]);
5012 /* Process change. */
5013 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5014 bgp_process(bgp
, rn
, afi
, safi
);
5016 if (SAFI_MPLS_VPN
== safi
5017 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5018 vpn_leak_to_vrf_update(bgp
, pi
);
5021 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5022 pi
->attr
, afi
, safi
, pi
->type
,
5023 pi
->sub_type
, &label
);
5025 bgp_unlock_node(rn
);
5026 aspath_unintern(&attr
.aspath
);
5032 /* Make new BGP info. */
5033 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5035 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5036 new->extra
= bgp_path_info_extra_new();
5038 new->extra
->label
[0] = bgp_static
->label
;
5039 new->extra
->num_labels
= num_labels
;
5042 label
= decode_label(&bgp_static
->label
);
5045 /* Aggregate address increment. */
5046 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5048 /* Register new BGP information. */
5049 bgp_path_info_add(rn
, new);
5050 /* route_node_get lock */
5051 bgp_unlock_node(rn
);
5053 /* Process change. */
5054 bgp_process(bgp
, rn
, afi
, safi
);
5056 if (SAFI_MPLS_VPN
== safi
5057 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5058 vpn_leak_to_vrf_update(bgp
, new);
5061 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5062 safi
, new->type
, new->sub_type
, &label
);
5065 /* Unintern original. */
5066 aspath_unintern(&attr
.aspath
);
5069 /* Configure static BGP network. When user don't run zebra, static
5070 route should be installed as valid. */
5071 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5072 const char *ip_str
, afi_t afi
, safi_t safi
,
5073 const char *rmap
, int backdoor
, uint32_t label_index
)
5075 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5078 struct bgp_static
*bgp_static
;
5079 struct bgp_node
*rn
;
5080 uint8_t need_update
= 0;
5082 /* Convert IP prefix string to struct prefix. */
5083 ret
= str2prefix(ip_str
, &p
);
5085 vty_out(vty
, "%% Malformed prefix\n");
5086 return CMD_WARNING_CONFIG_FAILED
;
5088 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5089 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5090 return CMD_WARNING_CONFIG_FAILED
;
5097 /* Set BGP static route configuration. */
5098 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5101 vty_out(vty
, "%% Can't find static route specified\n");
5102 return CMD_WARNING_CONFIG_FAILED
;
5105 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5107 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5108 && (label_index
!= bgp_static
->label_index
)) {
5110 "%% label-index doesn't match static route\n");
5111 return CMD_WARNING_CONFIG_FAILED
;
5114 if ((rmap
&& bgp_static
->rmap
.name
)
5115 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5117 "%% route-map name doesn't match static route\n");
5118 return CMD_WARNING_CONFIG_FAILED
;
5121 /* Update BGP RIB. */
5122 if (!bgp_static
->backdoor
)
5123 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5125 /* Clear configuration. */
5126 bgp_static_free(bgp_static
);
5127 bgp_node_set_bgp_static_info(rn
, NULL
);
5128 bgp_unlock_node(rn
);
5129 bgp_unlock_node(rn
);
5132 /* Set BGP static route configuration. */
5133 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5135 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5137 /* Configuration change. */
5138 /* Label index cannot be changed. */
5139 if (bgp_static
->label_index
!= label_index
) {
5140 vty_out(vty
, "%% cannot change label-index\n");
5141 return CMD_WARNING_CONFIG_FAILED
;
5144 /* Check previous routes are installed into BGP. */
5145 if (bgp_static
->valid
5146 && bgp_static
->backdoor
!= backdoor
)
5149 bgp_static
->backdoor
= backdoor
;
5152 XFREE(MTYPE_ROUTE_MAP_NAME
,
5153 bgp_static
->rmap
.name
);
5154 route_map_counter_decrement(
5155 bgp_static
->rmap
.map
);
5156 bgp_static
->rmap
.name
=
5157 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5158 bgp_static
->rmap
.map
=
5159 route_map_lookup_by_name(rmap
);
5160 route_map_counter_increment(
5161 bgp_static
->rmap
.map
);
5163 XFREE(MTYPE_ROUTE_MAP_NAME
,
5164 bgp_static
->rmap
.name
);
5165 route_map_counter_decrement(
5166 bgp_static
->rmap
.map
);
5167 bgp_static
->rmap
.name
= NULL
;
5168 bgp_static
->rmap
.map
= NULL
;
5169 bgp_static
->valid
= 0;
5171 bgp_unlock_node(rn
);
5173 /* New configuration. */
5174 bgp_static
= bgp_static_new();
5175 bgp_static
->backdoor
= backdoor
;
5176 bgp_static
->valid
= 0;
5177 bgp_static
->igpmetric
= 0;
5178 bgp_static
->igpnexthop
.s_addr
= 0;
5179 bgp_static
->label_index
= label_index
;
5182 XFREE(MTYPE_ROUTE_MAP_NAME
,
5183 bgp_static
->rmap
.name
);
5184 route_map_counter_decrement(
5185 bgp_static
->rmap
.map
);
5186 bgp_static
->rmap
.name
=
5187 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5188 bgp_static
->rmap
.map
=
5189 route_map_lookup_by_name(rmap
);
5190 route_map_counter_increment(
5191 bgp_static
->rmap
.map
);
5193 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5196 bgp_static
->valid
= 1;
5198 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5200 if (!bgp_static
->backdoor
)
5201 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5207 void bgp_static_add(struct bgp
*bgp
)
5211 struct bgp_node
*rn
;
5212 struct bgp_node
*rm
;
5213 struct bgp_table
*table
;
5214 struct bgp_static
*bgp_static
;
5216 FOREACH_AFI_SAFI (afi
, safi
)
5217 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5218 rn
= bgp_route_next(rn
)) {
5219 if (!bgp_node_has_bgp_path_info_data(rn
))
5222 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5223 || (safi
== SAFI_EVPN
)) {
5224 table
= bgp_node_get_bgp_table_info(rn
);
5226 for (rm
= bgp_table_top(table
); rm
;
5227 rm
= bgp_route_next(rm
)) {
5229 bgp_node_get_bgp_static_info(
5231 bgp_static_update_safi(bgp
, &rm
->p
,
5238 bgp_node_get_bgp_static_info(rn
), afi
,
5244 /* Called from bgp_delete(). Delete all static routes from the BGP
5246 void bgp_static_delete(struct bgp
*bgp
)
5250 struct bgp_node
*rn
;
5251 struct bgp_node
*rm
;
5252 struct bgp_table
*table
;
5253 struct bgp_static
*bgp_static
;
5255 FOREACH_AFI_SAFI (afi
, safi
)
5256 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5257 rn
= bgp_route_next(rn
)) {
5258 if (!bgp_node_has_bgp_path_info_data(rn
))
5261 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5262 || (safi
== SAFI_EVPN
)) {
5263 table
= bgp_node_get_bgp_table_info(rn
);
5265 for (rm
= bgp_table_top(table
); rm
;
5266 rm
= bgp_route_next(rm
)) {
5268 bgp_node_get_bgp_static_info(
5273 bgp_static_withdraw_safi(
5274 bgp
, &rm
->p
, AFI_IP
, safi
,
5275 (struct prefix_rd
*)&rn
->p
);
5276 bgp_static_free(bgp_static
);
5277 bgp_node_set_bgp_static_info(rn
, NULL
);
5278 bgp_unlock_node(rn
);
5281 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5282 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5283 bgp_static_free(bgp_static
);
5284 bgp_node_set_bgp_static_info(rn
, NULL
);
5285 bgp_unlock_node(rn
);
5290 void bgp_static_redo_import_check(struct bgp
*bgp
)
5294 struct bgp_node
*rn
;
5295 struct bgp_node
*rm
;
5296 struct bgp_table
*table
;
5297 struct bgp_static
*bgp_static
;
5299 /* Use this flag to force reprocessing of the route */
5300 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5301 FOREACH_AFI_SAFI (afi
, safi
) {
5302 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5303 rn
= bgp_route_next(rn
)) {
5304 if (!bgp_node_has_bgp_path_info_data(rn
))
5307 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5308 || (safi
== SAFI_EVPN
)) {
5309 table
= bgp_node_get_bgp_table_info(rn
);
5311 for (rm
= bgp_table_top(table
); rm
;
5312 rm
= bgp_route_next(rm
)) {
5314 bgp_node_get_bgp_static_info(
5316 bgp_static_update_safi(bgp
, &rm
->p
,
5321 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5322 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5327 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5330 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5333 struct bgp_table
*table
;
5334 struct bgp_node
*rn
;
5335 struct bgp_path_info
*pi
;
5337 /* Do not install the aggregate route if BGP is in the
5338 * process of termination.
5340 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5341 (bgp
->peer_self
== NULL
))
5344 table
= bgp
->rib
[afi
][safi
];
5345 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5346 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5347 if (pi
->peer
== bgp
->peer_self
5348 && ((pi
->type
== ZEBRA_ROUTE_BGP
5349 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5350 || (pi
->type
!= ZEBRA_ROUTE_BGP
5352 == BGP_ROUTE_REDISTRIBUTE
))) {
5353 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5355 bgp_unlink_nexthop(pi
);
5356 bgp_path_info_delete(rn
, pi
);
5357 bgp_process(bgp
, rn
, afi
, safi
);
5364 * Purge all networks and redistributed routes from routing table.
5365 * Invoked upon the instance going down.
5367 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5372 FOREACH_AFI_SAFI (afi
, safi
)
5373 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5378 * Currently this is used to set static routes for VPN and ENCAP.
5379 * I think it can probably be factored with bgp_static_set.
5381 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5382 const char *ip_str
, const char *rd_str
,
5383 const char *label_str
, const char *rmap_str
,
5384 int evpn_type
, const char *esi
, const char *gwip
,
5385 const char *ethtag
, const char *routermac
)
5387 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5390 struct prefix_rd prd
;
5391 struct bgp_node
*prn
;
5392 struct bgp_node
*rn
;
5393 struct bgp_table
*table
;
5394 struct bgp_static
*bgp_static
;
5395 mpls_label_t label
= MPLS_INVALID_LABEL
;
5396 struct prefix gw_ip
;
5398 /* validate ip prefix */
5399 ret
= str2prefix(ip_str
, &p
);
5401 vty_out(vty
, "%% Malformed prefix\n");
5402 return CMD_WARNING_CONFIG_FAILED
;
5405 if ((afi
== AFI_L2VPN
)
5406 && (bgp_build_evpn_prefix(evpn_type
,
5407 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5408 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5409 return CMD_WARNING_CONFIG_FAILED
;
5412 ret
= str2prefix_rd(rd_str
, &prd
);
5414 vty_out(vty
, "%% Malformed rd\n");
5415 return CMD_WARNING_CONFIG_FAILED
;
5419 unsigned long label_val
;
5420 label_val
= strtoul(label_str
, NULL
, 10);
5421 encode_label(label_val
, &label
);
5424 if (safi
== SAFI_EVPN
) {
5425 if (esi
&& str2esi(esi
, NULL
) == 0) {
5426 vty_out(vty
, "%% Malformed ESI\n");
5427 return CMD_WARNING_CONFIG_FAILED
;
5429 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5430 vty_out(vty
, "%% Malformed Router MAC\n");
5431 return CMD_WARNING_CONFIG_FAILED
;
5434 memset(&gw_ip
, 0, sizeof(struct prefix
));
5435 ret
= str2prefix(gwip
, &gw_ip
);
5437 vty_out(vty
, "%% Malformed GatewayIp\n");
5438 return CMD_WARNING_CONFIG_FAILED
;
5440 if ((gw_ip
.family
== AF_INET
5441 && is_evpn_prefix_ipaddr_v6(
5442 (struct prefix_evpn
*)&p
))
5443 || (gw_ip
.family
== AF_INET6
5444 && is_evpn_prefix_ipaddr_v4(
5445 (struct prefix_evpn
*)&p
))) {
5447 "%% GatewayIp family differs with IP prefix\n");
5448 return CMD_WARNING_CONFIG_FAILED
;
5452 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5453 if (!bgp_node_has_bgp_path_info_data(prn
))
5454 bgp_node_set_bgp_table_info(prn
,
5455 bgp_table_init(bgp
, afi
, safi
));
5456 table
= bgp_node_get_bgp_table_info(prn
);
5458 rn
= bgp_node_get(table
, &p
);
5460 if (bgp_node_has_bgp_path_info_data(rn
)) {
5461 vty_out(vty
, "%% Same network configuration exists\n");
5462 bgp_unlock_node(rn
);
5464 /* New configuration. */
5465 bgp_static
= bgp_static_new();
5466 bgp_static
->backdoor
= 0;
5467 bgp_static
->valid
= 0;
5468 bgp_static
->igpmetric
= 0;
5469 bgp_static
->igpnexthop
.s_addr
= 0;
5470 bgp_static
->label
= label
;
5471 bgp_static
->prd
= prd
;
5474 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5475 route_map_counter_decrement(bgp_static
->rmap
.map
);
5476 bgp_static
->rmap
.name
=
5477 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5478 bgp_static
->rmap
.map
=
5479 route_map_lookup_by_name(rmap_str
);
5480 route_map_counter_increment(bgp_static
->rmap
.map
);
5483 if (safi
== SAFI_EVPN
) {
5485 bgp_static
->eth_s_id
=
5487 sizeof(struct eth_segment_id
));
5488 str2esi(esi
, bgp_static
->eth_s_id
);
5491 bgp_static
->router_mac
=
5492 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5493 (void)prefix_str2mac(routermac
,
5494 bgp_static
->router_mac
);
5497 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5499 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5501 bgp_static
->valid
= 1;
5502 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5508 /* Configure static BGP network. */
5509 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5510 const char *ip_str
, const char *rd_str
,
5511 const char *label_str
, int evpn_type
, const char *esi
,
5512 const char *gwip
, const char *ethtag
)
5514 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5517 struct prefix_rd prd
;
5518 struct bgp_node
*prn
;
5519 struct bgp_node
*rn
;
5520 struct bgp_table
*table
;
5521 struct bgp_static
*bgp_static
;
5522 mpls_label_t label
= MPLS_INVALID_LABEL
;
5524 /* Convert IP prefix string to struct prefix. */
5525 ret
= str2prefix(ip_str
, &p
);
5527 vty_out(vty
, "%% Malformed prefix\n");
5528 return CMD_WARNING_CONFIG_FAILED
;
5531 if ((afi
== AFI_L2VPN
)
5532 && (bgp_build_evpn_prefix(evpn_type
,
5533 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5534 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5535 return CMD_WARNING_CONFIG_FAILED
;
5537 ret
= str2prefix_rd(rd_str
, &prd
);
5539 vty_out(vty
, "%% Malformed rd\n");
5540 return CMD_WARNING_CONFIG_FAILED
;
5544 unsigned long label_val
;
5545 label_val
= strtoul(label_str
, NULL
, 10);
5546 encode_label(label_val
, &label
);
5549 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5550 if (!bgp_node_has_bgp_path_info_data(prn
))
5551 bgp_node_set_bgp_table_info(prn
,
5552 bgp_table_init(bgp
, afi
, safi
));
5554 bgp_unlock_node(prn
);
5555 table
= bgp_node_get_bgp_table_info(prn
);
5557 rn
= bgp_node_lookup(table
, &p
);
5560 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5562 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5563 bgp_static_free(bgp_static
);
5564 bgp_node_set_bgp_static_info(rn
, NULL
);
5565 bgp_unlock_node(rn
);
5566 bgp_unlock_node(rn
);
5568 vty_out(vty
, "%% Can't find the route\n");
5573 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5574 const char *rmap_name
)
5576 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5577 struct bgp_rmap
*rmap
;
5579 rmap
= &bgp
->table_map
[afi
][safi
];
5581 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5582 route_map_counter_decrement(rmap
->map
);
5583 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5584 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5585 route_map_counter_increment(rmap
->map
);
5587 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5588 route_map_counter_decrement(rmap
->map
);
5593 if (bgp_fibupd_safi(safi
))
5594 bgp_zebra_announce_table(bgp
, afi
, safi
);
5599 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5600 const char *rmap_name
)
5602 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5603 struct bgp_rmap
*rmap
;
5605 rmap
= &bgp
->table_map
[afi
][safi
];
5606 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5607 route_map_counter_decrement(rmap
->map
);
5611 if (bgp_fibupd_safi(safi
))
5612 bgp_zebra_announce_table(bgp
, afi
, safi
);
5617 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5620 if (bgp
->table_map
[afi
][safi
].name
) {
5621 vty_out(vty
, " table-map %s\n",
5622 bgp
->table_map
[afi
][safi
].name
);
5626 DEFUN (bgp_table_map
,
5629 "BGP table to RIB route download filter\n"
5630 "Name of the route map\n")
5633 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5634 argv
[idx_word
]->arg
);
5636 DEFUN (no_bgp_table_map
,
5637 no_bgp_table_map_cmd
,
5638 "no table-map WORD",
5640 "BGP table to RIB route download filter\n"
5641 "Name of the route map\n")
5644 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5645 argv
[idx_word
]->arg
);
5651 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5652 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5653 backdoor$backdoor}]",
5655 "Specify a network to announce via BGP\n"
5660 "Route-map to modify the attributes\n"
5661 "Name of the route map\n"
5662 "Label index to associate with the prefix\n"
5663 "Label index value\n"
5664 "Specify a BGP backdoor route\n")
5666 char addr_prefix_str
[BUFSIZ
];
5671 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5674 vty_out(vty
, "%% Inconsistent address and mask\n");
5675 return CMD_WARNING_CONFIG_FAILED
;
5679 return bgp_static_set(
5680 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5681 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5682 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5685 DEFPY(ipv6_bgp_network
,
5686 ipv6_bgp_network_cmd
,
5687 "[no] network X:X::X:X/M$prefix \
5688 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5690 "Specify a network to announce via BGP\n"
5692 "Route-map to modify the attributes\n"
5693 "Name of the route map\n"
5694 "Label index to associate with the prefix\n"
5695 "Label index value\n")
5697 return bgp_static_set(
5698 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5699 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5702 static struct bgp_aggregate
*bgp_aggregate_new(void)
5704 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5707 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5709 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5710 route_map_counter_decrement(aggregate
->rmap
.map
);
5711 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5714 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5715 struct aspath
*aspath
,
5716 struct community
*comm
,
5717 struct ecommunity
*ecomm
,
5718 struct lcommunity
*lcomm
)
5720 static struct aspath
*ae
= NULL
;
5723 ae
= aspath_empty();
5728 if (origin
!= pi
->attr
->origin
)
5731 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5734 if (!community_cmp(pi
->attr
->community
, comm
))
5737 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5740 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5743 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5749 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5750 struct prefix
*p
, uint8_t origin
,
5751 struct aspath
*aspath
,
5752 struct community
*community
,
5753 struct ecommunity
*ecommunity
,
5754 struct lcommunity
*lcommunity
,
5755 uint8_t atomic_aggregate
,
5756 struct bgp_aggregate
*aggregate
)
5758 struct bgp_node
*rn
;
5759 struct bgp_table
*table
;
5760 struct bgp_path_info
*pi
, *orig
, *new;
5763 table
= bgp
->rib
[afi
][safi
];
5765 rn
= bgp_node_get(table
, p
);
5767 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5768 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5769 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5772 if (aggregate
->count
> 0) {
5774 * If the aggregate information has not changed
5775 * no need to re-install it again.
5777 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5778 ecommunity
, lcommunity
)) {
5779 bgp_unlock_node(rn
);
5782 aspath_free(aspath
);
5784 community_free(&community
);
5786 ecommunity_free(&ecommunity
);
5788 lcommunity_free(&lcommunity
);
5794 * Mark the old as unusable
5797 bgp_path_info_delete(rn
, pi
);
5799 attr
= bgp_attr_aggregate_intern(
5800 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5801 aggregate
, atomic_aggregate
, p
);
5804 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5808 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5809 bgp
->peer_self
, attr
, rn
);
5811 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5813 bgp_path_info_add(rn
, new);
5814 bgp_process(bgp
, rn
, afi
, safi
);
5816 for (pi
= orig
; pi
; pi
= pi
->next
)
5817 if (pi
->peer
== bgp
->peer_self
5818 && pi
->type
== ZEBRA_ROUTE_BGP
5819 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5822 /* Withdraw static BGP route from routing table. */
5824 bgp_path_info_delete(rn
, pi
);
5825 bgp_process(bgp
, rn
, afi
, safi
);
5829 bgp_unlock_node(rn
);
5832 /* Update an aggregate as routes are added/removed from the BGP table */
5833 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5834 afi_t afi
, safi_t safi
,
5835 struct bgp_aggregate
*aggregate
)
5837 struct bgp_table
*table
;
5838 struct bgp_node
*top
;
5839 struct bgp_node
*rn
;
5841 struct aspath
*aspath
= NULL
;
5842 struct community
*community
= NULL
;
5843 struct ecommunity
*ecommunity
= NULL
;
5844 struct lcommunity
*lcommunity
= NULL
;
5845 struct bgp_path_info
*pi
;
5846 unsigned long match
= 0;
5847 uint8_t atomic_aggregate
= 0;
5849 /* If the bgp instance is being deleted or self peer is deleted
5850 * then do not create aggregate route
5852 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5853 (bgp
->peer_self
== NULL
))
5856 /* ORIGIN attribute: If at least one route among routes that are
5857 aggregated has ORIGIN with the value INCOMPLETE, then the
5858 aggregated route must have the ORIGIN attribute with the value
5859 INCOMPLETE. Otherwise, if at least one route among routes that
5860 are aggregated has ORIGIN with the value EGP, then the aggregated
5861 route must have the origin attribute with the value EGP. In all
5862 other case the value of the ORIGIN attribute of the aggregated
5863 route is INTERNAL. */
5864 origin
= BGP_ORIGIN_IGP
;
5866 table
= bgp
->rib
[afi
][safi
];
5868 top
= bgp_node_get(table
, p
);
5869 for (rn
= bgp_node_get(table
, p
); rn
;
5870 rn
= bgp_route_next_until(rn
, top
)) {
5871 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5876 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5877 if (BGP_PATH_HOLDDOWN(pi
))
5881 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5882 atomic_aggregate
= 1;
5884 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5888 * summary-only aggregate route suppress
5889 * aggregated route announcements.
5891 if (aggregate
->summary_only
) {
5892 (bgp_path_info_extra_get(pi
))->suppress
++;
5893 bgp_path_info_set_flag(rn
, pi
,
5894 BGP_PATH_ATTR_CHANGED
);
5901 * If at least one route among routes that are
5902 * aggregated has ORIGIN with the value INCOMPLETE,
5903 * then the aggregated route MUST have the ORIGIN
5904 * attribute with the value INCOMPLETE. Otherwise, if
5905 * at least one route among routes that are aggregated
5906 * has ORIGIN with the value EGP, then the aggregated
5907 * route MUST have the ORIGIN attribute with the value
5910 switch (pi
->attr
->origin
) {
5911 case BGP_ORIGIN_INCOMPLETE
:
5912 aggregate
->incomplete_origin_count
++;
5914 case BGP_ORIGIN_EGP
:
5915 aggregate
->egp_origin_count
++;
5923 if (!aggregate
->as_set
)
5927 * as-set aggregate route generate origin, as path,
5928 * and community aggregation.
5930 /* Compute aggregate route's as-path.
5932 bgp_compute_aggregate_aspath_hash(aggregate
,
5935 /* Compute aggregate route's community.
5937 if (pi
->attr
->community
)
5938 bgp_compute_aggregate_community_hash(
5940 pi
->attr
->community
);
5942 /* Compute aggregate route's extended community.
5944 if (pi
->attr
->ecommunity
)
5945 bgp_compute_aggregate_ecommunity_hash(
5947 pi
->attr
->ecommunity
);
5949 /* Compute aggregate route's large community.
5951 if (pi
->attr
->lcommunity
)
5952 bgp_compute_aggregate_lcommunity_hash(
5954 pi
->attr
->lcommunity
);
5957 bgp_process(bgp
, rn
, afi
, safi
);
5959 if (aggregate
->as_set
) {
5960 bgp_compute_aggregate_aspath_val(aggregate
);
5961 bgp_compute_aggregate_community_val(aggregate
);
5962 bgp_compute_aggregate_ecommunity_val(aggregate
);
5963 bgp_compute_aggregate_lcommunity_val(aggregate
);
5967 bgp_unlock_node(top
);
5970 if (aggregate
->incomplete_origin_count
> 0)
5971 origin
= BGP_ORIGIN_INCOMPLETE
;
5972 else if (aggregate
->egp_origin_count
> 0)
5973 origin
= BGP_ORIGIN_EGP
;
5975 if (aggregate
->as_set
) {
5976 if (aggregate
->aspath
)
5977 /* Retrieve aggregate route's as-path.
5979 aspath
= aspath_dup(aggregate
->aspath
);
5981 if (aggregate
->community
)
5982 /* Retrieve aggregate route's community.
5984 community
= community_dup(aggregate
->community
);
5986 if (aggregate
->ecommunity
)
5987 /* Retrieve aggregate route's ecommunity.
5989 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5991 if (aggregate
->lcommunity
)
5992 /* Retrieve aggregate route's lcommunity.
5994 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
5997 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
5998 ecommunity
, lcommunity
, atomic_aggregate
,
6002 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6003 safi_t safi
, struct bgp_aggregate
*aggregate
)
6005 struct bgp_table
*table
;
6006 struct bgp_node
*top
;
6007 struct bgp_node
*rn
;
6008 struct bgp_path_info
*pi
;
6009 unsigned long match
;
6011 table
= bgp
->rib
[afi
][safi
];
6013 /* If routes exists below this node, generate aggregate routes. */
6014 top
= bgp_node_get(table
, p
);
6015 for (rn
= bgp_node_get(table
, p
); rn
;
6016 rn
= bgp_route_next_until(rn
, top
)) {
6017 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6021 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6022 if (BGP_PATH_HOLDDOWN(pi
))
6025 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6028 if (aggregate
->summary_only
&& pi
->extra
) {
6029 pi
->extra
->suppress
--;
6031 if (pi
->extra
->suppress
== 0) {
6032 bgp_path_info_set_flag(
6033 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6039 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6040 aggregate
->incomplete_origin_count
--;
6041 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6042 aggregate
->egp_origin_count
--;
6044 if (aggregate
->as_set
) {
6045 /* Remove as-path from aggregate.
6047 bgp_remove_aspath_from_aggregate_hash(
6051 if (pi
->attr
->community
)
6052 /* Remove community from aggregate.
6054 bgp_remove_comm_from_aggregate_hash(
6056 pi
->attr
->community
);
6058 if (pi
->attr
->ecommunity
)
6059 /* Remove ecommunity from aggregate.
6061 bgp_remove_ecomm_from_aggregate_hash(
6063 pi
->attr
->ecommunity
);
6065 if (pi
->attr
->lcommunity
)
6066 /* Remove lcommunity from aggregate.
6068 bgp_remove_lcomm_from_aggregate_hash(
6070 pi
->attr
->lcommunity
);
6075 /* If this node was suppressed, process the change. */
6077 bgp_process(bgp
, rn
, afi
, safi
);
6079 if (aggregate
->as_set
) {
6080 aspath_free(aggregate
->aspath
);
6081 aggregate
->aspath
= NULL
;
6082 if (aggregate
->community
)
6083 community_free(&aggregate
->community
);
6084 if (aggregate
->ecommunity
)
6085 ecommunity_free(&aggregate
->ecommunity
);
6086 if (aggregate
->lcommunity
)
6087 lcommunity_free(&aggregate
->lcommunity
);
6090 bgp_unlock_node(top
);
6093 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6094 struct bgp_path_info
*pinew
, afi_t afi
,
6096 struct bgp_aggregate
*aggregate
)
6099 struct aspath
*aspath
= NULL
;
6100 uint8_t atomic_aggregate
= 0;
6101 struct community
*community
= NULL
;
6102 struct ecommunity
*ecommunity
= NULL
;
6103 struct lcommunity
*lcommunity
= NULL
;
6105 /* ORIGIN attribute: If at least one route among routes that are
6106 * aggregated has ORIGIN with the value INCOMPLETE, then the
6107 * aggregated route must have the ORIGIN attribute with the value
6108 * INCOMPLETE. Otherwise, if at least one route among routes that
6109 * are aggregated has ORIGIN with the value EGP, then the aggregated
6110 * route must have the origin attribute with the value EGP. In all
6111 * other case the value of the ORIGIN attribute of the aggregated
6112 * route is INTERNAL.
6114 origin
= BGP_ORIGIN_IGP
;
6118 if (aggregate
->summary_only
)
6119 (bgp_path_info_extra_get(pinew
))->suppress
++;
6121 switch (pinew
->attr
->origin
) {
6122 case BGP_ORIGIN_INCOMPLETE
:
6123 aggregate
->incomplete_origin_count
++;
6125 case BGP_ORIGIN_EGP
:
6126 aggregate
->egp_origin_count
++;
6134 if (aggregate
->incomplete_origin_count
> 0)
6135 origin
= BGP_ORIGIN_INCOMPLETE
;
6136 else if (aggregate
->egp_origin_count
> 0)
6137 origin
= BGP_ORIGIN_EGP
;
6139 if (aggregate
->as_set
) {
6140 /* Compute aggregate route's as-path.
6142 bgp_compute_aggregate_aspath(aggregate
,
6143 pinew
->attr
->aspath
);
6145 /* Compute aggregate route's community.
6147 if (pinew
->attr
->community
)
6148 bgp_compute_aggregate_community(
6150 pinew
->attr
->community
);
6152 /* Compute aggregate route's extended community.
6154 if (pinew
->attr
->ecommunity
)
6155 bgp_compute_aggregate_ecommunity(
6157 pinew
->attr
->ecommunity
);
6159 /* Compute aggregate route's large community.
6161 if (pinew
->attr
->lcommunity
)
6162 bgp_compute_aggregate_lcommunity(
6164 pinew
->attr
->lcommunity
);
6166 /* Retrieve aggregate route's as-path.
6168 if (aggregate
->aspath
)
6169 aspath
= aspath_dup(aggregate
->aspath
);
6171 /* Retrieve aggregate route's community.
6173 if (aggregate
->community
)
6174 community
= community_dup(aggregate
->community
);
6176 /* Retrieve aggregate route's ecommunity.
6178 if (aggregate
->ecommunity
)
6179 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6181 /* Retrieve aggregate route's lcommunity.
6183 if (aggregate
->lcommunity
)
6184 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6187 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6188 aspath
, community
, ecommunity
,
6189 lcommunity
, atomic_aggregate
, aggregate
);
6192 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6194 struct bgp_path_info
*pi
,
6195 struct bgp_aggregate
*aggregate
,
6196 struct prefix
*aggr_p
)
6199 struct aspath
*aspath
= NULL
;
6200 uint8_t atomic_aggregate
= 0;
6201 struct community
*community
= NULL
;
6202 struct ecommunity
*ecommunity
= NULL
;
6203 struct lcommunity
*lcommunity
= NULL
;
6204 unsigned long match
= 0;
6206 if (BGP_PATH_HOLDDOWN(pi
))
6209 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6212 if (aggregate
->summary_only
6214 && pi
->extra
->suppress
> 0) {
6215 pi
->extra
->suppress
--;
6217 if (pi
->extra
->suppress
== 0) {
6218 bgp_path_info_set_flag(pi
->net
, pi
,
6219 BGP_PATH_ATTR_CHANGED
);
6224 if (aggregate
->count
> 0)
6227 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6228 aggregate
->incomplete_origin_count
--;
6229 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6230 aggregate
->egp_origin_count
--;
6232 if (aggregate
->as_set
) {
6233 /* Remove as-path from aggregate.
6235 bgp_remove_aspath_from_aggregate(aggregate
,
6238 if (pi
->attr
->community
)
6239 /* Remove community from aggregate.
6241 bgp_remove_community_from_aggregate(
6243 pi
->attr
->community
);
6245 if (pi
->attr
->ecommunity
)
6246 /* Remove ecommunity from aggregate.
6248 bgp_remove_ecommunity_from_aggregate(
6250 pi
->attr
->ecommunity
);
6252 if (pi
->attr
->lcommunity
)
6253 /* Remove lcommunity from aggregate.
6255 bgp_remove_lcommunity_from_aggregate(
6257 pi
->attr
->lcommunity
);
6260 /* If this node was suppressed, process the change. */
6262 bgp_process(bgp
, pi
->net
, afi
, safi
);
6264 origin
= BGP_ORIGIN_IGP
;
6265 if (aggregate
->incomplete_origin_count
> 0)
6266 origin
= BGP_ORIGIN_INCOMPLETE
;
6267 else if (aggregate
->egp_origin_count
> 0)
6268 origin
= BGP_ORIGIN_EGP
;
6270 if (aggregate
->as_set
) {
6271 /* Retrieve aggregate route's as-path.
6273 if (aggregate
->aspath
)
6274 aspath
= aspath_dup(aggregate
->aspath
);
6276 /* Retrieve aggregate route's community.
6278 if (aggregate
->community
)
6279 community
= community_dup(aggregate
->community
);
6281 /* Retrieve aggregate route's ecommunity.
6283 if (aggregate
->ecommunity
)
6284 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6286 /* Retrieve aggregate route's lcommunity.
6288 if (aggregate
->lcommunity
)
6289 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6292 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6293 aspath
, community
, ecommunity
,
6294 lcommunity
, atomic_aggregate
, aggregate
);
6297 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6298 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6300 struct bgp_node
*child
;
6301 struct bgp_node
*rn
;
6302 struct bgp_aggregate
*aggregate
;
6303 struct bgp_table
*table
;
6305 table
= bgp
->aggregate
[afi
][safi
];
6307 /* No aggregates configured. */
6308 if (bgp_table_top_nolock(table
) == NULL
)
6311 if (p
->prefixlen
== 0)
6314 if (BGP_PATH_HOLDDOWN(pi
))
6317 child
= bgp_node_get(table
, p
);
6319 /* Aggregate address configuration check. */
6320 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6321 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6322 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6323 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6327 bgp_unlock_node(child
);
6330 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6331 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6333 struct bgp_node
*child
;
6334 struct bgp_node
*rn
;
6335 struct bgp_aggregate
*aggregate
;
6336 struct bgp_table
*table
;
6338 table
= bgp
->aggregate
[afi
][safi
];
6340 /* No aggregates configured. */
6341 if (bgp_table_top_nolock(table
) == NULL
)
6344 if (p
->prefixlen
== 0)
6347 child
= bgp_node_get(table
, p
);
6349 /* Aggregate address configuration check. */
6350 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6351 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6352 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6353 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6354 del
, aggregate
, &rn
->p
);
6357 bgp_unlock_node(child
);
6360 /* Aggregate route attribute. */
6361 #define AGGREGATE_SUMMARY_ONLY 1
6362 #define AGGREGATE_AS_SET 1
6364 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6365 afi_t afi
, safi_t safi
)
6367 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6370 struct bgp_node
*rn
;
6371 struct bgp_aggregate
*aggregate
;
6373 /* Convert string to prefix structure. */
6374 ret
= str2prefix(prefix_str
, &p
);
6376 vty_out(vty
, "Malformed prefix\n");
6377 return CMD_WARNING_CONFIG_FAILED
;
6381 /* Old configuration check. */
6382 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6385 "%% There is no aggregate-address configuration.\n");
6386 return CMD_WARNING_CONFIG_FAILED
;
6389 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6390 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6391 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6392 NULL
, NULL
, 0, aggregate
);
6394 /* Unlock aggregate address configuration. */
6395 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6397 if (aggregate
->community
)
6398 community_free(&aggregate
->community
);
6400 if (aggregate
->community_hash
) {
6401 /* Delete all communities in the hash.
6403 hash_clean(aggregate
->community_hash
,
6404 bgp_aggr_community_remove
);
6405 /* Free up the community_hash.
6407 hash_free(aggregate
->community_hash
);
6410 if (aggregate
->ecommunity
)
6411 ecommunity_free(&aggregate
->ecommunity
);
6413 if (aggregate
->ecommunity_hash
) {
6414 /* Delete all ecommunities in the hash.
6416 hash_clean(aggregate
->ecommunity_hash
,
6417 bgp_aggr_ecommunity_remove
);
6418 /* Free up the ecommunity_hash.
6420 hash_free(aggregate
->ecommunity_hash
);
6423 if (aggregate
->lcommunity
)
6424 lcommunity_free(&aggregate
->lcommunity
);
6426 if (aggregate
->lcommunity_hash
) {
6427 /* Delete all lcommunities in the hash.
6429 hash_clean(aggregate
->lcommunity_hash
,
6430 bgp_aggr_lcommunity_remove
);
6431 /* Free up the lcommunity_hash.
6433 hash_free(aggregate
->lcommunity_hash
);
6436 if (aggregate
->aspath
)
6437 aspath_free(aggregate
->aspath
);
6439 if (aggregate
->aspath_hash
) {
6440 /* Delete all as-paths in the hash.
6442 hash_clean(aggregate
->aspath_hash
,
6443 bgp_aggr_aspath_remove
);
6444 /* Free up the aspath_hash.
6446 hash_free(aggregate
->aspath_hash
);
6449 bgp_aggregate_free(aggregate
);
6450 bgp_unlock_node(rn
);
6451 bgp_unlock_node(rn
);
6456 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6457 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6460 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6463 struct bgp_node
*rn
;
6464 struct bgp_aggregate
*aggregate
;
6466 /* Convert string to prefix structure. */
6467 ret
= str2prefix(prefix_str
, &p
);
6469 vty_out(vty
, "Malformed prefix\n");
6470 return CMD_WARNING_CONFIG_FAILED
;
6474 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6475 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6476 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6478 return CMD_WARNING_CONFIG_FAILED
;
6481 /* Old configuration check. */
6482 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6483 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6486 vty_out(vty
, "There is already same aggregate network.\n");
6487 /* try to remove the old entry */
6488 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6490 vty_out(vty
, "Error deleting aggregate.\n");
6491 bgp_unlock_node(rn
);
6492 return CMD_WARNING_CONFIG_FAILED
;
6496 /* Make aggregate address structure. */
6497 aggregate
= bgp_aggregate_new();
6498 aggregate
->summary_only
= summary_only
;
6499 aggregate
->as_set
= as_set
;
6500 aggregate
->safi
= safi
;
6503 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6504 route_map_counter_decrement(aggregate
->rmap
.map
);
6505 aggregate
->rmap
.name
=
6506 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6507 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6508 route_map_counter_increment(aggregate
->rmap
.map
);
6510 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6512 /* Aggregate address insert into BGP routing table. */
6513 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6518 DEFUN (aggregate_address
,
6519 aggregate_address_cmd
,
6520 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6521 "Configure BGP aggregate entries\n"
6522 "Aggregate prefix\n"
6523 "Generate AS set path information\n"
6524 "Filter more specific routes from updates\n"
6525 "Filter more specific routes from updates\n"
6526 "Generate AS set path information\n"
6527 "Apply route map to aggregate network\n"
6528 "Name of route map\n")
6531 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6532 char *prefix
= argv
[idx
]->arg
;
6535 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6537 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6538 ? AGGREGATE_SUMMARY_ONLY
6542 argv_find(argv
, argc
, "WORD", &idx
);
6544 rmap
= argv
[idx
]->arg
;
6546 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6547 rmap
, summary_only
, as_set
);
6550 DEFUN (aggregate_address_mask
,
6551 aggregate_address_mask_cmd
,
6552 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6553 "Configure BGP aggregate entries\n"
6554 "Aggregate address\n"
6556 "Generate AS set path information\n"
6557 "Filter more specific routes from updates\n"
6558 "Filter more specific routes from updates\n"
6559 "Generate AS set path information\n"
6560 "Apply route map to aggregate network\n"
6561 "Name of route map\n")
6564 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6565 char *prefix
= argv
[idx
]->arg
;
6566 char *mask
= argv
[idx
+ 1]->arg
;
6570 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6572 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6573 ? AGGREGATE_SUMMARY_ONLY
6576 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6578 rmap
= argv
[idx
]->arg
;
6580 char prefix_str
[BUFSIZ
];
6581 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6584 vty_out(vty
, "%% Inconsistent address and mask\n");
6585 return CMD_WARNING_CONFIG_FAILED
;
6588 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6589 rmap
, summary_only
, as_set
);
6592 DEFUN (no_aggregate_address
,
6593 no_aggregate_address_cmd
,
6594 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6596 "Configure BGP aggregate entries\n"
6597 "Aggregate prefix\n"
6598 "Generate AS set path information\n"
6599 "Filter more specific routes from updates\n"
6600 "Filter more specific routes from updates\n"
6601 "Generate AS set path information\n"
6602 "Apply route map to aggregate network\n"
6603 "Name of route map\n")
6606 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6607 char *prefix
= argv
[idx
]->arg
;
6608 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6611 DEFUN (no_aggregate_address_mask
,
6612 no_aggregate_address_mask_cmd
,
6613 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6615 "Configure BGP aggregate entries\n"
6616 "Aggregate address\n"
6618 "Generate AS set path information\n"
6619 "Filter more specific routes from updates\n"
6620 "Filter more specific routes from updates\n"
6621 "Generate AS set path information\n"
6622 "Apply route map to aggregate network\n"
6623 "Name of route map\n")
6626 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6627 char *prefix
= argv
[idx
]->arg
;
6628 char *mask
= argv
[idx
+ 1]->arg
;
6630 char prefix_str
[BUFSIZ
];
6631 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6634 vty_out(vty
, "%% Inconsistent address and mask\n");
6635 return CMD_WARNING_CONFIG_FAILED
;
6638 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6641 DEFUN (ipv6_aggregate_address
,
6642 ipv6_aggregate_address_cmd
,
6643 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6644 "Configure BGP aggregate entries\n"
6645 "Aggregate prefix\n"
6646 "Generate AS set path information\n"
6647 "Filter more specific routes from updates\n"
6648 "Filter more specific routes from updates\n"
6649 "Generate AS set path information\n"
6650 "Apply route map to aggregate network\n"
6651 "Name of route map\n")
6654 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6655 char *prefix
= argv
[idx
]->arg
;
6659 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6662 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6663 ? AGGREGATE_SUMMARY_ONLY
6666 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6668 rmap
= argv
[idx
]->arg
;
6670 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6674 DEFUN (no_ipv6_aggregate_address
,
6675 no_ipv6_aggregate_address_cmd
,
6676 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6678 "Configure BGP aggregate entries\n"
6679 "Aggregate prefix\n"
6680 "Generate AS set path information\n"
6681 "Filter more specific routes from updates\n"
6682 "Filter more specific routes from updates\n"
6683 "Generate AS set path information\n"
6684 "Apply route map to aggregate network\n"
6685 "Name of route map\n")
6688 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6689 char *prefix
= argv
[idx
]->arg
;
6690 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6693 /* Redistribute route treatment. */
6694 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6695 const union g_addr
*nexthop
, ifindex_t ifindex
,
6696 enum nexthop_types_t nhtype
, uint32_t metric
,
6697 uint8_t type
, unsigned short instance
,
6700 struct bgp_path_info
*new;
6701 struct bgp_path_info
*bpi
;
6702 struct bgp_path_info rmap_path
;
6703 struct bgp_node
*bn
;
6705 struct attr
*new_attr
;
6707 route_map_result_t ret
;
6708 struct bgp_redist
*red
;
6710 /* Make default attribute. */
6711 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6713 * This must not be NULL to satisfy Coverity SA
6715 assert(attr
.aspath
);
6718 case NEXTHOP_TYPE_IFINDEX
:
6720 case NEXTHOP_TYPE_IPV4
:
6721 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6722 attr
.nexthop
= nexthop
->ipv4
;
6724 case NEXTHOP_TYPE_IPV6
:
6725 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6726 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6727 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6729 case NEXTHOP_TYPE_BLACKHOLE
:
6730 switch (p
->family
) {
6732 attr
.nexthop
.s_addr
= INADDR_ANY
;
6735 memset(&attr
.mp_nexthop_global
, 0,
6736 sizeof(attr
.mp_nexthop_global
));
6737 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6742 attr
.nh_ifindex
= ifindex
;
6745 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6748 afi
= family2afi(p
->family
);
6750 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6752 struct attr attr_new
;
6754 /* Copy attribute for modification. */
6755 bgp_attr_dup(&attr_new
, &attr
);
6757 if (red
->redist_metric_flag
)
6758 attr_new
.med
= red
->redist_metric
;
6760 /* Apply route-map. */
6761 if (red
->rmap
.name
) {
6762 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6763 rmap_path
.peer
= bgp
->peer_self
;
6764 rmap_path
.attr
= &attr_new
;
6766 SET_FLAG(bgp
->peer_self
->rmap_type
,
6767 PEER_RMAP_TYPE_REDISTRIBUTE
);
6769 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6772 bgp
->peer_self
->rmap_type
= 0;
6774 if (ret
== RMAP_DENYMATCH
) {
6775 /* Free uninterned attribute. */
6776 bgp_attr_flush(&attr_new
);
6778 /* Unintern original. */
6779 aspath_unintern(&attr
.aspath
);
6780 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6785 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6786 bgp_attr_add_gshut_community(&attr_new
);
6788 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6789 SAFI_UNICAST
, p
, NULL
);
6791 new_attr
= bgp_attr_intern(&attr_new
);
6793 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6795 if (bpi
->peer
== bgp
->peer_self
6796 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6800 /* Ensure the (source route) type is updated. */
6802 if (attrhash_cmp(bpi
->attr
, new_attr
)
6803 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6804 bgp_attr_unintern(&new_attr
);
6805 aspath_unintern(&attr
.aspath
);
6806 bgp_unlock_node(bn
);
6809 /* The attribute is changed. */
6810 bgp_path_info_set_flag(bn
, bpi
,
6811 BGP_PATH_ATTR_CHANGED
);
6813 /* Rewrite BGP route information. */
6814 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6815 bgp_path_info_restore(bn
, bpi
);
6817 bgp_aggregate_decrement(
6818 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6819 bgp_attr_unintern(&bpi
->attr
);
6820 bpi
->attr
= new_attr
;
6821 bpi
->uptime
= bgp_clock();
6823 /* Process change. */
6824 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6826 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6827 bgp_unlock_node(bn
);
6828 aspath_unintern(&attr
.aspath
);
6830 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6832 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6834 vpn_leak_from_vrf_update(
6835 bgp_get_default(), bgp
, bpi
);
6841 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6842 bgp
->peer_self
, new_attr
, bn
);
6843 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6845 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6846 bgp_path_info_add(bn
, new);
6847 bgp_unlock_node(bn
);
6848 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6850 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6851 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6853 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6857 /* Unintern original. */
6858 aspath_unintern(&attr
.aspath
);
6861 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6862 unsigned short instance
)
6865 struct bgp_node
*rn
;
6866 struct bgp_path_info
*pi
;
6867 struct bgp_redist
*red
;
6869 afi
= family2afi(p
->family
);
6871 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6873 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6874 SAFI_UNICAST
, p
, NULL
);
6876 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6877 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6881 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6882 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6884 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6887 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6888 bgp_path_info_delete(rn
, pi
);
6889 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6891 bgp_unlock_node(rn
);
6895 /* Withdraw specified route type's route. */
6896 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6897 unsigned short instance
)
6899 struct bgp_node
*rn
;
6900 struct bgp_path_info
*pi
;
6901 struct bgp_table
*table
;
6903 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6905 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6906 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6907 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6908 && pi
->instance
== instance
)
6912 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6913 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6915 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6918 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6920 bgp_path_info_delete(rn
, pi
);
6921 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6926 /* Static function to display route. */
6927 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6934 if (p
->family
== AF_INET
) {
6938 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6941 json_object_string_add(json
, "prefix",
6942 inet_ntop(p
->family
,
6945 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6946 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6947 json_object_string_add(json
, "network", buf2
);
6949 } else if (p
->family
== AF_ETHERNET
) {
6950 prefix2str(p
, buf
, PREFIX_STRLEN
);
6951 len
= vty_out(vty
, "%s", buf
);
6952 } else if (p
->family
== AF_EVPN
) {
6956 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6959 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6960 } else if (p
->family
== AF_FLOWSPEC
) {
6961 route_vty_out_flowspec(vty
, p
, NULL
,
6963 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6964 NLRI_STRING_FORMAT_MIN
, json
);
6969 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6972 json_object_string_add(json
, "prefix",
6973 inet_ntop(p
->family
,
6976 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6977 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6978 json_object_string_add(json
, "network", buf2
);
6985 vty_out(vty
, "\n%*s", 20, " ");
6987 vty_out(vty
, "%*s", len
, " ");
6991 enum bgp_display_type
{
6995 /* Print the short form route status for a bgp_path_info */
6996 static void route_vty_short_status_out(struct vty
*vty
,
6997 struct bgp_path_info
*path
,
6998 json_object
*json_path
)
7002 /* Route status display. */
7003 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7004 json_object_boolean_true_add(json_path
, "removed");
7006 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7007 json_object_boolean_true_add(json_path
, "stale");
7009 if (path
->extra
&& path
->extra
->suppress
)
7010 json_object_boolean_true_add(json_path
, "suppressed");
7012 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7013 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7014 json_object_boolean_true_add(json_path
, "valid");
7017 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7018 json_object_boolean_true_add(json_path
, "history");
7020 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7021 json_object_boolean_true_add(json_path
, "damped");
7023 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7024 json_object_boolean_true_add(json_path
, "bestpath");
7026 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7027 json_object_boolean_true_add(json_path
, "multipath");
7029 /* Internal route. */
7030 if ((path
->peer
->as
)
7031 && (path
->peer
->as
== path
->peer
->local_as
))
7032 json_object_string_add(json_path
, "pathFrom",
7035 json_object_string_add(json_path
, "pathFrom",
7041 /* Route status display. */
7042 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7044 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7046 else if (path
->extra
&& path
->extra
->suppress
)
7048 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7049 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7055 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7057 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7059 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7061 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7066 /* Internal route. */
7067 if (path
->peer
&& (path
->peer
->as
)
7068 && (path
->peer
->as
== path
->peer
->local_as
))
7074 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7076 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7077 return peer
->hostname
;
7081 /* called from terminal list command */
7082 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7083 struct bgp_path_info
*path
, int display
, safi_t safi
,
7084 json_object
*json_paths
)
7087 json_object
*json_path
= NULL
;
7088 json_object
*json_nexthops
= NULL
;
7089 json_object
*json_nexthop_global
= NULL
;
7090 json_object
*json_nexthop_ll
= NULL
;
7091 json_object
*json_ext_community
= NULL
;
7092 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7094 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7095 bool nexthop_othervrf
= false;
7096 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7097 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7098 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7101 json_path
= json_object_new_object();
7103 /* short status lead text */
7104 route_vty_short_status_out(vty
, path
, json_path
);
7107 /* print prefix and mask */
7109 route_vty_out_route(p
, vty
, json_path
);
7111 vty_out(vty
, "%*s", 17, " ");
7113 route_vty_out_route(p
, vty
, json_path
);
7116 /* Print attribute */
7120 * If vrf id of nexthop is different from that of prefix,
7121 * set up printable string to append
7123 if (path
->extra
&& path
->extra
->bgp_orig
) {
7124 const char *self
= "";
7129 nexthop_othervrf
= true;
7130 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7132 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7133 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7134 "@%s%s", VRFID_NONE_STR
, self
);
7136 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7137 path
->extra
->bgp_orig
->vrf_id
, self
);
7139 if (path
->extra
->bgp_orig
->inst_type
7140 != BGP_INSTANCE_TYPE_DEFAULT
)
7142 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7144 const char *self
= "";
7149 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7153 * For ENCAP and EVPN routes, nexthop address family is not
7154 * neccessarily the same as the prefix address family.
7155 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7156 * EVPN routes are also exchanged with a MP nexthop. Currently,
7158 * is only IPv4, the value will be present in either
7160 * attr->mp_nexthop_global_in
7162 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7165 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7169 sprintf(nexthop
, "%s",
7170 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7174 sprintf(nexthop
, "%s",
7175 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7179 sprintf(nexthop
, "?");
7184 json_nexthop_global
= json_object_new_object();
7186 json_object_string_add(
7187 json_nexthop_global
, "afi",
7188 nexthop_fqdn
? "fqdn"
7189 : (af
== AF_INET
) ? "ip" : "ipv6");
7190 json_object_string_add(
7191 json_nexthop_global
,
7192 nexthop_fqdn
? "fqdn"
7193 : (af
== AF_INET
) ? "ip" : "ipv6",
7194 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7195 json_object_boolean_true_add(json_nexthop_global
,
7198 vty_out(vty
, "%s%s",
7199 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7201 } else if (safi
== SAFI_EVPN
) {
7203 json_nexthop_global
= json_object_new_object();
7205 json_object_string_add(
7206 json_nexthop_global
,
7207 nexthop_fqdn
? "fqdn" : "ip",
7208 nexthop_fqdn
? nexthop_fqdn
7209 : inet_ntoa(attr
->nexthop
));
7210 json_object_string_add(json_nexthop_global
, "afi",
7212 json_object_boolean_true_add(json_nexthop_global
,
7215 vty_out(vty
, "%-16s%s",
7216 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7218 } else if (safi
== SAFI_FLOWSPEC
) {
7219 if (attr
->nexthop
.s_addr
!= 0) {
7221 json_nexthop_global
= json_object_new_object();
7222 json_object_string_add(
7223 json_nexthop_global
,
7224 nexthop_fqdn
? "fqdn" : "ip",
7227 : inet_ntoa(attr
->nexthop
));
7228 json_object_string_add(json_nexthop_global
,
7230 json_object_boolean_true_add(
7231 json_nexthop_global
,
7234 vty_out(vty
, "%-16s",
7237 : inet_ntoa(attr
->nexthop
));
7240 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7242 json_nexthop_global
= json_object_new_object();
7244 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_EVPN
))
7245 json_object_string_add(
7246 json_nexthop_global
,
7247 nexthop_fqdn
? "fqdn" : "ip",
7251 attr
->mp_nexthop_global_in
));
7253 json_object_string_add(
7254 json_nexthop_global
,
7255 nexthop_fqdn
? "fqdn" : "ip",
7258 : inet_ntoa(attr
->nexthop
));
7260 json_object_string_add(json_nexthop_global
, "afi",
7262 json_object_boolean_true_add(json_nexthop_global
,
7267 snprintf(buf
, sizeof(buf
), "%s%s",
7268 nexthop_fqdn
? nexthop_fqdn
7269 : inet_ntoa(attr
->nexthop
),
7271 vty_out(vty
, "%-16s", buf
);
7276 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7281 json_nexthop_global
= json_object_new_object();
7282 json_object_string_add(
7283 json_nexthop_global
,
7284 nexthop_fqdn
? "fqdn" : "ip",
7287 : inet_ntop(AF_INET6
,
7288 &attr
->mp_nexthop_global
,
7290 json_object_string_add(json_nexthop_global
, "afi",
7292 json_object_string_add(json_nexthop_global
, "scope",
7295 /* We display both LL & GL if both have been
7297 if ((attr
->mp_nexthop_len
7298 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7299 || (path
->peer
->conf_if
)) {
7300 json_nexthop_ll
= json_object_new_object();
7301 json_object_string_add(
7303 nexthop_fqdn
? "fqdn" : "ip",
7308 &attr
->mp_nexthop_local
,
7310 json_object_string_add(json_nexthop_ll
, "afi",
7312 json_object_string_add(json_nexthop_ll
, "scope",
7315 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7316 &attr
->mp_nexthop_local
)
7318 && !attr
->mp_nexthop_prefer_global
)
7319 json_object_boolean_true_add(
7320 json_nexthop_ll
, "used");
7322 json_object_boolean_true_add(
7323 json_nexthop_global
, "used");
7325 json_object_boolean_true_add(
7326 json_nexthop_global
, "used");
7328 /* Display LL if LL/Global both in table unless
7329 * prefer-global is set */
7330 if (((attr
->mp_nexthop_len
7331 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7332 && !attr
->mp_nexthop_prefer_global
)
7333 || (path
->peer
->conf_if
)) {
7334 if (path
->peer
->conf_if
) {
7335 len
= vty_out(vty
, "%s",
7336 path
->peer
->conf_if
);
7337 len
= 16 - len
; /* len of IPv6
7343 vty_out(vty
, "\n%*s", 36, " ");
7345 vty_out(vty
, "%*s", len
, " ");
7353 &attr
->mp_nexthop_local
,
7359 vty_out(vty
, "\n%*s", 36, " ");
7361 vty_out(vty
, "%*s", len
, " ");
7370 &attr
->mp_nexthop_global
,
7376 vty_out(vty
, "\n%*s", 36, " ");
7378 vty_out(vty
, "%*s", len
, " ");
7384 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7388 * Adding "metric" field to match with corresponding
7389 * CLI. "med" will be deprecated in future.
7391 json_object_int_add(json_path
, "med", attr
->med
);
7392 json_object_int_add(json_path
, "metric", attr
->med
);
7394 vty_out(vty
, "%10u", attr
->med
);
7395 else if (!json_paths
)
7399 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7403 * Adding "locPrf" field to match with corresponding
7404 * CLI. "localPref" will be deprecated in future.
7406 json_object_int_add(json_path
, "localpref",
7408 json_object_int_add(json_path
, "locPrf",
7411 vty_out(vty
, "%7u", attr
->local_pref
);
7412 else if (!json_paths
)
7416 json_object_int_add(json_path
, "weight", attr
->weight
);
7418 vty_out(vty
, "%7u ", attr
->weight
);
7422 json_object_string_add(
7423 json_path
, "peerId",
7424 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7432 * Adding "path" field to match with corresponding
7433 * CLI. "aspath" will be deprecated in future.
7435 json_object_string_add(json_path
, "aspath",
7437 json_object_string_add(json_path
, "path",
7440 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7445 json_object_string_add(json_path
, "origin",
7446 bgp_origin_long_str
[attr
->origin
]);
7448 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7451 if (safi
== SAFI_EVPN
&&
7452 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7453 json_ext_community
= json_object_new_object();
7454 json_object_string_add(json_ext_community
,
7456 attr
->ecommunity
->str
);
7457 json_object_object_add(json_path
,
7458 "extendedCommunity",
7459 json_ext_community
);
7463 json_object_boolean_true_add(json_path
,
7464 "announceNexthopSelf");
7465 if (nexthop_othervrf
) {
7466 json_object_string_add(json_path
, "nhVrfName",
7469 json_object_int_add(json_path
, "nhVrfId",
7470 ((nexthop_vrfid
== VRF_UNKNOWN
)
7472 : (int)nexthop_vrfid
));
7477 if (json_nexthop_global
|| json_nexthop_ll
) {
7478 json_nexthops
= json_object_new_array();
7480 if (json_nexthop_global
)
7481 json_object_array_add(json_nexthops
,
7482 json_nexthop_global
);
7484 if (json_nexthop_ll
)
7485 json_object_array_add(json_nexthops
,
7488 json_object_object_add(json_path
, "nexthops",
7492 json_object_array_add(json_paths
, json_path
);
7496 if (safi
== SAFI_EVPN
&&
7497 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7498 vty_out(vty
, "%*s", 20, " ");
7499 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7503 /* prints an additional line, indented, with VNC info, if
7505 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7506 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7511 /* called from terminal list command */
7512 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7513 safi_t safi
, bool use_json
, json_object
*json_ar
)
7515 json_object
*json_status
= NULL
;
7516 json_object
*json_net
= NULL
;
7519 /* Route status display. */
7521 json_status
= json_object_new_object();
7522 json_net
= json_object_new_object();
7529 /* print prefix and mask */
7531 if (safi
== SAFI_EVPN
)
7532 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7533 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7534 json_object_string_add(
7535 json_net
, "addrPrefix",
7536 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7538 json_object_int_add(json_net
, "prefixLen",
7540 prefix2str(p
, buff
, PREFIX_STRLEN
);
7541 json_object_string_add(json_net
, "network", buff
);
7544 route_vty_out_route(p
, vty
, NULL
);
7546 /* Print attribute */
7549 if (p
->family
== AF_INET
7550 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7551 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7552 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7553 json_object_string_add(
7554 json_net
, "nextHop",
7556 attr
->mp_nexthop_global_in
));
7558 json_object_string_add(
7559 json_net
, "nextHop",
7560 inet_ntoa(attr
->nexthop
));
7561 } else if (p
->family
== AF_INET6
7562 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7565 json_object_string_add(
7566 json_net
, "nextHopGlobal",
7568 &attr
->mp_nexthop_global
, buf
,
7570 } else if (p
->family
== AF_EVPN
&&
7571 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7572 json_object_string_add(json_net
,
7573 "nextHop", inet_ntoa(
7574 attr
->mp_nexthop_global_in
));
7577 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7578 json_object_int_add(json_net
, "metric",
7581 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7584 * Adding "locPrf" field to match with
7585 * corresponding CLI. "localPref" will be
7586 * deprecated in future.
7588 json_object_int_add(json_net
, "localPref",
7590 json_object_int_add(json_net
, "locPrf",
7594 json_object_int_add(json_net
, "weight", attr
->weight
);
7600 * Adding "path" field to match with
7601 * corresponding CLI. "localPref" will be
7602 * deprecated in future.
7604 json_object_string_add(json_net
, "asPath",
7606 json_object_string_add(json_net
, "path",
7611 json_object_string_add(json_net
, "bgpOriginCode",
7612 bgp_origin_str
[attr
->origin
]);
7614 if (p
->family
== AF_INET
7615 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7616 || safi
== SAFI_EVPN
7617 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7618 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7619 || safi
== SAFI_EVPN
)
7620 vty_out(vty
, "%-16s",
7622 attr
->mp_nexthop_global_in
));
7624 vty_out(vty
, "%-16s",
7625 inet_ntoa(attr
->nexthop
));
7626 } else if (p
->family
== AF_INET6
7627 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7634 &attr
->mp_nexthop_global
, buf
,
7638 vty_out(vty
, "\n%*s", 36, " ");
7640 vty_out(vty
, "%*s", len
, " ");
7643 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7644 vty_out(vty
, "%10u", attr
->med
);
7648 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7649 vty_out(vty
, "%7u", attr
->local_pref
);
7653 vty_out(vty
, "%7u ", attr
->weight
);
7657 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7660 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7664 json_object_boolean_true_add(json_status
, "*");
7665 json_object_boolean_true_add(json_status
, ">");
7666 json_object_object_add(json_net
, "appliedStatusSymbols",
7669 prefix2str(p
, buff
, PREFIX_STRLEN
);
7670 json_object_object_add(json_ar
, buff
, json_net
);
7675 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7676 struct bgp_path_info
*path
, int display
, safi_t safi
,
7679 json_object
*json_out
= NULL
;
7681 mpls_label_t label
= MPLS_INVALID_LABEL
;
7687 json_out
= json_object_new_object();
7689 /* short status lead text */
7690 route_vty_short_status_out(vty
, path
, json_out
);
7692 /* print prefix and mask */
7695 route_vty_out_route(p
, vty
, NULL
);
7697 vty_out(vty
, "%*s", 17, " ");
7700 /* Print attribute */
7702 if (((p
->family
== AF_INET
)
7703 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7704 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7705 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7706 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7707 || safi
== SAFI_EVPN
) {
7709 json_object_string_add(
7710 json_out
, "mpNexthopGlobalIn",
7711 inet_ntoa(attr
->mp_nexthop_global_in
));
7713 vty_out(vty
, "%-16s",
7714 inet_ntoa(attr
->mp_nexthop_global_in
));
7717 json_object_string_add(
7718 json_out
, "nexthop",
7719 inet_ntoa(attr
->nexthop
));
7721 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7723 } else if (((p
->family
== AF_INET6
)
7724 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7725 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7726 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7729 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7731 json_object_string_add(
7732 json_out
, "mpNexthopGlobalIn",
7734 &attr
->mp_nexthop_global
,
7735 buf_a
, sizeof(buf_a
)));
7739 &attr
->mp_nexthop_global
,
7740 buf_a
, sizeof(buf_a
)));
7741 } else if (attr
->mp_nexthop_len
7742 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7743 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7744 &attr
->mp_nexthop_global
,
7745 &attr
->mp_nexthop_local
);
7747 json_object_string_add(json_out
,
7748 "mpNexthopGlobalLocal",
7751 vty_out(vty
, "%s", buf_a
);
7755 label
= decode_label(&path
->extra
->label
[0]);
7757 if (bgp_is_valid_label(&label
)) {
7759 json_object_int_add(json_out
, "notag", label
);
7760 json_object_array_add(json
, json_out
);
7762 vty_out(vty
, "notag/%d", label
);
7768 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7769 struct bgp_path_info
*path
, int display
,
7770 json_object
*json_paths
)
7773 char buf
[BUFSIZ
] = {0};
7774 json_object
*json_path
= NULL
;
7775 json_object
*json_nexthop
= NULL
;
7776 json_object
*json_overlay
= NULL
;
7782 json_path
= json_object_new_object();
7783 json_overlay
= json_object_new_object();
7784 json_nexthop
= json_object_new_object();
7787 /* short status lead text */
7788 route_vty_short_status_out(vty
, path
, json_path
);
7790 /* print prefix and mask */
7792 route_vty_out_route(p
, vty
, json_path
);
7794 vty_out(vty
, "%*s", 17, " ");
7796 /* Print attribute */
7799 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7803 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7805 vty_out(vty
, "%-16s", buf
);
7807 json_object_string_add(json_nexthop
, "ip", buf
);
7809 json_object_string_add(json_nexthop
, "afi", "ipv4");
7811 json_object_object_add(json_path
, "nexthop",
7816 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7817 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7819 vty_out(vty
, "%s(%s)", buf
, buf1
);
7821 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7823 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7826 json_object_string_add(json_nexthop
, "afi", "ipv6");
7828 json_object_object_add(json_path
, "nexthop",
7836 json_object_string_add(json_nexthop
, "Error",
7837 "Unsupported address-family");
7841 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7844 vty_out(vty
, "%s", str
);
7846 json_object_string_add(json_overlay
, "esi", str
);
7848 XFREE(MTYPE_TMP
, str
);
7850 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7851 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7853 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7854 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7859 vty_out(vty
, "/%s", buf
);
7861 json_object_string_add(json_overlay
, "gw", buf
);
7863 if (attr
->ecommunity
) {
7865 struct ecommunity_val
*routermac
= ecommunity_lookup(
7866 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7867 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7870 mac
= ecom_mac2str((char *)routermac
->val
);
7873 vty_out(vty
, "/%s", (char *)mac
);
7875 json_object_string_add(json_overlay
, "rmac",
7878 XFREE(MTYPE_TMP
, mac
);
7885 json_object_object_add(json_path
, "overlay", json_overlay
);
7887 json_object_array_add(json_paths
, json_path
);
7891 /* dampening route */
7892 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7893 struct bgp_path_info
*path
, int display
,
7894 safi_t safi
, bool use_json
, json_object
*json
)
7898 char timebuf
[BGP_UPTIME_LEN
];
7900 /* short status lead text */
7901 route_vty_short_status_out(vty
, path
, json
);
7903 /* print prefix and mask */
7906 route_vty_out_route(p
, vty
, NULL
);
7908 vty_out(vty
, "%*s", 17, " ");
7911 len
= vty_out(vty
, "%s", path
->peer
->host
);
7915 vty_out(vty
, "\n%*s", 34, " ");
7918 json_object_int_add(json
, "peerHost", len
);
7920 vty_out(vty
, "%*s", len
, " ");
7924 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7928 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7929 BGP_UPTIME_LEN
, use_json
,
7932 /* Print attribute */
7938 json_object_string_add(json
, "asPath",
7941 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7946 json_object_string_add(json
, "origin",
7947 bgp_origin_str
[attr
->origin
]);
7949 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7956 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7957 struct bgp_path_info
*path
, int display
,
7958 safi_t safi
, bool use_json
, json_object
*json
)
7961 struct bgp_damp_info
*bdi
;
7962 char timebuf
[BGP_UPTIME_LEN
];
7968 bdi
= path
->extra
->damp_info
;
7970 /* short status lead text */
7971 route_vty_short_status_out(vty
, path
, json
);
7973 /* print prefix and mask */
7976 route_vty_out_route(p
, vty
, NULL
);
7978 vty_out(vty
, "%*s", 17, " ");
7981 len
= vty_out(vty
, "%s", path
->peer
->host
);
7985 vty_out(vty
, "\n%*s", 33, " ");
7988 json_object_int_add(json
, "peerHost", len
);
7990 vty_out(vty
, "%*s", len
, " ");
7993 len
= vty_out(vty
, "%d", bdi
->flap
);
8000 json_object_int_add(json
, "bdiFlap", len
);
8002 vty_out(vty
, "%*s", len
, " ");
8006 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8009 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8010 BGP_UPTIME_LEN
, 0, NULL
));
8012 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8013 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8015 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8016 BGP_UPTIME_LEN
, use_json
, json
);
8019 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8024 vty_out(vty
, "%*s ", 8, " ");
8027 /* Print attribute */
8033 json_object_string_add(json
, "asPath",
8036 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8041 json_object_string_add(json
, "origin",
8042 bgp_origin_str
[attr
->origin
]);
8044 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8050 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8051 int *first
, const char *header
,
8052 json_object
*json_adv_to
)
8054 char buf1
[INET6_ADDRSTRLEN
];
8055 json_object
*json_peer
= NULL
;
8058 /* 'advertised-to' is a dictionary of peers we have advertised
8060 * prefix too. The key is the peer's IP or swpX, the value is
8062 * hostname if we know it and "" if not.
8064 json_peer
= json_object_new_object();
8067 json_object_string_add(json_peer
, "hostname",
8071 json_object_object_add(json_adv_to
, peer
->conf_if
,
8074 json_object_object_add(
8076 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8080 vty_out(vty
, "%s", header
);
8085 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8087 vty_out(vty
, " %s(%s)", peer
->hostname
,
8090 vty_out(vty
, " %s(%s)", peer
->hostname
,
8091 sockunion2str(&peer
->su
, buf1
,
8095 vty_out(vty
, " %s", peer
->conf_if
);
8098 sockunion2str(&peer
->su
, buf1
,
8104 static void route_vty_out_tx_ids(struct vty
*vty
,
8105 struct bgp_addpath_info_data
*d
)
8109 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8110 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8111 d
->addpath_tx_id
[i
],
8112 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8116 static const char *bgp_path_selection_reason2str(
8117 enum bgp_path_selection_reason reason
)
8120 case bgp_path_selection_none
:
8121 return "Nothing to Select";
8123 case bgp_path_selection_first
:
8124 return "First path received";
8126 case bgp_path_selection_evpn_sticky_mac
:
8127 return "EVPN Sticky Mac";
8129 case bgp_path_selection_evpn_seq
:
8130 return "EVPN sequence number";
8132 case bgp_path_selection_evpn_lower_ip
:
8133 return "EVPN lower IP";
8135 case bgp_path_selection_weight
:
8138 case bgp_path_selection_local_pref
:
8139 return "Local Pref";
8141 case bgp_path_selection_local_route
:
8142 return "Local Route";
8144 case bgp_path_selection_confed_as_path
:
8145 return "Confederation based AS Path";
8147 case bgp_path_selection_as_path
:
8150 case bgp_path_selection_origin
:
8153 case bgp_path_selection_med
:
8156 case bgp_path_selection_peer
:
8159 case bgp_path_selection_confed
:
8160 return "Confed Peer Type";
8162 case bgp_path_selection_igp_metric
:
8163 return "IGP Metric";
8165 case bgp_path_selection_older
:
8166 return "Older Path";
8168 case bgp_path_selection_router_id
:
8171 case bgp_path_selection_cluster_length
:
8172 return "Cluser length";
8174 case bgp_path_selection_stale
:
8175 return "Path Staleness";
8177 case bgp_path_selection_local_configured
:
8178 return "Locally configured route";
8180 case bgp_path_selection_neighbor_ip
:
8181 return "Neighbor IP";
8183 case bgp_path_selection_default
:
8184 return "Nothing left to compare";
8187 return "Invalid (internal error)";
8190 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8191 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8192 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8194 char buf
[INET6_ADDRSTRLEN
];
8196 char buf2
[EVPN_ROUTE_STRLEN
];
8198 int sockunion_vty_out(struct vty
*, union sockunion
*);
8200 json_object
*json_bestpath
= NULL
;
8201 json_object
*json_cluster_list
= NULL
;
8202 json_object
*json_cluster_list_list
= NULL
;
8203 json_object
*json_ext_community
= NULL
;
8204 json_object
*json_last_update
= NULL
;
8205 json_object
*json_pmsi
= NULL
;
8206 json_object
*json_nexthop_global
= NULL
;
8207 json_object
*json_nexthop_ll
= NULL
;
8208 json_object
*json_nexthops
= NULL
;
8209 json_object
*json_path
= NULL
;
8210 json_object
*json_peer
= NULL
;
8211 json_object
*json_string
= NULL
;
8212 json_object
*json_adv_to
= NULL
;
8214 struct listnode
*node
, *nnode
;
8216 int addpath_capable
;
8218 unsigned int first_as
;
8220 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8222 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8225 json_path
= json_object_new_object();
8226 json_peer
= json_object_new_object();
8227 json_nexthop_global
= json_object_new_object();
8235 if (path
->extra
&& path
->extra
->num_labels
) {
8236 bgp_evpn_label2str(path
->extra
->label
,
8237 path
->extra
->num_labels
, tag_buf
,
8240 if (safi
== SAFI_EVPN
) {
8242 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8243 buf2
, sizeof(buf2
));
8244 vty_out(vty
, " Route %s", buf2
);
8245 if (tag_buf
[0] != '\0')
8246 vty_out(vty
, " VNI %s", tag_buf
);
8250 json_object_string_add(json_path
, "VNI",
8255 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8256 struct bgp_path_info
*parent_ri
;
8257 struct bgp_node
*rn
, *prn
;
8259 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8260 rn
= parent_ri
->net
;
8261 if (rn
&& rn
->prn
) {
8263 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8264 buf1
, sizeof(buf1
));
8265 if (is_pi_family_evpn(parent_ri
)) {
8266 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8267 buf2
, sizeof(buf2
));
8268 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8270 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8277 /* Line1 display AS-path, Aggregator */
8280 if (!attr
->aspath
->json
)
8281 aspath_str_update(attr
->aspath
, true);
8282 json_object_lock(attr
->aspath
->json
);
8283 json_object_object_add(json_path
, "aspath",
8284 attr
->aspath
->json
);
8286 if (attr
->aspath
->segments
)
8287 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8289 vty_out(vty
, " Local");
8293 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8295 json_object_boolean_true_add(json_path
, "removed");
8297 vty_out(vty
, ", (removed)");
8300 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8302 json_object_boolean_true_add(json_path
, "stale");
8304 vty_out(vty
, ", (stale)");
8307 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8309 json_object_int_add(json_path
, "aggregatorAs",
8310 attr
->aggregator_as
);
8311 json_object_string_add(
8312 json_path
, "aggregatorId",
8313 inet_ntoa(attr
->aggregator_addr
));
8315 vty_out(vty
, ", (aggregated by %u %s)",
8316 attr
->aggregator_as
,
8317 inet_ntoa(attr
->aggregator_addr
));
8321 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8322 PEER_FLAG_REFLECTOR_CLIENT
)) {
8324 json_object_boolean_true_add(json_path
,
8325 "rxedFromRrClient");
8327 vty_out(vty
, ", (Received from a RR-client)");
8330 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8331 PEER_FLAG_RSERVER_CLIENT
)) {
8333 json_object_boolean_true_add(json_path
,
8334 "rxedFromRsClient");
8336 vty_out(vty
, ", (Received from a RS-client)");
8339 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8341 json_object_boolean_true_add(json_path
,
8342 "dampeningHistoryEntry");
8344 vty_out(vty
, ", (history entry)");
8345 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8347 json_object_boolean_true_add(json_path
,
8348 "dampeningSuppressed");
8350 vty_out(vty
, ", (suppressed due to dampening)");
8356 /* Line2 display Next-hop, Neighbor, Router-id */
8357 /* Display the nexthop */
8358 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8359 || bn
->p
.family
== AF_EVPN
)
8360 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8361 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8362 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8363 || safi
== SAFI_EVPN
) {
8365 json_object_string_add(
8366 json_nexthop_global
,
8367 nexthop_fqdn
? "fqdn" : "ip",
8371 attr
->mp_nexthop_global_in
));
8377 attr
->mp_nexthop_global_in
));
8380 json_object_string_add(
8381 json_nexthop_global
,
8382 nexthop_fqdn
? "fqdn" : "ip",
8385 : inet_ntoa(attr
->nexthop
));
8390 : inet_ntoa(attr
->nexthop
));
8394 json_object_string_add(json_nexthop_global
, "afi",
8398 json_object_string_add(
8399 json_nexthop_global
,
8400 nexthop_fqdn
? "fqdn" : "ip",
8403 : inet_ntop(AF_INET6
,
8404 &attr
->mp_nexthop_global
,
8405 buf
, INET6_ADDRSTRLEN
));
8406 json_object_string_add(json_nexthop_global
, "afi",
8408 json_object_string_add(json_nexthop_global
, "scope",
8414 : inet_ntop(AF_INET6
,
8415 &attr
->mp_nexthop_global
,
8416 buf
, INET6_ADDRSTRLEN
));
8420 /* Display the IGP cost or 'inaccessible' */
8421 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8423 json_object_boolean_false_add(json_nexthop_global
,
8426 vty_out(vty
, " (inaccessible)");
8428 if (path
->extra
&& path
->extra
->igpmetric
) {
8430 json_object_int_add(json_nexthop_global
,
8432 path
->extra
->igpmetric
);
8434 vty_out(vty
, " (metric %u)",
8435 path
->extra
->igpmetric
);
8438 /* IGP cost is 0, display this only for json */
8441 json_object_int_add(json_nexthop_global
,
8446 json_object_boolean_true_add(json_nexthop_global
,
8450 /* Display peer "from" output */
8451 /* This path was originated locally */
8452 if (path
->peer
== bgp
->peer_self
) {
8454 if (safi
== SAFI_EVPN
8455 || (bn
->p
.family
== AF_INET
8456 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8458 json_object_string_add(json_peer
, "peerId",
8461 vty_out(vty
, " from 0.0.0.0 ");
8464 json_object_string_add(json_peer
, "peerId",
8467 vty_out(vty
, " from :: ");
8471 json_object_string_add(json_peer
, "routerId",
8472 inet_ntoa(bgp
->router_id
));
8474 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8477 /* We RXed this path from one of our peers */
8481 json_object_string_add(json_peer
, "peerId",
8482 sockunion2str(&path
->peer
->su
,
8485 json_object_string_add(json_peer
, "routerId",
8487 &path
->peer
->remote_id
,
8488 buf1
, sizeof(buf1
)));
8490 if (path
->peer
->hostname
)
8491 json_object_string_add(json_peer
, "hostname",
8492 path
->peer
->hostname
);
8494 if (path
->peer
->domainname
)
8495 json_object_string_add(json_peer
, "domainname",
8496 path
->peer
->domainname
);
8498 if (path
->peer
->conf_if
)
8499 json_object_string_add(json_peer
, "interface",
8500 path
->peer
->conf_if
);
8502 if (path
->peer
->conf_if
) {
8503 if (path
->peer
->hostname
8504 && bgp_flag_check(path
->peer
->bgp
,
8505 BGP_FLAG_SHOW_HOSTNAME
))
8506 vty_out(vty
, " from %s(%s)",
8507 path
->peer
->hostname
,
8508 path
->peer
->conf_if
);
8510 vty_out(vty
, " from %s",
8511 path
->peer
->conf_if
);
8513 if (path
->peer
->hostname
8514 && bgp_flag_check(path
->peer
->bgp
,
8515 BGP_FLAG_SHOW_HOSTNAME
))
8516 vty_out(vty
, " from %s(%s)",
8517 path
->peer
->hostname
,
8520 vty_out(vty
, " from %s",
8521 sockunion2str(&path
->peer
->su
,
8526 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8527 vty_out(vty
, " (%s)",
8528 inet_ntoa(attr
->originator_id
));
8530 vty_out(vty
, " (%s)",
8532 &path
->peer
->remote_id
, buf1
,
8538 * Note when vrfid of nexthop is different from that of prefix
8540 if (path
->extra
&& path
->extra
->bgp_orig
) {
8541 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8546 if (path
->extra
->bgp_orig
->inst_type
8547 == BGP_INSTANCE_TYPE_DEFAULT
)
8548 vn
= VRF_DEFAULT_NAME
;
8550 vn
= path
->extra
->bgp_orig
->name
;
8552 json_object_string_add(json_path
, "nhVrfName", vn
);
8554 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8555 json_object_int_add(json_path
, "nhVrfId", -1);
8557 json_object_int_add(json_path
, "nhVrfId",
8558 (int)nexthop_vrfid
);
8561 if (nexthop_vrfid
== VRF_UNKNOWN
)
8562 vty_out(vty
, " vrf ?");
8564 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8570 json_object_boolean_true_add(json_path
,
8571 "announceNexthopSelf");
8573 vty_out(vty
, " announce-nh-self");
8580 /* display the link-local nexthop */
8581 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8583 json_nexthop_ll
= json_object_new_object();
8584 json_object_string_add(
8585 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8588 : inet_ntop(AF_INET6
,
8589 &attr
->mp_nexthop_local
,
8590 buf
, INET6_ADDRSTRLEN
));
8591 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8592 json_object_string_add(json_nexthop_ll
, "scope",
8595 json_object_boolean_true_add(json_nexthop_ll
,
8598 if (!attr
->mp_nexthop_prefer_global
)
8599 json_object_boolean_true_add(json_nexthop_ll
,
8602 json_object_boolean_true_add(
8603 json_nexthop_global
, "used");
8605 vty_out(vty
, " (%s) %s\n",
8606 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8607 buf
, INET6_ADDRSTRLEN
),
8608 attr
->mp_nexthop_prefer_global
8613 /* If we do not have a link-local nexthop then we must flag the
8617 json_object_boolean_true_add(json_nexthop_global
,
8621 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8622 * Int/Ext/Local, Atomic, best */
8624 json_object_string_add(json_path
, "origin",
8625 bgp_origin_long_str
[attr
->origin
]);
8627 vty_out(vty
, " Origin %s",
8628 bgp_origin_long_str
[attr
->origin
]);
8630 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8633 * Adding "metric" field to match with
8634 * corresponding CLI. "med" will be
8635 * deprecated in future.
8637 json_object_int_add(json_path
, "med", attr
->med
);
8638 json_object_int_add(json_path
, "metric", attr
->med
);
8640 vty_out(vty
, ", metric %u", attr
->med
);
8643 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8645 json_object_int_add(json_path
, "localpref",
8648 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8651 if (attr
->weight
!= 0) {
8653 json_object_int_add(json_path
, "weight", attr
->weight
);
8655 vty_out(vty
, ", weight %u", attr
->weight
);
8658 if (attr
->tag
!= 0) {
8660 json_object_int_add(json_path
, "tag", attr
->tag
);
8662 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8665 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8667 json_object_boolean_false_add(json_path
, "valid");
8669 vty_out(vty
, ", invalid");
8670 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8672 json_object_boolean_true_add(json_path
, "valid");
8674 vty_out(vty
, ", valid");
8677 if (path
->peer
!= bgp
->peer_self
) {
8678 if (path
->peer
->as
== path
->peer
->local_as
) {
8679 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8681 json_object_string_add(
8685 vty_out(vty
, ", confed-internal");
8688 json_object_string_add(
8689 json_peer
, "type", "internal");
8691 vty_out(vty
, ", internal");
8694 if (bgp_confederation_peers_check(bgp
,
8697 json_object_string_add(
8701 vty_out(vty
, ", confed-external");
8704 json_object_string_add(
8705 json_peer
, "type", "external");
8707 vty_out(vty
, ", external");
8710 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8712 json_object_boolean_true_add(json_path
, "aggregated");
8713 json_object_boolean_true_add(json_path
, "local");
8715 vty_out(vty
, ", aggregated, local");
8717 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8719 json_object_boolean_true_add(json_path
, "sourced");
8721 vty_out(vty
, ", sourced");
8724 json_object_boolean_true_add(json_path
, "sourced");
8725 json_object_boolean_true_add(json_path
, "local");
8727 vty_out(vty
, ", sourced, local");
8731 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8733 json_object_boolean_true_add(json_path
,
8736 vty_out(vty
, ", atomic-aggregate");
8739 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8740 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8741 && bgp_path_info_mpath_count(path
))) {
8743 json_object_boolean_true_add(json_path
, "multipath");
8745 vty_out(vty
, ", multipath");
8748 // Mark the bestpath(s)
8749 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8750 first_as
= aspath_get_first_as(attr
->aspath
);
8754 json_bestpath
= json_object_new_object();
8755 json_object_int_add(json_bestpath
, "bestpathFromAs",
8759 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8761 vty_out(vty
, ", bestpath-from-AS Local");
8765 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8768 json_bestpath
= json_object_new_object();
8769 json_object_boolean_true_add(json_bestpath
, "overall");
8770 json_object_string_add(
8771 json_bestpath
, "selectionReason",
8772 bgp_path_selection_reason2str(bn
->reason
));
8774 vty_out(vty
, ", best");
8775 vty_out(vty
, " (%s)",
8776 bgp_path_selection_reason2str(bn
->reason
));
8781 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8786 /* Line 4 display Community */
8787 if (attr
->community
) {
8789 if (!attr
->community
->json
)
8790 community_str(attr
->community
, true);
8791 json_object_lock(attr
->community
->json
);
8792 json_object_object_add(json_path
, "community",
8793 attr
->community
->json
);
8795 vty_out(vty
, " Community: %s\n",
8796 attr
->community
->str
);
8800 /* Line 5 display Extended-community */
8801 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8803 json_ext_community
= json_object_new_object();
8804 json_object_string_add(json_ext_community
, "string",
8805 attr
->ecommunity
->str
);
8806 json_object_object_add(json_path
, "extendedCommunity",
8807 json_ext_community
);
8809 vty_out(vty
, " Extended Community: %s\n",
8810 attr
->ecommunity
->str
);
8814 /* Line 6 display Large community */
8815 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8817 if (!attr
->lcommunity
->json
)
8818 lcommunity_str(attr
->lcommunity
, true);
8819 json_object_lock(attr
->lcommunity
->json
);
8820 json_object_object_add(json_path
, "largeCommunity",
8821 attr
->lcommunity
->json
);
8823 vty_out(vty
, " Large Community: %s\n",
8824 attr
->lcommunity
->str
);
8828 /* Line 7 display Originator, Cluster-id */
8829 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8830 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8831 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8833 json_object_string_add(
8834 json_path
, "originatorId",
8835 inet_ntoa(attr
->originator_id
));
8837 vty_out(vty
, " Originator: %s",
8838 inet_ntoa(attr
->originator_id
));
8841 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8845 json_cluster_list
= json_object_new_object();
8846 json_cluster_list_list
=
8847 json_object_new_array();
8849 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8851 json_string
= json_object_new_string(
8852 inet_ntoa(attr
->cluster
8854 json_object_array_add(
8855 json_cluster_list_list
,
8860 * struct cluster_list does not have
8861 * "str" variable like aspath and community
8862 * do. Add this someday if someone asks
8864 * json_object_string_add(json_cluster_list,
8865 * "string", attr->cluster->str);
8867 json_object_object_add(json_cluster_list
,
8869 json_cluster_list_list
);
8870 json_object_object_add(json_path
, "clusterList",
8873 vty_out(vty
, ", Cluster list: ");
8875 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8878 inet_ntoa(attr
->cluster
8888 if (path
->extra
&& path
->extra
->damp_info
)
8889 bgp_damp_info_vty(vty
, path
, json_path
);
8892 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8893 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8894 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8897 json_object_int_add(json_path
, "remoteLabel", label
);
8899 vty_out(vty
, " Remote label: %d\n", label
);
8903 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8905 json_object_int_add(json_path
, "labelIndex",
8908 vty_out(vty
, " Label Index: %d\n",
8912 /* Line 8 display Addpath IDs */
8913 if (path
->addpath_rx_id
8914 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8916 json_object_int_add(json_path
, "addpathRxId",
8917 path
->addpath_rx_id
);
8919 /* Keep backwards compatibility with the old API
8920 * by putting TX All's ID in the old field
8922 json_object_int_add(
8923 json_path
, "addpathTxId",
8925 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8927 /* ... but create a specific field for each
8930 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8931 json_object_int_add(
8933 bgp_addpath_names(i
)->id_json_name
,
8934 path
->tx_addpath
.addpath_tx_id
[i
]);
8937 vty_out(vty
, " AddPath ID: RX %u, ",
8938 path
->addpath_rx_id
);
8940 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8944 /* If we used addpath to TX a non-bestpath we need to display
8945 * "Advertised to" on a path-by-path basis
8947 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8950 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8952 bgp_addpath_encode_tx(peer
, afi
, safi
);
8953 has_adj
= bgp_adj_out_lookup(
8955 bgp_addpath_id_for_peer(peer
, afi
, safi
,
8956 &path
->tx_addpath
));
8958 if ((addpath_capable
&& has_adj
)
8959 || (!addpath_capable
&& has_adj
8960 && CHECK_FLAG(path
->flags
,
8961 BGP_PATH_SELECTED
))) {
8962 if (json_path
&& !json_adv_to
)
8963 json_adv_to
= json_object_new_object();
8965 route_vty_out_advertised_to(
8967 " Advertised to:", json_adv_to
);
8973 json_object_object_add(
8974 json_path
, "advertisedTo", json_adv_to
);
8983 /* Line 9 display Uptime */
8984 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8986 json_last_update
= json_object_new_object();
8987 json_object_int_add(json_last_update
, "epoch", tbuf
);
8988 json_object_string_add(json_last_update
, "string",
8990 json_object_object_add(json_path
, "lastUpdate",
8993 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8995 /* Line 10 display PMSI tunnel attribute, if present */
8996 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8998 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
8999 PMSI_TNLTYPE_STR_DEFAULT
);
9002 json_pmsi
= json_object_new_object();
9003 json_object_string_add(json_pmsi
, "tunnelType", str
);
9004 json_object_int_add(json_pmsi
, "label",
9005 label2vni(&attr
->label
));
9006 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9008 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9009 str
, label2vni(&attr
->label
));
9012 /* We've constructed the json object for this path, add it to the json
9016 if (json_nexthop_global
|| json_nexthop_ll
) {
9017 json_nexthops
= json_object_new_array();
9019 if (json_nexthop_global
)
9020 json_object_array_add(json_nexthops
,
9021 json_nexthop_global
);
9023 if (json_nexthop_ll
)
9024 json_object_array_add(json_nexthops
,
9027 json_object_object_add(json_path
, "nexthops",
9031 json_object_object_add(json_path
, "peer", json_peer
);
9032 json_object_array_add(json_paths
, json_path
);
9036 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9037 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9038 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9040 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9041 const char *prefix_list_str
, afi_t afi
,
9042 safi_t safi
, enum bgp_show_type type
);
9043 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9044 const char *filter
, afi_t afi
, safi_t safi
,
9045 enum bgp_show_type type
);
9046 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9047 const char *rmap_str
, afi_t afi
, safi_t safi
,
9048 enum bgp_show_type type
);
9049 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9050 const char *com
, int exact
, afi_t afi
,
9052 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9053 const char *prefix
, afi_t afi
, safi_t safi
,
9054 enum bgp_show_type type
);
9055 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9056 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9057 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9058 const char *comstr
, int exact
, afi_t afi
,
9059 safi_t safi
, bool use_json
);
9062 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9063 struct bgp_table
*table
, enum bgp_show_type type
,
9064 void *output_arg
, bool use_json
, char *rd
,
9065 int is_last
, unsigned long *output_cum
,
9066 unsigned long *total_cum
,
9067 unsigned long *json_header_depth
)
9069 struct bgp_path_info
*pi
;
9070 struct bgp_node
*rn
;
9073 unsigned long output_count
= 0;
9074 unsigned long total_count
= 0;
9077 json_object
*json_paths
= NULL
;
9080 if (output_cum
&& *output_cum
!= 0)
9083 if (use_json
&& !*json_header_depth
) {
9085 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9086 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9087 " \"localAS\": %u,\n \"routes\": { ",
9088 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9089 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9092 table
->version
, inet_ntoa(bgp
->router_id
),
9093 bgp
->default_local_pref
, bgp
->as
);
9094 *json_header_depth
= 2;
9096 vty_out(vty
, " \"routeDistinguishers\" : {");
9097 ++*json_header_depth
;
9101 if (use_json
&& rd
) {
9102 vty_out(vty
, " \"%s\" : { ", rd
);
9105 /* Start processing of routes. */
9106 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9107 pi
= bgp_node_get_bgp_path_info(rn
);
9113 json_paths
= json_object_new_array();
9117 for (; pi
; pi
= pi
->next
) {
9119 if (type
== bgp_show_type_flap_statistics
9120 || type
== bgp_show_type_flap_neighbor
9121 || type
== bgp_show_type_dampend_paths
9122 || type
== bgp_show_type_damp_neighbor
) {
9123 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9126 if (type
== bgp_show_type_regexp
) {
9127 regex_t
*regex
= output_arg
;
9129 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9133 if (type
== bgp_show_type_prefix_list
) {
9134 struct prefix_list
*plist
= output_arg
;
9136 if (prefix_list_apply(plist
, &rn
->p
)
9140 if (type
== bgp_show_type_filter_list
) {
9141 struct as_list
*as_list
= output_arg
;
9143 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9144 != AS_FILTER_PERMIT
)
9147 if (type
== bgp_show_type_route_map
) {
9148 struct route_map
*rmap
= output_arg
;
9149 struct bgp_path_info path
;
9150 struct attr dummy_attr
;
9151 route_map_result_t ret
;
9153 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9155 path
.peer
= pi
->peer
;
9156 path
.attr
= &dummy_attr
;
9158 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9160 if (ret
== RMAP_DENYMATCH
)
9163 if (type
== bgp_show_type_neighbor
9164 || type
== bgp_show_type_flap_neighbor
9165 || type
== bgp_show_type_damp_neighbor
) {
9166 union sockunion
*su
= output_arg
;
9168 if (pi
->peer
== NULL
9169 || pi
->peer
->su_remote
== NULL
9170 || !sockunion_same(pi
->peer
->su_remote
, su
))
9173 if (type
== bgp_show_type_cidr_only
) {
9174 uint32_t destination
;
9176 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9177 if (IN_CLASSC(destination
)
9178 && rn
->p
.prefixlen
== 24)
9180 if (IN_CLASSB(destination
)
9181 && rn
->p
.prefixlen
== 16)
9183 if (IN_CLASSA(destination
)
9184 && rn
->p
.prefixlen
== 8)
9187 if (type
== bgp_show_type_prefix_longer
) {
9189 if (!prefix_match(p
, &rn
->p
))
9192 if (type
== bgp_show_type_community_all
) {
9193 if (!pi
->attr
->community
)
9196 if (type
== bgp_show_type_community
) {
9197 struct community
*com
= output_arg
;
9199 if (!pi
->attr
->community
9200 || !community_match(pi
->attr
->community
,
9204 if (type
== bgp_show_type_community_exact
) {
9205 struct community
*com
= output_arg
;
9207 if (!pi
->attr
->community
9208 || !community_cmp(pi
->attr
->community
, com
))
9211 if (type
== bgp_show_type_community_list
) {
9212 struct community_list
*list
= output_arg
;
9214 if (!community_list_match(pi
->attr
->community
,
9218 if (type
== bgp_show_type_community_list_exact
) {
9219 struct community_list
*list
= output_arg
;
9221 if (!community_list_exact_match(
9222 pi
->attr
->community
, list
))
9225 if (type
== bgp_show_type_lcommunity
) {
9226 struct lcommunity
*lcom
= output_arg
;
9228 if (!pi
->attr
->lcommunity
9229 || !lcommunity_match(pi
->attr
->lcommunity
,
9234 if (type
== bgp_show_type_lcommunity_exact
) {
9235 struct lcommunity
*lcom
= output_arg
;
9237 if (!pi
->attr
->lcommunity
9238 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9242 if (type
== bgp_show_type_lcommunity_list
) {
9243 struct community_list
*list
= output_arg
;
9245 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9250 == bgp_show_type_lcommunity_list_exact
) {
9251 struct community_list
*list
= output_arg
;
9253 if (!lcommunity_list_exact_match(
9254 pi
->attr
->lcommunity
, list
))
9257 if (type
== bgp_show_type_lcommunity_all
) {
9258 if (!pi
->attr
->lcommunity
)
9261 if (type
== bgp_show_type_dampend_paths
9262 || type
== bgp_show_type_damp_neighbor
) {
9263 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9264 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9268 if (!use_json
&& header
) {
9269 vty_out(vty
, "BGP table version is %" PRIu64
9270 ", local router ID is %s, vrf id ",
9272 inet_ntoa(bgp
->router_id
));
9273 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9274 vty_out(vty
, "%s", VRFID_NONE_STR
);
9276 vty_out(vty
, "%u", bgp
->vrf_id
);
9278 vty_out(vty
, "Default local pref %u, ",
9279 bgp
->default_local_pref
);
9280 vty_out(vty
, "local AS %u\n", bgp
->as
);
9281 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9282 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9283 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9284 if (type
== bgp_show_type_dampend_paths
9285 || type
== bgp_show_type_damp_neighbor
)
9286 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9287 else if (type
== bgp_show_type_flap_statistics
9288 || type
== bgp_show_type_flap_neighbor
)
9289 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9291 vty_out(vty
, BGP_SHOW_HEADER
);
9294 if (rd
!= NULL
&& !display
&& !output_count
) {
9297 "Route Distinguisher: %s\n",
9300 if (type
== bgp_show_type_dampend_paths
9301 || type
== bgp_show_type_damp_neighbor
)
9302 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9303 safi
, use_json
, json_paths
);
9304 else if (type
== bgp_show_type_flap_statistics
9305 || type
== bgp_show_type_flap_neighbor
)
9306 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9307 safi
, use_json
, json_paths
);
9309 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9321 if (p
->family
== AF_FLOWSPEC
) {
9322 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9324 bgp_fs_nlri_get_string((unsigned char *)
9325 p
->u
.prefix_flowspec
.ptr
,
9326 p
->u
.prefix_flowspec
9329 NLRI_STRING_FORMAT_MIN
,
9332 vty_out(vty
, "\"%s/%d\": ",
9334 p
->u
.prefix_flowspec
.prefixlen
);
9336 vty_out(vty
, ",\"%s/%d\": ",
9338 p
->u
.prefix_flowspec
.prefixlen
);
9340 prefix2str(p
, buf2
, sizeof(buf2
));
9342 vty_out(vty
, "\"%s\": ", buf2
);
9344 vty_out(vty
, ",\"%s\": ", buf2
);
9347 json_object_to_json_string(json_paths
));
9348 json_object_free(json_paths
);
9355 output_count
+= *output_cum
;
9356 *output_cum
= output_count
;
9359 total_count
+= *total_cum
;
9360 *total_cum
= total_count
;
9364 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9368 for (i
= 0; i
< *json_header_depth
; ++i
)
9369 vty_out(vty
, " } ");
9374 /* No route is displayed */
9375 if (output_count
== 0) {
9376 if (type
== bgp_show_type_normal
)
9378 "No BGP prefixes displayed, %ld exist\n",
9382 "\nDisplayed %ld routes and %ld total paths\n",
9383 output_count
, total_count
);
9390 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9391 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9392 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9394 struct bgp_node
*rn
, *next
;
9395 unsigned long output_cum
= 0;
9396 unsigned long total_cum
= 0;
9397 unsigned long json_header_depth
= 0;
9398 struct bgp_table
*itable
;
9401 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9403 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9404 next
= bgp_route_next(rn
);
9405 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9408 itable
= bgp_node_get_bgp_table_info(rn
);
9409 if (itable
!= NULL
) {
9410 struct prefix_rd prd
;
9411 char rd
[RD_ADDRSTRLEN
];
9413 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9414 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9415 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9416 use_json
, rd
, next
== NULL
, &output_cum
,
9417 &total_cum
, &json_header_depth
);
9423 if (output_cum
== 0)
9424 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9428 "\nDisplayed %ld routes and %ld total paths\n",
9429 output_cum
, total_cum
);
9433 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9434 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9436 struct bgp_table
*table
;
9437 unsigned long json_header_depth
= 0;
9440 bgp
= bgp_get_default();
9445 vty_out(vty
, "No BGP process is configured\n");
9447 vty_out(vty
, "{}\n");
9451 table
= bgp
->rib
[afi
][safi
];
9452 /* use MPLS and ENCAP specific shows until they are merged */
9453 if (safi
== SAFI_MPLS_VPN
) {
9454 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9455 output_arg
, use_json
);
9458 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9459 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9460 output_arg
, use_json
,
9463 /* labeled-unicast routes live in the unicast table */
9464 else if (safi
== SAFI_LABELED_UNICAST
)
9465 safi
= SAFI_UNICAST
;
9467 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9468 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9471 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9472 safi_t safi
, bool use_json
)
9474 struct listnode
*node
, *nnode
;
9477 bool route_output
= false;
9480 vty_out(vty
, "{\n");
9482 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9483 route_output
= true;
9486 vty_out(vty
, ",\n");
9490 vty_out(vty
, "\"%s\":",
9491 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9495 vty_out(vty
, "\nInstance %s:\n",
9496 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9500 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9505 vty_out(vty
, "}\n");
9506 else if (!route_output
)
9507 vty_out(vty
, "%% BGP instance not found\n");
9510 /* Header of detailed BGP route information */
9511 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9512 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9513 afi_t afi
, safi_t safi
, json_object
*json
)
9515 struct bgp_path_info
*pi
;
9518 struct listnode
*node
, *nnode
;
9519 char buf1
[RD_ADDRSTRLEN
];
9520 char buf2
[INET6_ADDRSTRLEN
];
9521 char buf3
[EVPN_ROUTE_STRLEN
];
9522 char prefix_str
[BUFSIZ
];
9527 int route_filter_translated_v4
= 0;
9528 int route_filter_v4
= 0;
9529 int route_filter_translated_v6
= 0;
9530 int route_filter_v6
= 0;
9533 int accept_own_nexthop
= 0;
9536 int no_advertise
= 0;
9540 int has_valid_label
= 0;
9541 mpls_label_t label
= 0;
9542 json_object
*json_adv_to
= NULL
;
9545 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9547 if (has_valid_label
)
9548 label
= label_pton(&rn
->local_label
);
9550 if (safi
== SAFI_EVPN
) {
9553 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9554 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9555 : "", prd
? ":" : "",
9556 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9557 buf3
, sizeof(buf3
)));
9559 json_object_string_add(json
, "rd",
9560 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9562 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9566 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9567 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9568 ? prefix_rd2str(prd
, buf1
,
9571 safi
== SAFI_MPLS_VPN
? ":" : "",
9572 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9577 json_object_string_add(json
, "prefix",
9578 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9581 if (has_valid_label
) {
9583 json_object_int_add(json
, "localLabel", label
);
9585 vty_out(vty
, "Local label: %d\n", label
);
9589 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9590 vty_out(vty
, "not allocated\n");
9592 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9594 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9596 if (pi
->extra
&& pi
->extra
->suppress
)
9599 if (pi
->attr
->community
== NULL
)
9602 no_advertise
+= community_include(
9603 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9604 no_export
+= community_include(pi
->attr
->community
,
9605 COMMUNITY_NO_EXPORT
);
9606 local_as
+= community_include(pi
->attr
->community
,
9607 COMMUNITY_LOCAL_AS
);
9608 accept_own
+= community_include(pi
->attr
->community
,
9609 COMMUNITY_ACCEPT_OWN
);
9610 route_filter_translated_v4
+= community_include(
9611 pi
->attr
->community
,
9612 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9613 route_filter_translated_v6
+= community_include(
9614 pi
->attr
->community
,
9615 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9616 route_filter_v4
+= community_include(
9617 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9618 route_filter_v6
+= community_include(
9619 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9620 llgr_stale
+= community_include(pi
->attr
->community
,
9621 COMMUNITY_LLGR_STALE
);
9622 no_llgr
+= community_include(pi
->attr
->community
,
9624 accept_own_nexthop
+=
9625 community_include(pi
->attr
->community
,
9626 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9627 blackhole
+= community_include(pi
->attr
->community
,
9628 COMMUNITY_BLACKHOLE
);
9629 no_peer
+= community_include(pi
->attr
->community
,
9635 vty_out(vty
, "Paths: (%d available", count
);
9637 vty_out(vty
, ", best #%d", best
);
9638 if (safi
== SAFI_UNICAST
) {
9639 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9640 vty_out(vty
, ", table %s",
9643 vty_out(vty
, ", vrf %s",
9647 vty_out(vty
, ", no best path");
9651 ", accept own local route exported and imported in different VRF");
9652 else if (route_filter_translated_v4
)
9654 ", mark translated RTs for VPNv4 route filtering");
9655 else if (route_filter_v4
)
9657 ", attach RT as-is for VPNv4 route filtering");
9658 else if (route_filter_translated_v6
)
9660 ", mark translated RTs for VPNv6 route filtering");
9661 else if (route_filter_v6
)
9663 ", attach RT as-is for VPNv6 route filtering");
9664 else if (llgr_stale
)
9666 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9669 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9670 else if (accept_own_nexthop
)
9672 ", accept local nexthop");
9674 vty_out(vty
, ", inform peer to blackhole prefix");
9676 vty_out(vty
, ", not advertised to EBGP peer");
9677 else if (no_advertise
)
9678 vty_out(vty
, ", not advertised to any peer");
9680 vty_out(vty
, ", not advertised outside local AS");
9683 ", inform EBGP peer not to advertise to their EBGP peers");
9687 ", Advertisements suppressed by an aggregate.");
9688 vty_out(vty
, ")\n");
9691 /* If we are not using addpath then we can display Advertised to and
9693 * show what peers we advertised the bestpath to. If we are using
9695 * though then we must display Advertised to on a path-by-path basis. */
9696 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9697 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9698 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9699 if (json
&& !json_adv_to
)
9700 json_adv_to
= json_object_new_object();
9702 route_vty_out_advertised_to(
9704 " Advertised to non peer-group peers:\n ",
9711 json_object_object_add(json
, "advertisedTo",
9716 vty_out(vty
, " Not advertised to any peer");
9722 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9723 struct bgp_node
*bgp_node
, struct vty
*vty
,
9724 struct bgp
*bgp
, afi_t afi
,
9725 safi_t safi
, json_object
*json
,
9726 enum bgp_path_type pathtype
, int *display
)
9728 struct bgp_path_info
*pi
;
9730 char rdbuf
[RD_ADDRSTRLEN
];
9731 json_object
*json_header
= NULL
;
9732 json_object
*json_paths
= NULL
;
9734 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9737 if (json
&& !json_paths
) {
9738 /* Instantiate json_paths only if path is valid */
9739 json_paths
= json_object_new_array();
9741 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9742 json_header
= json_object_new_object();
9748 route_vty_out_detail_header(
9749 vty
, bgp
, bgp_node
, pfx_rd
,
9750 AFI_IP
, safi
, json_header
);
9755 if (pathtype
== BGP_PATH_SHOW_ALL
9756 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9757 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9758 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9759 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9760 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9761 route_vty_out_detail(vty
, bgp
, bgp_node
,
9766 if (json
&& json_paths
) {
9767 json_object_object_add(json_header
, "paths", json_paths
);
9770 json_object_object_add(json
, rdbuf
, json_header
);
9774 /* Display specified route of BGP table. */
9775 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9776 struct bgp_table
*rib
, const char *ip_str
,
9777 afi_t afi
, safi_t safi
,
9778 struct prefix_rd
*prd
, int prefix_check
,
9779 enum bgp_path_type pathtype
, bool use_json
)
9783 struct prefix match
;
9784 struct bgp_node
*rn
;
9785 struct bgp_node
*rm
;
9786 struct bgp_table
*table
;
9787 json_object
*json
= NULL
;
9788 json_object
*json_paths
= NULL
;
9790 /* Check IP address argument. */
9791 ret
= str2prefix(ip_str
, &match
);
9793 vty_out(vty
, "address is malformed\n");
9797 match
.family
= afi2family(afi
);
9800 json
= json_object_new_object();
9802 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9803 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9804 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9806 table
= bgp_node_get_bgp_table_info(rn
);
9810 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9814 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9815 bgp_unlock_node(rm
);
9819 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9820 vty
, bgp
, afi
, safi
, json
,
9821 pathtype
, &display
);
9823 bgp_unlock_node(rm
);
9825 } else if (safi
== SAFI_EVPN
) {
9826 struct bgp_node
*longest_pfx
;
9827 bool is_exact_pfxlen_match
= FALSE
;
9829 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9830 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9832 table
= bgp_node_get_bgp_table_info(rn
);
9837 is_exact_pfxlen_match
= FALSE
;
9839 * Search through all the prefixes for a match. The
9840 * pfx's are enumerated in ascending order of pfxlens.
9841 * So, the last pfx match is the longest match. Set
9842 * is_exact_pfxlen_match when we get exact pfxlen match
9844 for (rm
= bgp_table_top(table
); rm
;
9845 rm
= bgp_route_next(rm
)) {
9847 * Get prefixlen of the ip-prefix within type5
9850 if (evpn_type5_prefix_match(&rm
->p
,
9851 &match
) && rm
->info
) {
9854 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9855 if (type5_pfxlen
== match
.prefixlen
) {
9856 is_exact_pfxlen_match
= TRUE
;
9857 bgp_unlock_node(rm
);
9866 if (prefix_check
&& !is_exact_pfxlen_match
)
9872 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9873 vty
, bgp
, afi
, safi
, json
,
9874 pathtype
, &display
);
9876 bgp_unlock_node(rm
);
9878 } else if (safi
== SAFI_FLOWSPEC
) {
9880 json_paths
= json_object_new_array();
9882 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9883 &match
, prefix_check
,
9887 if (use_json
&& display
)
9888 json_object_object_add(json
, "paths", json_paths
);
9890 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9892 || rn
->p
.prefixlen
== match
.prefixlen
) {
9893 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9895 pathtype
, &display
);
9898 bgp_unlock_node(rn
);
9903 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9904 json
, JSON_C_TO_STRING_PRETTY
|
9905 JSON_C_TO_STRING_NOSLASHESCAPE
));
9906 json_object_free(json
);
9909 vty_out(vty
, "%% Network not in table\n");
9917 /* Display specified route of Main RIB */
9918 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9919 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9920 int prefix_check
, enum bgp_path_type pathtype
,
9924 bgp
= bgp_get_default();
9927 vty_out(vty
, "No BGP process is configured\n");
9929 vty_out(vty
, "{}\n");
9934 /* labeled-unicast routes live in the unicast table */
9935 if (safi
== SAFI_LABELED_UNICAST
)
9936 safi
= SAFI_UNICAST
;
9938 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9939 afi
, safi
, prd
, prefix_check
, pathtype
,
9943 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9944 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9945 safi_t safi
, bool uj
)
9947 struct lcommunity
*lcom
;
9953 b
= buffer_new(1024);
9954 for (i
= 0; i
< argc
; i
++) {
9956 buffer_putc(b
, ' ');
9958 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9960 buffer_putstr(b
, argv
[i
]->arg
);
9964 buffer_putc(b
, '\0');
9966 str
= buffer_getstr(b
);
9969 lcom
= lcommunity_str2com(str
);
9970 XFREE(MTYPE_TMP
, str
);
9972 vty_out(vty
, "%% Large-community malformed\n");
9976 return bgp_show(vty
, bgp
, afi
, safi
,
9977 (exact
? bgp_show_type_lcommunity_exact
9978 : bgp_show_type_lcommunity
),
9982 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9983 const char *lcom
, bool exact
, afi_t afi
,
9984 safi_t safi
, bool uj
)
9986 struct community_list
*list
;
9988 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9989 LARGE_COMMUNITY_LIST_MASTER
);
9991 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9996 return bgp_show(vty
, bgp
, afi
, safi
,
9997 (exact
? bgp_show_type_lcommunity_list_exact
9998 : bgp_show_type_lcommunity_list
),
10002 DEFUN (show_ip_bgp_large_community_list
,
10003 show_ip_bgp_large_community_list_cmd
,
10004 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
10008 BGP_INSTANCE_HELP_STR
10010 BGP_SAFI_WITH_LABEL_HELP_STR
10011 "Display routes matching the large-community-list\n"
10012 "large-community-list number\n"
10013 "large-community-list name\n"
10014 "Exact match of the large-communities\n"
10018 afi_t afi
= AFI_IP6
;
10019 safi_t safi
= SAFI_UNICAST
;
10021 bool exact_match
= 0;
10023 if (argv_find(argv
, argc
, "ip", &idx
))
10025 if (argv_find(argv
, argc
, "view", &idx
)
10026 || argv_find(argv
, argc
, "vrf", &idx
))
10027 vrf
= argv
[++idx
]->arg
;
10028 if (argv_find(argv
, argc
, "ipv4", &idx
)
10029 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10030 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10031 if (argv_find(argv
, argc
, "unicast", &idx
)
10032 || argv_find(argv
, argc
, "multicast", &idx
))
10033 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10036 bool uj
= use_json(argc
, argv
);
10038 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10040 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10041 return CMD_WARNING
;
10044 argv_find(argv
, argc
, "large-community-list", &idx
);
10046 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10048 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10051 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10052 exact_match
, afi
, safi
, uj
);
10054 DEFUN (show_ip_bgp_large_community
,
10055 show_ip_bgp_large_community_cmd
,
10056 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10060 BGP_INSTANCE_HELP_STR
10062 BGP_SAFI_WITH_LABEL_HELP_STR
10063 "Display routes matching the large-communities\n"
10064 "List of large-community numbers\n"
10065 "Exact match of the large-communities\n"
10069 afi_t afi
= AFI_IP6
;
10070 safi_t safi
= SAFI_UNICAST
;
10072 bool exact_match
= 0;
10074 if (argv_find(argv
, argc
, "ip", &idx
))
10076 if (argv_find(argv
, argc
, "view", &idx
)
10077 || argv_find(argv
, argc
, "vrf", &idx
))
10078 vrf
= argv
[++idx
]->arg
;
10079 if (argv_find(argv
, argc
, "ipv4", &idx
)
10080 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10081 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10082 if (argv_find(argv
, argc
, "unicast", &idx
)
10083 || argv_find(argv
, argc
, "multicast", &idx
))
10084 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10087 bool uj
= use_json(argc
, argv
);
10089 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10091 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10092 return CMD_WARNING
;
10095 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10096 if (argv_find(argv
, argc
, "exact-match", &idx
))
10098 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10099 exact_match
, afi
, safi
, uj
);
10101 return bgp_show(vty
, bgp
, afi
, safi
,
10102 bgp_show_type_lcommunity_all
, NULL
, uj
);
10105 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10109 /* BGP route print out function without JSON */
10110 DEFUN (show_ip_bgp
,
10112 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10113 <dampening <parameters>\
10118 |community-list <(1-500)|WORD> [exact-match]\
10119 |A.B.C.D/M longer-prefixes\
10120 |X:X::X:X/M longer-prefixes\
10125 BGP_INSTANCE_HELP_STR
10127 BGP_SAFI_WITH_LABEL_HELP_STR
10128 "Display detailed information about dampening\n"
10129 "Display detail of configured dampening parameters\n"
10130 "Display routes matching the route-map\n"
10131 "A route-map to match on\n"
10132 "Display routes conforming to the prefix-list\n"
10133 "Prefix-list name\n"
10134 "Display routes conforming to the filter-list\n"
10135 "Regular expression access list name\n"
10136 "BGP RIB advertisement statistics\n"
10137 "Display routes matching the community-list\n"
10138 "community-list number\n"
10139 "community-list name\n"
10140 "Exact match of the communities\n"
10142 "Display route and more specific routes\n"
10144 "Display route and more specific routes\n")
10146 afi_t afi
= AFI_IP6
;
10147 safi_t safi
= SAFI_UNICAST
;
10148 int exact_match
= 0;
10149 struct bgp
*bgp
= NULL
;
10152 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10155 return CMD_WARNING
;
10157 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10158 if (argv_find(argv
, argc
, "parameters", &idx
))
10159 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10162 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10163 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10164 safi
, bgp_show_type_prefix_list
);
10166 if (argv_find(argv
, argc
, "filter-list", &idx
))
10167 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10168 safi
, bgp_show_type_filter_list
);
10170 if (argv_find(argv
, argc
, "statistics", &idx
))
10171 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10173 if (argv_find(argv
, argc
, "route-map", &idx
))
10174 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10175 safi
, bgp_show_type_route_map
);
10177 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10178 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10179 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10181 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10182 exact_match
, afi
, safi
);
10184 /* prefix-longer */
10185 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10186 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10187 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10189 bgp_show_type_prefix_longer
);
10191 return CMD_WARNING
;
10194 /* BGP route print out function with JSON */
10195 DEFUN (show_ip_bgp_json
,
10196 show_ip_bgp_json_cmd
,
10197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10199 |dampening <flap-statistics|dampened-paths>\
10200 |community [AA:NN|local-AS|no-advertise|no-export\
10201 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10202 |accept-own|accept-own-nexthop|route-filter-v6\
10203 |route-filter-v4|route-filter-translated-v6\
10204 |route-filter-translated-v4] [exact-match]\
10209 BGP_INSTANCE_HELP_STR
10211 BGP_SAFI_WITH_LABEL_HELP_STR
10212 "Display only routes with non-natural netmasks\n"
10213 "Display detailed information about dampening\n"
10214 "Display flap statistics of routes\n"
10215 "Display paths suppressed due to dampening\n"
10216 "Display routes matching the communities\n"
10218 "Do not send outside local AS (well-known community)\n"
10219 "Do not advertise to any peer (well-known community)\n"
10220 "Do not export to next AS (well-known community)\n"
10221 "Graceful shutdown (well-known community)\n"
10222 "Do not export to any peer (well-known community)\n"
10223 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10224 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10225 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10226 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10227 "Should accept VPN route with local nexthop (well-known community)\n"
10228 "RT VPNv6 route filtering (well-known community)\n"
10229 "RT VPNv4 route filtering (well-known community)\n"
10230 "RT translated VPNv6 route filtering (well-known community)\n"
10231 "RT translated VPNv4 route filtering (well-known community)\n"
10232 "Exact match of the communities\n"
10235 afi_t afi
= AFI_IP6
;
10236 safi_t safi
= SAFI_UNICAST
;
10237 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10238 struct bgp
*bgp
= NULL
;
10240 int exact_match
= 0;
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 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10252 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10255 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10256 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10257 return bgp_show(vty
, bgp
, afi
, safi
,
10258 bgp_show_type_dampend_paths
, NULL
, uj
);
10259 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10260 return bgp_show(vty
, bgp
, afi
, safi
,
10261 bgp_show_type_flap_statistics
, NULL
,
10265 if (argv_find(argv
, argc
, "community", &idx
)) {
10266 char *maybecomm
= NULL
;
10267 char *community
= NULL
;
10269 if (idx
+ 1 < argc
) {
10270 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10271 maybecomm
= argv
[idx
+ 1]->arg
;
10273 maybecomm
= argv
[idx
+ 1]->text
;
10276 if (maybecomm
&& !strmatch(maybecomm
, "json")
10277 && !strmatch(maybecomm
, "exact-match"))
10278 community
= maybecomm
;
10280 if (argv_find(argv
, argc
, "exact-match", &idx
))
10284 return bgp_show_community(vty
, bgp
, community
,
10285 exact_match
, afi
, safi
, uj
);
10287 return (bgp_show(vty
, bgp
, afi
, safi
,
10288 bgp_show_type_community_all
, NULL
,
10292 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10295 DEFUN (show_ip_bgp_route
,
10296 show_ip_bgp_route_cmd
,
10297 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10298 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10302 BGP_INSTANCE_HELP_STR
10304 BGP_SAFI_WITH_LABEL_HELP_STR
10305 "Network in the BGP routing table to display\n"
10307 "Network in the BGP routing table to display\n"
10309 "Display only the bestpath\n"
10310 "Display only multipaths\n"
10313 int prefix_check
= 0;
10315 afi_t afi
= AFI_IP6
;
10316 safi_t safi
= SAFI_UNICAST
;
10317 char *prefix
= NULL
;
10318 struct bgp
*bgp
= NULL
;
10319 enum bgp_path_type path_type
;
10320 bool uj
= use_json(argc
, argv
);
10324 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10327 return CMD_WARNING
;
10331 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10332 return CMD_WARNING
;
10335 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10336 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10337 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10339 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10340 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10343 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10344 && afi
!= AFI_IP6
) {
10346 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10347 return CMD_WARNING
;
10349 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10350 && afi
!= AFI_IP
) {
10352 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10353 return CMD_WARNING
;
10356 prefix
= argv
[idx
]->arg
;
10358 /* [<bestpath|multipath>] */
10359 if (argv_find(argv
, argc
, "bestpath", &idx
))
10360 path_type
= BGP_PATH_SHOW_BESTPATH
;
10361 else if (argv_find(argv
, argc
, "multipath", &idx
))
10362 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10364 path_type
= BGP_PATH_SHOW_ALL
;
10366 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10370 DEFUN (show_ip_bgp_regexp
,
10371 show_ip_bgp_regexp_cmd
,
10372 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10376 BGP_INSTANCE_HELP_STR
10378 BGP_SAFI_WITH_LABEL_HELP_STR
10379 "Display routes matching the AS path regular expression\n"
10380 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10382 afi_t afi
= AFI_IP6
;
10383 safi_t safi
= SAFI_UNICAST
;
10384 struct bgp
*bgp
= NULL
;
10387 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10390 return CMD_WARNING
;
10392 // get index of regex
10393 argv_find(argv
, argc
, "regexp", &idx
);
10396 char *regstr
= argv_concat(argv
, argc
, idx
);
10397 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10398 bgp_show_type_regexp
);
10399 XFREE(MTYPE_TMP
, regstr
);
10403 DEFUN (show_ip_bgp_instance_all
,
10404 show_ip_bgp_instance_all_cmd
,
10405 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10409 BGP_INSTANCE_ALL_HELP_STR
10411 BGP_SAFI_WITH_LABEL_HELP_STR
10414 afi_t afi
= AFI_IP
;
10415 safi_t safi
= SAFI_UNICAST
;
10416 struct bgp
*bgp
= NULL
;
10418 bool uj
= use_json(argc
, argv
);
10423 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10426 return CMD_WARNING
;
10428 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10429 return CMD_SUCCESS
;
10432 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10433 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10438 if (!config_bgp_aspath_validate(regstr
)) {
10439 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10441 return CMD_WARNING_CONFIG_FAILED
;
10444 regex
= bgp_regcomp(regstr
);
10446 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10447 return CMD_WARNING
;
10450 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10451 bgp_regex_free(regex
);
10455 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10456 const char *prefix_list_str
, afi_t afi
,
10457 safi_t safi
, enum bgp_show_type type
)
10459 struct prefix_list
*plist
;
10461 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10462 if (plist
== NULL
) {
10463 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10465 return CMD_WARNING
;
10468 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10471 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10472 const char *filter
, afi_t afi
, safi_t safi
,
10473 enum bgp_show_type type
)
10475 struct as_list
*as_list
;
10477 as_list
= as_list_lookup(filter
);
10478 if (as_list
== NULL
) {
10479 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10481 return CMD_WARNING
;
10484 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10487 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10488 const char *rmap_str
, afi_t afi
, safi_t safi
,
10489 enum bgp_show_type type
)
10491 struct route_map
*rmap
;
10493 rmap
= route_map_lookup_by_name(rmap_str
);
10495 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10496 return CMD_WARNING
;
10499 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10502 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10503 const char *comstr
, int exact
, afi_t afi
,
10504 safi_t safi
, bool use_json
)
10506 struct community
*com
;
10509 com
= community_str2com(comstr
);
10511 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10512 return CMD_WARNING
;
10515 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10516 (exact
? bgp_show_type_community_exact
10517 : bgp_show_type_community
),
10519 community_free(&com
);
10524 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10525 const char *com
, int exact
, afi_t afi
,
10528 struct community_list
*list
;
10530 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10531 if (list
== NULL
) {
10532 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10533 return CMD_WARNING
;
10536 return bgp_show(vty
, bgp
, afi
, safi
,
10537 (exact
? bgp_show_type_community_list_exact
10538 : bgp_show_type_community_list
),
10542 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10543 const char *prefix
, afi_t afi
, safi_t safi
,
10544 enum bgp_show_type type
)
10551 ret
= str2prefix(prefix
, p
);
10553 vty_out(vty
, "%% Malformed Prefix\n");
10554 return CMD_WARNING
;
10557 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10563 BGP_STATS_MAXBITLEN
= 0,
10565 BGP_STATS_PREFIXES
,
10567 BGP_STATS_UNAGGREGATEABLE
,
10568 BGP_STATS_MAX_AGGREGATEABLE
,
10569 BGP_STATS_AGGREGATES
,
10571 BGP_STATS_ASPATH_COUNT
,
10572 BGP_STATS_ASPATH_MAXHOPS
,
10573 BGP_STATS_ASPATH_TOTHOPS
,
10574 BGP_STATS_ASPATH_MAXSIZE
,
10575 BGP_STATS_ASPATH_TOTSIZE
,
10576 BGP_STATS_ASN_HIGHEST
,
10580 static const char *table_stats_strs
[] = {
10581 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10582 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10583 [BGP_STATS_RIB
] = "Total Advertisements",
10584 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10585 [BGP_STATS_MAX_AGGREGATEABLE
] =
10586 "Maximum aggregateable prefixes",
10587 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10588 [BGP_STATS_SPACE
] = "Address space advertised",
10589 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10590 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10591 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10592 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10593 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10594 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10595 [BGP_STATS_MAX
] = NULL
,
10598 struct bgp_table_stats
{
10599 struct bgp_table
*table
;
10600 unsigned long long counts
[BGP_STATS_MAX
];
10601 double total_space
;
10605 #define TALLY_SIGFIG 100000
10606 static unsigned long
10607 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10609 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10610 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10611 unsigned long ret
= newtot
/ count
;
10613 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10620 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10621 struct bgp_table_stats
*ts
, unsigned int space
)
10623 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10624 struct bgp_path_info
*pi
;
10629 if (!bgp_node_has_bgp_path_info_data(rn
))
10632 ts
->counts
[BGP_STATS_PREFIXES
]++;
10633 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10636 ts
->counts
[BGP_STATS_AVGPLEN
]
10637 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10638 ts
->counts
[BGP_STATS_AVGPLEN
],
10642 /* check if the prefix is included by any other announcements */
10643 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10644 prn
= bgp_node_parent_nolock(prn
);
10646 if (prn
== NULL
|| prn
== top
) {
10647 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10648 /* announced address space */
10650 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10651 } else if (bgp_node_has_bgp_path_info_data(prn
))
10652 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10655 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10656 ts
->counts
[BGP_STATS_RIB
]++;
10658 if (CHECK_FLAG(pi
->attr
->flag
,
10659 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10660 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10662 /* as-path stats */
10663 if (pi
->attr
->aspath
) {
10664 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10665 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10666 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10668 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10670 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10671 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10673 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10674 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10676 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10677 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10679 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10680 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10681 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10683 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10684 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10685 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10688 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10689 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10694 static int bgp_table_stats_walker(struct thread
*t
)
10696 struct bgp_node
*rn
, *nrn
;
10697 struct bgp_node
*top
;
10698 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10699 unsigned int space
= 0;
10701 if (!(top
= bgp_table_top(ts
->table
)))
10704 switch (ts
->table
->afi
) {
10706 space
= IPV4_MAX_BITLEN
;
10709 space
= IPV6_MAX_BITLEN
;
10715 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10717 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10718 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10719 struct bgp_table
*table
;
10721 table
= bgp_node_get_bgp_table_info(rn
);
10725 top
= bgp_table_top(table
);
10726 for (nrn
= bgp_table_top(table
); nrn
;
10727 nrn
= bgp_route_next(nrn
))
10728 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10730 bgp_table_stats_rn(rn
, top
, ts
, space
);
10737 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10740 struct bgp_table_stats ts
;
10743 if (!bgp
->rib
[afi
][safi
]) {
10744 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10746 return CMD_WARNING
;
10749 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10751 /* labeled-unicast routes live in the unicast table */
10752 if (safi
== SAFI_LABELED_UNICAST
)
10753 safi
= SAFI_UNICAST
;
10755 memset(&ts
, 0, sizeof(ts
));
10756 ts
.table
= bgp
->rib
[afi
][safi
];
10757 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10759 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10760 if (!table_stats_strs
[i
])
10765 case BGP_STATS_ASPATH_AVGHOPS
:
10766 case BGP_STATS_ASPATH_AVGSIZE
:
10767 case BGP_STATS_AVGPLEN
:
10768 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10769 vty_out (vty
, "%12.2f",
10770 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10773 case BGP_STATS_ASPATH_TOTHOPS
:
10774 case BGP_STATS_ASPATH_TOTSIZE
:
10775 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10776 vty_out(vty
, "%12.2f",
10778 ? (float)ts
.counts
[i
]
10780 [BGP_STATS_ASPATH_COUNT
]
10783 case BGP_STATS_TOTPLEN
:
10784 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10785 vty_out(vty
, "%12.2f",
10787 ? (float)ts
.counts
[i
]
10789 [BGP_STATS_PREFIXES
]
10792 case BGP_STATS_SPACE
:
10793 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10794 vty_out(vty
, "%12g\n", ts
.total_space
);
10796 if (afi
== AFI_IP6
) {
10797 vty_out(vty
, "%30s: ", "/32 equivalent ");
10798 vty_out(vty
, "%12g\n",
10799 ts
.total_space
* pow(2.0, -128 + 32));
10800 vty_out(vty
, "%30s: ", "/48 equivalent ");
10801 vty_out(vty
, "%12g\n",
10802 ts
.total_space
* pow(2.0, -128 + 48));
10804 vty_out(vty
, "%30s: ", "% announced ");
10805 vty_out(vty
, "%12.2f\n",
10806 ts
.total_space
* 100. * pow(2.0, -32));
10807 vty_out(vty
, "%30s: ", "/8 equivalent ");
10808 vty_out(vty
, "%12.2f\n",
10809 ts
.total_space
* pow(2.0, -32 + 8));
10810 vty_out(vty
, "%30s: ", "/24 equivalent ");
10811 vty_out(vty
, "%12.2f\n",
10812 ts
.total_space
* pow(2.0, -32 + 24));
10816 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10817 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10820 vty_out(vty
, "\n");
10822 return CMD_SUCCESS
;
10834 PCOUNT_PFCNT
, /* the figure we display to users */
10838 static const char *pcount_strs
[] = {
10839 [PCOUNT_ADJ_IN
] = "Adj-in",
10840 [PCOUNT_DAMPED
] = "Damped",
10841 [PCOUNT_REMOVED
] = "Removed",
10842 [PCOUNT_HISTORY
] = "History",
10843 [PCOUNT_STALE
] = "Stale",
10844 [PCOUNT_VALID
] = "Valid",
10845 [PCOUNT_ALL
] = "All RIB",
10846 [PCOUNT_COUNTED
] = "PfxCt counted",
10847 [PCOUNT_PFCNT
] = "Useable",
10848 [PCOUNT_MAX
] = NULL
,
10851 struct peer_pcounts
{
10852 unsigned int count
[PCOUNT_MAX
];
10853 const struct peer
*peer
;
10854 const struct bgp_table
*table
;
10857 static int bgp_peer_count_walker(struct thread
*t
)
10859 struct bgp_node
*rn
;
10860 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10861 const struct peer
*peer
= pc
->peer
;
10863 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10864 struct bgp_adj_in
*ain
;
10865 struct bgp_path_info
*pi
;
10867 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10868 if (ain
->peer
== peer
)
10869 pc
->count
[PCOUNT_ADJ_IN
]++;
10871 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10873 if (pi
->peer
!= peer
)
10876 pc
->count
[PCOUNT_ALL
]++;
10878 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10879 pc
->count
[PCOUNT_DAMPED
]++;
10880 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10881 pc
->count
[PCOUNT_HISTORY
]++;
10882 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10883 pc
->count
[PCOUNT_REMOVED
]++;
10884 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10885 pc
->count
[PCOUNT_STALE
]++;
10886 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10887 pc
->count
[PCOUNT_VALID
]++;
10888 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10889 pc
->count
[PCOUNT_PFCNT
]++;
10891 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10892 pc
->count
[PCOUNT_COUNTED
]++;
10893 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10895 EC_LIB_DEVELOPMENT
,
10896 "Attempting to count but flags say it is unusable");
10898 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10900 EC_LIB_DEVELOPMENT
,
10901 "Not counted but flags say we should");
10908 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10909 safi_t safi
, bool use_json
)
10911 struct peer_pcounts pcounts
= {.peer
= peer
};
10913 json_object
*json
= NULL
;
10914 json_object
*json_loop
= NULL
;
10917 json
= json_object_new_object();
10918 json_loop
= json_object_new_object();
10921 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10922 || !peer
->bgp
->rib
[afi
][safi
]) {
10924 json_object_string_add(
10926 "No such neighbor or address family");
10927 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10928 json_object_free(json
);
10930 vty_out(vty
, "%% No such neighbor or address family\n");
10932 return CMD_WARNING
;
10935 memset(&pcounts
, 0, sizeof(pcounts
));
10936 pcounts
.peer
= peer
;
10937 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10939 /* in-place call via thread subsystem so as to record execution time
10940 * stats for the thread-walk (i.e. ensure this can't be blamed on
10941 * on just vty_read()).
10943 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10946 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10947 json_object_string_add(json
, "multiProtocol",
10948 get_afi_safi_str(afi
, safi
, true));
10949 json_object_int_add(json
, "pfxCounter",
10950 peer
->pcount
[afi
][safi
]);
10952 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10953 json_object_int_add(json_loop
, pcount_strs
[i
],
10956 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10958 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10959 json_object_string_add(json
, "pfxctDriftFor",
10961 json_object_string_add(
10962 json
, "recommended",
10963 "Please report this bug, with the above command output");
10965 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10966 json
, JSON_C_TO_STRING_PRETTY
));
10967 json_object_free(json
);
10971 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10972 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10973 peer
->hostname
, peer
->host
,
10974 get_afi_safi_str(afi
, safi
, false));
10976 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10977 get_afi_safi_str(afi
, safi
, false));
10980 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
10981 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10983 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10984 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10987 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10988 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10990 "Please report this bug, with the above command output\n");
10994 return CMD_SUCCESS
;
10997 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10998 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10999 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
11000 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11004 BGP_INSTANCE_HELP_STR
11007 "Detailed information on TCP and BGP neighbor connections\n"
11008 "Neighbor to display information about\n"
11009 "Neighbor to display information about\n"
11010 "Neighbor on BGP configured interface\n"
11011 "Display detailed prefix count information\n"
11014 afi_t afi
= AFI_IP6
;
11015 safi_t safi
= SAFI_UNICAST
;
11018 struct bgp
*bgp
= NULL
;
11019 bool uj
= use_json(argc
, argv
);
11024 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11027 return CMD_WARNING
;
11029 argv_find(argv
, argc
, "neighbors", &idx
);
11030 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11032 return CMD_WARNING
;
11034 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11037 #ifdef KEEP_OLD_VPN_COMMANDS
11038 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11039 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11040 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11045 "Display information about all VPNv4 NLRIs\n"
11046 "Detailed information on TCP and BGP neighbor connections\n"
11047 "Neighbor to display information about\n"
11048 "Neighbor to display information about\n"
11049 "Neighbor on BGP configured interface\n"
11050 "Display detailed prefix count information\n"
11055 bool uj
= use_json(argc
, argv
);
11057 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11059 return CMD_WARNING
;
11061 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11064 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11065 show_ip_bgp_vpn_all_route_prefix_cmd
,
11066 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11071 "Display information about all VPNv4 NLRIs\n"
11072 "Network in the BGP routing table to display\n"
11073 "Network in the BGP routing table to display\n"
11077 char *network
= NULL
;
11078 struct bgp
*bgp
= bgp_get_default();
11080 vty_out(vty
, "Can't find default instance\n");
11081 return CMD_WARNING
;
11084 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11085 network
= argv
[idx
]->arg
;
11086 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11087 network
= argv
[idx
]->arg
;
11089 vty_out(vty
, "Unable to figure out Network\n");
11090 return CMD_WARNING
;
11093 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11094 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11096 #endif /* KEEP_OLD_VPN_COMMANDS */
11098 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11099 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11100 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11105 "Network in the BGP routing table to display\n"
11106 "Network in the BGP routing table to display\n"
11107 "Network in the BGP routing table to display\n"
11108 "Network in the BGP routing table to display\n"
11112 char *network
= NULL
;
11113 int prefix_check
= 0;
11115 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11116 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11117 network
= argv
[idx
]->arg
;
11118 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11119 argv_find(argv
, argc
, "A.B.C.D/M", &idx
)) {
11120 network
= argv
[idx
]->arg
;
11123 vty_out(vty
, "Unable to figure out Network\n");
11124 return CMD_WARNING
;
11126 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11127 prefix_check
, BGP_PATH_SHOW_ALL
,
11128 use_json(argc
, argv
));
11131 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11132 safi_t safi
, enum bgp_show_adj_route_type type
,
11133 const char *rmap_name
, bool use_json
,
11136 struct bgp_table
*table
;
11137 struct bgp_adj_in
*ain
;
11138 struct bgp_adj_out
*adj
;
11139 unsigned long output_count
;
11140 unsigned long filtered_count
;
11141 struct bgp_node
*rn
;
11147 struct update_subgroup
*subgrp
;
11148 json_object
*json_scode
= NULL
;
11149 json_object
*json_ocode
= NULL
;
11150 json_object
*json_ar
= NULL
;
11151 struct peer_af
*paf
;
11152 bool route_filtered
;
11155 json_scode
= json_object_new_object();
11156 json_ocode
= json_object_new_object();
11157 json_ar
= json_object_new_object();
11159 json_object_string_add(json_scode
, "suppressed", "s");
11160 json_object_string_add(json_scode
, "damped", "d");
11161 json_object_string_add(json_scode
, "history", "h");
11162 json_object_string_add(json_scode
, "valid", "*");
11163 json_object_string_add(json_scode
, "best", ">");
11164 json_object_string_add(json_scode
, "multipath", "=");
11165 json_object_string_add(json_scode
, "internal", "i");
11166 json_object_string_add(json_scode
, "ribFailure", "r");
11167 json_object_string_add(json_scode
, "stale", "S");
11168 json_object_string_add(json_scode
, "removed", "R");
11170 json_object_string_add(json_ocode
, "igp", "i");
11171 json_object_string_add(json_ocode
, "egp", "e");
11172 json_object_string_add(json_ocode
, "incomplete", "?");
11179 json_object_string_add(json
, "alert", "no BGP");
11180 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11181 json_object_free(json
);
11183 vty_out(vty
, "%% No bgp\n");
11187 /* labeled-unicast routes live in the unicast table */
11188 if (safi
== SAFI_LABELED_UNICAST
)
11189 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11191 table
= bgp
->rib
[afi
][safi
];
11193 output_count
= filtered_count
= 0;
11194 subgrp
= peer_subgroup(peer
, afi
, safi
);
11196 if (type
== bgp_show_adj_route_advertised
&& subgrp
11197 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11199 json_object_int_add(json
, "bgpTableVersion",
11201 json_object_string_add(json
, "bgpLocalRouterId",
11202 inet_ntoa(bgp
->router_id
));
11203 json_object_int_add(json
, "defaultLocPrf",
11204 bgp
->default_local_pref
);
11205 json_object_int_add(json
, "localAS", bgp
->as
);
11206 json_object_object_add(json
, "bgpStatusCodes",
11208 json_object_object_add(json
, "bgpOriginCodes",
11210 json_object_string_add(
11211 json
, "bgpOriginatingDefaultNetwork",
11212 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11214 vty_out(vty
, "BGP table version is %" PRIu64
11215 ", local router ID is %s, vrf id ",
11216 table
->version
, inet_ntoa(bgp
->router_id
));
11217 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11218 vty_out(vty
, "%s", VRFID_NONE_STR
);
11220 vty_out(vty
, "%u", bgp
->vrf_id
);
11221 vty_out(vty
, "\n");
11222 vty_out(vty
, "Default local pref %u, ",
11223 bgp
->default_local_pref
);
11224 vty_out(vty
, "local AS %u\n", bgp
->as
);
11225 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11226 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11227 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11229 vty_out(vty
, "Originating default network %s\n\n",
11230 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11235 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11236 if (type
== bgp_show_adj_route_received
11237 || type
== bgp_show_adj_route_filtered
) {
11238 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11239 if (ain
->peer
!= peer
)
11244 json_object_int_add(
11245 json
, "bgpTableVersion",
11247 json_object_string_add(
11249 "bgpLocalRouterId",
11252 json_object_int_add(json
,
11254 bgp
->default_local_pref
);
11255 json_object_int_add(json
,
11256 "localAS", bgp
->as
);
11257 json_object_object_add(
11258 json
, "bgpStatusCodes",
11260 json_object_object_add(
11261 json
, "bgpOriginCodes",
11265 "BGP table version is 0, local router ID is %s, vrf id ",
11268 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11274 vty_out(vty
, "\n");
11276 "Default local pref %u, ",
11277 bgp
->default_local_pref
);
11278 vty_out(vty
, "local AS %u\n",
11281 BGP_SHOW_SCODE_HEADER
);
11283 BGP_SHOW_NCODE_HEADER
);
11285 BGP_SHOW_OCODE_HEADER
);
11291 vty_out(vty
, BGP_SHOW_HEADER
);
11295 bgp_attr_dup(&attr
, ain
->attr
);
11296 route_filtered
= false;
11298 /* Filter prefix using distribute list,
11299 * filter list or prefix list
11301 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11302 safi
)) == FILTER_DENY
)
11303 route_filtered
= true;
11305 /* Filter prefix using route-map */
11306 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11307 afi
, safi
, rmap_name
, NULL
, 0);
11309 if (type
== bgp_show_adj_route_filtered
&&
11310 !route_filtered
&& ret
!= RMAP_DENY
) {
11311 bgp_attr_undup(&attr
, ain
->attr
);
11315 if (type
== bgp_show_adj_route_received
&&
11316 (route_filtered
|| ret
== RMAP_DENY
))
11319 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11320 use_json
, json_ar
);
11321 bgp_attr_undup(&attr
, ain
->attr
);
11324 } else if (type
== bgp_show_adj_route_advertised
) {
11325 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11326 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11327 if (paf
->peer
!= peer
|| !adj
->attr
)
11332 json_object_int_add(
11336 json_object_string_add(
11338 "bgpLocalRouterId",
11341 json_object_int_add(
11342 json
, "defaultLocPrf",
11343 bgp
->default_local_pref
11345 json_object_int_add(
11348 json_object_object_add(
11352 json_object_object_add(
11358 "BGP table version is %" PRIu64
11359 ", local router ID is %s, vrf id ",
11372 vty_out(vty
, "\n");
11374 "Default local pref %u, ",
11375 bgp
->default_local_pref
11381 BGP_SHOW_SCODE_HEADER
);
11383 BGP_SHOW_NCODE_HEADER
);
11385 BGP_SHOW_OCODE_HEADER
);
11396 bgp_attr_dup(&attr
, adj
->attr
);
11397 ret
= bgp_output_modifier(
11398 peer
, &rn
->p
, &attr
, afi
, safi
,
11401 if (ret
!= RMAP_DENY
) {
11402 route_vty_out_tmp(vty
, &rn
->p
,
11411 bgp_attr_undup(&attr
, adj
->attr
);
11417 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11418 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11419 json_object_int_add(json
, "filteredPrefixCounter",
11422 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11423 json
, JSON_C_TO_STRING_PRETTY
));
11424 json_object_free(json
);
11425 } else if (output_count
> 0) {
11426 if (filtered_count
> 0)
11428 "\nTotal number of prefixes %ld (%ld filtered)\n",
11429 output_count
, filtered_count
);
11431 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11436 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11437 safi_t safi
, enum bgp_show_adj_route_type type
,
11438 const char *rmap_name
, bool use_json
)
11440 json_object
*json
= NULL
;
11443 json
= json_object_new_object();
11445 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11447 json_object_string_add(
11449 "No such neighbor or address family");
11450 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11451 json_object_free(json
);
11453 vty_out(vty
, "%% No such neighbor or address family\n");
11455 return CMD_WARNING
;
11458 if ((type
== bgp_show_adj_route_received
11459 || type
== bgp_show_adj_route_filtered
)
11460 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11461 PEER_FLAG_SOFT_RECONFIG
)) {
11463 json_object_string_add(
11465 "Inbound soft reconfiguration not enabled");
11466 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11467 json_object_free(json
);
11470 "%% Inbound soft reconfiguration not enabled\n");
11472 return CMD_WARNING
;
11475 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11477 return CMD_SUCCESS
;
11480 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11481 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11482 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11483 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11487 BGP_INSTANCE_HELP_STR
11489 BGP_SAFI_WITH_LABEL_HELP_STR
11490 "Detailed information on TCP and BGP neighbor connections\n"
11491 "Neighbor to display information about\n"
11492 "Neighbor to display information about\n"
11493 "Neighbor on BGP configured interface\n"
11494 "Display the routes advertised to a BGP neighbor\n"
11495 "Display the received routes from neighbor\n"
11496 "Display the filtered routes received from neighbor\n"
11497 "Route-map to modify the attributes\n"
11498 "Name of the route map\n"
11501 afi_t afi
= AFI_IP6
;
11502 safi_t safi
= SAFI_UNICAST
;
11503 char *rmap_name
= NULL
;
11504 char *peerstr
= NULL
;
11505 struct bgp
*bgp
= NULL
;
11507 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11509 bool uj
= use_json(argc
, argv
);
11514 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11517 return CMD_WARNING
;
11519 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11520 argv_find(argv
, argc
, "neighbors", &idx
);
11521 peerstr
= argv
[++idx
]->arg
;
11523 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11525 return CMD_WARNING
;
11527 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11528 type
= bgp_show_adj_route_advertised
;
11529 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11530 type
= bgp_show_adj_route_received
;
11531 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11532 type
= bgp_show_adj_route_filtered
;
11534 if (argv_find(argv
, argc
, "route-map", &idx
))
11535 rmap_name
= argv
[++idx
]->arg
;
11537 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11540 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11541 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11542 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11548 "Address Family modifier\n"
11549 "Detailed information on TCP and BGP neighbor connections\n"
11550 "Neighbor to display information about\n"
11551 "Neighbor to display information about\n"
11552 "Neighbor on BGP configured interface\n"
11553 "Display information received from a BGP neighbor\n"
11554 "Display the prefixlist filter\n"
11557 afi_t afi
= AFI_IP6
;
11558 safi_t safi
= SAFI_UNICAST
;
11559 char *peerstr
= NULL
;
11562 union sockunion su
;
11568 /* show [ip] bgp */
11569 if (argv_find(argv
, argc
, "ip", &idx
))
11571 /* [<ipv4|ipv6> [unicast]] */
11572 if (argv_find(argv
, argc
, "ipv4", &idx
))
11574 if (argv_find(argv
, argc
, "ipv6", &idx
))
11576 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11577 argv_find(argv
, argc
, "neighbors", &idx
);
11578 peerstr
= argv
[++idx
]->arg
;
11580 bool uj
= use_json(argc
, argv
);
11582 ret
= str2sockunion(peerstr
, &su
);
11584 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11587 vty_out(vty
, "{}\n");
11590 "%% Malformed address or name: %s\n",
11592 return CMD_WARNING
;
11595 peer
= peer_lookup(NULL
, &su
);
11598 vty_out(vty
, "{}\n");
11600 vty_out(vty
, "No peer\n");
11601 return CMD_WARNING
;
11605 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11606 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11609 vty_out(vty
, "Address Family: %s\n",
11610 get_afi_safi_str(afi
, safi
, false));
11611 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11614 vty_out(vty
, "{}\n");
11616 vty_out(vty
, "No functional output\n");
11619 return CMD_SUCCESS
;
11622 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11623 afi_t afi
, safi_t safi
,
11624 enum bgp_show_type type
, bool use_json
)
11626 /* labeled-unicast routes live in the unicast table */
11627 if (safi
== SAFI_LABELED_UNICAST
)
11628 safi
= SAFI_UNICAST
;
11630 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11632 json_object
*json_no
= NULL
;
11633 json_no
= json_object_new_object();
11634 json_object_string_add(
11635 json_no
, "warning",
11636 "No such neighbor or address family");
11637 vty_out(vty
, "%s\n",
11638 json_object_to_json_string(json_no
));
11639 json_object_free(json_no
);
11641 vty_out(vty
, "%% No such neighbor or address family\n");
11642 return CMD_WARNING
;
11645 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11648 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11649 show_ip_bgp_flowspec_routes_detailed_cmd
,
11650 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11654 BGP_INSTANCE_HELP_STR
11657 "Detailed information on flowspec entries\n"
11660 afi_t afi
= AFI_IP
;
11661 safi_t safi
= SAFI_UNICAST
;
11662 struct bgp
*bgp
= NULL
;
11664 bool uj
= use_json(argc
, argv
);
11669 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11672 return CMD_WARNING
;
11674 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11677 DEFUN (show_ip_bgp_neighbor_routes
,
11678 show_ip_bgp_neighbor_routes_cmd
,
11679 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11680 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11684 BGP_INSTANCE_HELP_STR
11686 BGP_SAFI_WITH_LABEL_HELP_STR
11687 "Detailed information on TCP and BGP neighbor connections\n"
11688 "Neighbor to display information about\n"
11689 "Neighbor to display information about\n"
11690 "Neighbor on BGP configured interface\n"
11691 "Display flap statistics of the routes learned from neighbor\n"
11692 "Display the dampened routes received from neighbor\n"
11693 "Display routes learned from neighbor\n"
11696 char *peerstr
= NULL
;
11697 struct bgp
*bgp
= NULL
;
11698 afi_t afi
= AFI_IP6
;
11699 safi_t safi
= SAFI_UNICAST
;
11701 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11703 bool uj
= use_json(argc
, argv
);
11708 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11711 return CMD_WARNING
;
11713 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11714 argv_find(argv
, argc
, "neighbors", &idx
);
11715 peerstr
= argv
[++idx
]->arg
;
11717 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11719 return CMD_WARNING
;
11721 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11722 sh_type
= bgp_show_type_flap_neighbor
;
11723 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11724 sh_type
= bgp_show_type_damp_neighbor
;
11725 else if (argv_find(argv
, argc
, "routes", &idx
))
11726 sh_type
= bgp_show_type_neighbor
;
11728 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11731 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11733 struct bgp_distance
{
11734 /* Distance value for the IP source prefix. */
11737 /* Name of the access-list to be matched. */
11741 DEFUN (show_bgp_afi_vpn_rd_route
,
11742 show_bgp_afi_vpn_rd_route_cmd
,
11743 "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]",
11747 "Address Family modifier\n"
11748 "Display information for a route distinguisher\n"
11749 "Route Distinguisher\n"
11750 "Network in the BGP routing table to display\n"
11751 "Network in the BGP routing table to display\n"
11755 struct prefix_rd prd
;
11756 afi_t afi
= AFI_MAX
;
11759 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11760 vty_out(vty
, "%% Malformed Address Family\n");
11761 return CMD_WARNING
;
11764 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11766 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11767 return CMD_WARNING
;
11770 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11771 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11774 static struct bgp_distance
*bgp_distance_new(void)
11776 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11779 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11781 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11784 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11785 const char *ip_str
, const char *access_list_str
)
11792 struct bgp_node
*rn
;
11793 struct bgp_distance
*bdistance
;
11795 afi
= bgp_node_afi(vty
);
11796 safi
= bgp_node_safi(vty
);
11798 ret
= str2prefix(ip_str
, &p
);
11800 vty_out(vty
, "Malformed prefix\n");
11801 return CMD_WARNING_CONFIG_FAILED
;
11804 distance
= atoi(distance_str
);
11806 /* Get BGP distance node. */
11807 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11808 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11810 bgp_unlock_node(rn
);
11812 bdistance
= bgp_distance_new();
11813 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11816 /* Set distance value. */
11817 bdistance
->distance
= distance
;
11819 /* Reset access-list configuration. */
11820 if (bdistance
->access_list
) {
11821 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11822 bdistance
->access_list
= NULL
;
11824 if (access_list_str
)
11825 bdistance
->access_list
=
11826 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11828 return CMD_SUCCESS
;
11831 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11832 const char *ip_str
, const char *access_list_str
)
11839 struct bgp_node
*rn
;
11840 struct bgp_distance
*bdistance
;
11842 afi
= bgp_node_afi(vty
);
11843 safi
= bgp_node_safi(vty
);
11845 ret
= str2prefix(ip_str
, &p
);
11847 vty_out(vty
, "Malformed prefix\n");
11848 return CMD_WARNING_CONFIG_FAILED
;
11851 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11852 (struct prefix
*)&p
);
11854 vty_out(vty
, "Can't find specified prefix\n");
11855 return CMD_WARNING_CONFIG_FAILED
;
11858 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11859 distance
= atoi(distance_str
);
11861 if (bdistance
->distance
!= distance
) {
11862 vty_out(vty
, "Distance does not match configured\n");
11863 return CMD_WARNING_CONFIG_FAILED
;
11866 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11867 bgp_distance_free(bdistance
);
11869 bgp_node_set_bgp_path_info(rn
, NULL
);
11870 bgp_unlock_node(rn
);
11871 bgp_unlock_node(rn
);
11873 return CMD_SUCCESS
;
11876 /* Apply BGP information to distance method. */
11877 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11878 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11880 struct bgp_node
*rn
;
11883 struct bgp_distance
*bdistance
;
11884 struct access_list
*alist
;
11885 struct bgp_static
*bgp_static
;
11890 peer
= pinfo
->peer
;
11892 if (pinfo
->attr
->distance
)
11893 return pinfo
->attr
->distance
;
11895 /* Check source address. */
11896 sockunion2hostprefix(&peer
->su
, &q
);
11897 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11899 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11900 bgp_unlock_node(rn
);
11902 if (bdistance
->access_list
) {
11903 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11905 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11906 return bdistance
->distance
;
11908 return bdistance
->distance
;
11911 /* Backdoor check. */
11912 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11914 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11915 bgp_unlock_node(rn
);
11917 if (bgp_static
->backdoor
) {
11918 if (bgp
->distance_local
[afi
][safi
])
11919 return bgp
->distance_local
[afi
][safi
];
11921 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11925 if (peer
->sort
== BGP_PEER_EBGP
) {
11926 if (bgp
->distance_ebgp
[afi
][safi
])
11927 return bgp
->distance_ebgp
[afi
][safi
];
11928 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11930 if (bgp
->distance_ibgp
[afi
][safi
])
11931 return bgp
->distance_ibgp
[afi
][safi
];
11932 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11936 DEFUN (bgp_distance
,
11938 "distance bgp (1-255) (1-255) (1-255)",
11939 "Define an administrative distance\n"
11941 "Distance for routes external to the AS\n"
11942 "Distance for routes internal to the AS\n"
11943 "Distance for local routes\n")
11945 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11946 int idx_number
= 2;
11947 int idx_number_2
= 3;
11948 int idx_number_3
= 4;
11952 afi
= bgp_node_afi(vty
);
11953 safi
= bgp_node_safi(vty
);
11955 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11956 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11957 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11958 return CMD_SUCCESS
;
11961 DEFUN (no_bgp_distance
,
11962 no_bgp_distance_cmd
,
11963 "no distance bgp [(1-255) (1-255) (1-255)]",
11965 "Define an administrative distance\n"
11967 "Distance for routes external to the AS\n"
11968 "Distance for routes internal to the AS\n"
11969 "Distance for local routes\n")
11971 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11975 afi
= bgp_node_afi(vty
);
11976 safi
= bgp_node_safi(vty
);
11978 bgp
->distance_ebgp
[afi
][safi
] = 0;
11979 bgp
->distance_ibgp
[afi
][safi
] = 0;
11980 bgp
->distance_local
[afi
][safi
] = 0;
11981 return CMD_SUCCESS
;
11985 DEFUN (bgp_distance_source
,
11986 bgp_distance_source_cmd
,
11987 "distance (1-255) A.B.C.D/M",
11988 "Define an administrative distance\n"
11989 "Administrative distance\n"
11990 "IP source prefix\n")
11992 int idx_number
= 1;
11993 int idx_ipv4_prefixlen
= 2;
11994 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11995 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11996 return CMD_SUCCESS
;
11999 DEFUN (no_bgp_distance_source
,
12000 no_bgp_distance_source_cmd
,
12001 "no distance (1-255) A.B.C.D/M",
12003 "Define an administrative distance\n"
12004 "Administrative distance\n"
12005 "IP source prefix\n")
12007 int idx_number
= 2;
12008 int idx_ipv4_prefixlen
= 3;
12009 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12010 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12011 return CMD_SUCCESS
;
12014 DEFUN (bgp_distance_source_access_list
,
12015 bgp_distance_source_access_list_cmd
,
12016 "distance (1-255) A.B.C.D/M WORD",
12017 "Define an administrative distance\n"
12018 "Administrative distance\n"
12019 "IP source prefix\n"
12020 "Access list name\n")
12022 int idx_number
= 1;
12023 int idx_ipv4_prefixlen
= 2;
12025 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12026 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12027 return CMD_SUCCESS
;
12030 DEFUN (no_bgp_distance_source_access_list
,
12031 no_bgp_distance_source_access_list_cmd
,
12032 "no distance (1-255) A.B.C.D/M WORD",
12034 "Define an administrative distance\n"
12035 "Administrative distance\n"
12036 "IP source prefix\n"
12037 "Access list name\n")
12039 int idx_number
= 2;
12040 int idx_ipv4_prefixlen
= 3;
12042 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12043 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12044 return CMD_SUCCESS
;
12047 DEFUN (ipv6_bgp_distance_source
,
12048 ipv6_bgp_distance_source_cmd
,
12049 "distance (1-255) X:X::X:X/M",
12050 "Define an administrative distance\n"
12051 "Administrative distance\n"
12052 "IP source prefix\n")
12054 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12055 return CMD_SUCCESS
;
12058 DEFUN (no_ipv6_bgp_distance_source
,
12059 no_ipv6_bgp_distance_source_cmd
,
12060 "no distance (1-255) X:X::X:X/M",
12062 "Define an administrative distance\n"
12063 "Administrative distance\n"
12064 "IP source prefix\n")
12066 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12067 return CMD_SUCCESS
;
12070 DEFUN (ipv6_bgp_distance_source_access_list
,
12071 ipv6_bgp_distance_source_access_list_cmd
,
12072 "distance (1-255) X:X::X:X/M WORD",
12073 "Define an administrative distance\n"
12074 "Administrative distance\n"
12075 "IP source prefix\n"
12076 "Access list name\n")
12078 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12079 return CMD_SUCCESS
;
12082 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12083 no_ipv6_bgp_distance_source_access_list_cmd
,
12084 "no distance (1-255) X:X::X:X/M WORD",
12086 "Define an administrative distance\n"
12087 "Administrative distance\n"
12088 "IP source prefix\n"
12089 "Access list name\n")
12091 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12092 return CMD_SUCCESS
;
12095 DEFUN (bgp_damp_set
,
12097 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12098 "BGP Specific commands\n"
12099 "Enable route-flap dampening\n"
12100 "Half-life time for the penalty\n"
12101 "Value to start reusing a route\n"
12102 "Value to start suppressing a route\n"
12103 "Maximum duration to suppress a stable route\n")
12105 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12106 int idx_half_life
= 2;
12108 int idx_suppress
= 4;
12109 int idx_max_suppress
= 5;
12110 int half
= DEFAULT_HALF_LIFE
* 60;
12111 int reuse
= DEFAULT_REUSE
;
12112 int suppress
= DEFAULT_SUPPRESS
;
12113 int max
= 4 * half
;
12116 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12117 reuse
= atoi(argv
[idx_reuse
]->arg
);
12118 suppress
= atoi(argv
[idx_suppress
]->arg
);
12119 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12120 } else if (argc
== 3) {
12121 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12125 if (suppress
< reuse
) {
12127 "Suppress value cannot be less than reuse value \n");
12131 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12132 reuse
, suppress
, max
);
12135 DEFUN (bgp_damp_unset
,
12136 bgp_damp_unset_cmd
,
12137 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12139 "BGP Specific commands\n"
12140 "Enable route-flap dampening\n"
12141 "Half-life time for the penalty\n"
12142 "Value to start reusing a route\n"
12143 "Value to start suppressing a route\n"
12144 "Maximum duration to suppress a stable route\n")
12146 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12147 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12150 /* Display specified route of BGP table. */
12151 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12152 const char *ip_str
, afi_t afi
, safi_t safi
,
12153 struct prefix_rd
*prd
, int prefix_check
)
12156 struct prefix match
;
12157 struct bgp_node
*rn
;
12158 struct bgp_node
*rm
;
12159 struct bgp_path_info
*pi
;
12160 struct bgp_path_info
*pi_temp
;
12162 struct bgp_table
*table
;
12164 /* BGP structure lookup. */
12166 bgp
= bgp_lookup_by_name(view_name
);
12168 vty_out(vty
, "%% Can't find BGP instance %s\n",
12170 return CMD_WARNING
;
12173 bgp
= bgp_get_default();
12175 vty_out(vty
, "%% No BGP process is configured\n");
12176 return CMD_WARNING
;
12180 /* Check IP address argument. */
12181 ret
= str2prefix(ip_str
, &match
);
12183 vty_out(vty
, "%% address is malformed\n");
12184 return CMD_WARNING
;
12187 match
.family
= afi2family(afi
);
12189 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12190 || (safi
== SAFI_EVPN
)) {
12191 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12192 rn
= bgp_route_next(rn
)) {
12193 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12195 table
= bgp_node_get_bgp_table_info(rn
);
12198 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12202 || rm
->p
.prefixlen
== match
.prefixlen
) {
12203 pi
= bgp_node_get_bgp_path_info(rm
);
12205 if (pi
->extra
&& pi
->extra
->damp_info
) {
12206 pi_temp
= pi
->next
;
12207 bgp_damp_info_free(
12208 pi
->extra
->damp_info
,
12216 bgp_unlock_node(rm
);
12219 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12222 || rn
->p
.prefixlen
== match
.prefixlen
) {
12223 pi
= bgp_node_get_bgp_path_info(rn
);
12225 if (pi
->extra
&& pi
->extra
->damp_info
) {
12226 pi_temp
= pi
->next
;
12227 bgp_damp_info_free(
12228 pi
->extra
->damp_info
,
12236 bgp_unlock_node(rn
);
12240 return CMD_SUCCESS
;
12243 DEFUN (clear_ip_bgp_dampening
,
12244 clear_ip_bgp_dampening_cmd
,
12245 "clear ip bgp dampening",
12249 "Clear route flap dampening information\n")
12251 bgp_damp_info_clean();
12252 return CMD_SUCCESS
;
12255 DEFUN (clear_ip_bgp_dampening_prefix
,
12256 clear_ip_bgp_dampening_prefix_cmd
,
12257 "clear ip bgp dampening A.B.C.D/M",
12261 "Clear route flap dampening information\n"
12264 int idx_ipv4_prefixlen
= 4;
12265 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12266 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12269 DEFUN (clear_ip_bgp_dampening_address
,
12270 clear_ip_bgp_dampening_address_cmd
,
12271 "clear ip bgp dampening A.B.C.D",
12275 "Clear route flap dampening information\n"
12276 "Network to clear damping information\n")
12279 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12280 SAFI_UNICAST
, NULL
, 0);
12283 DEFUN (clear_ip_bgp_dampening_address_mask
,
12284 clear_ip_bgp_dampening_address_mask_cmd
,
12285 "clear ip bgp dampening A.B.C.D A.B.C.D",
12289 "Clear route flap dampening information\n"
12290 "Network to clear damping information\n"
12294 int idx_ipv4_2
= 5;
12296 char prefix_str
[BUFSIZ
];
12298 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12301 vty_out(vty
, "%% Inconsistent address and mask\n");
12302 return CMD_WARNING
;
12305 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12309 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12311 struct vty
*vty
= arg
;
12312 struct peer
*peer
= bucket
->data
;
12313 char buf
[SU_ADDRSTRLEN
];
12315 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12316 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12319 DEFUN (show_bgp_peerhash
,
12320 show_bgp_peerhash_cmd
,
12321 "show bgp peerhash",
12324 "Display information about the BGP peerhash\n")
12326 struct list
*instances
= bm
->bgp
;
12327 struct listnode
*node
;
12330 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12331 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12332 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12336 return CMD_SUCCESS
;
12339 /* also used for encap safi */
12340 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12341 afi_t afi
, safi_t safi
)
12343 struct bgp_node
*prn
;
12344 struct bgp_node
*rn
;
12345 struct bgp_table
*table
;
12347 struct prefix_rd
*prd
;
12348 struct bgp_static
*bgp_static
;
12349 mpls_label_t label
;
12350 char buf
[SU_ADDRSTRLEN
];
12351 char rdbuf
[RD_ADDRSTRLEN
];
12353 /* Network configuration. */
12354 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12355 prn
= bgp_route_next(prn
)) {
12356 table
= bgp_node_get_bgp_table_info(prn
);
12360 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12361 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12362 if (bgp_static
== NULL
)
12366 prd
= (struct prefix_rd
*)&prn
->p
;
12368 /* "network" configuration display. */
12369 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12370 label
= decode_label(&bgp_static
->label
);
12372 vty_out(vty
, " network %s/%d rd %s",
12373 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12375 p
->prefixlen
, rdbuf
);
12376 if (safi
== SAFI_MPLS_VPN
)
12377 vty_out(vty
, " label %u", label
);
12379 if (bgp_static
->rmap
.name
)
12380 vty_out(vty
, " route-map %s",
12381 bgp_static
->rmap
.name
);
12383 if (bgp_static
->backdoor
)
12384 vty_out(vty
, " backdoor");
12386 vty_out(vty
, "\n");
12391 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12392 afi_t afi
, safi_t safi
)
12394 struct bgp_node
*prn
;
12395 struct bgp_node
*rn
;
12396 struct bgp_table
*table
;
12398 struct prefix_rd
*prd
;
12399 struct bgp_static
*bgp_static
;
12400 char buf
[PREFIX_STRLEN
* 2];
12401 char buf2
[SU_ADDRSTRLEN
];
12402 char rdbuf
[RD_ADDRSTRLEN
];
12404 /* Network configuration. */
12405 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12406 prn
= bgp_route_next(prn
)) {
12407 table
= bgp_node_get_bgp_table_info(prn
);
12411 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12412 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12413 if (bgp_static
== NULL
)
12416 char *macrouter
= NULL
;
12419 if (bgp_static
->router_mac
)
12420 macrouter
= prefix_mac2str(
12421 bgp_static
->router_mac
, NULL
, 0);
12422 if (bgp_static
->eth_s_id
)
12423 esi
= esi2str(bgp_static
->eth_s_id
);
12425 prd
= (struct prefix_rd
*)&prn
->p
;
12427 /* "network" configuration display. */
12428 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12429 if (p
->u
.prefix_evpn
.route_type
== 5) {
12430 char local_buf
[PREFIX_STRLEN
];
12431 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12432 struct prefix_evpn
*)p
)
12436 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12437 local_buf
, PREFIX_STRLEN
);
12438 sprintf(buf
, "%s/%u", local_buf
,
12439 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12441 prefix2str(p
, buf
, sizeof(buf
));
12444 if (bgp_static
->gatewayIp
.family
== AF_INET
12445 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12446 inet_ntop(bgp_static
->gatewayIp
.family
,
12447 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12450 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12452 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12453 decode_label(&bgp_static
->label
), esi
, buf2
,
12456 XFREE(MTYPE_TMP
, macrouter
);
12457 XFREE(MTYPE_TMP
, esi
);
12462 /* Configuration of static route announcement and aggregate
12464 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12467 struct bgp_node
*rn
;
12469 struct bgp_static
*bgp_static
;
12470 struct bgp_aggregate
*bgp_aggregate
;
12471 char buf
[SU_ADDRSTRLEN
];
12473 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12474 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12478 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12479 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12483 /* Network configuration. */
12484 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12485 rn
= bgp_route_next(rn
)) {
12486 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12487 if (bgp_static
== NULL
)
12492 vty_out(vty
, " network %s/%d",
12493 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12496 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12497 vty_out(vty
, " label-index %u",
12498 bgp_static
->label_index
);
12500 if (bgp_static
->rmap
.name
)
12501 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12503 if (bgp_static
->backdoor
)
12504 vty_out(vty
, " backdoor");
12506 vty_out(vty
, "\n");
12509 /* Aggregate-address configuration. */
12510 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12511 rn
= bgp_route_next(rn
)) {
12512 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12513 if (bgp_aggregate
== NULL
)
12518 vty_out(vty
, " aggregate-address %s/%d",
12519 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12522 if (bgp_aggregate
->as_set
)
12523 vty_out(vty
, " as-set");
12525 if (bgp_aggregate
->summary_only
)
12526 vty_out(vty
, " summary-only");
12528 if (bgp_aggregate
->rmap
.name
)
12529 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12531 vty_out(vty
, "\n");
12535 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12538 struct bgp_node
*rn
;
12539 struct bgp_distance
*bdistance
;
12541 /* Distance configuration. */
12542 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12543 && bgp
->distance_local
[afi
][safi
]
12544 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12545 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12546 || bgp
->distance_local
[afi
][safi
]
12547 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12548 vty_out(vty
, " distance bgp %d %d %d\n",
12549 bgp
->distance_ebgp
[afi
][safi
],
12550 bgp
->distance_ibgp
[afi
][safi
],
12551 bgp
->distance_local
[afi
][safi
]);
12554 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12555 rn
= bgp_route_next(rn
)) {
12556 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12557 if (bdistance
!= NULL
) {
12558 char buf
[PREFIX_STRLEN
];
12560 vty_out(vty
, " distance %d %s %s\n",
12561 bdistance
->distance
,
12562 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12563 bdistance
->access_list
? bdistance
->access_list
12569 /* Allocate routing table structure and install commands. */
12570 void bgp_route_init(void)
12575 /* Init BGP distance table. */
12576 FOREACH_AFI_SAFI (afi
, safi
)
12577 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12579 /* IPv4 BGP commands. */
12580 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12581 install_element(BGP_NODE
, &bgp_network_cmd
);
12582 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12584 install_element(BGP_NODE
, &aggregate_address_cmd
);
12585 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12586 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12587 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12589 /* IPv4 unicast configuration. */
12590 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12591 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12592 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12594 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12595 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12596 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12597 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12599 /* IPv4 multicast configuration. */
12600 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12601 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12602 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12603 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12604 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12605 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12606 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12608 /* IPv4 labeled-unicast configuration. */
12609 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12610 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12611 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12612 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12613 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12615 install_element(VIEW_NODE
,
12616 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12617 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12618 install_element(VIEW_NODE
,
12619 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12620 #ifdef KEEP_OLD_VPN_COMMANDS
12621 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12622 #endif /* KEEP_OLD_VPN_COMMANDS */
12623 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12624 install_element(VIEW_NODE
,
12625 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12627 /* BGP dampening clear commands */
12628 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12629 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12631 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12632 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12635 install_element(ENABLE_NODE
,
12636 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12637 #ifdef KEEP_OLD_VPN_COMMANDS
12638 install_element(ENABLE_NODE
,
12639 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12640 #endif /* KEEP_OLD_VPN_COMMANDS */
12642 /* New config IPv6 BGP commands. */
12643 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12644 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12645 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12647 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12648 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12650 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12652 install_element(BGP_NODE
, &bgp_distance_cmd
);
12653 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12654 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12655 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12656 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12657 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12658 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12659 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12660 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12661 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12662 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12663 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12664 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12665 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12666 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12667 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12668 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12669 install_element(BGP_IPV4M_NODE
,
12670 &no_bgp_distance_source_access_list_cmd
);
12671 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12672 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12673 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12674 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12675 install_element(BGP_IPV6_NODE
,
12676 &ipv6_bgp_distance_source_access_list_cmd
);
12677 install_element(BGP_IPV6_NODE
,
12678 &no_ipv6_bgp_distance_source_access_list_cmd
);
12679 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12680 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12681 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12682 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12683 install_element(BGP_IPV6M_NODE
,
12684 &ipv6_bgp_distance_source_access_list_cmd
);
12685 install_element(BGP_IPV6M_NODE
,
12686 &no_ipv6_bgp_distance_source_access_list_cmd
);
12688 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12689 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12690 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12691 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12693 /* IPv4 Multicast Mode */
12694 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12695 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12697 /* Large Communities */
12698 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12699 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12701 /* show bgp ipv4 flowspec detailed */
12702 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12704 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12707 void bgp_route_finish(void)
12712 FOREACH_AFI_SAFI (afi
, safi
) {
12713 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12714 bgp_distance_table
[afi
][safi
] = NULL
;