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 /* AS path loop check. */
1643 if (onlypeer
&& onlypeer
->as_path_loop_detection
1644 && 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
);
1653 /* If we're a CONFED we need to loop check the CONFED ID too */
1654 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
1655 if (aspath_loop_check(piattr
->aspath
, bgp
->confed_id
)) {
1656 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1658 "%s [Update:SEND] suppress announcement to peer AS %u"
1660 peer
->host
, bgp
->confed_id
);
1665 /* Route-Reflect check. */
1666 if (from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1671 /* IBGP reflection check. */
1672 if (reflect
&& !samepeer_safe
) {
1673 /* A route from a Client peer. */
1674 if (CHECK_FLAG(from
->af_flags
[afi
][safi
],
1675 PEER_FLAG_REFLECTOR_CLIENT
)) {
1676 /* Reflect to all the Non-Client peers and also to the
1677 Client peers other than the originator. Originator
1679 is already done. So there is noting to do. */
1680 /* no bgp client-to-client reflection check. */
1681 if (bgp_flag_check(bgp
, BGP_FLAG_NO_CLIENT_TO_CLIENT
))
1682 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1683 PEER_FLAG_REFLECTOR_CLIENT
))
1686 /* A route from a Non-client peer. Reflect to all other
1688 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1689 PEER_FLAG_REFLECTOR_CLIENT
))
1694 /* For modify attribute, copy it to temporary structure. */
1695 bgp_attr_dup(attr
, piattr
);
1697 /* If local-preference is not set. */
1698 if ((peer
->sort
== BGP_PEER_IBGP
|| peer
->sort
== BGP_PEER_CONFED
)
1699 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)))) {
1700 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1701 attr
->local_pref
= bgp
->default_local_pref
;
1704 /* If originator-id is not set and the route is to be reflected,
1705 set the originator id */
1707 && (!(attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)))) {
1708 IPV4_ADDR_COPY(&(attr
->originator_id
), &(from
->remote_id
));
1709 SET_FLAG(attr
->flag
, BGP_ATTR_ORIGINATOR_ID
);
1712 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1714 if (peer
->sort
== BGP_PEER_EBGP
1715 && attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
1716 if (from
!= bgp
->peer_self
&& !transparent
1717 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1718 PEER_FLAG_MED_UNCHANGED
))
1720 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
));
1723 /* Since the nexthop attribute can vary per peer, it is not explicitly
1725 * in announce check, only certain flags and length (or number of
1727 * -- for IPv6/MP_REACH) are set here in order to guide the update
1729 * code in setting the nexthop(s) on a per peer basis in
1731 * Typically, the source nexthop in the attribute is preserved but in
1733 * scenarios where we know it will always be overwritten, we reset the
1734 * nexthop to "0" in an attempt to achieve better Update packing. An
1735 * example of this is when a prefix from each of 2 IBGP peers needs to
1737 * announced to an EBGP peer (and they have the same attributes barring
1741 SET_FLAG(attr
->rmap_change_flags
, BATTR_REFLECTED
);
1743 #define NEXTHOP_IS_V6 \
1744 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1745 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1746 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1747 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1749 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1751 * the peer (group) is configured to receive link-local nexthop
1753 * and it is available in the prefix OR we're not reflecting the route,
1754 * link-local nexthop address is valid and
1755 * the peer (group) to whom we're going to announce is on a shared
1757 * and this is either a self-originated route or the peer is EBGP.
1758 * By checking if nexthop LL address is valid we are sure that
1759 * we do not announce LL address as `::`.
1761 if (NEXTHOP_IS_V6
) {
1762 attr
->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
1763 if ((CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1764 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)
1765 && IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_local
))
1767 && IN6_IS_ADDR_LINKLOCAL(&peer
->nexthop
.v6_local
)
1768 && peer
->shared_network
1769 && (from
== bgp
->peer_self
1770 || peer
->sort
== BGP_PEER_EBGP
))) {
1771 attr
->mp_nexthop_len
=
1772 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
;
1775 /* Clear off link-local nexthop in source, whenever it is not
1777 * ensure more prefixes share the same attribute for
1780 if (!(CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1781 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED
)))
1782 memset(&attr
->mp_nexthop_local
, 0, IPV6_MAX_BYTELEN
);
1785 bgp_peer_remove_private_as(bgp
, afi
, safi
, peer
, attr
);
1786 bgp_peer_as_override(bgp
, afi
, safi
, peer
, attr
);
1788 /* Route map & unsuppress-map apply. */
1789 if (ROUTE_MAP_OUT_NAME(filter
) || (pi
->extra
&& pi
->extra
->suppress
)) {
1790 struct bgp_path_info rmap_path
= {0};
1791 struct bgp_path_info_extra dummy_rmap_path_extra
= {0};
1792 struct attr dummy_attr
= {0};
1794 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
1795 rmap_path
.peer
= peer
;
1796 rmap_path
.attr
= attr
;
1799 memcpy(&dummy_rmap_path_extra
, pi
->extra
,
1800 sizeof(struct bgp_path_info_extra
));
1801 rmap_path
.extra
= &dummy_rmap_path_extra
;
1804 /* don't confuse inbound and outbound setting */
1805 RESET_FLAG(attr
->rmap_change_flags
);
1808 * The route reflector is not allowed to modify the attributes
1809 * of the reflected IBGP routes unless explicitly allowed.
1811 if ((from
->sort
== BGP_PEER_IBGP
&& peer
->sort
== BGP_PEER_IBGP
)
1812 && !bgp_flag_check(bgp
,
1813 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY
)) {
1814 bgp_attr_dup(&dummy_attr
, attr
);
1815 rmap_path
.attr
= &dummy_attr
;
1818 SET_FLAG(peer
->rmap_type
, PEER_RMAP_TYPE_OUT
);
1820 if (pi
->extra
&& pi
->extra
->suppress
)
1821 ret
= route_map_apply(UNSUPPRESS_MAP(filter
), p
,
1822 RMAP_BGP
, &rmap_path
);
1824 ret
= route_map_apply(ROUTE_MAP_OUT(filter
), p
,
1825 RMAP_BGP
, &rmap_path
);
1827 peer
->rmap_type
= 0;
1829 if (ret
== RMAP_DENYMATCH
) {
1830 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1831 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1832 peer
->host
, prefix2str(p
, buf
, sizeof(buf
)));
1834 bgp_attr_flush(attr
);
1839 /* RFC 8212 to prevent route leaks.
1840 * This specification intends to improve this situation by requiring the
1841 * explicit configuration of both BGP Import and Export Policies for any
1842 * External BGP (EBGP) session such as customers, peers, or
1843 * confederation boundaries for all enabled address families. Through
1844 * codification of the aforementioned requirement, operators will
1845 * benefit from consistent behavior across different BGP
1848 if (peer
->bgp
->ebgp_requires_policy
1849 == DEFAULT_EBGP_POLICY_ENABLED
)
1850 if (!bgp_outbound_policy_exists(peer
, filter
))
1853 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
1854 if (peer
->sort
== BGP_PEER_IBGP
1855 || peer
->sort
== BGP_PEER_CONFED
) {
1856 attr
->flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
1857 attr
->local_pref
= BGP_GSHUT_LOCAL_PREF
;
1859 bgp_attr_add_gshut_community(attr
);
1863 /* After route-map has been applied, we check to see if the nexthop to
1864 * be carried in the attribute (that is used for the announcement) can
1865 * be cleared off or not. We do this in all cases where we would be
1866 * setting the nexthop to "ourselves". For IPv6, we only need to
1868 * the global nexthop here; the link-local nexthop would have been
1870 * already, and if not, it is required by the update formation code.
1871 * Also see earlier comments in this function.
1874 * If route-map has performed some operation on the nexthop or the peer
1875 * configuration says to pass it unchanged, we cannot reset the nexthop
1876 * here, so only attempt to do it if these aren't true. Note that the
1877 * route-map handler itself might have cleared the nexthop, if for
1879 * it is configured as 'peer-address'.
1881 if (!bgp_rmap_nhop_changed(attr
->rmap_change_flags
,
1882 piattr
->rmap_change_flags
)
1884 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1885 PEER_FLAG_NEXTHOP_UNCHANGED
)) {
1886 /* We can reset the nexthop, if setting (or forcing) it to
1888 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1889 PEER_FLAG_NEXTHOP_SELF
)
1890 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1891 PEER_FLAG_FORCE_NEXTHOP_SELF
)) {
1893 || CHECK_FLAG(peer
->af_flags
[afi
][safi
],
1894 PEER_FLAG_FORCE_NEXTHOP_SELF
))
1895 subgroup_announce_reset_nhop(
1896 (peer_cap_enhe(peer
, afi
, safi
)
1900 } else if (peer
->sort
== BGP_PEER_EBGP
) {
1901 /* Can also reset the nexthop if announcing to EBGP, but
1903 * no peer in the subgroup is on a shared subnet.
1904 * Note: 3rd party nexthop currently implemented for
1907 if ((p
->family
== AF_INET
) &&
1908 (!bgp_subgrp_multiaccess_check_v4(
1911 subgroup_announce_reset_nhop(
1912 (peer_cap_enhe(peer
, afi
, safi
)
1917 if ((p
->family
== AF_INET6
) &&
1918 (!bgp_subgrp_multiaccess_check_v6(
1919 piattr
->mp_nexthop_global
,
1921 subgroup_announce_reset_nhop(
1922 (peer_cap_enhe(peer
, afi
, safi
)
1929 } else if (CHECK_FLAG(pi
->flags
, BGP_PATH_ANNC_NH_SELF
)) {
1931 * This flag is used for leaked vpn-vrf routes
1933 int family
= p
->family
;
1935 if (peer_cap_enhe(peer
, afi
, safi
))
1938 if (bgp_debug_update(NULL
, p
, subgrp
->update_group
, 0))
1940 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
1941 __func__
, family2str(family
));
1942 subgroup_announce_reset_nhop(family
, attr
);
1946 /* If IPv6/MP and nexthop does not have any override and happens
1948 * be a link-local address, reset it so that we don't pass along
1950 * source's link-local IPv6 address to recipients who may not be
1952 * the same interface.
1954 if (p
->family
== AF_INET6
|| peer_cap_enhe(peer
, afi
, safi
)) {
1955 if (IN6_IS_ADDR_LINKLOCAL(&attr
->mp_nexthop_global
))
1956 subgroup_announce_reset_nhop(AF_INET6
, attr
);
1962 void bgp_best_selection(struct bgp
*bgp
, struct bgp_node
*rn
,
1963 struct bgp_maxpaths_cfg
*mpath_cfg
,
1964 struct bgp_path_info_pair
*result
, afi_t afi
,
1967 struct bgp_path_info
*new_select
;
1968 struct bgp_path_info
*old_select
;
1969 struct bgp_path_info
*pi
;
1970 struct bgp_path_info
*pi1
;
1971 struct bgp_path_info
*pi2
;
1972 struct bgp_path_info
*nextpi
= NULL
;
1973 int paths_eq
, do_mpath
, debug
;
1974 struct list mp_list
;
1975 char pfx_buf
[PREFIX2STR_BUFFER
];
1976 char path_buf
[PATH_ADDPATH_STR_BUFFER
];
1978 bgp_mp_list_init(&mp_list
);
1980 (mpath_cfg
->maxpaths_ebgp
> 1 || mpath_cfg
->maxpaths_ibgp
> 1);
1982 debug
= bgp_debug_bestpath(&rn
->p
);
1985 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
1987 /* bgp deterministic-med */
1989 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)) {
1991 /* Clear BGP_PATH_DMED_SELECTED for all paths */
1992 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1994 bgp_path_info_unset_flag(rn
, pi1
,
1995 BGP_PATH_DMED_SELECTED
);
1997 for (pi1
= bgp_node_get_bgp_path_info(rn
); pi1
;
1999 if (CHECK_FLAG(pi1
->flags
, BGP_PATH_DMED_CHECK
))
2001 if (BGP_PATH_HOLDDOWN(pi1
))
2003 if (pi1
->peer
!= bgp
->peer_self
)
2004 if (pi1
->peer
->status
!= Established
)
2009 for (pi2
= pi1
->next
; pi2
; pi2
= pi2
->next
) {
2010 if (CHECK_FLAG(pi2
->flags
,
2011 BGP_PATH_DMED_CHECK
))
2013 if (BGP_PATH_HOLDDOWN(pi2
))
2015 if (pi2
->peer
!= bgp
->peer_self
2018 PEER_STATUS_NSF_WAIT
))
2019 if (pi2
->peer
->status
2023 if (!aspath_cmp_left(pi1
->attr
->aspath
,
2025 && !aspath_cmp_left_confed(
2030 if (bgp_path_info_cmp(
2031 bgp
, pi2
, new_select
,
2032 &paths_eq
, mpath_cfg
, debug
,
2035 bgp_path_info_unset_flag(
2037 BGP_PATH_DMED_SELECTED
);
2041 bgp_path_info_set_flag(
2042 rn
, pi2
, BGP_PATH_DMED_CHECK
);
2045 bgp_path_info_set_flag(rn
, new_select
,
2046 BGP_PATH_DMED_CHECK
);
2047 bgp_path_info_set_flag(rn
, new_select
,
2048 BGP_PATH_DMED_SELECTED
);
2051 bgp_path_info_path_with_addpath_rx_str(
2052 new_select
, path_buf
);
2053 zlog_debug("%s: %s is the bestpath from AS %u",
2055 aspath_get_first_as(
2056 new_select
->attr
->aspath
));
2061 /* Check old selected route and new selected route. */
2064 for (pi
= bgp_node_get_bgp_path_info(rn
);
2065 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2066 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
2069 if (BGP_PATH_HOLDDOWN(pi
)) {
2070 /* reap REMOVED routes, if needs be
2071 * selected route must stay for a while longer though
2073 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
2074 && (pi
!= old_select
))
2075 bgp_path_info_reap(rn
, pi
);
2078 zlog_debug("%s: pi %p in holddown", __func__
,
2084 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2085 && !CHECK_FLAG(pi
->peer
->sflags
, PEER_STATUS_NSF_WAIT
))
2086 if (pi
->peer
->status
!= Established
) {
2090 "%s: pi %p non self peer %s not estab state",
2091 __func__
, pi
, pi
->peer
->host
);
2096 if (bgp_flag_check(bgp
, BGP_FLAG_DETERMINISTIC_MED
)
2097 && (!CHECK_FLAG(pi
->flags
, BGP_PATH_DMED_SELECTED
))) {
2098 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2100 zlog_debug("%s: pi %p dmed", __func__
, pi
);
2104 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_DMED_CHECK
);
2106 if (bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
, mpath_cfg
,
2107 debug
, pfx_buf
, afi
, safi
, &rn
->reason
)) {
2112 /* Now that we know which path is the bestpath see if any of the other
2114 * qualify as multipaths
2118 bgp_path_info_path_with_addpath_rx_str(new_select
,
2121 sprintf(path_buf
, "NONE");
2123 "%s: After path selection, newbest is %s oldbest was %s",
2125 old_select
? old_select
->peer
->host
: "NONE");
2128 if (do_mpath
&& new_select
) {
2129 for (pi
= bgp_node_get_bgp_path_info(rn
);
2130 (pi
!= NULL
) && (nextpi
= pi
->next
, 1); pi
= nextpi
) {
2133 bgp_path_info_path_with_addpath_rx_str(
2136 if (pi
== new_select
) {
2139 "%s: %s is the bestpath, add to the multipath list",
2141 bgp_mp_list_add(&mp_list
, pi
);
2145 if (BGP_PATH_HOLDDOWN(pi
))
2148 if (pi
->peer
&& pi
->peer
!= bgp
->peer_self
2149 && !CHECK_FLAG(pi
->peer
->sflags
,
2150 PEER_STATUS_NSF_WAIT
))
2151 if (pi
->peer
->status
!= Established
)
2154 if (!bgp_path_info_nexthop_cmp(pi
, new_select
)) {
2157 "%s: %s has the same nexthop as the bestpath, skip it",
2162 bgp_path_info_cmp(bgp
, pi
, new_select
, &paths_eq
,
2163 mpath_cfg
, debug
, pfx_buf
, afi
, safi
,
2169 "%s: %s is equivalent to the bestpath, add to the multipath list",
2171 bgp_mp_list_add(&mp_list
, pi
);
2176 bgp_path_info_mpath_update(rn
, new_select
, old_select
, &mp_list
,
2178 bgp_path_info_mpath_aggregate_update(new_select
, old_select
);
2179 bgp_mp_list_clear(&mp_list
);
2181 bgp_addpath_update_ids(bgp
, rn
, afi
, safi
);
2183 result
->old
= old_select
;
2184 result
->new = new_select
;
2190 * A new route/change in bestpath of an existing route. Evaluate the path
2191 * for advertisement to the subgroup.
2193 int subgroup_process_announce_selected(struct update_subgroup
*subgrp
,
2194 struct bgp_path_info
*selected
,
2195 struct bgp_node
*rn
,
2196 uint32_t addpath_tx_id
)
2199 struct peer
*onlypeer
;
2205 afi
= SUBGRP_AFI(subgrp
);
2206 safi
= SUBGRP_SAFI(subgrp
);
2207 onlypeer
= ((SUBGRP_PCOUNT(subgrp
) == 1) ? (SUBGRP_PFIRST(subgrp
))->peer
2210 if (BGP_DEBUG(update
, UPDATE_OUT
)) {
2211 char buf_prefix
[PREFIX_STRLEN
];
2212 prefix2str(p
, buf_prefix
, sizeof(buf_prefix
));
2213 zlog_debug("%s: p=%s, selected=%p", __func__
, buf_prefix
,
2217 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2218 if (onlypeer
&& CHECK_FLAG(onlypeer
->af_sflags
[afi
][safi
],
2219 PEER_STATUS_ORF_WAIT_REFRESH
))
2222 memset(&attr
, 0, sizeof(struct attr
));
2223 /* It's initialized in bgp_announce_check() */
2225 /* Announcement to the subgroup. If the route is filtered withdraw it.
2228 if (subgroup_announce_check(rn
, selected
, subgrp
, p
, &attr
))
2229 bgp_adj_out_set_subgroup(rn
, subgrp
, &attr
, selected
);
2231 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1,
2235 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2237 bgp_adj_out_unset_subgroup(rn
, subgrp
, 1, addpath_tx_id
);
2244 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2245 * This is called at the end of route processing.
2247 void bgp_zebra_clear_route_change_flags(struct bgp_node
*rn
)
2249 struct bgp_path_info
*pi
;
2251 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2252 if (BGP_PATH_HOLDDOWN(pi
))
2254 UNSET_FLAG(pi
->flags
, BGP_PATH_IGP_CHANGED
);
2255 UNSET_FLAG(pi
->flags
, BGP_PATH_ATTR_CHANGED
);
2260 * Has the route changed from the RIB's perspective? This is invoked only
2261 * if the route selection returns the same best route as earlier - to
2262 * determine if we need to update zebra or not.
2264 int bgp_zebra_has_route_changed(struct bgp_node
*rn
,
2265 struct bgp_path_info
*selected
)
2267 struct bgp_path_info
*mpinfo
;
2269 /* If this is multipath, check all selected paths for any nexthop
2270 * change or attribute change. Some attribute changes (e.g., community)
2271 * aren't of relevance to the RIB, but we'll update zebra to ensure
2272 * we handle the case of BGP nexthop change. This is the behavior
2273 * when the best path has an attribute change anyway.
2275 if (CHECK_FLAG(selected
->flags
, BGP_PATH_IGP_CHANGED
)
2276 || CHECK_FLAG(selected
->flags
, BGP_PATH_MULTIPATH_CHG
))
2280 * If this is multipath, check all selected paths for any nexthop change
2282 for (mpinfo
= bgp_path_info_mpath_first(selected
); mpinfo
;
2283 mpinfo
= bgp_path_info_mpath_next(mpinfo
)) {
2284 if (CHECK_FLAG(mpinfo
->flags
, BGP_PATH_IGP_CHANGED
)
2285 || CHECK_FLAG(mpinfo
->flags
, BGP_PATH_ATTR_CHANGED
))
2289 /* Nothing has changed from the RIB's perspective. */
2293 struct bgp_process_queue
{
2295 STAILQ_HEAD(, bgp_node
) pqueue
;
2296 #define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2298 unsigned int queued
;
2302 * old_select = The old best path
2303 * new_select = the new best path
2305 * if (!old_select && new_select)
2306 * We are sending new information on.
2308 * if (old_select && new_select) {
2309 * if (new_select != old_select)
2310 * We have a new best path send a change
2312 * We've received a update with new attributes that needs
2316 * if (old_select && !new_select)
2317 * We have no eligible route that we can announce or the rn
2320 static void bgp_process_main_one(struct bgp
*bgp
, struct bgp_node
*rn
,
2321 afi_t afi
, safi_t safi
)
2323 struct bgp_path_info
*new_select
;
2324 struct bgp_path_info
*old_select
;
2325 struct bgp_path_info_pair old_and_new
;
2326 char pfx_buf
[PREFIX2STR_BUFFER
];
2329 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
)) {
2331 debug
= bgp_debug_bestpath(&rn
->p
);
2333 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2335 "%s: bgp delete in progress, ignoring event, p=%s",
2340 /* Is it end of initial update? (after startup) */
2342 quagga_timestamp(3, bgp
->update_delay_zebra_resume_time
,
2343 sizeof(bgp
->update_delay_zebra_resume_time
));
2345 bgp
->main_zebra_update_hold
= 0;
2346 FOREACH_AFI_SAFI (afi
, safi
) {
2347 if (bgp_fibupd_safi(safi
))
2348 bgp_zebra_announce_table(bgp
, afi
, safi
);
2350 bgp
->main_peers_update_hold
= 0;
2352 bgp_start_routeadv(bgp
);
2356 struct prefix
*p
= &rn
->p
;
2358 debug
= bgp_debug_bestpath(&rn
->p
);
2360 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2361 zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__
, pfx_buf
,
2362 afi2str(afi
), safi2str(safi
));
2365 /* Best path selection. */
2366 bgp_best_selection(bgp
, rn
, &bgp
->maxpaths
[afi
][safi
], &old_and_new
,
2368 old_select
= old_and_new
.old
;
2369 new_select
= old_and_new
.new;
2371 /* Do we need to allocate or free labels?
2372 * Right now, since we only deal with per-prefix labels, it is not
2373 * necessary to do this upon changes to best path. Exceptions:
2374 * - label index has changed -> recalculate resulting label
2375 * - path_info sub_type changed -> switch to/from implicit-null
2376 * - no valid label (due to removed static label binding) -> get new one
2378 if (bgp
->allocate_mpls_labels
[afi
][safi
]) {
2381 || bgp_label_index_differs(new_select
, old_select
)
2382 || new_select
->sub_type
!= old_select
->sub_type
2383 || !bgp_is_valid_label(&rn
->local_label
)) {
2384 /* Enforced penultimate hop popping:
2385 * implicit-null for local routes, aggregate
2386 * and redistributed routes
2388 if (new_select
->sub_type
== BGP_ROUTE_STATIC
2389 || new_select
->sub_type
2390 == BGP_ROUTE_AGGREGATE
2391 || new_select
->sub_type
2392 == BGP_ROUTE_REDISTRIBUTE
) {
2395 BGP_NODE_REGISTERED_FOR_LABEL
))
2396 bgp_unregister_for_label(rn
);
2397 label_ntop(MPLS_LABEL_IMPLICIT_NULL
, 1,
2399 bgp_set_valid_label(&rn
->local_label
);
2401 bgp_register_for_label(rn
, new_select
);
2403 } else if (CHECK_FLAG(rn
->flags
,
2404 BGP_NODE_REGISTERED_FOR_LABEL
)) {
2405 bgp_unregister_for_label(rn
);
2407 } else if (CHECK_FLAG(rn
->flags
, BGP_NODE_REGISTERED_FOR_LABEL
)) {
2408 bgp_unregister_for_label(rn
);
2412 prefix2str(&rn
->p
, pfx_buf
, sizeof(pfx_buf
));
2414 "%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
2415 __func__
, pfx_buf
, afi2str(afi
), safi2str(safi
),
2416 old_select
, new_select
);
2419 /* If best route remains the same and this is not due to user-initiated
2420 * clear, see exactly what needs to be done.
2422 if (old_select
&& old_select
== new_select
2423 && !CHECK_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
)
2424 && !CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2425 && !bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
2426 if (bgp_zebra_has_route_changed(rn
, old_select
)) {
2428 vnc_import_bgp_add_route(bgp
, p
, old_select
);
2429 vnc_import_bgp_exterior_add_route(bgp
, p
, old_select
);
2431 if (bgp_fibupd_safi(safi
)
2432 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2434 if (new_select
->type
== ZEBRA_ROUTE_BGP
2435 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2436 || new_select
->sub_type
2437 == BGP_ROUTE_IMPORTED
))
2439 bgp_zebra_announce(rn
, p
, old_select
,
2443 UNSET_FLAG(old_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2444 bgp_zebra_clear_route_change_flags(rn
);
2446 /* If there is a change of interest to peers, reannounce the
2448 if (CHECK_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
)
2449 || CHECK_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
)) {
2450 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2452 /* unicast routes must also be annouced to
2453 * labeled-unicast update-groups */
2454 if (safi
== SAFI_UNICAST
)
2455 group_announce_route(bgp
, afi
,
2456 SAFI_LABELED_UNICAST
, rn
,
2459 UNSET_FLAG(old_select
->flags
, BGP_PATH_ATTR_CHANGED
);
2460 UNSET_FLAG(rn
->flags
, BGP_NODE_LABEL_CHANGED
);
2463 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2467 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2469 UNSET_FLAG(rn
->flags
, BGP_NODE_USER_CLEAR
);
2471 /* bestpath has changed; bump version */
2472 if (old_select
|| new_select
) {
2473 bgp_bump_version(rn
);
2475 if (!bgp
->t_rmap_def_originate_eval
) {
2479 update_group_refresh_default_originate_route_map
,
2480 bgp
, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER
,
2481 &bgp
->t_rmap_def_originate_eval
);
2486 bgp_path_info_unset_flag(rn
, old_select
, BGP_PATH_SELECTED
);
2489 zlog_debug("%s: setting SELECTED flag", __func__
);
2490 bgp_path_info_set_flag(rn
, new_select
, BGP_PATH_SELECTED
);
2491 bgp_path_info_unset_flag(rn
, new_select
, BGP_PATH_ATTR_CHANGED
);
2492 UNSET_FLAG(new_select
->flags
, BGP_PATH_MULTIPATH_CHG
);
2496 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2497 if (old_select
!= new_select
) {
2499 vnc_import_bgp_exterior_del_route(bgp
, p
,
2501 vnc_import_bgp_del_route(bgp
, p
, old_select
);
2504 vnc_import_bgp_exterior_add_route(bgp
, p
,
2506 vnc_import_bgp_add_route(bgp
, p
, new_select
);
2512 group_announce_route(bgp
, afi
, safi
, rn
, new_select
);
2514 /* unicast routes must also be annouced to labeled-unicast update-groups
2516 if (safi
== SAFI_UNICAST
)
2517 group_announce_route(bgp
, afi
, SAFI_LABELED_UNICAST
, rn
,
2521 if (bgp_fibupd_safi(safi
) && (bgp
->inst_type
!= BGP_INSTANCE_TYPE_VIEW
)
2522 && !bgp_option_check(BGP_OPT_NO_FIB
)) {
2523 if (new_select
&& new_select
->type
== ZEBRA_ROUTE_BGP
2524 && (new_select
->sub_type
== BGP_ROUTE_NORMAL
2525 || new_select
->sub_type
== BGP_ROUTE_AGGREGATE
2526 || new_select
->sub_type
== BGP_ROUTE_IMPORTED
)) {
2528 /* if this is an evpn imported type-5 prefix,
2529 * we need to withdraw the route first to clear
2530 * the nh neigh and the RMAC entry.
2533 is_route_parent_evpn(old_select
))
2534 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2536 bgp_zebra_announce(rn
, p
, new_select
, bgp
, afi
, safi
);
2538 /* Withdraw the route from the kernel. */
2539 if (old_select
&& old_select
->type
== ZEBRA_ROUTE_BGP
2540 && (old_select
->sub_type
== BGP_ROUTE_NORMAL
2541 || old_select
->sub_type
== BGP_ROUTE_AGGREGATE
2542 || old_select
->sub_type
== BGP_ROUTE_IMPORTED
))
2544 bgp_zebra_withdraw(p
, old_select
, bgp
, safi
);
2548 /* advertise/withdraw type-5 routes */
2549 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2550 if (advertise_type5_routes(bgp
, afi
) &&
2552 is_route_injectable_into_evpn(new_select
)) {
2554 /* apply the route-map */
2555 if (bgp
->adv_cmd_rmap
[afi
][safi
].map
) {
2556 route_map_result_t ret
;
2558 ret
= route_map_apply(
2559 bgp
->adv_cmd_rmap
[afi
][safi
].map
,
2560 &rn
->p
, RMAP_BGP
, new_select
);
2561 if (ret
== RMAP_PERMITMATCH
)
2562 bgp_evpn_advertise_type5_route(
2563 bgp
, &rn
->p
, new_select
->attr
,
2566 bgp_evpn_withdraw_type5_route(
2567 bgp
, &rn
->p
, afi
, safi
);
2569 bgp_evpn_advertise_type5_route(bgp
,
2575 } else if (advertise_type5_routes(bgp
, afi
) &&
2577 is_route_injectable_into_evpn(old_select
))
2578 bgp_evpn_withdraw_type5_route(bgp
, &rn
->p
, afi
, safi
);
2581 /* Clear any route change flags. */
2582 bgp_zebra_clear_route_change_flags(rn
);
2584 /* Reap old select bgp_path_info, if it has been removed */
2585 if (old_select
&& CHECK_FLAG(old_select
->flags
, BGP_PATH_REMOVED
))
2586 bgp_path_info_reap(rn
, old_select
);
2588 UNSET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2592 static wq_item_status
bgp_process_wq(struct work_queue
*wq
, void *data
)
2594 struct bgp_process_queue
*pqnode
= data
;
2595 struct bgp
*bgp
= pqnode
->bgp
;
2596 struct bgp_table
*table
;
2597 struct bgp_node
*rn
;
2600 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)) {
2601 bgp_process_main_one(bgp
, NULL
, 0, 0);
2602 /* should always have dedicated wq call */
2603 assert(STAILQ_FIRST(&pqnode
->pqueue
) == NULL
);
2607 while (!STAILQ_EMPTY(&pqnode
->pqueue
)) {
2608 rn
= STAILQ_FIRST(&pqnode
->pqueue
);
2609 STAILQ_REMOVE_HEAD(&pqnode
->pqueue
, pq
);
2610 STAILQ_NEXT(rn
, pq
) = NULL
; /* complete unlink */
2611 table
= bgp_node_table(rn
);
2612 /* note, new RNs may be added as part of processing */
2613 bgp_process_main_one(bgp
, rn
, table
->afi
, table
->safi
);
2615 bgp_unlock_node(rn
);
2616 bgp_table_unlock(table
);
2622 static void bgp_processq_del(struct work_queue
*wq
, void *data
)
2624 struct bgp_process_queue
*pqnode
= data
;
2626 bgp_unlock(pqnode
->bgp
);
2628 XFREE(MTYPE_BGP_PROCESS_QUEUE
, pqnode
);
2631 void bgp_process_queue_init(void)
2633 if (!bm
->process_main_queue
)
2634 bm
->process_main_queue
=
2635 work_queue_new(bm
->master
, "process_main_queue");
2637 bm
->process_main_queue
->spec
.workfunc
= &bgp_process_wq
;
2638 bm
->process_main_queue
->spec
.del_item_data
= &bgp_processq_del
;
2639 bm
->process_main_queue
->spec
.max_retries
= 0;
2640 bm
->process_main_queue
->spec
.hold
= 50;
2641 /* Use a higher yield value of 50ms for main queue processing */
2642 bm
->process_main_queue
->spec
.yield
= 50 * 1000L;
2645 static struct bgp_process_queue
*bgp_processq_alloc(struct bgp
*bgp
)
2647 struct bgp_process_queue
*pqnode
;
2649 pqnode
= XCALLOC(MTYPE_BGP_PROCESS_QUEUE
,
2650 sizeof(struct bgp_process_queue
));
2652 /* unlocked in bgp_processq_del */
2653 pqnode
->bgp
= bgp_lock(bgp
);
2654 STAILQ_INIT(&pqnode
->pqueue
);
2659 void bgp_process(struct bgp
*bgp
, struct bgp_node
*rn
, afi_t afi
, safi_t safi
)
2661 #define ARBITRARY_PROCESS_QLEN 10000
2662 struct work_queue
*wq
= bm
->process_main_queue
;
2663 struct bgp_process_queue
*pqnode
;
2664 int pqnode_reuse
= 0;
2666 /* already scheduled for processing? */
2667 if (CHECK_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
))
2673 /* Add route nodes to an existing work queue item until reaching the
2674 limit only if is from the same BGP view and it's not an EOIU marker
2676 if (work_queue_item_count(wq
)) {
2677 struct work_queue_item
*item
= work_queue_last_item(wq
);
2678 pqnode
= item
->data
;
2680 if (CHECK_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
)
2681 || pqnode
->bgp
!= bgp
2682 || pqnode
->queued
>= ARBITRARY_PROCESS_QLEN
)
2683 pqnode
= bgp_processq_alloc(bgp
);
2687 pqnode
= bgp_processq_alloc(bgp
);
2688 /* all unlocked in bgp_process_wq */
2689 bgp_table_lock(bgp_node_table(rn
));
2691 SET_FLAG(rn
->flags
, BGP_NODE_PROCESS_SCHEDULED
);
2694 /* can't be enqueued twice */
2695 assert(STAILQ_NEXT(rn
, pq
) == NULL
);
2696 STAILQ_INSERT_TAIL(&pqnode
->pqueue
, rn
, pq
);
2700 work_queue_add(wq
, pqnode
);
2705 void bgp_add_eoiu_mark(struct bgp
*bgp
)
2707 struct bgp_process_queue
*pqnode
;
2709 if (bm
->process_main_queue
== NULL
)
2712 pqnode
= bgp_processq_alloc(bgp
);
2714 SET_FLAG(pqnode
->flags
, BGP_PROCESS_QUEUE_EOIU_MARKER
);
2715 work_queue_add(bm
->process_main_queue
, pqnode
);
2718 static int bgp_maximum_prefix_restart_timer(struct thread
*thread
)
2722 peer
= THREAD_ARG(thread
);
2723 peer
->t_pmax_restart
= NULL
;
2725 if (bgp_debug_neighbor_events(peer
))
2727 "%s Maximum-prefix restart timer expired, restore peering",
2730 if ((peer_clear(peer
, NULL
) < 0) && bgp_debug_neighbor_events(peer
))
2731 zlog_debug("%s: %s peer_clear failed",
2732 __PRETTY_FUNCTION__
, peer
->host
);
2737 int bgp_maximum_prefix_overflow(struct peer
*peer
, afi_t afi
, safi_t safi
,
2741 iana_safi_t pkt_safi
;
2743 if (!CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_MAX_PREFIX
))
2746 if (peer
->pcount
[afi
][safi
] > peer
->pmax
[afi
][safi
]) {
2747 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2748 PEER_STATUS_PREFIX_LIMIT
)
2753 "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32
2754 " exceed, limit %" PRIu32
,
2755 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2756 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2757 SET_FLAG(peer
->af_sflags
[afi
][safi
], PEER_STATUS_PREFIX_LIMIT
);
2759 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
],
2760 PEER_FLAG_MAX_PREFIX_WARNING
))
2763 /* Convert AFI, SAFI to values for packet. */
2764 pkt_afi
= afi_int2iana(afi
);
2765 pkt_safi
= safi_int2iana(safi
);
2769 ndata
[0] = (pkt_afi
>> 8);
2771 ndata
[2] = pkt_safi
;
2772 ndata
[3] = (peer
->pmax
[afi
][safi
] >> 24);
2773 ndata
[4] = (peer
->pmax
[afi
][safi
] >> 16);
2774 ndata
[5] = (peer
->pmax
[afi
][safi
] >> 8);
2775 ndata
[6] = (peer
->pmax
[afi
][safi
]);
2777 SET_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
);
2778 bgp_notify_send_with_data(peer
, BGP_NOTIFY_CEASE
,
2779 BGP_NOTIFY_CEASE_MAX_PREFIX
,
2783 /* Dynamic peers will just close their connection. */
2784 if (peer_dynamic_neighbor(peer
))
2787 /* restart timer start */
2788 if (peer
->pmax_restart
[afi
][safi
]) {
2789 peer
->v_pmax_restart
=
2790 peer
->pmax_restart
[afi
][safi
] * 60;
2792 if (bgp_debug_neighbor_events(peer
))
2794 "%s Maximum-prefix restart timer started for %d secs",
2795 peer
->host
, peer
->v_pmax_restart
);
2797 BGP_TIMER_ON(peer
->t_pmax_restart
,
2798 bgp_maximum_prefix_restart_timer
,
2799 peer
->v_pmax_restart
);
2804 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2805 PEER_STATUS_PREFIX_LIMIT
);
2807 if (peer
->pcount
[afi
][safi
]
2808 > (peer
->pmax
[afi
][safi
] * peer
->pmax_threshold
[afi
][safi
] / 100)) {
2809 if (CHECK_FLAG(peer
->af_sflags
[afi
][safi
],
2810 PEER_STATUS_PREFIX_THRESHOLD
)
2815 "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32
2817 get_afi_safi_str(afi
, safi
, false), peer
->host
,
2818 peer
->pcount
[afi
][safi
], peer
->pmax
[afi
][safi
]);
2819 SET_FLAG(peer
->af_sflags
[afi
][safi
],
2820 PEER_STATUS_PREFIX_THRESHOLD
);
2822 UNSET_FLAG(peer
->af_sflags
[afi
][safi
],
2823 PEER_STATUS_PREFIX_THRESHOLD
);
2827 /* Unconditionally remove the route from the RIB, without taking
2828 * damping into consideration (eg, because the session went down)
2830 void bgp_rib_remove(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2831 struct peer
*peer
, afi_t afi
, safi_t safi
)
2833 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
, safi
);
2835 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
2836 bgp_path_info_delete(rn
, pi
); /* keep historical info */
2838 hook_call(bgp_process
, peer
->bgp
, afi
, safi
, rn
, peer
, true);
2840 bgp_process(peer
->bgp
, rn
, afi
, safi
);
2843 static void bgp_rib_withdraw(struct bgp_node
*rn
, struct bgp_path_info
*pi
,
2844 struct peer
*peer
, afi_t afi
, safi_t safi
,
2845 struct prefix_rd
*prd
)
2847 /* apply dampening, if result is suppressed, we'll be retaining
2848 * the bgp_path_info in the RIB for historical reference.
2850 if (CHECK_FLAG(peer
->bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
2851 && peer
->sort
== BGP_PEER_EBGP
)
2852 if ((bgp_damp_withdraw(pi
, rn
, afi
, safi
, 0))
2853 == BGP_DAMP_SUPPRESSED
) {
2854 bgp_aggregate_decrement(peer
->bgp
, &rn
->p
, pi
, afi
,
2860 if (safi
== SAFI_MPLS_VPN
) {
2861 struct bgp_node
*prn
= NULL
;
2862 struct bgp_table
*table
= NULL
;
2864 prn
= bgp_node_get(peer
->bgp
->rib
[afi
][safi
],
2865 (struct prefix
*)prd
);
2866 if (bgp_node_has_bgp_path_info_data(prn
)) {
2867 table
= bgp_node_get_bgp_table_info(prn
);
2869 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
2870 peer
->bgp
, prd
, table
, &rn
->p
, pi
);
2872 bgp_unlock_node(prn
);
2874 if ((afi
== AFI_IP
|| afi
== AFI_IP6
) && (safi
== SAFI_UNICAST
)) {
2875 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
2877 vnc_import_bgp_del_route(peer
->bgp
, &rn
->p
, pi
);
2878 vnc_import_bgp_exterior_del_route(peer
->bgp
, &rn
->p
,
2884 /* If this is an EVPN route, process for un-import. */
2885 if (safi
== SAFI_EVPN
)
2886 bgp_evpn_unimport_route(peer
->bgp
, afi
, safi
, &rn
->p
, pi
);
2888 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
2891 struct bgp_path_info
*info_make(int type
, int sub_type
, unsigned short instance
,
2892 struct peer
*peer
, struct attr
*attr
,
2893 struct bgp_node
*rn
)
2895 struct bgp_path_info
*new;
2897 /* Make new BGP info. */
2898 new = XCALLOC(MTYPE_BGP_ROUTE
, sizeof(struct bgp_path_info
));
2900 new->instance
= instance
;
2901 new->sub_type
= sub_type
;
2904 new->uptime
= bgp_clock();
2909 static void overlay_index_update(struct attr
*attr
,
2910 struct eth_segment_id
*eth_s_id
,
2911 union gw_addr
*gw_ip
)
2916 if (eth_s_id
== NULL
) {
2917 memset(&(attr
->evpn_overlay
.eth_s_id
), 0,
2918 sizeof(struct eth_segment_id
));
2920 memcpy(&(attr
->evpn_overlay
.eth_s_id
), eth_s_id
,
2921 sizeof(struct eth_segment_id
));
2923 if (gw_ip
== NULL
) {
2924 memset(&(attr
->evpn_overlay
.gw_ip
), 0, sizeof(union gw_addr
));
2926 memcpy(&(attr
->evpn_overlay
.gw_ip
), gw_ip
,
2927 sizeof(union gw_addr
));
2931 static bool overlay_index_equal(afi_t afi
, struct bgp_path_info
*path
,
2932 struct eth_segment_id
*eth_s_id
,
2933 union gw_addr
*gw_ip
)
2935 struct eth_segment_id
*path_eth_s_id
, *path_eth_s_id_remote
;
2936 union gw_addr
*path_gw_ip
, *path_gw_ip_remote
;
2938 struct eth_segment_id esi
;
2942 if (afi
!= AFI_L2VPN
)
2945 path_eth_s_id
= &(path
->attr
->evpn_overlay
.eth_s_id
);
2946 path_gw_ip
= &(path
->attr
->evpn_overlay
.gw_ip
);
2948 if (gw_ip
== NULL
) {
2949 memset(&temp
, 0, sizeof(temp
));
2950 path_gw_ip_remote
= &temp
.ip
;
2952 path_gw_ip_remote
= gw_ip
;
2954 if (eth_s_id
== NULL
) {
2955 memset(&temp
, 0, sizeof(temp
));
2956 path_eth_s_id_remote
= &temp
.esi
;
2958 path_eth_s_id_remote
= eth_s_id
;
2960 if (!memcmp(path_gw_ip
, path_gw_ip_remote
, sizeof(union gw_addr
)))
2963 return !memcmp(path_eth_s_id
, path_eth_s_id_remote
,
2964 sizeof(struct eth_segment_id
));
2967 /* Check if received nexthop is valid or not. */
2968 static int bgp_update_martian_nexthop(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
2973 /* Only validated for unicast and multicast currently. */
2974 /* Also valid for EVPN where the nexthop is an IP address. */
2975 if (safi
!= SAFI_UNICAST
&& safi
!= SAFI_MULTICAST
&& safi
!= SAFI_EVPN
)
2978 /* If NEXT_HOP is present, validate it. */
2979 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
2980 if (attr
->nexthop
.s_addr
== 0
2981 || IPV4_CLASS_DE(ntohl(attr
->nexthop
.s_addr
))
2982 || bgp_nexthop_self(bgp
, attr
->nexthop
))
2986 /* If MP_NEXTHOP is present, validate it. */
2987 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
2988 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
2989 * it is not an IPv6 link-local address.
2991 if (attr
->mp_nexthop_len
) {
2992 switch (attr
->mp_nexthop_len
) {
2993 case BGP_ATTR_NHLEN_IPV4
:
2994 case BGP_ATTR_NHLEN_VPNV4
:
2995 ret
= (attr
->mp_nexthop_global_in
.s_addr
== 0
2996 || IPV4_CLASS_DE(ntohl(
2997 attr
->mp_nexthop_global_in
.s_addr
))
2998 || bgp_nexthop_self(bgp
,
2999 attr
->mp_nexthop_global_in
));
3002 case BGP_ATTR_NHLEN_IPV6_GLOBAL
:
3003 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
:
3004 case BGP_ATTR_NHLEN_VPNV6_GLOBAL
:
3005 ret
= (IN6_IS_ADDR_UNSPECIFIED(&attr
->mp_nexthop_global
)
3006 || IN6_IS_ADDR_LOOPBACK(&attr
->mp_nexthop_global
)
3007 || IN6_IS_ADDR_MULTICAST(
3008 &attr
->mp_nexthop_global
));
3020 int bgp_update(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3021 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3022 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3023 uint32_t num_labels
, int soft_reconfig
,
3024 struct bgp_route_evpn
*evpn
)
3027 int aspath_loop_count
= 0;
3028 struct bgp_node
*rn
;
3030 struct attr new_attr
;
3031 struct attr
*attr_new
;
3032 struct bgp_path_info
*pi
;
3033 struct bgp_path_info
*new;
3034 struct bgp_path_info_extra
*extra
;
3036 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3038 int do_loop_check
= 1;
3039 int has_valid_label
= 0;
3041 int vnc_implicit_withdraw
= 0;
3045 memset(&new_attr
, 0, sizeof(struct attr
));
3046 new_attr
.label_index
= BGP_INVALID_LABEL_INDEX
;
3047 new_attr
.label
= MPLS_INVALID_LABEL
;
3050 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3051 /* TODO: Check to see if we can get rid of "is_valid_label" */
3052 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
)
3053 has_valid_label
= (num_labels
> 0) ? 1 : 0;
3055 has_valid_label
= bgp_is_valid_label(label
);
3057 /* When peer's soft reconfiguration enabled. Record input packet in
3060 && CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3061 && peer
!= bgp
->peer_self
)
3062 bgp_adj_in_set(rn
, peer
, attr
, addpath_id
);
3064 /* Check previously received route. */
3065 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3066 if (pi
->peer
== peer
&& pi
->type
== type
3067 && pi
->sub_type
== sub_type
3068 && pi
->addpath_rx_id
== addpath_id
)
3071 /* AS path local-as loop check. */
3072 if (peer
->change_local_as
) {
3073 if (peer
->allowas_in
[afi
][safi
])
3074 aspath_loop_count
= peer
->allowas_in
[afi
][safi
];
3075 else if (!CHECK_FLAG(peer
->flags
,
3076 PEER_FLAG_LOCAL_AS_NO_PREPEND
))
3077 aspath_loop_count
= 1;
3079 if (aspath_loop_check(attr
->aspath
, peer
->change_local_as
)
3080 > aspath_loop_count
) {
3081 peer
->stat_pfx_aspath_loop
++;
3082 reason
= "as-path contains our own AS;";
3087 /* If the peer is configured for "allowas-in origin" and the last ASN in
3089 * as-path is our ASN then we do not need to call aspath_loop_check
3091 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_ALLOWAS_IN_ORIGIN
))
3092 if (aspath_get_last_as(attr
->aspath
) == bgp
->as
)
3095 /* AS path loop check. */
3096 if (do_loop_check
) {
3097 if (aspath_loop_check(attr
->aspath
, bgp
->as
)
3098 > peer
->allowas_in
[afi
][safi
]
3099 || (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)
3100 && aspath_loop_check(attr
->aspath
, bgp
->confed_id
)
3101 > peer
->allowas_in
[afi
][safi
])) {
3102 peer
->stat_pfx_aspath_loop
++;
3103 reason
= "as-path contains our own AS;";
3108 /* Route reflector originator ID check. */
3109 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)
3110 && IPV4_ADDR_SAME(&bgp
->router_id
, &attr
->originator_id
)) {
3111 peer
->stat_pfx_originator_loop
++;
3112 reason
= "originator is us;";
3116 /* Route reflector cluster ID check. */
3117 if (bgp_cluster_filter(peer
, attr
)) {
3118 peer
->stat_pfx_cluster_loop
++;
3119 reason
= "reflected from the same cluster;";
3123 /* Apply incoming filter. */
3124 if (bgp_input_filter(peer
, p
, attr
, afi
, safi
) == FILTER_DENY
) {
3125 peer
->stat_pfx_filter
++;
3130 /* RFC 8212 to prevent route leaks.
3131 * This specification intends to improve this situation by requiring the
3132 * explicit configuration of both BGP Import and Export Policies for any
3133 * External BGP (EBGP) session such as customers, peers, or
3134 * confederation boundaries for all enabled address families. Through
3135 * codification of the aforementioned requirement, operators will
3136 * benefit from consistent behavior across different BGP
3139 if (peer
->bgp
->ebgp_requires_policy
== DEFAULT_EBGP_POLICY_ENABLED
)
3140 if (!bgp_inbound_policy_exists(peer
,
3141 &peer
->filter
[afi
][safi
])) {
3142 reason
= "inbound policy missing";
3146 bgp_attr_dup(&new_attr
, attr
);
3148 /* Apply incoming route-map.
3149 * NB: new_attr may now contain newly allocated values from route-map
3151 * commands, so we need bgp_attr_flush in the error paths, until we
3153 * the attr (which takes over the memory references) */
3154 if (bgp_input_modifier(peer
, p
, &new_attr
, afi
, safi
, NULL
,
3155 label
, num_labels
) == RMAP_DENY
) {
3156 peer
->stat_pfx_filter
++;
3157 reason
= "route-map;";
3158 bgp_attr_flush(&new_attr
);
3162 if (pi
&& pi
->attr
->rmap_table_id
!= new_attr
.rmap_table_id
) {
3163 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
3164 /* remove from RIB previous entry */
3165 bgp_zebra_withdraw(p
, pi
, bgp
, safi
);
3168 if (peer
->sort
== BGP_PEER_EBGP
) {
3170 /* If we receive the graceful-shutdown community from an eBGP
3171 * peer we must lower local-preference */
3172 if (new_attr
.community
3173 && community_include(new_attr
.community
, COMMUNITY_GSHUT
)) {
3174 new_attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
);
3175 new_attr
.local_pref
= BGP_GSHUT_LOCAL_PREF
;
3177 /* If graceful-shutdown is configured then add the GSHUT
3178 * community to all paths received from eBGP peers */
3179 } else if (bgp_flag_check(peer
->bgp
,
3180 BGP_FLAG_GRACEFUL_SHUTDOWN
)) {
3181 bgp_attr_add_gshut_community(&new_attr
);
3185 /* next hop check. */
3186 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
)
3187 && bgp_update_martian_nexthop(bgp
, afi
, safi
, &new_attr
)) {
3188 peer
->stat_pfx_nh_invalid
++;
3189 reason
= "martian or self next-hop;";
3190 bgp_attr_flush(&new_attr
);
3194 if (bgp_mac_entry_exists(p
) || bgp_mac_exist(&attr
->rmac
)) {
3195 peer
->stat_pfx_nh_invalid
++;
3196 reason
= "self mac;";
3200 attr_new
= bgp_attr_intern(&new_attr
);
3202 /* If the update is implicit withdraw. */
3204 pi
->uptime
= bgp_clock();
3205 same_attr
= attrhash_cmp(pi
->attr
, attr_new
);
3207 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3209 /* Same attribute comes in. */
3210 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
3211 && attrhash_cmp(pi
->attr
, attr_new
)
3212 && (!has_valid_label
3213 || memcmp(&(bgp_path_info_extra_get(pi
))->label
, label
,
3214 num_labels
* sizeof(mpls_label_t
))
3216 && (overlay_index_equal(
3217 afi
, pi
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3218 evpn
== NULL
? NULL
: &evpn
->gw_ip
))) {
3219 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
],
3220 BGP_CONFIG_DAMPENING
)
3221 && peer
->sort
== BGP_PEER_EBGP
3222 && CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3223 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3224 bgp_debug_rdpfxpath2str(
3225 afi
, safi
, prd
, p
, label
,
3226 num_labels
, addpath_id
? 1 : 0,
3227 addpath_id
, pfx_buf
,
3229 zlog_debug("%s rcvd %s", peer
->host
,
3233 if (bgp_damp_update(pi
, rn
, afi
, safi
)
3234 != BGP_DAMP_SUPPRESSED
) {
3235 bgp_aggregate_increment(bgp
, p
, pi
, afi
,
3237 bgp_process(bgp
, rn
, afi
, safi
);
3239 } else /* Duplicate - odd */
3241 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3242 if (!peer
->rcvd_attr_printed
) {
3244 "%s rcvd UPDATE w/ attr: %s",
3246 peer
->rcvd_attr_str
);
3247 peer
->rcvd_attr_printed
= 1;
3250 bgp_debug_rdpfxpath2str(
3251 afi
, safi
, prd
, p
, label
,
3252 num_labels
, addpath_id
? 1 : 0,
3253 addpath_id
, pfx_buf
,
3256 "%s rcvd %s...duplicate ignored",
3257 peer
->host
, pfx_buf
);
3260 /* graceful restart STALE flag unset. */
3261 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)) {
3262 bgp_path_info_unset_flag(
3263 rn
, pi
, BGP_PATH_STALE
);
3264 bgp_process(bgp
, rn
, afi
, safi
);
3268 bgp_unlock_node(rn
);
3269 bgp_attr_unintern(&attr_new
);
3274 /* Withdraw/Announce before we fully processed the withdraw */
3275 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
3276 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3277 bgp_debug_rdpfxpath2str(
3278 afi
, safi
, prd
, p
, label
, num_labels
,
3279 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3282 "%s rcvd %s, flapped quicker than processing",
3283 peer
->host
, pfx_buf
);
3286 bgp_path_info_restore(rn
, pi
);
3289 /* Received Logging. */
3290 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3291 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
,
3292 num_labels
, addpath_id
? 1 : 0,
3293 addpath_id
, pfx_buf
,
3295 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3298 /* graceful restart STALE flag unset. */
3299 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
3300 bgp_path_info_unset_flag(rn
, pi
, BGP_PATH_STALE
);
3302 /* The attribute is changed. */
3303 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
3305 /* implicit withdraw, decrement aggregate and pcount here.
3306 * only if update is accepted, they'll increment below.
3308 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
3310 /* Update bgp route dampening information. */
3311 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3312 && peer
->sort
== BGP_PEER_EBGP
) {
3313 /* This is implicit withdraw so we should update
3316 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
3317 bgp_damp_withdraw(pi
, rn
, afi
, safi
, 1);
3320 if (safi
== SAFI_MPLS_VPN
) {
3321 struct bgp_node
*prn
= NULL
;
3322 struct bgp_table
*table
= NULL
;
3324 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3325 (struct prefix
*)prd
);
3326 if (bgp_node_has_bgp_path_info_data(prn
)) {
3327 table
= bgp_node_get_bgp_table_info(prn
);
3329 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
3330 bgp
, prd
, table
, p
, pi
);
3332 bgp_unlock_node(prn
);
3334 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3335 && (safi
== SAFI_UNICAST
)) {
3336 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
3338 * Implicit withdraw case.
3340 ++vnc_implicit_withdraw
;
3341 vnc_import_bgp_del_route(bgp
, p
, pi
);
3342 vnc_import_bgp_exterior_del_route(bgp
, p
, pi
);
3347 /* Special handling for EVPN update of an existing route. If the
3348 * extended community attribute has changed, we need to
3350 * the route using its existing extended community. It will be
3351 * subsequently processed for import with the new extended
3354 if (safi
== SAFI_EVPN
&& !same_attr
) {
3356 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))
3358 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
))) {
3361 cmp
= ecommunity_cmp(pi
->attr
->ecommunity
,
3362 attr_new
->ecommunity
);
3364 if (bgp_debug_update(peer
, p
, NULL
, 1))
3366 "Change in EXT-COMM, existing %s new %s",
3368 pi
->attr
->ecommunity
),
3370 attr_new
->ecommunity
));
3371 bgp_evpn_unimport_route(bgp
, afi
, safi
,
3377 /* Update to new attribute. */
3378 bgp_attr_unintern(&pi
->attr
);
3379 pi
->attr
= attr_new
;
3381 /* Update MPLS label */
3382 if (has_valid_label
) {
3383 extra
= bgp_path_info_extra_get(pi
);
3384 if (extra
->label
!= label
) {
3385 memcpy(&extra
->label
, label
,
3386 num_labels
* sizeof(mpls_label_t
));
3387 extra
->num_labels
= num_labels
;
3389 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3390 bgp_set_valid_label(&extra
->label
[0]);
3394 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3395 && (safi
== SAFI_UNICAST
)) {
3396 if (vnc_implicit_withdraw
) {
3398 * Add back the route with its new attributes
3400 * The route is still selected, until the route
3402 * queued by bgp_process actually runs. We have
3404 * update to the VNC side immediately to avoid
3406 * configuration changes (e.g., route-map
3408 * trigger re-importation of the entire RIB.
3410 vnc_import_bgp_add_route(bgp
, p
, pi
);
3411 vnc_import_bgp_exterior_add_route(bgp
, p
, pi
);
3415 /* Update Overlay Index */
3416 if (afi
== AFI_L2VPN
) {
3417 overlay_index_update(
3418 pi
->attr
, evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3419 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3422 /* Update bgp route dampening information. */
3423 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)
3424 && peer
->sort
== BGP_PEER_EBGP
) {
3425 /* Now we do normal update dampening. */
3426 ret
= bgp_damp_update(pi
, rn
, afi
, safi
);
3427 if (ret
== BGP_DAMP_SUPPRESSED
) {
3428 bgp_unlock_node(rn
);
3433 /* Nexthop reachability check - for unicast and
3434 * labeled-unicast.. */
3435 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3436 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3437 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3438 && !CHECK_FLAG(peer
->flags
,
3439 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3441 bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3446 struct bgp
*bgp_nexthop
= bgp
;
3448 if (pi
->extra
&& pi
->extra
->bgp_orig
)
3449 bgp_nexthop
= pi
->extra
->bgp_orig
;
3451 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
, afi
, pi
,
3453 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3454 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3456 if (BGP_DEBUG(nht
, NHT
)) {
3457 char buf1
[INET6_ADDRSTRLEN
];
3459 (const void *)&attr_new
3461 buf1
, INET6_ADDRSTRLEN
);
3462 zlog_debug("%s(%s): NH unresolved",
3463 __FUNCTION__
, buf1
);
3465 bgp_path_info_unset_flag(rn
, pi
,
3469 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
3472 if (safi
== SAFI_MPLS_VPN
) {
3473 struct bgp_node
*prn
= NULL
;
3474 struct bgp_table
*table
= NULL
;
3476 prn
= bgp_node_get(bgp
->rib
[afi
][safi
],
3477 (struct prefix
*)prd
);
3478 if (bgp_node_has_bgp_path_info_data(prn
)) {
3479 table
= bgp_node_get_bgp_table_info(prn
);
3481 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3482 bgp
, prd
, table
, p
, pi
);
3484 bgp_unlock_node(prn
);
3488 /* If this is an EVPN route and some attribute has changed,
3490 * route for import. If the extended community has changed, we
3492 * have done the un-import earlier and the import would result
3494 * route getting injected into appropriate L2 VNIs. If it is
3496 * some other attribute change, the import will result in
3498 * the attributes for the route in the VNI(s).
3500 if (safi
== SAFI_EVPN
&& !same_attr
)
3501 bgp_evpn_import_route(bgp
, afi
, safi
, p
, pi
);
3503 /* Process change. */
3504 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
3506 bgp_process(bgp
, rn
, afi
, safi
);
3507 bgp_unlock_node(rn
);
3509 if (SAFI_UNICAST
== safi
3510 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3511 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3513 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, pi
);
3515 if ((SAFI_MPLS_VPN
== safi
)
3516 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3518 vpn_leak_to_vrf_update(bgp
, pi
);
3522 if (SAFI_MPLS_VPN
== safi
) {
3523 mpls_label_t label_decoded
= decode_label(label
);
3525 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3526 type
, sub_type
, &label_decoded
);
3528 if (SAFI_ENCAP
== safi
) {
3529 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
,
3530 type
, sub_type
, NULL
);
3535 } // End of implicit withdraw
3537 /* Received Logging. */
3538 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3539 if (!peer
->rcvd_attr_printed
) {
3540 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3541 peer
->rcvd_attr_str
);
3542 peer
->rcvd_attr_printed
= 1;
3545 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3546 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3548 zlog_debug("%s rcvd %s", peer
->host
, pfx_buf
);
3551 /* Make new BGP info. */
3552 new = info_make(type
, sub_type
, 0, peer
, attr_new
, rn
);
3554 /* Update MPLS label */
3555 if (has_valid_label
) {
3556 extra
= bgp_path_info_extra_get(new);
3557 if (extra
->label
!= label
) {
3558 memcpy(&extra
->label
, label
,
3559 num_labels
* sizeof(mpls_label_t
));
3560 extra
->num_labels
= num_labels
;
3562 if (!(afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
))
3563 bgp_set_valid_label(&extra
->label
[0]);
3566 /* Update Overlay Index */
3567 if (afi
== AFI_L2VPN
) {
3568 overlay_index_update(new->attr
,
3569 evpn
== NULL
? NULL
: &evpn
->eth_s_id
,
3570 evpn
== NULL
? NULL
: &evpn
->gw_ip
);
3572 /* Nexthop reachability check. */
3573 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
3574 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
3575 if (peer
->sort
== BGP_PEER_EBGP
&& peer
->ttl
== 1
3576 && !CHECK_FLAG(peer
->flags
,
3577 PEER_FLAG_DISABLE_CONNECTED_CHECK
)
3578 && !bgp_flag_check(bgp
, BGP_FLAG_DISABLE_NH_CONNECTED_CHK
))
3583 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, connected
)
3584 || CHECK_FLAG(peer
->flags
, PEER_FLAG_IS_RFAPI_HD
))
3585 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3587 if (BGP_DEBUG(nht
, NHT
)) {
3588 char buf1
[INET6_ADDRSTRLEN
];
3590 (const void *)&attr_new
->nexthop
,
3591 buf1
, INET6_ADDRSTRLEN
);
3592 zlog_debug("%s(%s): NH unresolved",
3593 __FUNCTION__
, buf1
);
3595 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
3598 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
3601 new->addpath_rx_id
= addpath_id
;
3603 /* Increment prefix */
3604 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
3606 /* Register new BGP information. */
3607 bgp_path_info_add(rn
, new);
3609 /* route_node_get lock */
3610 bgp_unlock_node(rn
);
3613 if (safi
== SAFI_MPLS_VPN
) {
3614 struct bgp_node
*prn
= NULL
;
3615 struct bgp_table
*table
= NULL
;
3617 prn
= bgp_node_get(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
3618 if (bgp_node_has_bgp_path_info_data(prn
)) {
3619 table
= bgp_node_get_bgp_table_info(prn
);
3621 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
3622 bgp
, prd
, table
, p
, new);
3624 bgp_unlock_node(prn
);
3628 /* If maximum prefix count is configured and current prefix
3630 if (bgp_maximum_prefix_overflow(peer
, afi
, safi
, 0))
3633 /* If this is an EVPN route, process for import. */
3634 if (safi
== SAFI_EVPN
)
3635 bgp_evpn_import_route(bgp
, afi
, safi
, p
, new);
3637 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, false);
3639 /* Process change. */
3640 bgp_process(bgp
, rn
, afi
, safi
);
3642 if (SAFI_UNICAST
== safi
3643 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3644 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3645 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
3647 if ((SAFI_MPLS_VPN
== safi
)
3648 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3650 vpn_leak_to_vrf_update(bgp
, new);
3653 if (SAFI_MPLS_VPN
== safi
) {
3654 mpls_label_t label_decoded
= decode_label(label
);
3656 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3657 sub_type
, &label_decoded
);
3659 if (SAFI_ENCAP
== safi
) {
3660 rfapiProcessUpdate(peer
, NULL
, p
, prd
, attr
, afi
, safi
, type
,
3667 /* This BGP update is filtered. Log the reason then update BGP
3670 hook_call(bgp_process
, bgp
, afi
, safi
, rn
, peer
, true);
3672 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3673 if (!peer
->rcvd_attr_printed
) {
3674 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer
->host
,
3675 peer
->rcvd_attr_str
);
3676 peer
->rcvd_attr_printed
= 1;
3679 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3680 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3682 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
3683 peer
->host
, pfx_buf
, reason
);
3687 /* If this is an EVPN route, un-import it as it is now filtered.
3689 if (safi
== SAFI_EVPN
)
3690 bgp_evpn_unimport_route(bgp
, afi
, safi
, p
, pi
);
3692 if (SAFI_UNICAST
== safi
3693 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3694 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3696 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3698 if ((SAFI_MPLS_VPN
== safi
)
3699 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3701 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3704 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
3707 bgp_unlock_node(rn
);
3711 * Filtered update is treated as an implicit withdrawal (see
3713 * a few lines above)
3715 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3716 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3724 int bgp_withdraw(struct peer
*peer
, struct prefix
*p
, uint32_t addpath_id
,
3725 struct attr
*attr
, afi_t afi
, safi_t safi
, int type
,
3726 int sub_type
, struct prefix_rd
*prd
, mpls_label_t
*label
,
3727 uint32_t num_labels
, struct bgp_route_evpn
*evpn
)
3730 char pfx_buf
[BGP_PRD_PATH_STRLEN
];
3731 struct bgp_node
*rn
;
3732 struct bgp_path_info
*pi
;
3735 if ((SAFI_MPLS_VPN
== safi
) || (SAFI_ENCAP
== safi
)) {
3736 rfapiProcessWithdraw(peer
, NULL
, p
, prd
, NULL
, afi
, safi
, type
,
3744 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
3746 /* If peer is soft reconfiguration enabled. Record input packet for
3747 * further calculation.
3749 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
3750 * routes that are filtered. This tanks out Quagga RS pretty badly due
3752 * the iteration over all RS clients.
3753 * Since we need to remove the entry from adj_in anyway, do that first
3755 * if there was no entry, we don't need to do anything more.
3757 if (CHECK_FLAG(peer
->af_flags
[afi
][safi
], PEER_FLAG_SOFT_RECONFIG
)
3758 && peer
!= bgp
->peer_self
)
3759 if (!bgp_adj_in_unset(rn
, peer
, addpath_id
)) {
3760 peer
->stat_pfx_dup_withdraw
++;
3762 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3763 bgp_debug_rdpfxpath2str(
3764 afi
, safi
, prd
, p
, label
, num_labels
,
3765 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3768 "%s withdrawing route %s not in adj-in",
3769 peer
->host
, pfx_buf
);
3771 bgp_unlock_node(rn
);
3775 /* Lookup withdrawn route. */
3776 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
3777 if (pi
->peer
== peer
&& pi
->type
== type
3778 && pi
->sub_type
== sub_type
3779 && pi
->addpath_rx_id
== addpath_id
)
3783 if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3784 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3785 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3787 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer
->host
,
3791 /* Withdraw specified route from routing table. */
3792 if (pi
&& !CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
)) {
3793 bgp_rib_withdraw(rn
, pi
, peer
, afi
, safi
, prd
);
3794 if (SAFI_UNICAST
== safi
3795 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
3796 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3797 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
3799 if ((SAFI_MPLS_VPN
== safi
)
3800 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
3802 vpn_leak_to_vrf_withdraw(bgp
, pi
);
3804 } else if (bgp_debug_update(peer
, p
, NULL
, 1)) {
3805 bgp_debug_rdpfxpath2str(afi
, safi
, prd
, p
, label
, num_labels
,
3806 addpath_id
? 1 : 0, addpath_id
, pfx_buf
,
3808 zlog_debug("%s Can't find the route %s", peer
->host
, pfx_buf
);
3811 /* Unlock bgp_node_get() lock. */
3812 bgp_unlock_node(rn
);
3817 void bgp_default_originate(struct peer
*peer
, afi_t afi
, safi_t safi
,
3820 struct update_subgroup
*subgrp
;
3821 subgrp
= peer_subgroup(peer
, afi
, safi
);
3822 subgroup_default_originate(subgrp
, withdraw
);
3827 * bgp_stop_announce_route_timer
3829 void bgp_stop_announce_route_timer(struct peer_af
*paf
)
3831 if (!paf
->t_announce_route
)
3834 THREAD_TIMER_OFF(paf
->t_announce_route
);
3838 * bgp_announce_route_timer_expired
3840 * Callback that is invoked when the route announcement timer for a
3843 static int bgp_announce_route_timer_expired(struct thread
*t
)
3845 struct peer_af
*paf
;
3848 paf
= THREAD_ARG(t
);
3851 if (peer
->status
!= Established
)
3854 if (!peer
->afc_nego
[paf
->afi
][paf
->safi
])
3857 peer_af_announce_route(paf
, 1);
3862 * bgp_announce_route
3864 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
3866 void bgp_announce_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
3868 struct peer_af
*paf
;
3869 struct update_subgroup
*subgrp
;
3871 paf
= peer_af_find(peer
, afi
, safi
);
3874 subgrp
= PAF_SUBGRP(paf
);
3877 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
3878 * or a refresh has already been triggered.
3880 if (!subgrp
|| paf
->t_announce_route
)
3884 * Start a timer to stagger/delay the announce. This serves
3885 * two purposes - announcement can potentially be combined for
3886 * multiple peers and the announcement doesn't happen in the
3889 thread_add_timer_msec(bm
->master
, bgp_announce_route_timer_expired
, paf
,
3890 (subgrp
->peer_count
== 1)
3891 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
3892 : BGP_ANNOUNCE_ROUTE_DELAY_MS
,
3893 &paf
->t_announce_route
);
3897 * Announce routes from all AF tables to a peer.
3899 * This should ONLY be called when there is a need to refresh the
3900 * routes to the peer based on a policy change for this peer alone
3901 * or a route refresh request received from the peer.
3902 * The operation will result in splitting the peer from its existing
3903 * subgroups and putting it in new subgroups.
3905 void bgp_announce_route_all(struct peer
*peer
)
3910 FOREACH_AFI_SAFI (afi
, safi
)
3911 bgp_announce_route(peer
, afi
, safi
);
3914 static void bgp_soft_reconfig_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
3915 struct bgp_table
*table
,
3916 struct prefix_rd
*prd
)
3919 struct bgp_node
*rn
;
3920 struct bgp_adj_in
*ain
;
3923 table
= peer
->bgp
->rib
[afi
][safi
];
3925 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
3926 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
3927 if (ain
->peer
!= peer
)
3930 struct bgp_path_info
*pi
;
3931 uint32_t num_labels
= 0;
3932 mpls_label_t
*label_pnt
= NULL
;
3933 struct bgp_route_evpn evpn
;
3935 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
3937 if (pi
->peer
== peer
)
3940 if (pi
&& pi
->extra
)
3941 num_labels
= pi
->extra
->num_labels
;
3943 label_pnt
= &pi
->extra
->label
[0];
3945 memcpy(&evpn
, &pi
->attr
->evpn_overlay
,
3948 memset(&evpn
, 0, sizeof(evpn
));
3950 ret
= bgp_update(peer
, &rn
->p
, ain
->addpath_rx_id
,
3951 ain
->attr
, afi
, safi
, ZEBRA_ROUTE_BGP
,
3952 BGP_ROUTE_NORMAL
, prd
, label_pnt
,
3953 num_labels
, 1, &evpn
);
3956 bgp_unlock_node(rn
);
3962 void bgp_soft_reconfig_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
3964 struct bgp_node
*rn
;
3965 struct bgp_table
*table
;
3967 if (peer
->status
!= Established
)
3970 if ((safi
!= SAFI_MPLS_VPN
) && (safi
!= SAFI_ENCAP
)
3971 && (safi
!= SAFI_EVPN
))
3972 bgp_soft_reconfig_table(peer
, afi
, safi
, NULL
, NULL
);
3974 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
3975 rn
= bgp_route_next(rn
)) {
3976 table
= bgp_node_get_bgp_table_info(rn
);
3977 if (table
!= NULL
) {
3978 struct prefix_rd prd
;
3980 prd
.family
= AF_UNSPEC
;
3982 memcpy(&prd
.val
, rn
->p
.u
.val
, 8);
3984 bgp_soft_reconfig_table(peer
, afi
, safi
, table
,
3991 struct bgp_clear_node_queue
{
3992 struct bgp_node
*rn
;
3995 static wq_item_status
bgp_clear_route_node(struct work_queue
*wq
, void *data
)
3997 struct bgp_clear_node_queue
*cnq
= data
;
3998 struct bgp_node
*rn
= cnq
->rn
;
3999 struct peer
*peer
= wq
->spec
.data
;
4000 struct bgp_path_info
*pi
;
4002 afi_t afi
= bgp_node_table(rn
)->afi
;
4003 safi_t safi
= bgp_node_table(rn
)->safi
;
4008 /* It is possible that we have multiple paths for a prefix from a peer
4009 * if that peer is using AddPath.
4011 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
4012 if (pi
->peer
!= peer
)
4015 /* graceful restart STALE flag set. */
4016 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_NSF_WAIT
)
4017 && peer
->nsf
[afi
][safi
]
4018 && !CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
)
4019 && !CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
4020 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_STALE
);
4022 /* If this is an EVPN route, process for
4024 if (safi
== SAFI_EVPN
)
4025 bgp_evpn_unimport_route(bgp
, afi
, safi
, &rn
->p
,
4027 /* Handle withdraw for VRF route-leaking and L3VPN */
4028 if (SAFI_UNICAST
== safi
4029 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
||
4030 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4031 vpn_leak_from_vrf_withdraw(bgp_get_default(),
4034 if (SAFI_MPLS_VPN
== safi
&&
4035 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4036 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4039 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4045 static void bgp_clear_node_queue_del(struct work_queue
*wq
, void *data
)
4047 struct bgp_clear_node_queue
*cnq
= data
;
4048 struct bgp_node
*rn
= cnq
->rn
;
4049 struct bgp_table
*table
= bgp_node_table(rn
);
4051 bgp_unlock_node(rn
);
4052 bgp_table_unlock(table
);
4053 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE
, cnq
);
4056 static void bgp_clear_node_complete(struct work_queue
*wq
)
4058 struct peer
*peer
= wq
->spec
.data
;
4060 /* Tickle FSM to start moving again */
4061 BGP_EVENT_ADD(peer
, Clearing_Completed
);
4063 peer_unlock(peer
); /* bgp_clear_route */
4066 static void bgp_clear_node_queue_init(struct peer
*peer
)
4068 char wname
[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4070 snprintf(wname
, sizeof(wname
), "clear %s", peer
->host
);
4071 #undef CLEAR_QUEUE_NAME_LEN
4073 peer
->clear_node_queue
= work_queue_new(bm
->master
, wname
);
4074 peer
->clear_node_queue
->spec
.hold
= 10;
4075 peer
->clear_node_queue
->spec
.workfunc
= &bgp_clear_route_node
;
4076 peer
->clear_node_queue
->spec
.del_item_data
= &bgp_clear_node_queue_del
;
4077 peer
->clear_node_queue
->spec
.completion_func
= &bgp_clear_node_complete
;
4078 peer
->clear_node_queue
->spec
.max_retries
= 0;
4080 /* we only 'lock' this peer reference when the queue is actually active
4082 peer
->clear_node_queue
->spec
.data
= peer
;
4085 static void bgp_clear_route_table(struct peer
*peer
, afi_t afi
, safi_t safi
,
4086 struct bgp_table
*table
)
4088 struct bgp_node
*rn
;
4089 int force
= bm
->process_main_queue
? 0 : 1;
4092 table
= peer
->bgp
->rib
[afi
][safi
];
4094 /* If still no table => afi/safi isn't configured at all or smth. */
4098 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4099 struct bgp_path_info
*pi
, *next
;
4100 struct bgp_adj_in
*ain
;
4101 struct bgp_adj_in
*ain_next
;
4103 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4104 * queued for every clearing peer, regardless of whether it is
4105 * relevant to the peer at hand.
4107 * Overview: There are 3 different indices which need to be
4108 * scrubbed, potentially, when a peer is removed:
4110 * 1 peer's routes visible via the RIB (ie accepted routes)
4111 * 2 peer's routes visible by the (optional) peer's adj-in index
4112 * 3 other routes visible by the peer's adj-out index
4114 * 3 there is no hurry in scrubbing, once the struct peer is
4115 * removed from bgp->peer, we could just GC such deleted peer's
4116 * adj-outs at our leisure.
4118 * 1 and 2 must be 'scrubbed' in some way, at least made
4119 * invisible via RIB index before peer session is allowed to be
4120 * brought back up. So one needs to know when such a 'search' is
4125 * - there'd be a single global queue or a single RIB walker
4126 * - rather than tracking which route_nodes still need to be
4127 * examined on a peer basis, we'd track which peers still
4130 * Given that our per-peer prefix-counts now should be reliable,
4131 * this may actually be achievable. It doesn't seem to be a huge
4132 * problem at this time,
4134 * It is possible that we have multiple paths for a prefix from
4136 * if that peer is using AddPath.
4140 ain_next
= ain
->next
;
4142 if (ain
->peer
== peer
) {
4143 bgp_adj_in_remove(rn
, ain
);
4144 bgp_unlock_node(rn
);
4150 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4152 if (pi
->peer
!= peer
)
4156 bgp_path_info_reap(rn
, pi
);
4158 struct bgp_clear_node_queue
*cnq
;
4160 /* both unlocked in bgp_clear_node_queue_del */
4161 bgp_table_lock(bgp_node_table(rn
));
4164 MTYPE_BGP_CLEAR_NODE_QUEUE
,
4165 sizeof(struct bgp_clear_node_queue
));
4167 work_queue_add(peer
->clear_node_queue
, cnq
);
4175 void bgp_clear_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4177 struct bgp_node
*rn
;
4178 struct bgp_table
*table
;
4180 if (peer
->clear_node_queue
== NULL
)
4181 bgp_clear_node_queue_init(peer
);
4183 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4184 * Idle until it receives a Clearing_Completed event. This protects
4185 * against peers which flap faster than we can we clear, which could
4188 * a) race with routes from the new session being installed before
4189 * clear_route_node visits the node (to delete the route of that
4191 * b) resource exhaustion, clear_route_node likely leads to an entry
4192 * on the process_main queue. Fast-flapping could cause that queue
4196 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4197 * the unlock will happen upon work-queue completion; other wise, the
4198 * unlock happens at the end of this function.
4200 if (!peer
->clear_node_queue
->thread
)
4203 if (safi
!= SAFI_MPLS_VPN
&& safi
!= SAFI_ENCAP
&& safi
!= SAFI_EVPN
)
4204 bgp_clear_route_table(peer
, afi
, safi
, NULL
);
4206 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4207 rn
= bgp_route_next(rn
)) {
4208 table
= bgp_node_get_bgp_table_info(rn
);
4212 bgp_clear_route_table(peer
, afi
, safi
, table
);
4215 /* unlock if no nodes got added to the clear-node-queue. */
4216 if (!peer
->clear_node_queue
->thread
)
4220 void bgp_clear_route_all(struct peer
*peer
)
4225 FOREACH_AFI_SAFI (afi
, safi
)
4226 bgp_clear_route(peer
, afi
, safi
);
4229 rfapiProcessPeerDown(peer
);
4233 void bgp_clear_adj_in(struct peer
*peer
, afi_t afi
, safi_t safi
)
4235 struct bgp_table
*table
;
4236 struct bgp_node
*rn
;
4237 struct bgp_adj_in
*ain
;
4238 struct bgp_adj_in
*ain_next
;
4240 table
= peer
->bgp
->rib
[afi
][safi
];
4242 /* It is possible that we have multiple paths for a prefix from a peer
4243 * if that peer is using AddPath.
4245 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
4249 ain_next
= ain
->next
;
4251 if (ain
->peer
== peer
) {
4252 bgp_adj_in_remove(rn
, ain
);
4253 bgp_unlock_node(rn
);
4261 void bgp_clear_stale_route(struct peer
*peer
, afi_t afi
, safi_t safi
)
4263 struct bgp_node
*rn
;
4264 struct bgp_path_info
*pi
;
4265 struct bgp_table
*table
;
4267 if (safi
== SAFI_MPLS_VPN
) {
4268 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4269 rn
= bgp_route_next(rn
)) {
4270 struct bgp_node
*rm
;
4272 /* look for neighbor in tables */
4273 table
= bgp_node_get_bgp_table_info(rn
);
4277 for (rm
= bgp_table_top(table
); rm
;
4278 rm
= bgp_route_next(rm
))
4279 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
4281 if (pi
->peer
!= peer
)
4283 if (!CHECK_FLAG(pi
->flags
,
4287 bgp_rib_remove(rm
, pi
, peer
, afi
, safi
);
4292 for (rn
= bgp_table_top(peer
->bgp
->rib
[afi
][safi
]); rn
;
4293 rn
= bgp_route_next(rn
))
4294 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
;
4296 if (pi
->peer
!= peer
)
4298 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
4300 bgp_rib_remove(rn
, pi
, peer
, afi
, safi
);
4306 int bgp_outbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4308 if (peer
->sort
== BGP_PEER_EBGP
4309 && (ROUTE_MAP_OUT_NAME(filter
) || PREFIX_LIST_OUT_NAME(filter
)
4310 || FILTER_LIST_OUT_NAME(filter
)
4311 || DISTRIBUTE_OUT_NAME(filter
)))
4316 int bgp_inbound_policy_exists(struct peer
*peer
, struct bgp_filter
*filter
)
4318 if (peer
->sort
== BGP_PEER_EBGP
4319 && (ROUTE_MAP_IN_NAME(filter
) || PREFIX_LIST_IN_NAME(filter
)
4320 || FILTER_LIST_IN_NAME(filter
)
4321 || DISTRIBUTE_IN_NAME(filter
)))
4326 static void bgp_cleanup_table(struct bgp
*bgp
, struct bgp_table
*table
,
4329 struct bgp_node
*rn
;
4330 struct bgp_path_info
*pi
;
4331 struct bgp_path_info
*next
;
4333 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
))
4334 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= next
) {
4337 /* Unimport EVPN routes from VRFs */
4338 if (safi
== SAFI_EVPN
)
4339 bgp_evpn_unimport_route(bgp
, AFI_L2VPN
,
4343 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
4344 && pi
->type
== ZEBRA_ROUTE_BGP
4345 && (pi
->sub_type
== BGP_ROUTE_NORMAL
4346 || pi
->sub_type
== BGP_ROUTE_AGGREGATE
4347 || pi
->sub_type
== BGP_ROUTE_IMPORTED
)) {
4349 if (bgp_fibupd_safi(safi
))
4350 bgp_zebra_withdraw(&rn
->p
, pi
, bgp
,
4352 bgp_path_info_reap(rn
, pi
);
4357 /* Delete all kernel routes. */
4358 void bgp_cleanup_routes(struct bgp
*bgp
)
4361 struct bgp_node
*rn
;
4362 struct bgp_table
*table
;
4364 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
4365 if (afi
== AFI_L2VPN
)
4367 bgp_cleanup_table(bgp
, bgp
->rib
[afi
][SAFI_UNICAST
],
4370 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4372 if (afi
!= AFI_L2VPN
) {
4374 safi
= SAFI_MPLS_VPN
;
4375 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4376 rn
= bgp_route_next(rn
)) {
4377 table
= bgp_node_get_bgp_table_info(rn
);
4378 if (table
!= NULL
) {
4379 bgp_cleanup_table(bgp
, table
, safi
);
4380 bgp_table_finish(&table
);
4381 bgp_node_set_bgp_table_info(rn
, NULL
);
4382 bgp_unlock_node(rn
);
4386 for (rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rn
;
4387 rn
= bgp_route_next(rn
)) {
4388 table
= bgp_node_get_bgp_table_info(rn
);
4389 if (table
!= NULL
) {
4390 bgp_cleanup_table(bgp
, table
, safi
);
4391 bgp_table_finish(&table
);
4392 bgp_node_set_bgp_table_info(rn
, NULL
);
4393 bgp_unlock_node(rn
);
4398 for (rn
= bgp_table_top(bgp
->rib
[AFI_L2VPN
][SAFI_EVPN
]); rn
;
4399 rn
= bgp_route_next(rn
)) {
4400 table
= bgp_node_get_bgp_table_info(rn
);
4401 if (table
!= NULL
) {
4402 bgp_cleanup_table(bgp
, table
, SAFI_EVPN
);
4403 bgp_table_finish(&table
);
4404 bgp_node_set_bgp_table_info(rn
, NULL
);
4405 bgp_unlock_node(rn
);
4410 void bgp_reset(void)
4413 bgp_zclient_reset();
4414 access_list_reset();
4415 prefix_list_reset();
4418 static int bgp_addpath_encode_rx(struct peer
*peer
, afi_t afi
, safi_t safi
)
4420 return (CHECK_FLAG(peer
->af_cap
[afi
][safi
], PEER_CAP_ADDPATH_AF_RX_ADV
)
4421 && CHECK_FLAG(peer
->af_cap
[afi
][safi
],
4422 PEER_CAP_ADDPATH_AF_TX_RCV
));
4425 /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4427 int bgp_nlri_parse_ip(struct peer
*peer
, struct attr
*attr
,
4428 struct bgp_nlri
*packet
)
4437 int addpath_encoded
;
4438 uint32_t addpath_id
;
4441 lim
= pnt
+ packet
->length
;
4443 safi
= packet
->safi
;
4445 addpath_encoded
= bgp_addpath_encode_rx(peer
, afi
, safi
);
4447 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4448 syntactic validity. If the field is syntactically incorrect,
4449 then the Error Subcode is set to Invalid Network Field. */
4450 for (; pnt
< lim
; pnt
+= psize
) {
4451 /* Clear prefix structure. */
4452 memset(&p
, 0, sizeof(struct prefix
));
4454 if (addpath_encoded
) {
4456 /* When packet overflow occurs return immediately. */
4457 if (pnt
+ BGP_ADDPATH_ID_LEN
> lim
)
4458 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4460 addpath_id
= ntohl(*((uint32_t *)pnt
));
4461 pnt
+= BGP_ADDPATH_ID_LEN
;
4464 /* Fetch prefix length. */
4465 p
.prefixlen
= *pnt
++;
4466 /* afi/safi validity already verified by caller,
4467 * bgp_update_receive */
4468 p
.family
= afi2family(afi
);
4470 /* Prefix length check. */
4471 if (p
.prefixlen
> prefix_blen(&p
) * 8) {
4474 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
4475 peer
->host
, p
.prefixlen
, packet
->afi
);
4476 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH
;
4479 /* Packet size overflow check. */
4480 psize
= PSIZE(p
.prefixlen
);
4482 /* When packet overflow occur return immediately. */
4483 if (pnt
+ psize
> lim
) {
4486 "%s [Error] Update packet error (prefix length %d overflows packet)",
4487 peer
->host
, p
.prefixlen
);
4488 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW
;
4491 /* Defensive coding, double-check the psize fits in a struct
4493 if (psize
> (ssize_t
)sizeof(p
.u
)) {
4496 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4497 peer
->host
, p
.prefixlen
, sizeof(p
.u
));
4498 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4501 /* Fetch prefix from NLRI packet. */
4502 memcpy(p
.u
.val
, pnt
, psize
);
4504 /* Check address. */
4505 if (afi
== AFI_IP
&& safi
== SAFI_UNICAST
) {
4506 if (IN_CLASSD(ntohl(p
.u
.prefix4
.s_addr
))) {
4507 /* From RFC4271 Section 6.3:
4509 * If a prefix in the NLRI field is semantically
4511 * (e.g., an unexpected multicast IP address),
4513 * be logged locally, and the prefix SHOULD be
4518 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4519 peer
->host
, inet_ntoa(p
.u
.prefix4
));
4524 /* Check address. */
4525 if (afi
== AFI_IP6
&& safi
== SAFI_UNICAST
) {
4526 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
4531 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
4533 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4538 if (IN6_IS_ADDR_MULTICAST(&p
.u
.prefix6
)) {
4543 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
4545 inet_ntop(AF_INET6
, &p
.u
.prefix6
, buf
,
4552 /* Normal process. */
4554 ret
= bgp_update(peer
, &p
, addpath_id
, attr
, afi
, safi
,
4555 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
,
4556 NULL
, NULL
, 0, 0, NULL
);
4558 ret
= bgp_withdraw(peer
, &p
, addpath_id
, attr
, afi
,
4559 safi
, ZEBRA_ROUTE_BGP
,
4560 BGP_ROUTE_NORMAL
, NULL
, NULL
, 0,
4563 /* Do not send BGP notification twice when maximum-prefix count
4565 if (CHECK_FLAG(peer
->sflags
, PEER_STATUS_PREFIX_OVERFLOW
))
4566 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW
;
4568 /* Address family configuration mismatch. */
4570 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY
;
4573 /* Packet length consistency check. */
4577 "%s [Error] Update packet error (prefix length mismatch with total length)",
4579 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH
;
4582 return BGP_NLRI_PARSE_OK
;
4585 static struct bgp_static
*bgp_static_new(void)
4587 return XCALLOC(MTYPE_BGP_STATIC
, sizeof(struct bgp_static
));
4590 static void bgp_static_free(struct bgp_static
*bgp_static
)
4592 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
4593 route_map_counter_decrement(bgp_static
->rmap
.map
);
4595 XFREE(MTYPE_ATTR
, bgp_static
->eth_s_id
);
4596 XFREE(MTYPE_BGP_STATIC
, bgp_static
);
4599 void bgp_static_update(struct bgp
*bgp
, struct prefix
*p
,
4600 struct bgp_static
*bgp_static
, afi_t afi
, safi_t safi
)
4602 struct bgp_node
*rn
;
4603 struct bgp_path_info
*pi
;
4604 struct bgp_path_info
*new;
4605 struct bgp_path_info rmap_path
;
4607 struct attr
*attr_new
;
4608 route_map_result_t ret
;
4610 int vnc_implicit_withdraw
= 0;
4617 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4619 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4621 attr
.nexthop
= bgp_static
->igpnexthop
;
4622 attr
.med
= bgp_static
->igpmetric
;
4623 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4625 if (bgp_static
->atomic
)
4626 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
);
4628 /* Store label index, if required. */
4629 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
4630 attr
.label_index
= bgp_static
->label_index
;
4631 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID
);
4634 /* Apply route-map. */
4635 if (bgp_static
->rmap
.name
) {
4636 struct attr attr_tmp
= attr
;
4638 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
4639 rmap_path
.peer
= bgp
->peer_self
;
4640 rmap_path
.attr
= &attr_tmp
;
4642 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4644 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4647 bgp
->peer_self
->rmap_type
= 0;
4649 if (ret
== RMAP_DENYMATCH
) {
4650 /* Free uninterned attribute. */
4651 bgp_attr_flush(&attr_tmp
);
4653 /* Unintern original. */
4654 aspath_unintern(&attr
.aspath
);
4655 bgp_static_withdraw(bgp
, p
, afi
, safi
);
4659 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4660 bgp_attr_add_gshut_community(&attr_tmp
);
4662 attr_new
= bgp_attr_intern(&attr_tmp
);
4665 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
4666 bgp_attr_add_gshut_community(&attr
);
4668 attr_new
= bgp_attr_intern(&attr
);
4671 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4672 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4673 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4677 if (attrhash_cmp(pi
->attr
, attr_new
)
4678 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)
4679 && !bgp_flag_check(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
)) {
4680 bgp_unlock_node(rn
);
4681 bgp_attr_unintern(&attr_new
);
4682 aspath_unintern(&attr
.aspath
);
4685 /* The attribute is changed. */
4686 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
4688 /* Rewrite BGP route information. */
4689 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
4690 bgp_path_info_restore(rn
, pi
);
4692 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4694 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4695 && (safi
== SAFI_UNICAST
)) {
4696 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
4698 * Implicit withdraw case.
4699 * We have to do this before pi is
4702 ++vnc_implicit_withdraw
;
4703 vnc_import_bgp_del_route(bgp
, p
, pi
);
4704 vnc_import_bgp_exterior_del_route(
4709 bgp_attr_unintern(&pi
->attr
);
4710 pi
->attr
= attr_new
;
4711 pi
->uptime
= bgp_clock();
4713 if ((afi
== AFI_IP
|| afi
== AFI_IP6
)
4714 && (safi
== SAFI_UNICAST
)) {
4715 if (vnc_implicit_withdraw
) {
4716 vnc_import_bgp_add_route(bgp
, p
, pi
);
4717 vnc_import_bgp_exterior_add_route(
4723 /* Nexthop reachability check. */
4724 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4725 && (safi
== SAFI_UNICAST
4726 || safi
== SAFI_LABELED_UNICAST
)) {
4728 struct bgp
*bgp_nexthop
= bgp
;
4730 if (pi
->extra
&& pi
->extra
->bgp_orig
)
4731 bgp_nexthop
= pi
->extra
->bgp_orig
;
4733 if (bgp_find_or_add_nexthop(bgp
, bgp_nexthop
,
4735 bgp_path_info_set_flag(rn
, pi
,
4738 if (BGP_DEBUG(nht
, NHT
)) {
4739 char buf1
[INET6_ADDRSTRLEN
];
4740 inet_ntop(p
->family
,
4744 "%s(%s): Route not in table, not advertising",
4745 __FUNCTION__
, buf1
);
4747 bgp_path_info_unset_flag(
4748 rn
, pi
, BGP_PATH_VALID
);
4751 /* Delete the NHT structure if any, if we're
4753 * enabling/disabling import check. We
4754 * deregister the route
4755 * from NHT to avoid overloading NHT and the
4756 * process interaction
4758 bgp_unlink_nexthop(pi
);
4759 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_VALID
);
4761 /* Process change. */
4762 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
4763 bgp_process(bgp
, rn
, afi
, safi
);
4765 if (SAFI_UNICAST
== safi
4766 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4768 == BGP_INSTANCE_TYPE_DEFAULT
)) {
4769 vpn_leak_from_vrf_update(bgp_get_default(), bgp
,
4773 bgp_unlock_node(rn
);
4774 aspath_unintern(&attr
.aspath
);
4779 /* Make new BGP info. */
4780 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
4782 /* Nexthop reachability check. */
4783 if (bgp_flag_check(bgp
, BGP_FLAG_IMPORT_CHECK
)
4784 && (safi
== SAFI_UNICAST
|| safi
== SAFI_LABELED_UNICAST
)) {
4785 if (bgp_find_or_add_nexthop(bgp
, bgp
, afi
, new, NULL
, 0))
4786 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4788 if (BGP_DEBUG(nht
, NHT
)) {
4789 char buf1
[INET6_ADDRSTRLEN
];
4790 inet_ntop(p
->family
, &p
->u
.prefix
, buf1
,
4793 "%s(%s): Route not in table, not advertising",
4794 __FUNCTION__
, buf1
);
4796 bgp_path_info_unset_flag(rn
, new, BGP_PATH_VALID
);
4799 /* Delete the NHT structure if any, if we're toggling between
4800 * enabling/disabling import check. We deregister the route
4801 * from NHT to avoid overloading NHT and the process interaction
4803 bgp_unlink_nexthop(new);
4805 bgp_path_info_set_flag(rn
, new, BGP_PATH_VALID
);
4808 /* Aggregate address increment. */
4809 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
4811 /* Register new BGP information. */
4812 bgp_path_info_add(rn
, new);
4814 /* route_node_get lock */
4815 bgp_unlock_node(rn
);
4817 /* Process change. */
4818 bgp_process(bgp
, rn
, afi
, safi
);
4820 if (SAFI_UNICAST
== safi
4821 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4822 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4823 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
4826 /* Unintern original. */
4827 aspath_unintern(&attr
.aspath
);
4830 void bgp_static_withdraw(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
4833 struct bgp_node
*rn
;
4834 struct bgp_path_info
*pi
;
4836 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, NULL
);
4838 /* Check selected route and self inserted route. */
4839 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4840 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4841 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4844 /* Withdraw static BGP route from routing table. */
4846 if (SAFI_UNICAST
== safi
4847 && (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
4848 || bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
4849 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp
, pi
);
4851 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4852 bgp_unlink_nexthop(pi
);
4853 bgp_path_info_delete(rn
, pi
);
4854 bgp_process(bgp
, rn
, afi
, safi
);
4857 /* Unlock bgp_node_lookup. */
4858 bgp_unlock_node(rn
);
4862 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
4864 static void bgp_static_withdraw_safi(struct bgp
*bgp
, struct prefix
*p
,
4865 afi_t afi
, safi_t safi
,
4866 struct prefix_rd
*prd
)
4868 struct bgp_node
*rn
;
4869 struct bgp_path_info
*pi
;
4871 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
, prd
);
4873 /* Check selected route and self inserted route. */
4874 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4875 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4876 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4879 /* Withdraw static BGP route from routing table. */
4882 rfapiProcessWithdraw(
4883 pi
->peer
, NULL
, p
, prd
, pi
->attr
, afi
, safi
, pi
->type
,
4884 1); /* Kill, since it is an administrative change */
4886 if (SAFI_MPLS_VPN
== safi
4887 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
4888 vpn_leak_to_vrf_withdraw(bgp
, pi
);
4890 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
4891 bgp_path_info_delete(rn
, pi
);
4892 bgp_process(bgp
, rn
, afi
, safi
);
4895 /* Unlock bgp_node_lookup. */
4896 bgp_unlock_node(rn
);
4899 static void bgp_static_update_safi(struct bgp
*bgp
, struct prefix
*p
,
4900 struct bgp_static
*bgp_static
, afi_t afi
,
4903 struct bgp_node
*rn
;
4904 struct bgp_path_info
*new;
4905 struct attr
*attr_new
;
4906 struct attr attr
= {0};
4907 struct bgp_path_info
*pi
;
4909 mpls_label_t label
= 0;
4911 uint32_t num_labels
= 0;
4916 if (bgp_static
->label
!= MPLS_INVALID_LABEL
)
4918 rn
= bgp_afi_node_get(bgp
->rib
[afi
][safi
], afi
, safi
, p
,
4921 bgp_attr_default_set(&attr
, BGP_ORIGIN_IGP
);
4923 attr
.nexthop
= bgp_static
->igpnexthop
;
4924 attr
.med
= bgp_static
->igpmetric
;
4925 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
4927 if ((safi
== SAFI_EVPN
) || (safi
== SAFI_MPLS_VPN
)
4928 || (safi
== SAFI_ENCAP
)) {
4929 if (afi
== AFI_IP
) {
4930 attr
.mp_nexthop_global_in
= bgp_static
->igpnexthop
;
4931 attr
.mp_nexthop_len
= IPV4_MAX_BYTELEN
;
4934 if (afi
== AFI_L2VPN
) {
4935 if (bgp_static
->gatewayIp
.family
== AF_INET
)
4937 bgp_static
->gatewayIp
.u
.prefix4
.s_addr
;
4938 else if (bgp_static
->gatewayIp
.family
== AF_INET6
)
4939 memcpy(&(add
.ipv6
), &(bgp_static
->gatewayIp
.u
.prefix6
),
4940 sizeof(struct in6_addr
));
4941 overlay_index_update(&attr
, bgp_static
->eth_s_id
, &add
);
4942 if (bgp_static
->encap_tunneltype
== BGP_ENCAP_TYPE_VXLAN
) {
4943 struct bgp_encap_type_vxlan bet
;
4944 memset(&bet
, 0, sizeof(struct bgp_encap_type_vxlan
));
4945 bet
.vnid
= p
->u
.prefix_evpn
.prefix_addr
.eth_tag
;
4946 bgp_encap_type_vxlan_to_tlv(&bet
, &attr
);
4948 if (bgp_static
->router_mac
) {
4949 bgp_add_routermac_ecom(&attr
, bgp_static
->router_mac
);
4952 /* Apply route-map. */
4953 if (bgp_static
->rmap
.name
) {
4954 struct attr attr_tmp
= attr
;
4955 struct bgp_path_info rmap_path
;
4956 route_map_result_t ret
;
4958 rmap_path
.peer
= bgp
->peer_self
;
4959 rmap_path
.attr
= &attr_tmp
;
4961 SET_FLAG(bgp
->peer_self
->rmap_type
, PEER_RMAP_TYPE_NETWORK
);
4963 ret
= route_map_apply(bgp_static
->rmap
.map
, p
, RMAP_BGP
,
4966 bgp
->peer_self
->rmap_type
= 0;
4968 if (ret
== RMAP_DENYMATCH
) {
4969 /* Free uninterned attribute. */
4970 bgp_attr_flush(&attr_tmp
);
4972 /* Unintern original. */
4973 aspath_unintern(&attr
.aspath
);
4974 bgp_static_withdraw_safi(bgp
, p
, afi
, safi
,
4979 attr_new
= bgp_attr_intern(&attr_tmp
);
4981 attr_new
= bgp_attr_intern(&attr
);
4984 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
4985 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
4986 && pi
->sub_type
== BGP_ROUTE_STATIC
)
4990 memset(&add
, 0, sizeof(union gw_addr
));
4991 if (attrhash_cmp(pi
->attr
, attr_new
)
4992 && overlay_index_equal(afi
, pi
, bgp_static
->eth_s_id
, &add
)
4993 && !CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
)) {
4994 bgp_unlock_node(rn
);
4995 bgp_attr_unintern(&attr_new
);
4996 aspath_unintern(&attr
.aspath
);
4999 /* The attribute is changed. */
5000 bgp_path_info_set_flag(rn
, pi
, BGP_PATH_ATTR_CHANGED
);
5002 /* Rewrite BGP route information. */
5003 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
5004 bgp_path_info_restore(rn
, pi
);
5006 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, safi
);
5007 bgp_attr_unintern(&pi
->attr
);
5008 pi
->attr
= attr_new
;
5009 pi
->uptime
= bgp_clock();
5012 label
= decode_label(&pi
->extra
->label
[0]);
5015 /* Process change. */
5016 bgp_aggregate_increment(bgp
, p
, pi
, afi
, safi
);
5017 bgp_process(bgp
, rn
, afi
, safi
);
5019 if (SAFI_MPLS_VPN
== safi
5020 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5021 vpn_leak_to_vrf_update(bgp
, pi
);
5024 rfapiProcessUpdate(pi
->peer
, NULL
, p
, &bgp_static
->prd
,
5025 pi
->attr
, afi
, safi
, pi
->type
,
5026 pi
->sub_type
, &label
);
5028 bgp_unlock_node(rn
);
5029 aspath_unintern(&attr
.aspath
);
5035 /* Make new BGP info. */
5036 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_STATIC
, 0, bgp
->peer_self
,
5038 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5039 new->extra
= bgp_path_info_extra_new();
5041 new->extra
->label
[0] = bgp_static
->label
;
5042 new->extra
->num_labels
= num_labels
;
5045 label
= decode_label(&bgp_static
->label
);
5048 /* Aggregate address increment. */
5049 bgp_aggregate_increment(bgp
, p
, new, afi
, safi
);
5051 /* Register new BGP information. */
5052 bgp_path_info_add(rn
, new);
5053 /* route_node_get lock */
5054 bgp_unlock_node(rn
);
5056 /* Process change. */
5057 bgp_process(bgp
, rn
, afi
, safi
);
5059 if (SAFI_MPLS_VPN
== safi
5060 && bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) {
5061 vpn_leak_to_vrf_update(bgp
, new);
5064 rfapiProcessUpdate(new->peer
, NULL
, p
, &bgp_static
->prd
, new->attr
, afi
,
5065 safi
, new->type
, new->sub_type
, &label
);
5068 /* Unintern original. */
5069 aspath_unintern(&attr
.aspath
);
5072 /* Configure static BGP network. When user don't run zebra, static
5073 route should be installed as valid. */
5074 static int bgp_static_set(struct vty
*vty
, const char *negate
,
5075 const char *ip_str
, afi_t afi
, safi_t safi
,
5076 const char *rmap
, int backdoor
, uint32_t label_index
)
5078 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5081 struct bgp_static
*bgp_static
;
5082 struct bgp_node
*rn
;
5083 uint8_t need_update
= 0;
5085 /* Convert IP prefix string to struct prefix. */
5086 ret
= str2prefix(ip_str
, &p
);
5088 vty_out(vty
, "%% Malformed prefix\n");
5089 return CMD_WARNING_CONFIG_FAILED
;
5091 if (afi
== AFI_IP6
&& IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
)) {
5092 vty_out(vty
, "%% Malformed prefix (link-local address)\n");
5093 return CMD_WARNING_CONFIG_FAILED
;
5100 /* Set BGP static route configuration. */
5101 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], &p
);
5104 vty_out(vty
, "%% Can't find static route specified\n");
5105 return CMD_WARNING_CONFIG_FAILED
;
5108 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5110 if ((label_index
!= BGP_INVALID_LABEL_INDEX
)
5111 && (label_index
!= bgp_static
->label_index
)) {
5113 "%% label-index doesn't match static route\n");
5114 return CMD_WARNING_CONFIG_FAILED
;
5117 if ((rmap
&& bgp_static
->rmap
.name
)
5118 && strcmp(rmap
, bgp_static
->rmap
.name
)) {
5120 "%% route-map name doesn't match static route\n");
5121 return CMD_WARNING_CONFIG_FAILED
;
5124 /* Update BGP RIB. */
5125 if (!bgp_static
->backdoor
)
5126 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5128 /* Clear configuration. */
5129 bgp_static_free(bgp_static
);
5130 bgp_node_set_bgp_static_info(rn
, NULL
);
5131 bgp_unlock_node(rn
);
5132 bgp_unlock_node(rn
);
5135 /* Set BGP static route configuration. */
5136 rn
= bgp_node_get(bgp
->route
[afi
][safi
], &p
);
5138 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5140 /* Configuration change. */
5141 /* Label index cannot be changed. */
5142 if (bgp_static
->label_index
!= label_index
) {
5143 vty_out(vty
, "%% cannot change label-index\n");
5144 return CMD_WARNING_CONFIG_FAILED
;
5147 /* Check previous routes are installed into BGP. */
5148 if (bgp_static
->valid
5149 && bgp_static
->backdoor
!= backdoor
)
5152 bgp_static
->backdoor
= backdoor
;
5155 XFREE(MTYPE_ROUTE_MAP_NAME
,
5156 bgp_static
->rmap
.name
);
5157 route_map_counter_decrement(
5158 bgp_static
->rmap
.map
);
5159 bgp_static
->rmap
.name
=
5160 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5161 bgp_static
->rmap
.map
=
5162 route_map_lookup_by_name(rmap
);
5163 route_map_counter_increment(
5164 bgp_static
->rmap
.map
);
5166 XFREE(MTYPE_ROUTE_MAP_NAME
,
5167 bgp_static
->rmap
.name
);
5168 route_map_counter_decrement(
5169 bgp_static
->rmap
.map
);
5170 bgp_static
->rmap
.name
= NULL
;
5171 bgp_static
->rmap
.map
= NULL
;
5172 bgp_static
->valid
= 0;
5174 bgp_unlock_node(rn
);
5176 /* New configuration. */
5177 bgp_static
= bgp_static_new();
5178 bgp_static
->backdoor
= backdoor
;
5179 bgp_static
->valid
= 0;
5180 bgp_static
->igpmetric
= 0;
5181 bgp_static
->igpnexthop
.s_addr
= 0;
5182 bgp_static
->label_index
= label_index
;
5185 XFREE(MTYPE_ROUTE_MAP_NAME
,
5186 bgp_static
->rmap
.name
);
5187 route_map_counter_decrement(
5188 bgp_static
->rmap
.map
);
5189 bgp_static
->rmap
.name
=
5190 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
5191 bgp_static
->rmap
.map
=
5192 route_map_lookup_by_name(rmap
);
5193 route_map_counter_increment(
5194 bgp_static
->rmap
.map
);
5196 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5199 bgp_static
->valid
= 1;
5201 bgp_static_withdraw(bgp
, &p
, afi
, safi
);
5203 if (!bgp_static
->backdoor
)
5204 bgp_static_update(bgp
, &p
, bgp_static
, afi
, safi
);
5210 void bgp_static_add(struct bgp
*bgp
)
5214 struct bgp_node
*rn
;
5215 struct bgp_node
*rm
;
5216 struct bgp_table
*table
;
5217 struct bgp_static
*bgp_static
;
5219 FOREACH_AFI_SAFI (afi
, safi
)
5220 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5221 rn
= bgp_route_next(rn
)) {
5222 if (!bgp_node_has_bgp_path_info_data(rn
))
5225 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5226 || (safi
== SAFI_EVPN
)) {
5227 table
= bgp_node_get_bgp_table_info(rn
);
5229 for (rm
= bgp_table_top(table
); rm
;
5230 rm
= bgp_route_next(rm
)) {
5232 bgp_node_get_bgp_static_info(
5234 bgp_static_update_safi(bgp
, &rm
->p
,
5241 bgp_node_get_bgp_static_info(rn
), afi
,
5247 /* Called from bgp_delete(). Delete all static routes from the BGP
5249 void bgp_static_delete(struct bgp
*bgp
)
5253 struct bgp_node
*rn
;
5254 struct bgp_node
*rm
;
5255 struct bgp_table
*table
;
5256 struct bgp_static
*bgp_static
;
5258 FOREACH_AFI_SAFI (afi
, safi
)
5259 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5260 rn
= bgp_route_next(rn
)) {
5261 if (!bgp_node_has_bgp_path_info_data(rn
))
5264 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5265 || (safi
== SAFI_EVPN
)) {
5266 table
= bgp_node_get_bgp_table_info(rn
);
5268 for (rm
= bgp_table_top(table
); rm
;
5269 rm
= bgp_route_next(rm
)) {
5271 bgp_node_get_bgp_static_info(
5276 bgp_static_withdraw_safi(
5277 bgp
, &rm
->p
, AFI_IP
, safi
,
5278 (struct prefix_rd
*)&rn
->p
);
5279 bgp_static_free(bgp_static
);
5280 bgp_node_set_bgp_static_info(rn
, NULL
);
5281 bgp_unlock_node(rn
);
5284 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5285 bgp_static_withdraw(bgp
, &rn
->p
, afi
, safi
);
5286 bgp_static_free(bgp_static
);
5287 bgp_node_set_bgp_static_info(rn
, NULL
);
5288 bgp_unlock_node(rn
);
5293 void bgp_static_redo_import_check(struct bgp
*bgp
)
5297 struct bgp_node
*rn
;
5298 struct bgp_node
*rm
;
5299 struct bgp_table
*table
;
5300 struct bgp_static
*bgp_static
;
5302 /* Use this flag to force reprocessing of the route */
5303 bgp_flag_set(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5304 FOREACH_AFI_SAFI (afi
, safi
) {
5305 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
5306 rn
= bgp_route_next(rn
)) {
5307 if (!bgp_node_has_bgp_path_info_data(rn
))
5310 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
5311 || (safi
== SAFI_EVPN
)) {
5312 table
= bgp_node_get_bgp_table_info(rn
);
5314 for (rm
= bgp_table_top(table
); rm
;
5315 rm
= bgp_route_next(rm
)) {
5317 bgp_node_get_bgp_static_info(
5319 bgp_static_update_safi(bgp
, &rm
->p
,
5324 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5325 bgp_static_update(bgp
, &rn
->p
, bgp_static
, afi
,
5330 bgp_flag_unset(bgp
, BGP_FLAG_FORCE_STATIC_PROCESS
);
5333 static void bgp_purge_af_static_redist_routes(struct bgp
*bgp
, afi_t afi
,
5336 struct bgp_table
*table
;
5337 struct bgp_node
*rn
;
5338 struct bgp_path_info
*pi
;
5340 /* Do not install the aggregate route if BGP is in the
5341 * process of termination.
5343 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5344 (bgp
->peer_self
== NULL
))
5347 table
= bgp
->rib
[afi
][safi
];
5348 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
5349 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5350 if (pi
->peer
== bgp
->peer_self
5351 && ((pi
->type
== ZEBRA_ROUTE_BGP
5352 && pi
->sub_type
== BGP_ROUTE_STATIC
)
5353 || (pi
->type
!= ZEBRA_ROUTE_BGP
5355 == BGP_ROUTE_REDISTRIBUTE
))) {
5356 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
5358 bgp_unlink_nexthop(pi
);
5359 bgp_path_info_delete(rn
, pi
);
5360 bgp_process(bgp
, rn
, afi
, safi
);
5367 * Purge all networks and redistributed routes from routing table.
5368 * Invoked upon the instance going down.
5370 void bgp_purge_static_redist_routes(struct bgp
*bgp
)
5375 FOREACH_AFI_SAFI (afi
, safi
)
5376 bgp_purge_af_static_redist_routes(bgp
, afi
, safi
);
5381 * Currently this is used to set static routes for VPN and ENCAP.
5382 * I think it can probably be factored with bgp_static_set.
5384 int bgp_static_set_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5385 const char *ip_str
, const char *rd_str
,
5386 const char *label_str
, const char *rmap_str
,
5387 int evpn_type
, const char *esi
, const char *gwip
,
5388 const char *ethtag
, const char *routermac
)
5390 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5393 struct prefix_rd prd
;
5394 struct bgp_node
*prn
;
5395 struct bgp_node
*rn
;
5396 struct bgp_table
*table
;
5397 struct bgp_static
*bgp_static
;
5398 mpls_label_t label
= MPLS_INVALID_LABEL
;
5399 struct prefix gw_ip
;
5401 /* validate ip prefix */
5402 ret
= str2prefix(ip_str
, &p
);
5404 vty_out(vty
, "%% Malformed prefix\n");
5405 return CMD_WARNING_CONFIG_FAILED
;
5408 if ((afi
== AFI_L2VPN
)
5409 && (bgp_build_evpn_prefix(evpn_type
,
5410 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5411 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5412 return CMD_WARNING_CONFIG_FAILED
;
5415 ret
= str2prefix_rd(rd_str
, &prd
);
5417 vty_out(vty
, "%% Malformed rd\n");
5418 return CMD_WARNING_CONFIG_FAILED
;
5422 unsigned long label_val
;
5423 label_val
= strtoul(label_str
, NULL
, 10);
5424 encode_label(label_val
, &label
);
5427 if (safi
== SAFI_EVPN
) {
5428 if (esi
&& str2esi(esi
, NULL
) == 0) {
5429 vty_out(vty
, "%% Malformed ESI\n");
5430 return CMD_WARNING_CONFIG_FAILED
;
5432 if (routermac
&& prefix_str2mac(routermac
, NULL
) == 0) {
5433 vty_out(vty
, "%% Malformed Router MAC\n");
5434 return CMD_WARNING_CONFIG_FAILED
;
5437 memset(&gw_ip
, 0, sizeof(struct prefix
));
5438 ret
= str2prefix(gwip
, &gw_ip
);
5440 vty_out(vty
, "%% Malformed GatewayIp\n");
5441 return CMD_WARNING_CONFIG_FAILED
;
5443 if ((gw_ip
.family
== AF_INET
5444 && is_evpn_prefix_ipaddr_v6(
5445 (struct prefix_evpn
*)&p
))
5446 || (gw_ip
.family
== AF_INET6
5447 && is_evpn_prefix_ipaddr_v4(
5448 (struct prefix_evpn
*)&p
))) {
5450 "%% GatewayIp family differs with IP prefix\n");
5451 return CMD_WARNING_CONFIG_FAILED
;
5455 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5456 if (!bgp_node_has_bgp_path_info_data(prn
))
5457 bgp_node_set_bgp_table_info(prn
,
5458 bgp_table_init(bgp
, afi
, safi
));
5459 table
= bgp_node_get_bgp_table_info(prn
);
5461 rn
= bgp_node_get(table
, &p
);
5463 if (bgp_node_has_bgp_path_info_data(rn
)) {
5464 vty_out(vty
, "%% Same network configuration exists\n");
5465 bgp_unlock_node(rn
);
5467 /* New configuration. */
5468 bgp_static
= bgp_static_new();
5469 bgp_static
->backdoor
= 0;
5470 bgp_static
->valid
= 0;
5471 bgp_static
->igpmetric
= 0;
5472 bgp_static
->igpnexthop
.s_addr
= 0;
5473 bgp_static
->label
= label
;
5474 bgp_static
->prd
= prd
;
5477 XFREE(MTYPE_ROUTE_MAP_NAME
, bgp_static
->rmap
.name
);
5478 route_map_counter_decrement(bgp_static
->rmap
.map
);
5479 bgp_static
->rmap
.name
=
5480 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_str
);
5481 bgp_static
->rmap
.map
=
5482 route_map_lookup_by_name(rmap_str
);
5483 route_map_counter_increment(bgp_static
->rmap
.map
);
5486 if (safi
== SAFI_EVPN
) {
5488 bgp_static
->eth_s_id
=
5490 sizeof(struct eth_segment_id
));
5491 str2esi(esi
, bgp_static
->eth_s_id
);
5494 bgp_static
->router_mac
=
5495 XCALLOC(MTYPE_ATTR
, ETH_ALEN
+ 1);
5496 (void)prefix_str2mac(routermac
,
5497 bgp_static
->router_mac
);
5500 prefix_copy(&bgp_static
->gatewayIp
, &gw_ip
);
5502 bgp_node_set_bgp_static_info(rn
, bgp_static
);
5504 bgp_static
->valid
= 1;
5505 bgp_static_update_safi(bgp
, &p
, bgp_static
, afi
, safi
);
5511 /* Configure static BGP network. */
5512 int bgp_static_unset_safi(afi_t afi
, safi_t safi
, struct vty
*vty
,
5513 const char *ip_str
, const char *rd_str
,
5514 const char *label_str
, int evpn_type
, const char *esi
,
5515 const char *gwip
, const char *ethtag
)
5517 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5520 struct prefix_rd prd
;
5521 struct bgp_node
*prn
;
5522 struct bgp_node
*rn
;
5523 struct bgp_table
*table
;
5524 struct bgp_static
*bgp_static
;
5525 mpls_label_t label
= MPLS_INVALID_LABEL
;
5527 /* Convert IP prefix string to struct prefix. */
5528 ret
= str2prefix(ip_str
, &p
);
5530 vty_out(vty
, "%% Malformed prefix\n");
5531 return CMD_WARNING_CONFIG_FAILED
;
5534 if ((afi
== AFI_L2VPN
)
5535 && (bgp_build_evpn_prefix(evpn_type
,
5536 ethtag
!= NULL
? atol(ethtag
) : 0, &p
))) {
5537 vty_out(vty
, "%% L2VPN prefix could not be forged\n");
5538 return CMD_WARNING_CONFIG_FAILED
;
5540 ret
= str2prefix_rd(rd_str
, &prd
);
5542 vty_out(vty
, "%% Malformed rd\n");
5543 return CMD_WARNING_CONFIG_FAILED
;
5547 unsigned long label_val
;
5548 label_val
= strtoul(label_str
, NULL
, 10);
5549 encode_label(label_val
, &label
);
5552 prn
= bgp_node_get(bgp
->route
[afi
][safi
], (struct prefix
*)&prd
);
5553 if (!bgp_node_has_bgp_path_info_data(prn
))
5554 bgp_node_set_bgp_table_info(prn
,
5555 bgp_table_init(bgp
, afi
, safi
));
5557 bgp_unlock_node(prn
);
5558 table
= bgp_node_get_bgp_table_info(prn
);
5560 rn
= bgp_node_lookup(table
, &p
);
5563 bgp_static_withdraw_safi(bgp
, &p
, afi
, safi
, &prd
);
5565 bgp_static
= bgp_node_get_bgp_static_info(rn
);
5566 bgp_static_free(bgp_static
);
5567 bgp_node_set_bgp_static_info(rn
, NULL
);
5568 bgp_unlock_node(rn
);
5569 bgp_unlock_node(rn
);
5571 vty_out(vty
, "%% Can't find the route\n");
5576 static int bgp_table_map_set(struct vty
*vty
, afi_t afi
, safi_t safi
,
5577 const char *rmap_name
)
5579 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5580 struct bgp_rmap
*rmap
;
5582 rmap
= &bgp
->table_map
[afi
][safi
];
5584 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5585 route_map_counter_decrement(rmap
->map
);
5586 rmap
->name
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap_name
);
5587 rmap
->map
= route_map_lookup_by_name(rmap_name
);
5588 route_map_counter_increment(rmap
->map
);
5590 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5591 route_map_counter_decrement(rmap
->map
);
5596 if (bgp_fibupd_safi(safi
))
5597 bgp_zebra_announce_table(bgp
, afi
, safi
);
5602 static int bgp_table_map_unset(struct vty
*vty
, afi_t afi
, safi_t safi
,
5603 const char *rmap_name
)
5605 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
5606 struct bgp_rmap
*rmap
;
5608 rmap
= &bgp
->table_map
[afi
][safi
];
5609 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
->name
);
5610 route_map_counter_decrement(rmap
->map
);
5614 if (bgp_fibupd_safi(safi
))
5615 bgp_zebra_announce_table(bgp
, afi
, safi
);
5620 void bgp_config_write_table_map(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5623 if (bgp
->table_map
[afi
][safi
].name
) {
5624 vty_out(vty
, " table-map %s\n",
5625 bgp
->table_map
[afi
][safi
].name
);
5629 DEFUN (bgp_table_map
,
5632 "BGP table to RIB route download filter\n"
5633 "Name of the route map\n")
5636 return bgp_table_map_set(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5637 argv
[idx_word
]->arg
);
5639 DEFUN (no_bgp_table_map
,
5640 no_bgp_table_map_cmd
,
5641 "no table-map WORD",
5643 "BGP table to RIB route download filter\n"
5644 "Name of the route map\n")
5647 return bgp_table_map_unset(vty
, bgp_node_afi(vty
), bgp_node_safi(vty
),
5648 argv
[idx_word
]->arg
);
5654 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
5655 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
5656 backdoor$backdoor}]",
5658 "Specify a network to announce via BGP\n"
5663 "Route-map to modify the attributes\n"
5664 "Name of the route map\n"
5665 "Label index to associate with the prefix\n"
5666 "Label index value\n"
5667 "Specify a BGP backdoor route\n")
5669 char addr_prefix_str
[BUFSIZ
];
5674 ret
= netmask_str2prefix_str(address_str
, netmask_str
,
5677 vty_out(vty
, "%% Inconsistent address and mask\n");
5678 return CMD_WARNING_CONFIG_FAILED
;
5682 return bgp_static_set(
5683 vty
, no
, address_str
? addr_prefix_str
: prefix_str
, AFI_IP
,
5684 bgp_node_safi(vty
), map_name
, backdoor
? 1 : 0,
5685 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5688 DEFPY(ipv6_bgp_network
,
5689 ipv6_bgp_network_cmd
,
5690 "[no] network X:X::X:X/M$prefix \
5691 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
5693 "Specify a network to announce via BGP\n"
5695 "Route-map to modify the attributes\n"
5696 "Name of the route map\n"
5697 "Label index to associate with the prefix\n"
5698 "Label index value\n")
5700 return bgp_static_set(
5701 vty
, no
, prefix_str
, AFI_IP6
, bgp_node_safi(vty
), map_name
, 0,
5702 label_index
? (uint32_t)label_index
: BGP_INVALID_LABEL_INDEX
);
5705 static struct bgp_aggregate
*bgp_aggregate_new(void)
5707 return XCALLOC(MTYPE_BGP_AGGREGATE
, sizeof(struct bgp_aggregate
));
5710 static void bgp_aggregate_free(struct bgp_aggregate
*aggregate
)
5712 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
5713 route_map_counter_decrement(aggregate
->rmap
.map
);
5714 XFREE(MTYPE_BGP_AGGREGATE
, aggregate
);
5717 static int bgp_aggregate_info_same(struct bgp_path_info
*pi
, uint8_t origin
,
5718 struct aspath
*aspath
,
5719 struct community
*comm
,
5720 struct ecommunity
*ecomm
,
5721 struct lcommunity
*lcomm
)
5723 static struct aspath
*ae
= NULL
;
5726 ae
= aspath_empty();
5731 if (origin
!= pi
->attr
->origin
)
5734 if (!aspath_cmp(pi
->attr
->aspath
, (aspath
) ? aspath
: ae
))
5737 if (!community_cmp(pi
->attr
->community
, comm
))
5740 if (!ecommunity_cmp(pi
->attr
->ecommunity
, ecomm
))
5743 if (!lcommunity_cmp(pi
->attr
->lcommunity
, lcomm
))
5746 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
5752 static void bgp_aggregate_install(struct bgp
*bgp
, afi_t afi
, safi_t safi
,
5753 struct prefix
*p
, uint8_t origin
,
5754 struct aspath
*aspath
,
5755 struct community
*community
,
5756 struct ecommunity
*ecommunity
,
5757 struct lcommunity
*lcommunity
,
5758 uint8_t atomic_aggregate
,
5759 struct bgp_aggregate
*aggregate
)
5761 struct bgp_node
*rn
;
5762 struct bgp_table
*table
;
5763 struct bgp_path_info
*pi
, *orig
, *new;
5766 table
= bgp
->rib
[afi
][safi
];
5768 rn
= bgp_node_get(table
, p
);
5770 for (orig
= pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
5771 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== ZEBRA_ROUTE_BGP
5772 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5775 if (aggregate
->count
> 0) {
5777 * If the aggregate information has not changed
5778 * no need to re-install it again.
5780 if (bgp_aggregate_info_same(orig
, origin
, aspath
, community
,
5781 ecommunity
, lcommunity
)) {
5782 bgp_unlock_node(rn
);
5785 aspath_free(aspath
);
5787 community_free(&community
);
5789 ecommunity_free(&ecommunity
);
5791 lcommunity_free(&lcommunity
);
5797 * Mark the old as unusable
5800 bgp_path_info_delete(rn
, pi
);
5802 attr
= bgp_attr_aggregate_intern(
5803 bgp
, origin
, aspath
, community
, ecommunity
, lcommunity
,
5804 aggregate
, atomic_aggregate
, p
);
5807 bgp_aggregate_delete(bgp
, p
, afi
, safi
, aggregate
);
5811 new = info_make(ZEBRA_ROUTE_BGP
, BGP_ROUTE_AGGREGATE
, 0,
5812 bgp
->peer_self
, attr
, rn
);
5814 SET_FLAG(new->flags
, BGP_PATH_VALID
);
5816 bgp_path_info_add(rn
, new);
5817 bgp_process(bgp
, rn
, afi
, safi
);
5819 for (pi
= orig
; pi
; pi
= pi
->next
)
5820 if (pi
->peer
== bgp
->peer_self
5821 && pi
->type
== ZEBRA_ROUTE_BGP
5822 && pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5825 /* Withdraw static BGP route from routing table. */
5827 bgp_path_info_delete(rn
, pi
);
5828 bgp_process(bgp
, rn
, afi
, safi
);
5832 bgp_unlock_node(rn
);
5835 /* Update an aggregate as routes are added/removed from the BGP table */
5836 void bgp_aggregate_route(struct bgp
*bgp
, struct prefix
*p
,
5837 afi_t afi
, safi_t safi
,
5838 struct bgp_aggregate
*aggregate
)
5840 struct bgp_table
*table
;
5841 struct bgp_node
*top
;
5842 struct bgp_node
*rn
;
5844 struct aspath
*aspath
= NULL
;
5845 struct community
*community
= NULL
;
5846 struct ecommunity
*ecommunity
= NULL
;
5847 struct lcommunity
*lcommunity
= NULL
;
5848 struct bgp_path_info
*pi
;
5849 unsigned long match
= 0;
5850 uint8_t atomic_aggregate
= 0;
5852 /* If the bgp instance is being deleted or self peer is deleted
5853 * then do not create aggregate route
5855 if (bgp_flag_check(bgp
, BGP_FLAG_DELETE_IN_PROGRESS
) ||
5856 (bgp
->peer_self
== NULL
))
5859 /* ORIGIN attribute: If at least one route among routes that are
5860 aggregated has ORIGIN with the value INCOMPLETE, then the
5861 aggregated route must have the ORIGIN attribute with the value
5862 INCOMPLETE. Otherwise, if at least one route among routes that
5863 are aggregated has ORIGIN with the value EGP, then the aggregated
5864 route must have the origin attribute with the value EGP. In all
5865 other case the value of the ORIGIN attribute of the aggregated
5866 route is INTERNAL. */
5867 origin
= BGP_ORIGIN_IGP
;
5869 table
= bgp
->rib
[afi
][safi
];
5871 top
= bgp_node_get(table
, p
);
5872 for (rn
= bgp_node_get(table
, p
); rn
;
5873 rn
= bgp_route_next_until(rn
, top
)) {
5874 if (rn
->p
.prefixlen
<= p
->prefixlen
)
5879 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
5880 if (BGP_PATH_HOLDDOWN(pi
))
5884 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
))
5885 atomic_aggregate
= 1;
5887 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
5891 * summary-only aggregate route suppress
5892 * aggregated route announcements.
5894 if (aggregate
->summary_only
) {
5895 (bgp_path_info_extra_get(pi
))->suppress
++;
5896 bgp_path_info_set_flag(rn
, pi
,
5897 BGP_PATH_ATTR_CHANGED
);
5904 * If at least one route among routes that are
5905 * aggregated has ORIGIN with the value INCOMPLETE,
5906 * then the aggregated route MUST have the ORIGIN
5907 * attribute with the value INCOMPLETE. Otherwise, if
5908 * at least one route among routes that are aggregated
5909 * has ORIGIN with the value EGP, then the aggregated
5910 * route MUST have the ORIGIN attribute with the value
5913 switch (pi
->attr
->origin
) {
5914 case BGP_ORIGIN_INCOMPLETE
:
5915 aggregate
->incomplete_origin_count
++;
5917 case BGP_ORIGIN_EGP
:
5918 aggregate
->egp_origin_count
++;
5926 if (!aggregate
->as_set
)
5930 * as-set aggregate route generate origin, as path,
5931 * and community aggregation.
5933 /* Compute aggregate route's as-path.
5935 bgp_compute_aggregate_aspath_hash(aggregate
,
5938 /* Compute aggregate route's community.
5940 if (pi
->attr
->community
)
5941 bgp_compute_aggregate_community_hash(
5943 pi
->attr
->community
);
5945 /* Compute aggregate route's extended community.
5947 if (pi
->attr
->ecommunity
)
5948 bgp_compute_aggregate_ecommunity_hash(
5950 pi
->attr
->ecommunity
);
5952 /* Compute aggregate route's large community.
5954 if (pi
->attr
->lcommunity
)
5955 bgp_compute_aggregate_lcommunity_hash(
5957 pi
->attr
->lcommunity
);
5960 bgp_process(bgp
, rn
, afi
, safi
);
5962 if (aggregate
->as_set
) {
5963 bgp_compute_aggregate_aspath_val(aggregate
);
5964 bgp_compute_aggregate_community_val(aggregate
);
5965 bgp_compute_aggregate_ecommunity_val(aggregate
);
5966 bgp_compute_aggregate_lcommunity_val(aggregate
);
5970 bgp_unlock_node(top
);
5973 if (aggregate
->incomplete_origin_count
> 0)
5974 origin
= BGP_ORIGIN_INCOMPLETE
;
5975 else if (aggregate
->egp_origin_count
> 0)
5976 origin
= BGP_ORIGIN_EGP
;
5978 if (aggregate
->as_set
) {
5979 if (aggregate
->aspath
)
5980 /* Retrieve aggregate route's as-path.
5982 aspath
= aspath_dup(aggregate
->aspath
);
5984 if (aggregate
->community
)
5985 /* Retrieve aggregate route's community.
5987 community
= community_dup(aggregate
->community
);
5989 if (aggregate
->ecommunity
)
5990 /* Retrieve aggregate route's ecommunity.
5992 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
5994 if (aggregate
->lcommunity
)
5995 /* Retrieve aggregate route's lcommunity.
5997 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6000 bgp_aggregate_install(bgp
, afi
, safi
, p
, origin
, aspath
, community
,
6001 ecommunity
, lcommunity
, atomic_aggregate
,
6005 void bgp_aggregate_delete(struct bgp
*bgp
, struct prefix
*p
, afi_t afi
,
6006 safi_t safi
, struct bgp_aggregate
*aggregate
)
6008 struct bgp_table
*table
;
6009 struct bgp_node
*top
;
6010 struct bgp_node
*rn
;
6011 struct bgp_path_info
*pi
;
6012 unsigned long match
;
6014 table
= bgp
->rib
[afi
][safi
];
6016 /* If routes exists below this node, generate aggregate routes. */
6017 top
= bgp_node_get(table
, p
);
6018 for (rn
= bgp_node_get(table
, p
); rn
;
6019 rn
= bgp_route_next_until(rn
, top
)) {
6020 if (rn
->p
.prefixlen
<= p
->prefixlen
)
6024 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
6025 if (BGP_PATH_HOLDDOWN(pi
))
6028 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6031 if (aggregate
->summary_only
&& pi
->extra
) {
6032 pi
->extra
->suppress
--;
6034 if (pi
->extra
->suppress
== 0) {
6035 bgp_path_info_set_flag(
6036 rn
, pi
, BGP_PATH_ATTR_CHANGED
);
6042 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6043 aggregate
->incomplete_origin_count
--;
6044 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6045 aggregate
->egp_origin_count
--;
6047 if (aggregate
->as_set
) {
6048 /* Remove as-path from aggregate.
6050 bgp_remove_aspath_from_aggregate_hash(
6054 if (pi
->attr
->community
)
6055 /* Remove community from aggregate.
6057 bgp_remove_comm_from_aggregate_hash(
6059 pi
->attr
->community
);
6061 if (pi
->attr
->ecommunity
)
6062 /* Remove ecommunity from aggregate.
6064 bgp_remove_ecomm_from_aggregate_hash(
6066 pi
->attr
->ecommunity
);
6068 if (pi
->attr
->lcommunity
)
6069 /* Remove lcommunity from aggregate.
6071 bgp_remove_lcomm_from_aggregate_hash(
6073 pi
->attr
->lcommunity
);
6078 /* If this node was suppressed, process the change. */
6080 bgp_process(bgp
, rn
, afi
, safi
);
6082 if (aggregate
->as_set
) {
6083 aspath_free(aggregate
->aspath
);
6084 aggregate
->aspath
= NULL
;
6085 if (aggregate
->community
)
6086 community_free(&aggregate
->community
);
6087 if (aggregate
->ecommunity
)
6088 ecommunity_free(&aggregate
->ecommunity
);
6089 if (aggregate
->lcommunity
)
6090 lcommunity_free(&aggregate
->lcommunity
);
6093 bgp_unlock_node(top
);
6096 static void bgp_add_route_to_aggregate(struct bgp
*bgp
, struct prefix
*aggr_p
,
6097 struct bgp_path_info
*pinew
, afi_t afi
,
6099 struct bgp_aggregate
*aggregate
)
6102 struct aspath
*aspath
= NULL
;
6103 uint8_t atomic_aggregate
= 0;
6104 struct community
*community
= NULL
;
6105 struct ecommunity
*ecommunity
= NULL
;
6106 struct lcommunity
*lcommunity
= NULL
;
6108 /* ORIGIN attribute: If at least one route among routes that are
6109 * aggregated has ORIGIN with the value INCOMPLETE, then the
6110 * aggregated route must have the ORIGIN attribute with the value
6111 * INCOMPLETE. Otherwise, if at least one route among routes that
6112 * are aggregated has ORIGIN with the value EGP, then the aggregated
6113 * route must have the origin attribute with the value EGP. In all
6114 * other case the value of the ORIGIN attribute of the aggregated
6115 * route is INTERNAL.
6117 origin
= BGP_ORIGIN_IGP
;
6121 if (aggregate
->summary_only
)
6122 (bgp_path_info_extra_get(pinew
))->suppress
++;
6124 switch (pinew
->attr
->origin
) {
6125 case BGP_ORIGIN_INCOMPLETE
:
6126 aggregate
->incomplete_origin_count
++;
6128 case BGP_ORIGIN_EGP
:
6129 aggregate
->egp_origin_count
++;
6137 if (aggregate
->incomplete_origin_count
> 0)
6138 origin
= BGP_ORIGIN_INCOMPLETE
;
6139 else if (aggregate
->egp_origin_count
> 0)
6140 origin
= BGP_ORIGIN_EGP
;
6142 if (aggregate
->as_set
) {
6143 /* Compute aggregate route's as-path.
6145 bgp_compute_aggregate_aspath(aggregate
,
6146 pinew
->attr
->aspath
);
6148 /* Compute aggregate route's community.
6150 if (pinew
->attr
->community
)
6151 bgp_compute_aggregate_community(
6153 pinew
->attr
->community
);
6155 /* Compute aggregate route's extended community.
6157 if (pinew
->attr
->ecommunity
)
6158 bgp_compute_aggregate_ecommunity(
6160 pinew
->attr
->ecommunity
);
6162 /* Compute aggregate route's large community.
6164 if (pinew
->attr
->lcommunity
)
6165 bgp_compute_aggregate_lcommunity(
6167 pinew
->attr
->lcommunity
);
6169 /* Retrieve aggregate route's as-path.
6171 if (aggregate
->aspath
)
6172 aspath
= aspath_dup(aggregate
->aspath
);
6174 /* Retrieve aggregate route's community.
6176 if (aggregate
->community
)
6177 community
= community_dup(aggregate
->community
);
6179 /* Retrieve aggregate route's ecommunity.
6181 if (aggregate
->ecommunity
)
6182 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6184 /* Retrieve aggregate route's lcommunity.
6186 if (aggregate
->lcommunity
)
6187 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6190 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6191 aspath
, community
, ecommunity
,
6192 lcommunity
, atomic_aggregate
, aggregate
);
6195 static void bgp_remove_route_from_aggregate(struct bgp
*bgp
, afi_t afi
,
6197 struct bgp_path_info
*pi
,
6198 struct bgp_aggregate
*aggregate
,
6199 struct prefix
*aggr_p
)
6202 struct aspath
*aspath
= NULL
;
6203 uint8_t atomic_aggregate
= 0;
6204 struct community
*community
= NULL
;
6205 struct ecommunity
*ecommunity
= NULL
;
6206 struct lcommunity
*lcommunity
= NULL
;
6207 unsigned long match
= 0;
6209 if (BGP_PATH_HOLDDOWN(pi
))
6212 if (pi
->sub_type
== BGP_ROUTE_AGGREGATE
)
6215 if (aggregate
->summary_only
6217 && pi
->extra
->suppress
> 0) {
6218 pi
->extra
->suppress
--;
6220 if (pi
->extra
->suppress
== 0) {
6221 bgp_path_info_set_flag(pi
->net
, pi
,
6222 BGP_PATH_ATTR_CHANGED
);
6227 if (aggregate
->count
> 0)
6230 if (pi
->attr
->origin
== BGP_ORIGIN_INCOMPLETE
)
6231 aggregate
->incomplete_origin_count
--;
6232 else if (pi
->attr
->origin
== BGP_ORIGIN_EGP
)
6233 aggregate
->egp_origin_count
--;
6235 if (aggregate
->as_set
) {
6236 /* Remove as-path from aggregate.
6238 bgp_remove_aspath_from_aggregate(aggregate
,
6241 if (pi
->attr
->community
)
6242 /* Remove community from aggregate.
6244 bgp_remove_community_from_aggregate(
6246 pi
->attr
->community
);
6248 if (pi
->attr
->ecommunity
)
6249 /* Remove ecommunity from aggregate.
6251 bgp_remove_ecommunity_from_aggregate(
6253 pi
->attr
->ecommunity
);
6255 if (pi
->attr
->lcommunity
)
6256 /* Remove lcommunity from aggregate.
6258 bgp_remove_lcommunity_from_aggregate(
6260 pi
->attr
->lcommunity
);
6263 /* If this node was suppressed, process the change. */
6265 bgp_process(bgp
, pi
->net
, afi
, safi
);
6267 origin
= BGP_ORIGIN_IGP
;
6268 if (aggregate
->incomplete_origin_count
> 0)
6269 origin
= BGP_ORIGIN_INCOMPLETE
;
6270 else if (aggregate
->egp_origin_count
> 0)
6271 origin
= BGP_ORIGIN_EGP
;
6273 if (aggregate
->as_set
) {
6274 /* Retrieve aggregate route's as-path.
6276 if (aggregate
->aspath
)
6277 aspath
= aspath_dup(aggregate
->aspath
);
6279 /* Retrieve aggregate route's community.
6281 if (aggregate
->community
)
6282 community
= community_dup(aggregate
->community
);
6284 /* Retrieve aggregate route's ecommunity.
6286 if (aggregate
->ecommunity
)
6287 ecommunity
= ecommunity_dup(aggregate
->ecommunity
);
6289 /* Retrieve aggregate route's lcommunity.
6291 if (aggregate
->lcommunity
)
6292 lcommunity
= lcommunity_dup(aggregate
->lcommunity
);
6295 bgp_aggregate_install(bgp
, afi
, safi
, aggr_p
, origin
,
6296 aspath
, community
, ecommunity
,
6297 lcommunity
, atomic_aggregate
, aggregate
);
6300 void bgp_aggregate_increment(struct bgp
*bgp
, struct prefix
*p
,
6301 struct bgp_path_info
*pi
, afi_t afi
, safi_t safi
)
6303 struct bgp_node
*child
;
6304 struct bgp_node
*rn
;
6305 struct bgp_aggregate
*aggregate
;
6306 struct bgp_table
*table
;
6308 table
= bgp
->aggregate
[afi
][safi
];
6310 /* No aggregates configured. */
6311 if (bgp_table_top_nolock(table
) == NULL
)
6314 if (p
->prefixlen
== 0)
6317 if (BGP_PATH_HOLDDOWN(pi
))
6320 child
= bgp_node_get(table
, p
);
6322 /* Aggregate address configuration check. */
6323 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6324 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6325 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6326 bgp_add_route_to_aggregate(bgp
, &rn
->p
, pi
, afi
,
6330 bgp_unlock_node(child
);
6333 void bgp_aggregate_decrement(struct bgp
*bgp
, struct prefix
*p
,
6334 struct bgp_path_info
*del
, afi_t afi
, safi_t safi
)
6336 struct bgp_node
*child
;
6337 struct bgp_node
*rn
;
6338 struct bgp_aggregate
*aggregate
;
6339 struct bgp_table
*table
;
6341 table
= bgp
->aggregate
[afi
][safi
];
6343 /* No aggregates configured. */
6344 if (bgp_table_top_nolock(table
) == NULL
)
6347 if (p
->prefixlen
== 0)
6350 child
= bgp_node_get(table
, p
);
6352 /* Aggregate address configuration check. */
6353 for (rn
= child
; rn
; rn
= bgp_node_parent_nolock(rn
)) {
6354 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6355 if (aggregate
!= NULL
&& rn
->p
.prefixlen
< p
->prefixlen
) {
6356 bgp_remove_route_from_aggregate(bgp
, afi
, safi
,
6357 del
, aggregate
, &rn
->p
);
6360 bgp_unlock_node(child
);
6363 /* Aggregate route attribute. */
6364 #define AGGREGATE_SUMMARY_ONLY 1
6365 #define AGGREGATE_AS_SET 1
6367 static int bgp_aggregate_unset(struct vty
*vty
, const char *prefix_str
,
6368 afi_t afi
, safi_t safi
)
6370 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6373 struct bgp_node
*rn
;
6374 struct bgp_aggregate
*aggregate
;
6376 /* Convert string to prefix structure. */
6377 ret
= str2prefix(prefix_str
, &p
);
6379 vty_out(vty
, "Malformed prefix\n");
6380 return CMD_WARNING_CONFIG_FAILED
;
6384 /* Old configuration check. */
6385 rn
= bgp_node_lookup(bgp
->aggregate
[afi
][safi
], &p
);
6388 "%% There is no aggregate-address configuration.\n");
6389 return CMD_WARNING_CONFIG_FAILED
;
6392 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6393 bgp_aggregate_delete(bgp
, &p
, afi
, safi
, aggregate
);
6394 bgp_aggregate_install(bgp
, afi
, safi
, &p
, 0, NULL
, NULL
,
6395 NULL
, NULL
, 0, aggregate
);
6397 /* Unlock aggregate address configuration. */
6398 bgp_node_set_bgp_aggregate_info(rn
, NULL
);
6400 if (aggregate
->community
)
6401 community_free(&aggregate
->community
);
6403 if (aggregate
->community_hash
) {
6404 /* Delete all communities in the hash.
6406 hash_clean(aggregate
->community_hash
,
6407 bgp_aggr_community_remove
);
6408 /* Free up the community_hash.
6410 hash_free(aggregate
->community_hash
);
6413 if (aggregate
->ecommunity
)
6414 ecommunity_free(&aggregate
->ecommunity
);
6416 if (aggregate
->ecommunity_hash
) {
6417 /* Delete all ecommunities in the hash.
6419 hash_clean(aggregate
->ecommunity_hash
,
6420 bgp_aggr_ecommunity_remove
);
6421 /* Free up the ecommunity_hash.
6423 hash_free(aggregate
->ecommunity_hash
);
6426 if (aggregate
->lcommunity
)
6427 lcommunity_free(&aggregate
->lcommunity
);
6429 if (aggregate
->lcommunity_hash
) {
6430 /* Delete all lcommunities in the hash.
6432 hash_clean(aggregate
->lcommunity_hash
,
6433 bgp_aggr_lcommunity_remove
);
6434 /* Free up the lcommunity_hash.
6436 hash_free(aggregate
->lcommunity_hash
);
6439 if (aggregate
->aspath
)
6440 aspath_free(aggregate
->aspath
);
6442 if (aggregate
->aspath_hash
) {
6443 /* Delete all as-paths in the hash.
6445 hash_clean(aggregate
->aspath_hash
,
6446 bgp_aggr_aspath_remove
);
6447 /* Free up the aspath_hash.
6449 hash_free(aggregate
->aspath_hash
);
6452 bgp_aggregate_free(aggregate
);
6453 bgp_unlock_node(rn
);
6454 bgp_unlock_node(rn
);
6459 static int bgp_aggregate_set(struct vty
*vty
, const char *prefix_str
, afi_t afi
,
6460 safi_t safi
, const char *rmap
, uint8_t summary_only
,
6463 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
6466 struct bgp_node
*rn
;
6467 struct bgp_aggregate
*aggregate
;
6469 /* Convert string to prefix structure. */
6470 ret
= str2prefix(prefix_str
, &p
);
6472 vty_out(vty
, "Malformed prefix\n");
6473 return CMD_WARNING_CONFIG_FAILED
;
6477 if ((afi
== AFI_IP
&& p
.prefixlen
== IPV4_MAX_BITLEN
) ||
6478 (afi
== AFI_IP6
&& p
.prefixlen
== IPV6_MAX_BITLEN
)) {
6479 vty_out(vty
, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
6481 return CMD_WARNING_CONFIG_FAILED
;
6484 /* Old configuration check. */
6485 rn
= bgp_node_get(bgp
->aggregate
[afi
][safi
], &p
);
6486 aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
6489 vty_out(vty
, "There is already same aggregate network.\n");
6490 /* try to remove the old entry */
6491 ret
= bgp_aggregate_unset(vty
, prefix_str
, afi
, safi
);
6493 vty_out(vty
, "Error deleting aggregate.\n");
6494 bgp_unlock_node(rn
);
6495 return CMD_WARNING_CONFIG_FAILED
;
6499 /* Make aggregate address structure. */
6500 aggregate
= bgp_aggregate_new();
6501 aggregate
->summary_only
= summary_only
;
6502 aggregate
->as_set
= as_set
;
6503 aggregate
->safi
= safi
;
6506 XFREE(MTYPE_ROUTE_MAP_NAME
, aggregate
->rmap
.name
);
6507 route_map_counter_decrement(aggregate
->rmap
.map
);
6508 aggregate
->rmap
.name
=
6509 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmap
);
6510 aggregate
->rmap
.map
= route_map_lookup_by_name(rmap
);
6511 route_map_counter_increment(aggregate
->rmap
.map
);
6513 bgp_node_set_bgp_aggregate_info(rn
, aggregate
);
6515 /* Aggregate address insert into BGP routing table. */
6516 bgp_aggregate_route(bgp
, &p
, afi
, safi
, aggregate
);
6521 DEFUN (aggregate_address
,
6522 aggregate_address_cmd
,
6523 "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6524 "Configure BGP aggregate entries\n"
6525 "Aggregate prefix\n"
6526 "Generate AS set path information\n"
6527 "Filter more specific routes from updates\n"
6528 "Filter more specific routes from updates\n"
6529 "Generate AS set path information\n"
6530 "Apply route map to aggregate network\n"
6531 "Name of route map\n")
6534 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6535 char *prefix
= argv
[idx
]->arg
;
6538 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6540 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6541 ? AGGREGATE_SUMMARY_ONLY
6545 argv_find(argv
, argc
, "WORD", &idx
);
6547 rmap
= argv
[idx
]->arg
;
6549 return bgp_aggregate_set(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
),
6550 rmap
, summary_only
, as_set
);
6553 DEFUN (aggregate_address_mask
,
6554 aggregate_address_mask_cmd
,
6555 "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6556 "Configure BGP aggregate entries\n"
6557 "Aggregate address\n"
6559 "Generate AS set path information\n"
6560 "Filter more specific routes from updates\n"
6561 "Filter more specific routes from updates\n"
6562 "Generate AS set path information\n"
6563 "Apply route map to aggregate network\n"
6564 "Name of route map\n")
6567 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6568 char *prefix
= argv
[idx
]->arg
;
6569 char *mask
= argv
[idx
+ 1]->arg
;
6573 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6575 int summary_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6576 ? AGGREGATE_SUMMARY_ONLY
6579 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6581 rmap
= argv
[idx
]->arg
;
6583 char prefix_str
[BUFSIZ
];
6584 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6587 vty_out(vty
, "%% Inconsistent address and mask\n");
6588 return CMD_WARNING_CONFIG_FAILED
;
6591 return bgp_aggregate_set(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
),
6592 rmap
, summary_only
, as_set
);
6595 DEFUN (no_aggregate_address
,
6596 no_aggregate_address_cmd
,
6597 "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6599 "Configure BGP aggregate entries\n"
6600 "Aggregate prefix\n"
6601 "Generate AS set path information\n"
6602 "Filter more specific routes from updates\n"
6603 "Filter more specific routes from updates\n"
6604 "Generate AS set path information\n"
6605 "Apply route map to aggregate network\n"
6606 "Name of route map\n")
6609 argv_find(argv
, argc
, "A.B.C.D/M", &idx
);
6610 char *prefix
= argv
[idx
]->arg
;
6611 return bgp_aggregate_unset(vty
, prefix
, AFI_IP
, bgp_node_safi(vty
));
6614 DEFUN (no_aggregate_address_mask
,
6615 no_aggregate_address_mask_cmd
,
6616 "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6618 "Configure BGP aggregate entries\n"
6619 "Aggregate address\n"
6621 "Generate AS set path information\n"
6622 "Filter more specific routes from updates\n"
6623 "Filter more specific routes from updates\n"
6624 "Generate AS set path information\n"
6625 "Apply route map to aggregate network\n"
6626 "Name of route map\n")
6629 argv_find(argv
, argc
, "A.B.C.D", &idx
);
6630 char *prefix
= argv
[idx
]->arg
;
6631 char *mask
= argv
[idx
+ 1]->arg
;
6633 char prefix_str
[BUFSIZ
];
6634 int ret
= netmask_str2prefix_str(prefix
, mask
, prefix_str
);
6637 vty_out(vty
, "%% Inconsistent address and mask\n");
6638 return CMD_WARNING_CONFIG_FAILED
;
6641 return bgp_aggregate_unset(vty
, prefix_str
, AFI_IP
, bgp_node_safi(vty
));
6644 DEFUN (ipv6_aggregate_address
,
6645 ipv6_aggregate_address_cmd
,
6646 "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6647 "Configure BGP aggregate entries\n"
6648 "Aggregate prefix\n"
6649 "Generate AS set path information\n"
6650 "Filter more specific routes from updates\n"
6651 "Filter more specific routes from updates\n"
6652 "Generate AS set path information\n"
6653 "Apply route map to aggregate network\n"
6654 "Name of route map\n")
6657 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6658 char *prefix
= argv
[idx
]->arg
;
6662 argv_find(argv
, argc
, "as-set", &idx
) ? AGGREGATE_AS_SET
: 0;
6665 int sum_only
= argv_find(argv
, argc
, "summary-only", &idx
)
6666 ? AGGREGATE_SUMMARY_ONLY
6669 rmap_found
= argv_find(argv
, argc
, "WORD", &idx
);
6671 rmap
= argv
[idx
]->arg
;
6673 return bgp_aggregate_set(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
, rmap
,
6677 DEFUN (no_ipv6_aggregate_address
,
6678 no_ipv6_aggregate_address_cmd
,
6679 "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
6681 "Configure BGP aggregate entries\n"
6682 "Aggregate prefix\n"
6683 "Generate AS set path information\n"
6684 "Filter more specific routes from updates\n"
6685 "Filter more specific routes from updates\n"
6686 "Generate AS set path information\n"
6687 "Apply route map to aggregate network\n"
6688 "Name of route map\n")
6691 argv_find(argv
, argc
, "X:X::X:X/M", &idx
);
6692 char *prefix
= argv
[idx
]->arg
;
6693 return bgp_aggregate_unset(vty
, prefix
, AFI_IP6
, SAFI_UNICAST
);
6696 /* Redistribute route treatment. */
6697 void bgp_redistribute_add(struct bgp
*bgp
, struct prefix
*p
,
6698 const union g_addr
*nexthop
, ifindex_t ifindex
,
6699 enum nexthop_types_t nhtype
, uint32_t metric
,
6700 uint8_t type
, unsigned short instance
,
6703 struct bgp_path_info
*new;
6704 struct bgp_path_info
*bpi
;
6705 struct bgp_path_info rmap_path
;
6706 struct bgp_node
*bn
;
6708 struct attr
*new_attr
;
6710 route_map_result_t ret
;
6711 struct bgp_redist
*red
;
6713 /* Make default attribute. */
6714 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
6716 * This must not be NULL to satisfy Coverity SA
6718 assert(attr
.aspath
);
6721 case NEXTHOP_TYPE_IFINDEX
:
6723 case NEXTHOP_TYPE_IPV4
:
6724 case NEXTHOP_TYPE_IPV4_IFINDEX
:
6725 attr
.nexthop
= nexthop
->ipv4
;
6727 case NEXTHOP_TYPE_IPV6
:
6728 case NEXTHOP_TYPE_IPV6_IFINDEX
:
6729 attr
.mp_nexthop_global
= nexthop
->ipv6
;
6730 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6732 case NEXTHOP_TYPE_BLACKHOLE
:
6733 switch (p
->family
) {
6735 attr
.nexthop
.s_addr
= INADDR_ANY
;
6738 memset(&attr
.mp_nexthop_global
, 0,
6739 sizeof(attr
.mp_nexthop_global
));
6740 attr
.mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
;
6745 attr
.nh_ifindex
= ifindex
;
6748 attr
.flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
6751 afi
= family2afi(p
->family
);
6753 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6755 struct attr attr_new
;
6757 /* Copy attribute for modification. */
6758 bgp_attr_dup(&attr_new
, &attr
);
6760 if (red
->redist_metric_flag
)
6761 attr_new
.med
= red
->redist_metric
;
6763 /* Apply route-map. */
6764 if (red
->rmap
.name
) {
6765 memset(&rmap_path
, 0, sizeof(struct bgp_path_info
));
6766 rmap_path
.peer
= bgp
->peer_self
;
6767 rmap_path
.attr
= &attr_new
;
6769 SET_FLAG(bgp
->peer_self
->rmap_type
,
6770 PEER_RMAP_TYPE_REDISTRIBUTE
);
6772 ret
= route_map_apply(red
->rmap
.map
, p
, RMAP_BGP
,
6775 bgp
->peer_self
->rmap_type
= 0;
6777 if (ret
== RMAP_DENYMATCH
) {
6778 /* Free uninterned attribute. */
6779 bgp_attr_flush(&attr_new
);
6781 /* Unintern original. */
6782 aspath_unintern(&attr
.aspath
);
6783 bgp_redistribute_delete(bgp
, p
, type
, instance
);
6788 if (bgp_flag_check(bgp
, BGP_FLAG_GRACEFUL_SHUTDOWN
))
6789 bgp_attr_add_gshut_community(&attr_new
);
6791 bn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6792 SAFI_UNICAST
, p
, NULL
);
6794 new_attr
= bgp_attr_intern(&attr_new
);
6796 for (bpi
= bgp_node_get_bgp_path_info(bn
); bpi
;
6798 if (bpi
->peer
== bgp
->peer_self
6799 && bpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
)
6803 /* Ensure the (source route) type is updated. */
6805 if (attrhash_cmp(bpi
->attr
, new_attr
)
6806 && !CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
)) {
6807 bgp_attr_unintern(&new_attr
);
6808 aspath_unintern(&attr
.aspath
);
6809 bgp_unlock_node(bn
);
6812 /* The attribute is changed. */
6813 bgp_path_info_set_flag(bn
, bpi
,
6814 BGP_PATH_ATTR_CHANGED
);
6816 /* Rewrite BGP route information. */
6817 if (CHECK_FLAG(bpi
->flags
, BGP_PATH_REMOVED
))
6818 bgp_path_info_restore(bn
, bpi
);
6820 bgp_aggregate_decrement(
6821 bgp
, p
, bpi
, afi
, SAFI_UNICAST
);
6822 bgp_attr_unintern(&bpi
->attr
);
6823 bpi
->attr
= new_attr
;
6824 bpi
->uptime
= bgp_clock();
6826 /* Process change. */
6827 bgp_aggregate_increment(bgp
, p
, bpi
, afi
,
6829 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6830 bgp_unlock_node(bn
);
6831 aspath_unintern(&attr
.aspath
);
6833 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6835 == BGP_INSTANCE_TYPE_DEFAULT
)) {
6837 vpn_leak_from_vrf_update(
6838 bgp_get_default(), bgp
, bpi
);
6844 new = info_make(type
, BGP_ROUTE_REDISTRIBUTE
, instance
,
6845 bgp
->peer_self
, new_attr
, bn
);
6846 SET_FLAG(new->flags
, BGP_PATH_VALID
);
6848 bgp_aggregate_increment(bgp
, p
, new, afi
, SAFI_UNICAST
);
6849 bgp_path_info_add(bn
, new);
6850 bgp_unlock_node(bn
);
6851 bgp_process(bgp
, bn
, afi
, SAFI_UNICAST
);
6853 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6854 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6856 vpn_leak_from_vrf_update(bgp_get_default(), bgp
, new);
6860 /* Unintern original. */
6861 aspath_unintern(&attr
.aspath
);
6864 void bgp_redistribute_delete(struct bgp
*bgp
, struct prefix
*p
, uint8_t type
,
6865 unsigned short instance
)
6868 struct bgp_node
*rn
;
6869 struct bgp_path_info
*pi
;
6870 struct bgp_redist
*red
;
6872 afi
= family2afi(p
->family
);
6874 red
= bgp_redist_lookup(bgp
, afi
, type
, instance
);
6876 rn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
,
6877 SAFI_UNICAST
, p
, NULL
);
6879 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6880 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
)
6884 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6885 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6887 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6890 bgp_aggregate_decrement(bgp
, p
, pi
, afi
, SAFI_UNICAST
);
6891 bgp_path_info_delete(rn
, pi
);
6892 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6894 bgp_unlock_node(rn
);
6898 /* Withdraw specified route type's route. */
6899 void bgp_redistribute_withdraw(struct bgp
*bgp
, afi_t afi
, int type
,
6900 unsigned short instance
)
6902 struct bgp_node
*rn
;
6903 struct bgp_path_info
*pi
;
6904 struct bgp_table
*table
;
6906 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
6908 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
6909 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
)
6910 if (pi
->peer
== bgp
->peer_self
&& pi
->type
== type
6911 && pi
->instance
== instance
)
6915 if ((bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
)
6916 || (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)) {
6918 vpn_leak_from_vrf_withdraw(bgp_get_default(),
6921 bgp_aggregate_decrement(bgp
, &rn
->p
, pi
, afi
,
6923 bgp_path_info_delete(rn
, pi
);
6924 bgp_process(bgp
, rn
, afi
, SAFI_UNICAST
);
6929 /* Static function to display route. */
6930 static void route_vty_out_route(struct prefix
*p
, struct vty
*vty
,
6937 if (p
->family
== AF_INET
) {
6941 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6944 json_object_string_add(json
, "prefix",
6945 inet_ntop(p
->family
,
6948 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6949 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6950 json_object_string_add(json
, "network", buf2
);
6952 } else if (p
->family
== AF_ETHERNET
) {
6953 prefix2str(p
, buf
, PREFIX_STRLEN
);
6954 len
= vty_out(vty
, "%s", buf
);
6955 } else if (p
->family
== AF_EVPN
) {
6959 bgp_evpn_route2str((struct prefix_evpn
*)p
, buf
,
6962 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
6963 } else if (p
->family
== AF_FLOWSPEC
) {
6964 route_vty_out_flowspec(vty
, p
, NULL
,
6966 NLRI_STRING_FORMAT_JSON_SIMPLE
:
6967 NLRI_STRING_FORMAT_MIN
, json
);
6972 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, BUFSIZ
),
6975 json_object_string_add(json
, "prefix",
6976 inet_ntop(p
->family
,
6979 json_object_int_add(json
, "prefixLen", p
->prefixlen
);
6980 prefix2str(p
, buf2
, PREFIX_STRLEN
);
6981 json_object_string_add(json
, "network", buf2
);
6988 vty_out(vty
, "\n%*s", 20, " ");
6990 vty_out(vty
, "%*s", len
, " ");
6994 enum bgp_display_type
{
6998 /* Print the short form route status for a bgp_path_info */
6999 static void route_vty_short_status_out(struct vty
*vty
,
7000 struct bgp_path_info
*path
,
7001 json_object
*json_path
)
7005 /* Route status display. */
7006 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7007 json_object_boolean_true_add(json_path
, "removed");
7009 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7010 json_object_boolean_true_add(json_path
, "stale");
7012 if (path
->extra
&& path
->extra
->suppress
)
7013 json_object_boolean_true_add(json_path
, "suppressed");
7015 if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7016 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7017 json_object_boolean_true_add(json_path
, "valid");
7020 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7021 json_object_boolean_true_add(json_path
, "history");
7023 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7024 json_object_boolean_true_add(json_path
, "damped");
7026 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7027 json_object_boolean_true_add(json_path
, "bestpath");
7029 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7030 json_object_boolean_true_add(json_path
, "multipath");
7032 /* Internal route. */
7033 if ((path
->peer
->as
)
7034 && (path
->peer
->as
== path
->peer
->local_as
))
7035 json_object_string_add(json_path
, "pathFrom",
7038 json_object_string_add(json_path
, "pathFrom",
7044 /* Route status display. */
7045 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
))
7047 else if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
))
7049 else if (path
->extra
&& path
->extra
->suppress
)
7051 else if (CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)
7052 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7058 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
7060 else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
7062 else if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
))
7064 else if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
))
7069 /* Internal route. */
7070 if (path
->peer
&& (path
->peer
->as
)
7071 && (path
->peer
->as
== path
->peer
->local_as
))
7077 static char *bgp_nexthop_fqdn(struct peer
*peer
)
7079 if (peer
->hostname
&& bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
))
7080 return peer
->hostname
;
7084 /* called from terminal list command */
7085 void route_vty_out(struct vty
*vty
, struct prefix
*p
,
7086 struct bgp_path_info
*path
, int display
, safi_t safi
,
7087 json_object
*json_paths
)
7090 json_object
*json_path
= NULL
;
7091 json_object
*json_nexthops
= NULL
;
7092 json_object
*json_nexthop_global
= NULL
;
7093 json_object
*json_nexthop_ll
= NULL
;
7094 json_object
*json_ext_community
= NULL
;
7095 char vrf_id_str
[VRF_NAMSIZ
] = {0};
7097 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
7098 bool nexthop_othervrf
= false;
7099 vrf_id_t nexthop_vrfid
= VRF_DEFAULT
;
7100 const char *nexthop_vrfname
= VRF_DEFAULT_NAME
;
7101 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
7104 json_path
= json_object_new_object();
7106 /* short status lead text */
7107 route_vty_short_status_out(vty
, path
, json_path
);
7110 /* print prefix and mask */
7112 route_vty_out_route(p
, vty
, json_path
);
7114 vty_out(vty
, "%*s", 17, " ");
7116 route_vty_out_route(p
, vty
, json_path
);
7119 /* Print attribute */
7123 * If vrf id of nexthop is different from that of prefix,
7124 * set up printable string to append
7126 if (path
->extra
&& path
->extra
->bgp_orig
) {
7127 const char *self
= "";
7132 nexthop_othervrf
= true;
7133 nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
7135 if (path
->extra
->bgp_orig
->vrf_id
== VRF_UNKNOWN
)
7136 snprintf(vrf_id_str
, sizeof(vrf_id_str
),
7137 "@%s%s", VRFID_NONE_STR
, self
);
7139 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "@%u%s",
7140 path
->extra
->bgp_orig
->vrf_id
, self
);
7142 if (path
->extra
->bgp_orig
->inst_type
7143 != BGP_INSTANCE_TYPE_DEFAULT
)
7145 nexthop_vrfname
= path
->extra
->bgp_orig
->name
;
7147 const char *self
= "";
7152 snprintf(vrf_id_str
, sizeof(vrf_id_str
), "%s", self
);
7156 * For ENCAP and EVPN routes, nexthop address family is not
7157 * neccessarily the same as the prefix address family.
7158 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7159 * EVPN routes are also exchanged with a MP nexthop. Currently,
7161 * is only IPv4, the value will be present in either
7163 * attr->mp_nexthop_global_in
7165 if ((safi
== SAFI_ENCAP
) || (safi
== SAFI_MPLS_VPN
)) {
7168 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7172 sprintf(nexthop
, "%s",
7173 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
,
7177 sprintf(nexthop
, "%s",
7178 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
,
7182 sprintf(nexthop
, "?");
7187 json_nexthop_global
= json_object_new_object();
7189 json_object_string_add(
7190 json_nexthop_global
, "afi",
7191 nexthop_fqdn
? "fqdn"
7192 : (af
== AF_INET
) ? "ip" : "ipv6");
7193 json_object_string_add(
7194 json_nexthop_global
,
7195 nexthop_fqdn
? "fqdn"
7196 : (af
== AF_INET
) ? "ip" : "ipv6",
7197 nexthop_fqdn
? nexthop_fqdn
: nexthop
);
7198 json_object_boolean_true_add(json_nexthop_global
,
7201 vty_out(vty
, "%s%s",
7202 nexthop_fqdn
? nexthop_fqdn
: nexthop
,
7204 } else if (safi
== SAFI_EVPN
) {
7206 json_nexthop_global
= json_object_new_object();
7208 json_object_string_add(
7209 json_nexthop_global
,
7210 nexthop_fqdn
? "fqdn" : "ip",
7211 nexthop_fqdn
? nexthop_fqdn
7212 : inet_ntoa(attr
->nexthop
));
7213 json_object_string_add(json_nexthop_global
, "afi",
7215 json_object_boolean_true_add(json_nexthop_global
,
7218 vty_out(vty
, "%-16s%s",
7219 nexthop_fqdn
?: inet_ntoa(attr
->nexthop
),
7221 } else if (safi
== SAFI_FLOWSPEC
) {
7222 if (attr
->nexthop
.s_addr
!= 0) {
7224 json_nexthop_global
= json_object_new_object();
7225 json_object_string_add(
7226 json_nexthop_global
,
7227 nexthop_fqdn
? "fqdn" : "ip",
7230 : inet_ntoa(attr
->nexthop
));
7231 json_object_string_add(json_nexthop_global
,
7233 json_object_boolean_true_add(
7234 json_nexthop_global
,
7237 vty_out(vty
, "%-16s",
7240 : inet_ntoa(attr
->nexthop
));
7243 } else if (p
->family
== AF_INET
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7245 json_nexthop_global
= json_object_new_object();
7247 json_object_string_add(json_nexthop_global
,
7248 nexthop_fqdn
? "fqdn" : "ip",
7251 : inet_ntoa(attr
->nexthop
));
7253 json_object_string_add(json_nexthop_global
, "afi",
7255 json_object_boolean_true_add(json_nexthop_global
,
7260 snprintf(buf
, sizeof(buf
), "%s%s",
7261 nexthop_fqdn
? nexthop_fqdn
7262 : inet_ntoa(attr
->nexthop
),
7264 vty_out(vty
, "%-16s", buf
);
7269 else if (p
->family
== AF_INET6
|| BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7274 json_nexthop_global
= json_object_new_object();
7275 json_object_string_add(
7276 json_nexthop_global
,
7277 nexthop_fqdn
? "fqdn" : "ip",
7280 : inet_ntop(AF_INET6
,
7281 &attr
->mp_nexthop_global
,
7283 json_object_string_add(json_nexthop_global
, "afi",
7285 json_object_string_add(json_nexthop_global
, "scope",
7288 /* We display both LL & GL if both have been
7290 if ((attr
->mp_nexthop_len
7291 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7292 || (path
->peer
->conf_if
)) {
7293 json_nexthop_ll
= json_object_new_object();
7294 json_object_string_add(
7296 nexthop_fqdn
? "fqdn" : "ip",
7301 &attr
->mp_nexthop_local
,
7303 json_object_string_add(json_nexthop_ll
, "afi",
7305 json_object_string_add(json_nexthop_ll
, "scope",
7308 if ((IPV6_ADDR_CMP(&attr
->mp_nexthop_global
,
7309 &attr
->mp_nexthop_local
)
7311 && !attr
->mp_nexthop_prefer_global
)
7312 json_object_boolean_true_add(
7313 json_nexthop_ll
, "used");
7315 json_object_boolean_true_add(
7316 json_nexthop_global
, "used");
7318 json_object_boolean_true_add(
7319 json_nexthop_global
, "used");
7321 /* Display LL if LL/Global both in table unless
7322 * prefer-global is set */
7323 if (((attr
->mp_nexthop_len
7324 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
)
7325 && !attr
->mp_nexthop_prefer_global
)
7326 || (path
->peer
->conf_if
)) {
7327 if (path
->peer
->conf_if
) {
7328 len
= vty_out(vty
, "%s",
7329 path
->peer
->conf_if
);
7330 len
= 16 - len
; /* len of IPv6
7336 vty_out(vty
, "\n%*s", 36, " ");
7338 vty_out(vty
, "%*s", len
, " ");
7346 &attr
->mp_nexthop_local
,
7352 vty_out(vty
, "\n%*s", 36, " ");
7354 vty_out(vty
, "%*s", len
, " ");
7363 &attr
->mp_nexthop_global
,
7369 vty_out(vty
, "\n%*s", 36, " ");
7371 vty_out(vty
, "%*s", len
, " ");
7377 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7381 * Adding "metric" field to match with corresponding
7382 * CLI. "med" will be deprecated in future.
7384 json_object_int_add(json_path
, "med", attr
->med
);
7385 json_object_int_add(json_path
, "metric", attr
->med
);
7387 vty_out(vty
, "%10u", attr
->med
);
7388 else if (!json_paths
)
7392 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7396 * Adding "locPrf" field to match with corresponding
7397 * CLI. "localPref" will be deprecated in future.
7399 json_object_int_add(json_path
, "localpref",
7401 json_object_int_add(json_path
, "locPrf",
7404 vty_out(vty
, "%7u", attr
->local_pref
);
7405 else if (!json_paths
)
7409 json_object_int_add(json_path
, "weight", attr
->weight
);
7411 vty_out(vty
, "%7u ", attr
->weight
);
7415 json_object_string_add(
7416 json_path
, "peerId",
7417 sockunion2str(&path
->peer
->su
, buf
, SU_ADDRSTRLEN
));
7425 * Adding "path" field to match with corresponding
7426 * CLI. "aspath" will be deprecated in future.
7428 json_object_string_add(json_path
, "aspath",
7430 json_object_string_add(json_path
, "path",
7433 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7438 json_object_string_add(json_path
, "origin",
7439 bgp_origin_long_str
[attr
->origin
]);
7441 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7444 if (safi
== SAFI_EVPN
&&
7445 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7446 json_ext_community
= json_object_new_object();
7447 json_object_string_add(json_ext_community
,
7449 attr
->ecommunity
->str
);
7450 json_object_object_add(json_path
,
7451 "extendedCommunity",
7452 json_ext_community
);
7456 json_object_boolean_true_add(json_path
,
7457 "announceNexthopSelf");
7458 if (nexthop_othervrf
) {
7459 json_object_string_add(json_path
, "nhVrfName",
7462 json_object_int_add(json_path
, "nhVrfId",
7463 ((nexthop_vrfid
== VRF_UNKNOWN
)
7465 : (int)nexthop_vrfid
));
7470 if (json_nexthop_global
|| json_nexthop_ll
) {
7471 json_nexthops
= json_object_new_array();
7473 if (json_nexthop_global
)
7474 json_object_array_add(json_nexthops
,
7475 json_nexthop_global
);
7477 if (json_nexthop_ll
)
7478 json_object_array_add(json_nexthops
,
7481 json_object_object_add(json_path
, "nexthops",
7485 json_object_array_add(json_paths
, json_path
);
7489 if (safi
== SAFI_EVPN
&&
7490 attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
7491 vty_out(vty
, "%*s", 20, " ");
7492 vty_out(vty
, "%s\n", attr
->ecommunity
->str
);
7496 /* prints an additional line, indented, with VNC info, if
7498 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
))
7499 rfapi_vty_out_vncinfo(vty
, p
, path
, safi
);
7504 /* called from terminal list command */
7505 void route_vty_out_tmp(struct vty
*vty
, struct prefix
*p
, struct attr
*attr
,
7506 safi_t safi
, bool use_json
, json_object
*json_ar
)
7508 json_object
*json_status
= NULL
;
7509 json_object
*json_net
= NULL
;
7512 /* Route status display. */
7514 json_status
= json_object_new_object();
7515 json_net
= json_object_new_object();
7522 /* print prefix and mask */
7524 if (safi
== SAFI_EVPN
)
7525 bgp_evpn_route2json((struct prefix_evpn
*)p
, json_net
);
7526 else if (p
->family
== AF_INET
|| p
->family
== AF_INET6
) {
7527 json_object_string_add(
7528 json_net
, "addrPrefix",
7529 inet_ntop(p
->family
, &p
->u
.prefix
, buff
,
7531 json_object_int_add(json_net
, "prefixLen",
7533 prefix2str(p
, buff
, PREFIX_STRLEN
);
7534 json_object_string_add(json_net
, "network", buff
);
7537 route_vty_out_route(p
, vty
, NULL
);
7539 /* Print attribute */
7542 if (p
->family
== AF_INET
7543 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7544 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7545 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
7546 json_object_string_add(
7547 json_net
, "nextHop",
7549 attr
->mp_nexthop_global_in
));
7551 json_object_string_add(
7552 json_net
, "nextHop",
7553 inet_ntoa(attr
->nexthop
));
7554 } else if (p
->family
== AF_INET6
7555 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7558 json_object_string_add(
7559 json_net
, "nextHopGlobal",
7561 &attr
->mp_nexthop_global
, buf
,
7563 } else if (p
->family
== AF_EVPN
&&
7564 !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7565 json_object_string_add(json_net
,
7566 "nextHop", inet_ntoa(
7567 attr
->mp_nexthop_global_in
));
7570 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7571 json_object_int_add(json_net
, "metric",
7574 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
7577 * Adding "locPrf" field to match with
7578 * corresponding CLI. "localPref" will be
7579 * deprecated in future.
7581 json_object_int_add(json_net
, "localPref",
7583 json_object_int_add(json_net
, "locPrf",
7587 json_object_int_add(json_net
, "weight", attr
->weight
);
7593 * Adding "path" field to match with
7594 * corresponding CLI. "localPref" will be
7595 * deprecated in future.
7597 json_object_string_add(json_net
, "asPath",
7599 json_object_string_add(json_net
, "path",
7604 json_object_string_add(json_net
, "bgpOriginCode",
7605 bgp_origin_str
[attr
->origin
]);
7607 if (p
->family
== AF_INET
7608 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7609 || safi
== SAFI_EVPN
7610 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7611 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7612 || safi
== SAFI_EVPN
)
7613 vty_out(vty
, "%-16s",
7615 attr
->mp_nexthop_global_in
));
7617 vty_out(vty
, "%-16s",
7618 inet_ntoa(attr
->nexthop
));
7619 } else if (p
->family
== AF_INET6
7620 || BGP_ATTR_NEXTHOP_AFI_IP6(attr
)) {
7627 &attr
->mp_nexthop_global
, buf
,
7631 vty_out(vty
, "\n%*s", 36, " ");
7633 vty_out(vty
, "%*s", len
, " ");
7636 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
))
7637 vty_out(vty
, "%10u", attr
->med
);
7641 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
))
7642 vty_out(vty
, "%7u", attr
->local_pref
);
7646 vty_out(vty
, "%7u ", attr
->weight
);
7650 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7653 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7657 json_object_boolean_true_add(json_status
, "*");
7658 json_object_boolean_true_add(json_status
, ">");
7659 json_object_object_add(json_net
, "appliedStatusSymbols",
7662 prefix2str(p
, buff
, PREFIX_STRLEN
);
7663 json_object_object_add(json_ar
, buff
, json_net
);
7668 void route_vty_out_tag(struct vty
*vty
, struct prefix
*p
,
7669 struct bgp_path_info
*path
, int display
, safi_t safi
,
7672 json_object
*json_out
= NULL
;
7674 mpls_label_t label
= MPLS_INVALID_LABEL
;
7680 json_out
= json_object_new_object();
7682 /* short status lead text */
7683 route_vty_short_status_out(vty
, path
, json_out
);
7685 /* print prefix and mask */
7688 route_vty_out_route(p
, vty
, NULL
);
7690 vty_out(vty
, "%*s", 17, " ");
7693 /* Print attribute */
7695 if (((p
->family
== AF_INET
)
7696 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7697 || (safi
== SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7698 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7699 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
7700 || safi
== SAFI_EVPN
) {
7702 json_object_string_add(
7703 json_out
, "mpNexthopGlobalIn",
7704 inet_ntoa(attr
->mp_nexthop_global_in
));
7706 vty_out(vty
, "%-16s",
7707 inet_ntoa(attr
->mp_nexthop_global_in
));
7710 json_object_string_add(
7711 json_out
, "nexthop",
7712 inet_ntoa(attr
->nexthop
));
7714 vty_out(vty
, "%-16s", inet_ntoa(attr
->nexthop
));
7716 } else if (((p
->family
== AF_INET6
)
7717 && ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)))
7718 || (safi
== SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr
))
7719 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
7722 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL
) {
7724 json_object_string_add(
7725 json_out
, "mpNexthopGlobalIn",
7727 &attr
->mp_nexthop_global
,
7728 buf_a
, sizeof(buf_a
)));
7732 &attr
->mp_nexthop_global
,
7733 buf_a
, sizeof(buf_a
)));
7734 } else if (attr
->mp_nexthop_len
7735 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
7736 snprintfrr(buf_a
, sizeof(buf_a
), "%pI6(%pI6)",
7737 &attr
->mp_nexthop_global
,
7738 &attr
->mp_nexthop_local
);
7740 json_object_string_add(json_out
,
7741 "mpNexthopGlobalLocal",
7744 vty_out(vty
, "%s", buf_a
);
7748 label
= decode_label(&path
->extra
->label
[0]);
7750 if (bgp_is_valid_label(&label
)) {
7752 json_object_int_add(json_out
, "notag", label
);
7753 json_object_array_add(json
, json_out
);
7755 vty_out(vty
, "notag/%d", label
);
7761 void route_vty_out_overlay(struct vty
*vty
, struct prefix
*p
,
7762 struct bgp_path_info
*path
, int display
,
7763 json_object
*json_paths
)
7766 char buf
[BUFSIZ
] = {0};
7767 json_object
*json_path
= NULL
;
7768 json_object
*json_nexthop
= NULL
;
7769 json_object
*json_overlay
= NULL
;
7775 json_path
= json_object_new_object();
7776 json_overlay
= json_object_new_object();
7777 json_nexthop
= json_object_new_object();
7780 /* short status lead text */
7781 route_vty_short_status_out(vty
, path
, json_path
);
7783 /* print prefix and mask */
7785 route_vty_out_route(p
, vty
, json_path
);
7787 vty_out(vty
, "%*s", 17, " ");
7789 /* Print attribute */
7792 int af
= NEXTHOP_FAMILY(attr
->mp_nexthop_len
);
7796 inet_ntop(af
, &attr
->mp_nexthop_global_in
, buf
, BUFSIZ
);
7798 vty_out(vty
, "%-16s", buf
);
7800 json_object_string_add(json_nexthop
, "ip", buf
);
7802 json_object_string_add(json_nexthop
, "afi", "ipv4");
7804 json_object_object_add(json_path
, "nexthop",
7809 inet_ntop(af
, &attr
->mp_nexthop_global
, buf
, BUFSIZ
);
7810 inet_ntop(af
, &attr
->mp_nexthop_local
, buf1
, BUFSIZ
);
7812 vty_out(vty
, "%s(%s)", buf
, buf1
);
7814 json_object_string_add(json_nexthop
, "ipv6Global", buf
);
7816 json_object_string_add(json_nexthop
, "ipv6LinkLocal",
7819 json_object_string_add(json_nexthop
, "afi", "ipv6");
7821 json_object_object_add(json_path
, "nexthop",
7829 json_object_string_add(json_nexthop
, "Error",
7830 "Unsupported address-family");
7834 char *str
= esi2str(&(attr
->evpn_overlay
.eth_s_id
));
7837 vty_out(vty
, "%s", str
);
7839 json_object_string_add(json_overlay
, "esi", str
);
7841 XFREE(MTYPE_TMP
, str
);
7843 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn
*)p
)) {
7844 inet_ntop(AF_INET
, &(attr
->evpn_overlay
.gw_ip
.ipv4
), buf
,
7846 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn
*)p
)) {
7847 inet_ntop(AF_INET6
, &(attr
->evpn_overlay
.gw_ip
.ipv6
), buf
,
7852 vty_out(vty
, "/%s", buf
);
7854 json_object_string_add(json_overlay
, "gw", buf
);
7856 if (attr
->ecommunity
) {
7858 struct ecommunity_val
*routermac
= ecommunity_lookup(
7859 attr
->ecommunity
, ECOMMUNITY_ENCODE_EVPN
,
7860 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
);
7863 mac
= ecom_mac2str((char *)routermac
->val
);
7866 vty_out(vty
, "/%s", (char *)mac
);
7868 json_object_string_add(json_overlay
, "rmac",
7871 XFREE(MTYPE_TMP
, mac
);
7878 json_object_object_add(json_path
, "overlay", json_overlay
);
7880 json_object_array_add(json_paths
, json_path
);
7884 /* dampening route */
7885 static void damp_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7886 struct bgp_path_info
*path
, int display
,
7887 safi_t safi
, bool use_json
, json_object
*json
)
7891 char timebuf
[BGP_UPTIME_LEN
];
7893 /* short status lead text */
7894 route_vty_short_status_out(vty
, path
, json
);
7896 /* print prefix and mask */
7899 route_vty_out_route(p
, vty
, NULL
);
7901 vty_out(vty
, "%*s", 17, " ");
7904 len
= vty_out(vty
, "%s", path
->peer
->host
);
7908 vty_out(vty
, "\n%*s", 34, " ");
7911 json_object_int_add(json
, "peerHost", len
);
7913 vty_out(vty
, "%*s", len
, " ");
7917 bgp_damp_reuse_time_vty(vty
, path
, timebuf
, BGP_UPTIME_LEN
,
7921 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
7922 BGP_UPTIME_LEN
, use_json
,
7925 /* Print attribute */
7931 json_object_string_add(json
, "asPath",
7934 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
7939 json_object_string_add(json
, "origin",
7940 bgp_origin_str
[attr
->origin
]);
7942 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
7949 static void flap_route_vty_out(struct vty
*vty
, struct prefix
*p
,
7950 struct bgp_path_info
*path
, int display
,
7951 safi_t safi
, bool use_json
, json_object
*json
)
7954 struct bgp_damp_info
*bdi
;
7955 char timebuf
[BGP_UPTIME_LEN
];
7961 bdi
= path
->extra
->damp_info
;
7963 /* short status lead text */
7964 route_vty_short_status_out(vty
, path
, json
);
7966 /* print prefix and mask */
7969 route_vty_out_route(p
, vty
, NULL
);
7971 vty_out(vty
, "%*s", 17, " ");
7974 len
= vty_out(vty
, "%s", path
->peer
->host
);
7978 vty_out(vty
, "\n%*s", 33, " ");
7981 json_object_int_add(json
, "peerHost", len
);
7983 vty_out(vty
, "%*s", len
, " ");
7986 len
= vty_out(vty
, "%d", bdi
->flap
);
7993 json_object_int_add(json
, "bdiFlap", len
);
7995 vty_out(vty
, "%*s", len
, " ");
7999 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, use_json
,
8002 vty_out(vty
, "%s ", peer_uptime(bdi
->start_time
, timebuf
,
8003 BGP_UPTIME_LEN
, 0, NULL
));
8005 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
8006 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8008 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8009 BGP_UPTIME_LEN
, use_json
, json
);
8012 bgp_damp_reuse_time_vty(vty
, path
, timebuf
,
8017 vty_out(vty
, "%*s ", 8, " ");
8020 /* Print attribute */
8026 json_object_string_add(json
, "asPath",
8029 aspath_print_vty(vty
, "%s", attr
->aspath
, " ");
8034 json_object_string_add(json
, "origin",
8035 bgp_origin_str
[attr
->origin
]);
8037 vty_out(vty
, "%s", bgp_origin_str
[attr
->origin
]);
8043 static void route_vty_out_advertised_to(struct vty
*vty
, struct peer
*peer
,
8044 int *first
, const char *header
,
8045 json_object
*json_adv_to
)
8047 char buf1
[INET6_ADDRSTRLEN
];
8048 json_object
*json_peer
= NULL
;
8051 /* 'advertised-to' is a dictionary of peers we have advertised
8053 * prefix too. The key is the peer's IP or swpX, the value is
8055 * hostname if we know it and "" if not.
8057 json_peer
= json_object_new_object();
8060 json_object_string_add(json_peer
, "hostname",
8064 json_object_object_add(json_adv_to
, peer
->conf_if
,
8067 json_object_object_add(
8069 sockunion2str(&peer
->su
, buf1
, SU_ADDRSTRLEN
),
8073 vty_out(vty
, "%s", header
);
8078 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
8080 vty_out(vty
, " %s(%s)", peer
->hostname
,
8083 vty_out(vty
, " %s(%s)", peer
->hostname
,
8084 sockunion2str(&peer
->su
, buf1
,
8088 vty_out(vty
, " %s", peer
->conf_if
);
8091 sockunion2str(&peer
->su
, buf1
,
8097 static void route_vty_out_tx_ids(struct vty
*vty
,
8098 struct bgp_addpath_info_data
*d
)
8102 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8103 vty_out(vty
, "TX-%s %u%s", bgp_addpath_names(i
)->human_name
,
8104 d
->addpath_tx_id
[i
],
8105 i
< BGP_ADDPATH_MAX
- 1 ? " " : "\n");
8109 static const char *bgp_path_selection_reason2str(
8110 enum bgp_path_selection_reason reason
)
8113 case bgp_path_selection_none
:
8114 return "Nothing to Select";
8116 case bgp_path_selection_first
:
8117 return "First path received";
8119 case bgp_path_selection_evpn_sticky_mac
:
8120 return "EVPN Sticky Mac";
8122 case bgp_path_selection_evpn_seq
:
8123 return "EVPN sequence number";
8125 case bgp_path_selection_evpn_lower_ip
:
8126 return "EVPN lower IP";
8128 case bgp_path_selection_weight
:
8131 case bgp_path_selection_local_pref
:
8132 return "Local Pref";
8134 case bgp_path_selection_local_route
:
8135 return "Local Route";
8137 case bgp_path_selection_confed_as_path
:
8138 return "Confederation based AS Path";
8140 case bgp_path_selection_as_path
:
8143 case bgp_path_selection_origin
:
8146 case bgp_path_selection_med
:
8149 case bgp_path_selection_peer
:
8152 case bgp_path_selection_confed
:
8153 return "Confed Peer Type";
8155 case bgp_path_selection_igp_metric
:
8156 return "IGP Metric";
8158 case bgp_path_selection_older
:
8159 return "Older Path";
8161 case bgp_path_selection_router_id
:
8164 case bgp_path_selection_cluster_length
:
8165 return "Cluser length";
8167 case bgp_path_selection_stale
:
8168 return "Path Staleness";
8170 case bgp_path_selection_local_configured
:
8171 return "Locally configured route";
8173 case bgp_path_selection_neighbor_ip
:
8174 return "Neighbor IP";
8176 case bgp_path_selection_default
:
8177 return "Nothing left to compare";
8180 return "Invalid (internal error)";
8183 void route_vty_out_detail(struct vty
*vty
, struct bgp
*bgp
,
8184 struct bgp_node
*bn
, struct bgp_path_info
*path
,
8185 afi_t afi
, safi_t safi
, json_object
*json_paths
)
8187 char buf
[INET6_ADDRSTRLEN
];
8189 char buf2
[EVPN_ROUTE_STRLEN
];
8191 int sockunion_vty_out(struct vty
*, union sockunion
*);
8193 json_object
*json_bestpath
= NULL
;
8194 json_object
*json_cluster_list
= NULL
;
8195 json_object
*json_cluster_list_list
= NULL
;
8196 json_object
*json_ext_community
= NULL
;
8197 json_object
*json_last_update
= NULL
;
8198 json_object
*json_pmsi
= NULL
;
8199 json_object
*json_nexthop_global
= NULL
;
8200 json_object
*json_nexthop_ll
= NULL
;
8201 json_object
*json_nexthops
= NULL
;
8202 json_object
*json_path
= NULL
;
8203 json_object
*json_peer
= NULL
;
8204 json_object
*json_string
= NULL
;
8205 json_object
*json_adv_to
= NULL
;
8207 struct listnode
*node
, *nnode
;
8209 int addpath_capable
;
8211 unsigned int first_as
;
8213 CHECK_FLAG(path
->flags
, BGP_PATH_ANNC_NH_SELF
) ? true : false;
8215 char *nexthop_fqdn
= bgp_nexthop_fqdn(path
->peer
);
8218 json_path
= json_object_new_object();
8219 json_peer
= json_object_new_object();
8220 json_nexthop_global
= json_object_new_object();
8228 if (path
->extra
&& path
->extra
->num_labels
) {
8229 bgp_evpn_label2str(path
->extra
->label
,
8230 path
->extra
->num_labels
, tag_buf
,
8233 if (safi
== SAFI_EVPN
) {
8235 bgp_evpn_route2str((struct prefix_evpn
*)&bn
->p
,
8236 buf2
, sizeof(buf2
));
8237 vty_out(vty
, " Route %s", buf2
);
8238 if (tag_buf
[0] != '\0')
8239 vty_out(vty
, " VNI %s", tag_buf
);
8243 json_object_string_add(json_path
, "VNI",
8248 if (path
->extra
&& path
->extra
->parent
&& !json_paths
) {
8249 struct bgp_path_info
*parent_ri
;
8250 struct bgp_node
*rn
, *prn
;
8252 parent_ri
= (struct bgp_path_info
*)path
->extra
->parent
;
8253 rn
= parent_ri
->net
;
8254 if (rn
&& rn
->prn
) {
8256 prefix_rd2str((struct prefix_rd
*)&prn
->p
,
8257 buf1
, sizeof(buf1
));
8258 if (is_pi_family_evpn(parent_ri
)) {
8259 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
8260 buf2
, sizeof(buf2
));
8261 vty_out(vty
, " Imported from %s:%s, VNI %s\n", buf1
, buf2
, tag_buf
);
8263 vty_out(vty
, " Imported from %s:%s\n", buf1
, buf2
);
8270 /* Line1 display AS-path, Aggregator */
8273 if (!attr
->aspath
->json
)
8274 aspath_str_update(attr
->aspath
, true);
8275 json_object_lock(attr
->aspath
->json
);
8276 json_object_object_add(json_path
, "aspath",
8277 attr
->aspath
->json
);
8279 if (attr
->aspath
->segments
)
8280 aspath_print_vty(vty
, " %s", attr
->aspath
, "");
8282 vty_out(vty
, " Local");
8286 if (CHECK_FLAG(path
->flags
, BGP_PATH_REMOVED
)) {
8288 json_object_boolean_true_add(json_path
, "removed");
8290 vty_out(vty
, ", (removed)");
8293 if (CHECK_FLAG(path
->flags
, BGP_PATH_STALE
)) {
8295 json_object_boolean_true_add(json_path
, "stale");
8297 vty_out(vty
, ", (stale)");
8300 if (CHECK_FLAG(attr
->flag
, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR
))) {
8302 json_object_int_add(json_path
, "aggregatorAs",
8303 attr
->aggregator_as
);
8304 json_object_string_add(
8305 json_path
, "aggregatorId",
8306 inet_ntoa(attr
->aggregator_addr
));
8308 vty_out(vty
, ", (aggregated by %u %s)",
8309 attr
->aggregator_as
,
8310 inet_ntoa(attr
->aggregator_addr
));
8314 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8315 PEER_FLAG_REFLECTOR_CLIENT
)) {
8317 json_object_boolean_true_add(json_path
,
8318 "rxedFromRrClient");
8320 vty_out(vty
, ", (Received from a RR-client)");
8323 if (CHECK_FLAG(path
->peer
->af_flags
[afi
][safi
],
8324 PEER_FLAG_RSERVER_CLIENT
)) {
8326 json_object_boolean_true_add(json_path
,
8327 "rxedFromRsClient");
8329 vty_out(vty
, ", (Received from a RS-client)");
8332 if (CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8334 json_object_boolean_true_add(json_path
,
8335 "dampeningHistoryEntry");
8337 vty_out(vty
, ", (history entry)");
8338 } else if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)) {
8340 json_object_boolean_true_add(json_path
,
8341 "dampeningSuppressed");
8343 vty_out(vty
, ", (suppressed due to dampening)");
8349 /* Line2 display Next-hop, Neighbor, Router-id */
8350 /* Display the nexthop */
8351 if ((bn
->p
.family
== AF_INET
|| bn
->p
.family
== AF_ETHERNET
8352 || bn
->p
.family
== AF_EVPN
)
8353 && (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
|| safi
== SAFI_EVPN
8354 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8355 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
8356 || safi
== SAFI_EVPN
) {
8358 json_object_string_add(
8359 json_nexthop_global
,
8360 nexthop_fqdn
? "fqdn" : "ip",
8364 attr
->mp_nexthop_global_in
));
8370 attr
->mp_nexthop_global_in
));
8373 json_object_string_add(
8374 json_nexthop_global
,
8375 nexthop_fqdn
? "fqdn" : "ip",
8378 : inet_ntoa(attr
->nexthop
));
8383 : inet_ntoa(attr
->nexthop
));
8387 json_object_string_add(json_nexthop_global
, "afi",
8391 json_object_string_add(
8392 json_nexthop_global
,
8393 nexthop_fqdn
? "fqdn" : "ip",
8396 : inet_ntop(AF_INET6
,
8397 &attr
->mp_nexthop_global
,
8398 buf
, INET6_ADDRSTRLEN
));
8399 json_object_string_add(json_nexthop_global
, "afi",
8401 json_object_string_add(json_nexthop_global
, "scope",
8407 : inet_ntop(AF_INET6
,
8408 &attr
->mp_nexthop_global
,
8409 buf
, INET6_ADDRSTRLEN
));
8413 /* Display the IGP cost or 'inaccessible' */
8414 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8416 json_object_boolean_false_add(json_nexthop_global
,
8419 vty_out(vty
, " (inaccessible)");
8421 if (path
->extra
&& path
->extra
->igpmetric
) {
8423 json_object_int_add(json_nexthop_global
,
8425 path
->extra
->igpmetric
);
8427 vty_out(vty
, " (metric %u)",
8428 path
->extra
->igpmetric
);
8431 /* IGP cost is 0, display this only for json */
8434 json_object_int_add(json_nexthop_global
,
8439 json_object_boolean_true_add(json_nexthop_global
,
8443 /* Display peer "from" output */
8444 /* This path was originated locally */
8445 if (path
->peer
== bgp
->peer_self
) {
8447 if (safi
== SAFI_EVPN
8448 || (bn
->p
.family
== AF_INET
8449 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr
))) {
8451 json_object_string_add(json_peer
, "peerId",
8454 vty_out(vty
, " from 0.0.0.0 ");
8457 json_object_string_add(json_peer
, "peerId",
8460 vty_out(vty
, " from :: ");
8464 json_object_string_add(json_peer
, "routerId",
8465 inet_ntoa(bgp
->router_id
));
8467 vty_out(vty
, "(%s)", inet_ntoa(bgp
->router_id
));
8470 /* We RXed this path from one of our peers */
8474 json_object_string_add(json_peer
, "peerId",
8475 sockunion2str(&path
->peer
->su
,
8478 json_object_string_add(json_peer
, "routerId",
8480 &path
->peer
->remote_id
,
8481 buf1
, sizeof(buf1
)));
8483 if (path
->peer
->hostname
)
8484 json_object_string_add(json_peer
, "hostname",
8485 path
->peer
->hostname
);
8487 if (path
->peer
->domainname
)
8488 json_object_string_add(json_peer
, "domainname",
8489 path
->peer
->domainname
);
8491 if (path
->peer
->conf_if
)
8492 json_object_string_add(json_peer
, "interface",
8493 path
->peer
->conf_if
);
8495 if (path
->peer
->conf_if
) {
8496 if (path
->peer
->hostname
8497 && bgp_flag_check(path
->peer
->bgp
,
8498 BGP_FLAG_SHOW_HOSTNAME
))
8499 vty_out(vty
, " from %s(%s)",
8500 path
->peer
->hostname
,
8501 path
->peer
->conf_if
);
8503 vty_out(vty
, " from %s",
8504 path
->peer
->conf_if
);
8506 if (path
->peer
->hostname
8507 && bgp_flag_check(path
->peer
->bgp
,
8508 BGP_FLAG_SHOW_HOSTNAME
))
8509 vty_out(vty
, " from %s(%s)",
8510 path
->peer
->hostname
,
8513 vty_out(vty
, " from %s",
8514 sockunion2str(&path
->peer
->su
,
8519 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8520 vty_out(vty
, " (%s)",
8521 inet_ntoa(attr
->originator_id
));
8523 vty_out(vty
, " (%s)",
8525 &path
->peer
->remote_id
, buf1
,
8531 * Note when vrfid of nexthop is different from that of prefix
8533 if (path
->extra
&& path
->extra
->bgp_orig
) {
8534 vrf_id_t nexthop_vrfid
= path
->extra
->bgp_orig
->vrf_id
;
8539 if (path
->extra
->bgp_orig
->inst_type
8540 == BGP_INSTANCE_TYPE_DEFAULT
)
8541 vn
= VRF_DEFAULT_NAME
;
8543 vn
= path
->extra
->bgp_orig
->name
;
8545 json_object_string_add(json_path
, "nhVrfName", vn
);
8547 if (nexthop_vrfid
== VRF_UNKNOWN
) {
8548 json_object_int_add(json_path
, "nhVrfId", -1);
8550 json_object_int_add(json_path
, "nhVrfId",
8551 (int)nexthop_vrfid
);
8554 if (nexthop_vrfid
== VRF_UNKNOWN
)
8555 vty_out(vty
, " vrf ?");
8557 vty_out(vty
, " vrf %u", nexthop_vrfid
);
8563 json_object_boolean_true_add(json_path
,
8564 "announceNexthopSelf");
8566 vty_out(vty
, " announce-nh-self");
8573 /* display the link-local nexthop */
8574 if (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
) {
8576 json_nexthop_ll
= json_object_new_object();
8577 json_object_string_add(
8578 json_nexthop_ll
, nexthop_fqdn
? "fqdn" : "ip",
8581 : inet_ntop(AF_INET6
,
8582 &attr
->mp_nexthop_local
,
8583 buf
, INET6_ADDRSTRLEN
));
8584 json_object_string_add(json_nexthop_ll
, "afi", "ipv6");
8585 json_object_string_add(json_nexthop_ll
, "scope",
8588 json_object_boolean_true_add(json_nexthop_ll
,
8591 if (!attr
->mp_nexthop_prefer_global
)
8592 json_object_boolean_true_add(json_nexthop_ll
,
8595 json_object_boolean_true_add(
8596 json_nexthop_global
, "used");
8598 vty_out(vty
, " (%s) %s\n",
8599 inet_ntop(AF_INET6
, &attr
->mp_nexthop_local
,
8600 buf
, INET6_ADDRSTRLEN
),
8601 attr
->mp_nexthop_prefer_global
8606 /* If we do not have a link-local nexthop then we must flag the
8610 json_object_boolean_true_add(json_nexthop_global
,
8614 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
8615 * Int/Ext/Local, Atomic, best */
8617 json_object_string_add(json_path
, "origin",
8618 bgp_origin_long_str
[attr
->origin
]);
8620 vty_out(vty
, " Origin %s",
8621 bgp_origin_long_str
[attr
->origin
]);
8623 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
)) {
8626 * Adding "metric" field to match with
8627 * corresponding CLI. "med" will be
8628 * deprecated in future.
8630 json_object_int_add(json_path
, "med", attr
->med
);
8631 json_object_int_add(json_path
, "metric", attr
->med
);
8633 vty_out(vty
, ", metric %u", attr
->med
);
8636 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF
)) {
8638 json_object_int_add(json_path
, "localpref",
8641 vty_out(vty
, ", localpref %u", attr
->local_pref
);
8644 if (attr
->weight
!= 0) {
8646 json_object_int_add(json_path
, "weight", attr
->weight
);
8648 vty_out(vty
, ", weight %u", attr
->weight
);
8651 if (attr
->tag
!= 0) {
8653 json_object_int_add(json_path
, "tag", attr
->tag
);
8655 vty_out(vty
, ", tag %" ROUTE_TAG_PRI
, attr
->tag
);
8658 if (!CHECK_FLAG(path
->flags
, BGP_PATH_VALID
)) {
8660 json_object_boolean_false_add(json_path
, "valid");
8662 vty_out(vty
, ", invalid");
8663 } else if (!CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
)) {
8665 json_object_boolean_true_add(json_path
, "valid");
8667 vty_out(vty
, ", valid");
8670 if (path
->peer
!= bgp
->peer_self
) {
8671 if (path
->peer
->as
== path
->peer
->local_as
) {
8672 if (CHECK_FLAG(bgp
->config
, BGP_CONFIG_CONFEDERATION
)) {
8674 json_object_string_add(
8678 vty_out(vty
, ", confed-internal");
8681 json_object_string_add(
8682 json_peer
, "type", "internal");
8684 vty_out(vty
, ", internal");
8687 if (bgp_confederation_peers_check(bgp
,
8690 json_object_string_add(
8694 vty_out(vty
, ", confed-external");
8697 json_object_string_add(
8698 json_peer
, "type", "external");
8700 vty_out(vty
, ", external");
8703 } else if (path
->sub_type
== BGP_ROUTE_AGGREGATE
) {
8705 json_object_boolean_true_add(json_path
, "aggregated");
8706 json_object_boolean_true_add(json_path
, "local");
8708 vty_out(vty
, ", aggregated, local");
8710 } else if (path
->type
!= ZEBRA_ROUTE_BGP
) {
8712 json_object_boolean_true_add(json_path
, "sourced");
8714 vty_out(vty
, ", sourced");
8717 json_object_boolean_true_add(json_path
, "sourced");
8718 json_object_boolean_true_add(json_path
, "local");
8720 vty_out(vty
, ", sourced, local");
8724 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)) {
8726 json_object_boolean_true_add(json_path
,
8729 vty_out(vty
, ", atomic-aggregate");
8732 if (CHECK_FLAG(path
->flags
, BGP_PATH_MULTIPATH
)
8733 || (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)
8734 && bgp_path_info_mpath_count(path
))) {
8736 json_object_boolean_true_add(json_path
, "multipath");
8738 vty_out(vty
, ", multipath");
8741 // Mark the bestpath(s)
8742 if (CHECK_FLAG(path
->flags
, BGP_PATH_DMED_SELECTED
)) {
8743 first_as
= aspath_get_first_as(attr
->aspath
);
8747 json_bestpath
= json_object_new_object();
8748 json_object_int_add(json_bestpath
, "bestpathFromAs",
8752 vty_out(vty
, ", bestpath-from-AS %u", first_as
);
8754 vty_out(vty
, ", bestpath-from-AS Local");
8758 if (CHECK_FLAG(path
->flags
, BGP_PATH_SELECTED
)) {
8761 json_bestpath
= json_object_new_object();
8762 json_object_boolean_true_add(json_bestpath
, "overall");
8763 json_object_string_add(
8764 json_bestpath
, "selectionReason",
8765 bgp_path_selection_reason2str(bn
->reason
));
8767 vty_out(vty
, ", best");
8768 vty_out(vty
, " (%s)",
8769 bgp_path_selection_reason2str(bn
->reason
));
8774 json_object_object_add(json_path
, "bestpath", json_bestpath
);
8779 /* Line 4 display Community */
8780 if (attr
->community
) {
8782 if (!attr
->community
->json
)
8783 community_str(attr
->community
, true);
8784 json_object_lock(attr
->community
->json
);
8785 json_object_object_add(json_path
, "community",
8786 attr
->community
->json
);
8788 vty_out(vty
, " Community: %s\n",
8789 attr
->community
->str
);
8793 /* Line 5 display Extended-community */
8794 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
)) {
8796 json_ext_community
= json_object_new_object();
8797 json_object_string_add(json_ext_community
, "string",
8798 attr
->ecommunity
->str
);
8799 json_object_object_add(json_path
, "extendedCommunity",
8800 json_ext_community
);
8802 vty_out(vty
, " Extended Community: %s\n",
8803 attr
->ecommunity
->str
);
8807 /* Line 6 display Large community */
8808 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES
)) {
8810 if (!attr
->lcommunity
->json
)
8811 lcommunity_str(attr
->lcommunity
, true);
8812 json_object_lock(attr
->lcommunity
->json
);
8813 json_object_object_add(json_path
, "largeCommunity",
8814 attr
->lcommunity
->json
);
8816 vty_out(vty
, " Large Community: %s\n",
8817 attr
->lcommunity
->str
);
8821 /* Line 7 display Originator, Cluster-id */
8822 if ((attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
))
8823 || (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
))) {
8824 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID
)) {
8826 json_object_string_add(
8827 json_path
, "originatorId",
8828 inet_ntoa(attr
->originator_id
));
8830 vty_out(vty
, " Originator: %s",
8831 inet_ntoa(attr
->originator_id
));
8834 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST
)) {
8838 json_cluster_list
= json_object_new_object();
8839 json_cluster_list_list
=
8840 json_object_new_array();
8842 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8844 json_string
= json_object_new_string(
8845 inet_ntoa(attr
->cluster
8847 json_object_array_add(
8848 json_cluster_list_list
,
8853 * struct cluster_list does not have
8854 * "str" variable like aspath and community
8855 * do. Add this someday if someone asks
8857 * json_object_string_add(json_cluster_list,
8858 * "string", attr->cluster->str);
8860 json_object_object_add(json_cluster_list
,
8862 json_cluster_list_list
);
8863 json_object_object_add(json_path
, "clusterList",
8866 vty_out(vty
, ", Cluster list: ");
8868 for (i
= 0; i
< attr
->cluster
->length
/ 4;
8871 inet_ntoa(attr
->cluster
8881 if (path
->extra
&& path
->extra
->damp_info
)
8882 bgp_damp_info_vty(vty
, path
, json_path
);
8885 if (path
->extra
&& bgp_is_valid_label(&path
->extra
->label
[0])
8886 && (safi
!= SAFI_EVPN
&& !is_route_parent_evpn(path
))) {
8887 mpls_label_t label
= label_pton(&path
->extra
->label
[0]);
8890 json_object_int_add(json_path
, "remoteLabel", label
);
8892 vty_out(vty
, " Remote label: %d\n", label
);
8896 if (attr
->label_index
!= BGP_INVALID_LABEL_INDEX
) {
8898 json_object_int_add(json_path
, "labelIndex",
8901 vty_out(vty
, " Label Index: %d\n",
8905 /* Line 8 display Addpath IDs */
8906 if (path
->addpath_rx_id
8907 || bgp_addpath_info_has_ids(&path
->tx_addpath
)) {
8909 json_object_int_add(json_path
, "addpathRxId",
8910 path
->addpath_rx_id
);
8912 /* Keep backwards compatibility with the old API
8913 * by putting TX All's ID in the old field
8915 json_object_int_add(
8916 json_path
, "addpathTxId",
8918 .addpath_tx_id
[BGP_ADDPATH_ALL
]);
8920 /* ... but create a specific field for each
8923 for (i
= 0; i
< BGP_ADDPATH_MAX
; i
++) {
8924 json_object_int_add(
8926 bgp_addpath_names(i
)->id_json_name
,
8927 path
->tx_addpath
.addpath_tx_id
[i
]);
8930 vty_out(vty
, " AddPath ID: RX %u, ",
8931 path
->addpath_rx_id
);
8933 route_vty_out_tx_ids(vty
, &path
->tx_addpath
);
8937 /* If we used addpath to TX a non-bestpath we need to display
8938 * "Advertised to" on a path-by-path basis
8940 if (bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
8943 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
8945 bgp_addpath_encode_tx(peer
, afi
, safi
);
8946 has_adj
= bgp_adj_out_lookup(
8948 bgp_addpath_id_for_peer(peer
, afi
, safi
,
8949 &path
->tx_addpath
));
8951 if ((addpath_capable
&& has_adj
)
8952 || (!addpath_capable
&& has_adj
8953 && CHECK_FLAG(path
->flags
,
8954 BGP_PATH_SELECTED
))) {
8955 if (json_path
&& !json_adv_to
)
8956 json_adv_to
= json_object_new_object();
8958 route_vty_out_advertised_to(
8960 " Advertised to:", json_adv_to
);
8966 json_object_object_add(
8967 json_path
, "advertisedTo", json_adv_to
);
8976 /* Line 9 display Uptime */
8977 tbuf
= time(NULL
) - (bgp_clock() - path
->uptime
);
8979 json_last_update
= json_object_new_object();
8980 json_object_int_add(json_last_update
, "epoch", tbuf
);
8981 json_object_string_add(json_last_update
, "string",
8983 json_object_object_add(json_path
, "lastUpdate",
8986 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
8988 /* Line 10 display PMSI tunnel attribute, if present */
8989 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL
)) {
8991 lookup_msg(bgp_pmsi_tnltype_str
, attr
->pmsi_tnl_type
,
8992 PMSI_TNLTYPE_STR_DEFAULT
);
8995 json_pmsi
= json_object_new_object();
8996 json_object_string_add(json_pmsi
, "tunnelType", str
);
8997 json_object_int_add(json_pmsi
, "label",
8998 label2vni(&attr
->label
));
8999 json_object_object_add(json_path
, "pmsi", json_pmsi
);
9001 vty_out(vty
, " PMSI Tunnel Type: %s, label: %d\n",
9002 str
, label2vni(&attr
->label
));
9005 /* We've constructed the json object for this path, add it to the json
9009 if (json_nexthop_global
|| json_nexthop_ll
) {
9010 json_nexthops
= json_object_new_array();
9012 if (json_nexthop_global
)
9013 json_object_array_add(json_nexthops
,
9014 json_nexthop_global
);
9016 if (json_nexthop_ll
)
9017 json_object_array_add(json_nexthops
,
9020 json_object_object_add(json_path
, "nexthops",
9024 json_object_object_add(json_path
, "peer", json_peer
);
9025 json_object_array_add(json_paths
, json_path
);
9029 #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
9030 #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9031 #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
9033 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
9034 const char *prefix_list_str
, afi_t afi
,
9035 safi_t safi
, enum bgp_show_type type
);
9036 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
9037 const char *filter
, afi_t afi
, safi_t safi
,
9038 enum bgp_show_type type
);
9039 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
9040 const char *rmap_str
, afi_t afi
, safi_t safi
,
9041 enum bgp_show_type type
);
9042 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
9043 const char *com
, int exact
, afi_t afi
,
9045 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
9046 const char *prefix
, afi_t afi
, safi_t safi
,
9047 enum bgp_show_type type
);
9048 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
9049 afi_t afi
, safi_t safi
, enum bgp_show_type type
);
9050 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
9051 const char *comstr
, int exact
, afi_t afi
,
9052 safi_t safi
, bool use_json
);
9055 static int bgp_show_table(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9056 struct bgp_table
*table
, enum bgp_show_type type
,
9057 void *output_arg
, bool use_json
, char *rd
,
9058 int is_last
, unsigned long *output_cum
,
9059 unsigned long *total_cum
,
9060 unsigned long *json_header_depth
)
9062 struct bgp_path_info
*pi
;
9063 struct bgp_node
*rn
;
9066 unsigned long output_count
= 0;
9067 unsigned long total_count
= 0;
9070 json_object
*json_paths
= NULL
;
9073 if (output_cum
&& *output_cum
!= 0)
9076 if (use_json
&& !*json_header_depth
) {
9078 "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
9079 ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
9080 " \"localAS\": %u,\n \"routes\": { ",
9081 bgp
->vrf_id
== VRF_UNKNOWN
? -1 : (int)bgp
->vrf_id
,
9082 bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
9085 table
->version
, inet_ntoa(bgp
->router_id
),
9086 bgp
->default_local_pref
, bgp
->as
);
9087 *json_header_depth
= 2;
9089 vty_out(vty
, " \"routeDistinguishers\" : {");
9090 ++*json_header_depth
;
9094 if (use_json
&& rd
) {
9095 vty_out(vty
, " \"%s\" : { ", rd
);
9098 /* Start processing of routes. */
9099 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
9100 pi
= bgp_node_get_bgp_path_info(rn
);
9106 json_paths
= json_object_new_array();
9110 for (; pi
; pi
= pi
->next
) {
9112 if (type
== bgp_show_type_flap_statistics
9113 || type
== bgp_show_type_flap_neighbor
9114 || type
== bgp_show_type_dampend_paths
9115 || type
== bgp_show_type_damp_neighbor
) {
9116 if (!(pi
->extra
&& pi
->extra
->damp_info
))
9119 if (type
== bgp_show_type_regexp
) {
9120 regex_t
*regex
= output_arg
;
9122 if (bgp_regexec(regex
, pi
->attr
->aspath
)
9126 if (type
== bgp_show_type_prefix_list
) {
9127 struct prefix_list
*plist
= output_arg
;
9129 if (prefix_list_apply(plist
, &rn
->p
)
9133 if (type
== bgp_show_type_filter_list
) {
9134 struct as_list
*as_list
= output_arg
;
9136 if (as_list_apply(as_list
, pi
->attr
->aspath
)
9137 != AS_FILTER_PERMIT
)
9140 if (type
== bgp_show_type_route_map
) {
9141 struct route_map
*rmap
= output_arg
;
9142 struct bgp_path_info path
;
9143 struct attr dummy_attr
;
9144 route_map_result_t ret
;
9146 bgp_attr_dup(&dummy_attr
, pi
->attr
);
9148 path
.peer
= pi
->peer
;
9149 path
.attr
= &dummy_attr
;
9151 ret
= route_map_apply(rmap
, &rn
->p
, RMAP_BGP
,
9153 if (ret
== RMAP_DENYMATCH
)
9156 if (type
== bgp_show_type_neighbor
9157 || type
== bgp_show_type_flap_neighbor
9158 || type
== bgp_show_type_damp_neighbor
) {
9159 union sockunion
*su
= output_arg
;
9161 if (pi
->peer
== NULL
9162 || pi
->peer
->su_remote
== NULL
9163 || !sockunion_same(pi
->peer
->su_remote
, su
))
9166 if (type
== bgp_show_type_cidr_only
) {
9167 uint32_t destination
;
9169 destination
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
9170 if (IN_CLASSC(destination
)
9171 && rn
->p
.prefixlen
== 24)
9173 if (IN_CLASSB(destination
)
9174 && rn
->p
.prefixlen
== 16)
9176 if (IN_CLASSA(destination
)
9177 && rn
->p
.prefixlen
== 8)
9180 if (type
== bgp_show_type_prefix_longer
) {
9182 if (!prefix_match(p
, &rn
->p
))
9185 if (type
== bgp_show_type_community_all
) {
9186 if (!pi
->attr
->community
)
9189 if (type
== bgp_show_type_community
) {
9190 struct community
*com
= output_arg
;
9192 if (!pi
->attr
->community
9193 || !community_match(pi
->attr
->community
,
9197 if (type
== bgp_show_type_community_exact
) {
9198 struct community
*com
= output_arg
;
9200 if (!pi
->attr
->community
9201 || !community_cmp(pi
->attr
->community
, com
))
9204 if (type
== bgp_show_type_community_list
) {
9205 struct community_list
*list
= output_arg
;
9207 if (!community_list_match(pi
->attr
->community
,
9211 if (type
== bgp_show_type_community_list_exact
) {
9212 struct community_list
*list
= output_arg
;
9214 if (!community_list_exact_match(
9215 pi
->attr
->community
, list
))
9218 if (type
== bgp_show_type_lcommunity
) {
9219 struct lcommunity
*lcom
= output_arg
;
9221 if (!pi
->attr
->lcommunity
9222 || !lcommunity_match(pi
->attr
->lcommunity
,
9227 if (type
== bgp_show_type_lcommunity_exact
) {
9228 struct lcommunity
*lcom
= output_arg
;
9230 if (!pi
->attr
->lcommunity
9231 || !lcommunity_cmp(pi
->attr
->lcommunity
,
9235 if (type
== bgp_show_type_lcommunity_list
) {
9236 struct community_list
*list
= output_arg
;
9238 if (!lcommunity_list_match(pi
->attr
->lcommunity
,
9243 == bgp_show_type_lcommunity_list_exact
) {
9244 struct community_list
*list
= output_arg
;
9246 if (!lcommunity_list_exact_match(
9247 pi
->attr
->lcommunity
, list
))
9250 if (type
== bgp_show_type_lcommunity_all
) {
9251 if (!pi
->attr
->lcommunity
)
9254 if (type
== bgp_show_type_dampend_paths
9255 || type
== bgp_show_type_damp_neighbor
) {
9256 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
)
9257 || CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
9261 if (!use_json
&& header
) {
9262 vty_out(vty
, "BGP table version is %" PRIu64
9263 ", local router ID is %s, vrf id ",
9265 inet_ntoa(bgp
->router_id
));
9266 if (bgp
->vrf_id
== VRF_UNKNOWN
)
9267 vty_out(vty
, "%s", VRFID_NONE_STR
);
9269 vty_out(vty
, "%u", bgp
->vrf_id
);
9271 vty_out(vty
, "Default local pref %u, ",
9272 bgp
->default_local_pref
);
9273 vty_out(vty
, "local AS %u\n", bgp
->as
);
9274 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
9275 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
9276 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
9277 if (type
== bgp_show_type_dampend_paths
9278 || type
== bgp_show_type_damp_neighbor
)
9279 vty_out(vty
, BGP_SHOW_DAMP_HEADER
);
9280 else if (type
== bgp_show_type_flap_statistics
9281 || type
== bgp_show_type_flap_neighbor
)
9282 vty_out(vty
, BGP_SHOW_FLAP_HEADER
);
9284 vty_out(vty
, BGP_SHOW_HEADER
);
9287 if (rd
!= NULL
&& !display
&& !output_count
) {
9290 "Route Distinguisher: %s\n",
9293 if (type
== bgp_show_type_dampend_paths
9294 || type
== bgp_show_type_damp_neighbor
)
9295 damp_route_vty_out(vty
, &rn
->p
, pi
, display
,
9296 safi
, use_json
, json_paths
);
9297 else if (type
== bgp_show_type_flap_statistics
9298 || type
== bgp_show_type_flap_neighbor
)
9299 flap_route_vty_out(vty
, &rn
->p
, pi
, display
,
9300 safi
, use_json
, json_paths
);
9302 route_vty_out(vty
, &rn
->p
, pi
, display
, safi
,
9314 if (p
->family
== AF_FLOWSPEC
) {
9315 char retstr
[BGP_FLOWSPEC_STRING_DISPLAY_MAX
];
9317 bgp_fs_nlri_get_string((unsigned char *)
9318 p
->u
.prefix_flowspec
.ptr
,
9319 p
->u
.prefix_flowspec
9322 NLRI_STRING_FORMAT_MIN
,
9325 vty_out(vty
, "\"%s/%d\": ",
9327 p
->u
.prefix_flowspec
.prefixlen
);
9329 vty_out(vty
, ",\"%s/%d\": ",
9331 p
->u
.prefix_flowspec
.prefixlen
);
9333 prefix2str(p
, buf2
, sizeof(buf2
));
9335 vty_out(vty
, "\"%s\": ", buf2
);
9337 vty_out(vty
, ",\"%s\": ", buf2
);
9340 json_object_to_json_string(json_paths
));
9341 json_object_free(json_paths
);
9348 output_count
+= *output_cum
;
9349 *output_cum
= output_count
;
9352 total_count
+= *total_cum
;
9353 *total_cum
= total_count
;
9357 vty_out(vty
, " }%s ", (is_last
? "" : ","));
9361 for (i
= 0; i
< *json_header_depth
; ++i
)
9362 vty_out(vty
, " } ");
9367 /* No route is displayed */
9368 if (output_count
== 0) {
9369 if (type
== bgp_show_type_normal
)
9371 "No BGP prefixes displayed, %ld exist\n",
9375 "\nDisplayed %ld routes and %ld total paths\n",
9376 output_count
, total_count
);
9383 int bgp_show_table_rd(struct vty
*vty
, struct bgp
*bgp
, safi_t safi
,
9384 struct bgp_table
*table
, struct prefix_rd
*prd_match
,
9385 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9387 struct bgp_node
*rn
, *next
;
9388 unsigned long output_cum
= 0;
9389 unsigned long total_cum
= 0;
9390 unsigned long json_header_depth
= 0;
9391 struct bgp_table
*itable
;
9394 show_msg
= (!use_json
&& type
== bgp_show_type_normal
);
9396 for (rn
= bgp_table_top(table
); rn
; rn
= next
) {
9397 next
= bgp_route_next(rn
);
9398 if (prd_match
&& memcmp(rn
->p
.u
.val
, prd_match
->val
, 8) != 0)
9401 itable
= bgp_node_get_bgp_table_info(rn
);
9402 if (itable
!= NULL
) {
9403 struct prefix_rd prd
;
9404 char rd
[RD_ADDRSTRLEN
];
9406 memcpy(&prd
, &(rn
->p
), sizeof(struct prefix_rd
));
9407 prefix_rd2str(&prd
, rd
, sizeof(rd
));
9408 bgp_show_table(vty
, bgp
, safi
, itable
, type
, output_arg
,
9409 use_json
, rd
, next
== NULL
, &output_cum
,
9410 &total_cum
, &json_header_depth
);
9416 if (output_cum
== 0)
9417 vty_out(vty
, "No BGP prefixes displayed, %ld exist\n",
9421 "\nDisplayed %ld routes and %ld total paths\n",
9422 output_cum
, total_cum
);
9426 static int bgp_show(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
, safi_t safi
,
9427 enum bgp_show_type type
, void *output_arg
, bool use_json
)
9429 struct bgp_table
*table
;
9430 unsigned long json_header_depth
= 0;
9433 bgp
= bgp_get_default();
9438 vty_out(vty
, "No BGP process is configured\n");
9440 vty_out(vty
, "{}\n");
9444 table
= bgp
->rib
[afi
][safi
];
9445 /* use MPLS and ENCAP specific shows until they are merged */
9446 if (safi
== SAFI_MPLS_VPN
) {
9447 return bgp_show_table_rd(vty
, bgp
, safi
, table
, NULL
, type
,
9448 output_arg
, use_json
);
9451 if (safi
== SAFI_FLOWSPEC
&& type
== bgp_show_type_detail
) {
9452 return bgp_show_table_flowspec(vty
, bgp
, afi
, table
, type
,
9453 output_arg
, use_json
,
9456 /* labeled-unicast routes live in the unicast table */
9457 else if (safi
== SAFI_LABELED_UNICAST
)
9458 safi
= SAFI_UNICAST
;
9460 return bgp_show_table(vty
, bgp
, safi
, table
, type
, output_arg
, use_json
,
9461 NULL
, 1, NULL
, NULL
, &json_header_depth
);
9464 static void bgp_show_all_instances_routes_vty(struct vty
*vty
, afi_t afi
,
9465 safi_t safi
, bool use_json
)
9467 struct listnode
*node
, *nnode
;
9470 bool route_output
= false;
9473 vty_out(vty
, "{\n");
9475 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
9476 route_output
= true;
9479 vty_out(vty
, ",\n");
9483 vty_out(vty
, "\"%s\":",
9484 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9488 vty_out(vty
, "\nInstance %s:\n",
9489 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9493 bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_normal
, NULL
,
9498 vty_out(vty
, "}\n");
9499 else if (!route_output
)
9500 vty_out(vty
, "%% BGP instance not found\n");
9503 /* Header of detailed BGP route information */
9504 void route_vty_out_detail_header(struct vty
*vty
, struct bgp
*bgp
,
9505 struct bgp_node
*rn
, struct prefix_rd
*prd
,
9506 afi_t afi
, safi_t safi
, json_object
*json
)
9508 struct bgp_path_info
*pi
;
9511 struct listnode
*node
, *nnode
;
9512 char buf1
[RD_ADDRSTRLEN
];
9513 char buf2
[INET6_ADDRSTRLEN
];
9514 char buf3
[EVPN_ROUTE_STRLEN
];
9515 char prefix_str
[BUFSIZ
];
9520 int route_filter_translated_v4
= 0;
9521 int route_filter_v4
= 0;
9522 int route_filter_translated_v6
= 0;
9523 int route_filter_v6
= 0;
9526 int accept_own_nexthop
= 0;
9529 int no_advertise
= 0;
9533 int has_valid_label
= 0;
9534 mpls_label_t label
= 0;
9535 json_object
*json_adv_to
= NULL
;
9538 has_valid_label
= bgp_is_valid_label(&rn
->local_label
);
9540 if (has_valid_label
)
9541 label
= label_pton(&rn
->local_label
);
9543 if (safi
== SAFI_EVPN
) {
9546 vty_out(vty
, "BGP routing table entry for %s%s%s\n",
9547 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
))
9548 : "", prd
? ":" : "",
9549 bgp_evpn_route2str((struct prefix_evpn
*)p
,
9550 buf3
, sizeof(buf3
)));
9552 json_object_string_add(json
, "rd",
9553 prd
? prefix_rd2str(prd
, buf1
, sizeof(buf1
)) :
9555 bgp_evpn_route2json((struct prefix_evpn
*)p
, json
);
9559 vty_out(vty
, "BGP routing table entry for %s%s%s/%d\n",
9560 ((safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
)
9561 ? prefix_rd2str(prd
, buf1
,
9564 safi
== SAFI_MPLS_VPN
? ":" : "",
9565 inet_ntop(p
->family
, &p
->u
.prefix
, buf2
,
9570 json_object_string_add(json
, "prefix",
9571 prefix2str(p
, prefix_str
, sizeof(prefix_str
)));
9574 if (has_valid_label
) {
9576 json_object_int_add(json
, "localLabel", label
);
9578 vty_out(vty
, "Local label: %d\n", label
);
9582 if (bgp_labeled_safi(safi
) && safi
!= SAFI_EVPN
)
9583 vty_out(vty
, "not allocated\n");
9585 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
9587 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)) {
9589 if (pi
->extra
&& pi
->extra
->suppress
)
9592 if (pi
->attr
->community
== NULL
)
9595 no_advertise
+= community_include(
9596 pi
->attr
->community
, COMMUNITY_NO_ADVERTISE
);
9597 no_export
+= community_include(pi
->attr
->community
,
9598 COMMUNITY_NO_EXPORT
);
9599 local_as
+= community_include(pi
->attr
->community
,
9600 COMMUNITY_LOCAL_AS
);
9601 accept_own
+= community_include(pi
->attr
->community
,
9602 COMMUNITY_ACCEPT_OWN
);
9603 route_filter_translated_v4
+= community_include(
9604 pi
->attr
->community
,
9605 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4
);
9606 route_filter_translated_v6
+= community_include(
9607 pi
->attr
->community
,
9608 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6
);
9609 route_filter_v4
+= community_include(
9610 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v4
);
9611 route_filter_v6
+= community_include(
9612 pi
->attr
->community
, COMMUNITY_ROUTE_FILTER_v6
);
9613 llgr_stale
+= community_include(pi
->attr
->community
,
9614 COMMUNITY_LLGR_STALE
);
9615 no_llgr
+= community_include(pi
->attr
->community
,
9617 accept_own_nexthop
+=
9618 community_include(pi
->attr
->community
,
9619 COMMUNITY_ACCEPT_OWN_NEXTHOP
);
9620 blackhole
+= community_include(pi
->attr
->community
,
9621 COMMUNITY_BLACKHOLE
);
9622 no_peer
+= community_include(pi
->attr
->community
,
9628 vty_out(vty
, "Paths: (%d available", count
);
9630 vty_out(vty
, ", best #%d", best
);
9631 if (safi
== SAFI_UNICAST
) {
9632 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
9633 vty_out(vty
, ", table %s",
9636 vty_out(vty
, ", vrf %s",
9640 vty_out(vty
, ", no best path");
9644 ", accept own local route exported and imported in different VRF");
9645 else if (route_filter_translated_v4
)
9647 ", mark translated RTs for VPNv4 route filtering");
9648 else if (route_filter_v4
)
9650 ", attach RT as-is for VPNv4 route filtering");
9651 else if (route_filter_translated_v6
)
9653 ", mark translated RTs for VPNv6 route filtering");
9654 else if (route_filter_v6
)
9656 ", attach RT as-is for VPNv6 route filtering");
9657 else if (llgr_stale
)
9659 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
9662 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
9663 else if (accept_own_nexthop
)
9665 ", accept local nexthop");
9667 vty_out(vty
, ", inform peer to blackhole prefix");
9669 vty_out(vty
, ", not advertised to EBGP peer");
9670 else if (no_advertise
)
9671 vty_out(vty
, ", not advertised to any peer");
9673 vty_out(vty
, ", not advertised outside local AS");
9676 ", inform EBGP peer not to advertise to their EBGP peers");
9680 ", Advertisements suppressed by an aggregate.");
9681 vty_out(vty
, ")\n");
9684 /* If we are not using addpath then we can display Advertised to and
9686 * show what peers we advertised the bestpath to. If we are using
9688 * though then we must display Advertised to on a path-by-path basis. */
9689 if (!bgp_addpath_is_addpath_used(&bgp
->tx_addpath
, afi
, safi
)) {
9690 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
9691 if (bgp_adj_out_lookup(peer
, rn
, 0)) {
9692 if (json
&& !json_adv_to
)
9693 json_adv_to
= json_object_new_object();
9695 route_vty_out_advertised_to(
9697 " Advertised to non peer-group peers:\n ",
9704 json_object_object_add(json
, "advertisedTo",
9709 vty_out(vty
, " Not advertised to any peer");
9715 static void bgp_show_path_info(struct prefix_rd
*pfx_rd
,
9716 struct bgp_node
*bgp_node
, struct vty
*vty
,
9717 struct bgp
*bgp
, afi_t afi
,
9718 safi_t safi
, json_object
*json
,
9719 enum bgp_path_type pathtype
, int *display
)
9721 struct bgp_path_info
*pi
;
9723 char rdbuf
[RD_ADDRSTRLEN
];
9724 json_object
*json_header
= NULL
;
9725 json_object
*json_paths
= NULL
;
9727 for (pi
= bgp_node_get_bgp_path_info(bgp_node
); pi
;
9730 if (json
&& !json_paths
) {
9731 /* Instantiate json_paths only if path is valid */
9732 json_paths
= json_object_new_array();
9734 prefix_rd2str(pfx_rd
, rdbuf
, sizeof(rdbuf
));
9735 json_header
= json_object_new_object();
9741 route_vty_out_detail_header(
9742 vty
, bgp
, bgp_node
, pfx_rd
,
9743 AFI_IP
, safi
, json_header
);
9748 if (pathtype
== BGP_PATH_SHOW_ALL
9749 || (pathtype
== BGP_PATH_SHOW_BESTPATH
9750 && CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))
9751 || (pathtype
== BGP_PATH_SHOW_MULTIPATH
9752 && (CHECK_FLAG(pi
->flags
, BGP_PATH_MULTIPATH
)
9753 || CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
))))
9754 route_vty_out_detail(vty
, bgp
, bgp_node
,
9759 if (json
&& json_paths
) {
9760 json_object_object_add(json_header
, "paths", json_paths
);
9763 json_object_object_add(json
, rdbuf
, json_header
);
9767 /* Display specified route of BGP table. */
9768 static int bgp_show_route_in_table(struct vty
*vty
, struct bgp
*bgp
,
9769 struct bgp_table
*rib
, const char *ip_str
,
9770 afi_t afi
, safi_t safi
,
9771 struct prefix_rd
*prd
, int prefix_check
,
9772 enum bgp_path_type pathtype
, bool use_json
)
9776 struct prefix match
;
9777 struct bgp_node
*rn
;
9778 struct bgp_node
*rm
;
9779 struct bgp_table
*table
;
9780 json_object
*json
= NULL
;
9781 json_object
*json_paths
= NULL
;
9783 /* Check IP address argument. */
9784 ret
= str2prefix(ip_str
, &match
);
9786 vty_out(vty
, "address is malformed\n");
9790 match
.family
= afi2family(afi
);
9793 json
= json_object_new_object();
9795 if (safi
== SAFI_MPLS_VPN
|| safi
== SAFI_ENCAP
) {
9796 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9797 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9799 table
= bgp_node_get_bgp_table_info(rn
);
9803 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
9807 && rm
->p
.prefixlen
!= match
.prefixlen
) {
9808 bgp_unlock_node(rm
);
9812 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9813 vty
, bgp
, afi
, safi
, json
,
9814 pathtype
, &display
);
9816 bgp_unlock_node(rm
);
9818 } else if (safi
== SAFI_EVPN
) {
9819 struct bgp_node
*longest_pfx
;
9820 bool is_exact_pfxlen_match
= FALSE
;
9822 for (rn
= bgp_table_top(rib
); rn
; rn
= bgp_route_next(rn
)) {
9823 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
9825 table
= bgp_node_get_bgp_table_info(rn
);
9830 is_exact_pfxlen_match
= FALSE
;
9832 * Search through all the prefixes for a match. The
9833 * pfx's are enumerated in ascending order of pfxlens.
9834 * So, the last pfx match is the longest match. Set
9835 * is_exact_pfxlen_match when we get exact pfxlen match
9837 for (rm
= bgp_table_top(table
); rm
;
9838 rm
= bgp_route_next(rm
)) {
9840 * Get prefixlen of the ip-prefix within type5
9843 if (evpn_type5_prefix_match(&rm
->p
,
9844 &match
) && rm
->info
) {
9847 bgp_evpn_get_type5_prefixlen(&rm
->p
);
9848 if (type5_pfxlen
== match
.prefixlen
) {
9849 is_exact_pfxlen_match
= TRUE
;
9850 bgp_unlock_node(rm
);
9859 if (prefix_check
&& !is_exact_pfxlen_match
)
9865 bgp_show_path_info((struct prefix_rd
*)&rn
->p
, rm
,
9866 vty
, bgp
, afi
, safi
, json
,
9867 pathtype
, &display
);
9869 bgp_unlock_node(rm
);
9871 } else if (safi
== SAFI_FLOWSPEC
) {
9873 json_paths
= json_object_new_array();
9875 display
= bgp_flowspec_display_match_per_ip(afi
, rib
,
9876 &match
, prefix_check
,
9880 if (use_json
&& display
)
9881 json_object_object_add(json
, "paths", json_paths
);
9883 if ((rn
= bgp_node_match(rib
, &match
)) != NULL
) {
9885 || rn
->p
.prefixlen
== match
.prefixlen
) {
9886 bgp_show_path_info(NULL
, rn
, vty
, bgp
, afi
,
9888 pathtype
, &display
);
9891 bgp_unlock_node(rn
);
9896 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9897 json
, JSON_C_TO_STRING_PRETTY
|
9898 JSON_C_TO_STRING_NOSLASHESCAPE
));
9899 json_object_free(json
);
9902 vty_out(vty
, "%% Network not in table\n");
9910 /* Display specified route of Main RIB */
9911 static int bgp_show_route(struct vty
*vty
, struct bgp
*bgp
, const char *ip_str
,
9912 afi_t afi
, safi_t safi
, struct prefix_rd
*prd
,
9913 int prefix_check
, enum bgp_path_type pathtype
,
9917 bgp
= bgp_get_default();
9920 vty_out(vty
, "No BGP process is configured\n");
9922 vty_out(vty
, "{}\n");
9927 /* labeled-unicast routes live in the unicast table */
9928 if (safi
== SAFI_LABELED_UNICAST
)
9929 safi
= SAFI_UNICAST
;
9931 return bgp_show_route_in_table(vty
, bgp
, bgp
->rib
[afi
][safi
], ip_str
,
9932 afi
, safi
, prd
, prefix_check
, pathtype
,
9936 static int bgp_show_lcommunity(struct vty
*vty
, struct bgp
*bgp
, int argc
,
9937 struct cmd_token
**argv
, bool exact
, afi_t afi
,
9938 safi_t safi
, bool uj
)
9940 struct lcommunity
*lcom
;
9946 b
= buffer_new(1024);
9947 for (i
= 0; i
< argc
; i
++) {
9949 buffer_putc(b
, ' ');
9951 if (strmatch(argv
[i
]->text
, "AA:BB:CC")) {
9953 buffer_putstr(b
, argv
[i
]->arg
);
9957 buffer_putc(b
, '\0');
9959 str
= buffer_getstr(b
);
9962 lcom
= lcommunity_str2com(str
);
9963 XFREE(MTYPE_TMP
, str
);
9965 vty_out(vty
, "%% Large-community malformed\n");
9969 return bgp_show(vty
, bgp
, afi
, safi
,
9970 (exact
? bgp_show_type_lcommunity_exact
9971 : bgp_show_type_lcommunity
),
9975 static int bgp_show_lcommunity_list(struct vty
*vty
, struct bgp
*bgp
,
9976 const char *lcom
, bool exact
, afi_t afi
,
9977 safi_t safi
, bool uj
)
9979 struct community_list
*list
;
9981 list
= community_list_lookup(bgp_clist
, lcom
, 0,
9982 LARGE_COMMUNITY_LIST_MASTER
);
9984 vty_out(vty
, "%% %s is not a valid large-community-list name\n",
9989 return bgp_show(vty
, bgp
, afi
, safi
,
9990 (exact
? bgp_show_type_lcommunity_list_exact
9991 : bgp_show_type_lcommunity_list
),
9995 DEFUN (show_ip_bgp_large_community_list
,
9996 show_ip_bgp_large_community_list_cmd
,
9997 "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]",
10001 BGP_INSTANCE_HELP_STR
10003 BGP_SAFI_WITH_LABEL_HELP_STR
10004 "Display routes matching the large-community-list\n"
10005 "large-community-list number\n"
10006 "large-community-list name\n"
10007 "Exact match of the large-communities\n"
10011 afi_t afi
= AFI_IP6
;
10012 safi_t safi
= SAFI_UNICAST
;
10014 bool exact_match
= 0;
10016 if (argv_find(argv
, argc
, "ip", &idx
))
10018 if (argv_find(argv
, argc
, "view", &idx
)
10019 || argv_find(argv
, argc
, "vrf", &idx
))
10020 vrf
= argv
[++idx
]->arg
;
10021 if (argv_find(argv
, argc
, "ipv4", &idx
)
10022 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10023 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10024 if (argv_find(argv
, argc
, "unicast", &idx
)
10025 || argv_find(argv
, argc
, "multicast", &idx
))
10026 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10029 bool uj
= use_json(argc
, argv
);
10031 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10033 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10034 return CMD_WARNING
;
10037 argv_find(argv
, argc
, "large-community-list", &idx
);
10039 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10041 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10044 return bgp_show_lcommunity_list(vty
, bgp
, clist_number_or_name
,
10045 exact_match
, afi
, safi
, uj
);
10047 DEFUN (show_ip_bgp_large_community
,
10048 show_ip_bgp_large_community_cmd
,
10049 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] large-community [<AA:BB:CC> [exact-match]] [json]",
10053 BGP_INSTANCE_HELP_STR
10055 BGP_SAFI_WITH_LABEL_HELP_STR
10056 "Display routes matching the large-communities\n"
10057 "List of large-community numbers\n"
10058 "Exact match of the large-communities\n"
10062 afi_t afi
= AFI_IP6
;
10063 safi_t safi
= SAFI_UNICAST
;
10065 bool exact_match
= 0;
10067 if (argv_find(argv
, argc
, "ip", &idx
))
10069 if (argv_find(argv
, argc
, "view", &idx
)
10070 || argv_find(argv
, argc
, "vrf", &idx
))
10071 vrf
= argv
[++idx
]->arg
;
10072 if (argv_find(argv
, argc
, "ipv4", &idx
)
10073 || argv_find(argv
, argc
, "ipv6", &idx
)) {
10074 afi
= strmatch(argv
[idx
]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
10075 if (argv_find(argv
, argc
, "unicast", &idx
)
10076 || argv_find(argv
, argc
, "multicast", &idx
))
10077 safi
= bgp_vty_safi_from_str(argv
[idx
]->text
);
10080 bool uj
= use_json(argc
, argv
);
10082 struct bgp
*bgp
= bgp_lookup_by_name(vrf
);
10084 vty_out(vty
, "Can't find BGP instance %s\n", vrf
);
10085 return CMD_WARNING
;
10088 if (argv_find(argv
, argc
, "AA:BB:CC", &idx
)) {
10089 if (argv_find(argv
, argc
, "exact-match", &idx
))
10091 return bgp_show_lcommunity(vty
, bgp
, argc
, argv
,
10092 exact_match
, afi
, safi
, uj
);
10094 return bgp_show(vty
, bgp
, afi
, safi
,
10095 bgp_show_type_lcommunity_all
, NULL
, uj
);
10098 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10102 /* BGP route print out function without JSON */
10103 DEFUN (show_ip_bgp
,
10105 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10106 <dampening <parameters>\
10111 |community-list <(1-500)|WORD> [exact-match]\
10112 |A.B.C.D/M longer-prefixes\
10113 |X:X::X:X/M longer-prefixes\
10118 BGP_INSTANCE_HELP_STR
10120 BGP_SAFI_WITH_LABEL_HELP_STR
10121 "Display detailed information about dampening\n"
10122 "Display detail of configured dampening parameters\n"
10123 "Display routes matching the route-map\n"
10124 "A route-map to match on\n"
10125 "Display routes conforming to the prefix-list\n"
10126 "Prefix-list name\n"
10127 "Display routes conforming to the filter-list\n"
10128 "Regular expression access list name\n"
10129 "BGP RIB advertisement statistics\n"
10130 "Display routes matching the community-list\n"
10131 "community-list number\n"
10132 "community-list name\n"
10133 "Exact match of the communities\n"
10135 "Display route and more specific routes\n"
10137 "Display route and more specific routes\n")
10139 afi_t afi
= AFI_IP6
;
10140 safi_t safi
= SAFI_UNICAST
;
10141 int exact_match
= 0;
10142 struct bgp
*bgp
= NULL
;
10145 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10148 return CMD_WARNING
;
10150 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10151 if (argv_find(argv
, argc
, "parameters", &idx
))
10152 return bgp_show_dampening_parameters(vty
, afi
, safi
);
10155 if (argv_find(argv
, argc
, "prefix-list", &idx
))
10156 return bgp_show_prefix_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10157 safi
, bgp_show_type_prefix_list
);
10159 if (argv_find(argv
, argc
, "filter-list", &idx
))
10160 return bgp_show_filter_list(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10161 safi
, bgp_show_type_filter_list
);
10163 if (argv_find(argv
, argc
, "statistics", &idx
))
10164 return bgp_table_stats(vty
, bgp
, afi
, safi
);
10166 if (argv_find(argv
, argc
, "route-map", &idx
))
10167 return bgp_show_route_map(vty
, bgp
, argv
[idx
+ 1]->arg
, afi
,
10168 safi
, bgp_show_type_route_map
);
10170 if (argv_find(argv
, argc
, "community-list", &idx
)) {
10171 const char *clist_number_or_name
= argv
[++idx
]->arg
;
10172 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
10174 return bgp_show_community_list(vty
, bgp
, clist_number_or_name
,
10175 exact_match
, afi
, safi
);
10177 /* prefix-longer */
10178 if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10179 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10180 return bgp_show_prefix_longer(vty
, bgp
, argv
[idx
]->arg
, afi
,
10182 bgp_show_type_prefix_longer
);
10184 return CMD_WARNING
;
10187 /* BGP route print out function with JSON */
10188 DEFUN (show_ip_bgp_json
,
10189 show_ip_bgp_json_cmd
,
10190 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
10192 |dampening <flap-statistics|dampened-paths>\
10193 |community [AA:NN|local-AS|no-advertise|no-export\
10194 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
10195 |accept-own|accept-own-nexthop|route-filter-v6\
10196 |route-filter-v4|route-filter-translated-v6\
10197 |route-filter-translated-v4] [exact-match]\
10202 BGP_INSTANCE_HELP_STR
10204 BGP_SAFI_WITH_LABEL_HELP_STR
10205 "Display only routes with non-natural netmasks\n"
10206 "Display detailed information about dampening\n"
10207 "Display flap statistics of routes\n"
10208 "Display paths suppressed due to dampening\n"
10209 "Display routes matching the communities\n"
10211 "Do not send outside local AS (well-known community)\n"
10212 "Do not advertise to any peer (well-known community)\n"
10213 "Do not export to next AS (well-known community)\n"
10214 "Graceful shutdown (well-known community)\n"
10215 "Do not export to any peer (well-known community)\n"
10216 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
10217 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
10218 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
10219 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
10220 "Should accept VPN route with local nexthop (well-known community)\n"
10221 "RT VPNv6 route filtering (well-known community)\n"
10222 "RT VPNv4 route filtering (well-known community)\n"
10223 "RT translated VPNv6 route filtering (well-known community)\n"
10224 "RT translated VPNv4 route filtering (well-known community)\n"
10225 "Exact match of the communities\n"
10228 afi_t afi
= AFI_IP6
;
10229 safi_t safi
= SAFI_UNICAST
;
10230 enum bgp_show_type sh_type
= bgp_show_type_normal
;
10231 struct bgp
*bgp
= NULL
;
10233 int exact_match
= 0;
10234 bool uj
= use_json(argc
, argv
);
10239 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10242 return CMD_WARNING
;
10244 if (argv_find(argv
, argc
, "cidr-only", &idx
))
10245 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_cidr_only
,
10248 if (argv_find(argv
, argc
, "dampening", &idx
)) {
10249 if (argv_find(argv
, argc
, "dampened-paths", &idx
))
10250 return bgp_show(vty
, bgp
, afi
, safi
,
10251 bgp_show_type_dampend_paths
, NULL
, uj
);
10252 else if (argv_find(argv
, argc
, "flap-statistics", &idx
))
10253 return bgp_show(vty
, bgp
, afi
, safi
,
10254 bgp_show_type_flap_statistics
, NULL
,
10258 if (argv_find(argv
, argc
, "community", &idx
)) {
10259 char *maybecomm
= NULL
;
10260 char *community
= NULL
;
10262 if (idx
+ 1 < argc
) {
10263 if (argv
[idx
+ 1]->type
== VARIABLE_TKN
)
10264 maybecomm
= argv
[idx
+ 1]->arg
;
10266 maybecomm
= argv
[idx
+ 1]->text
;
10269 if (maybecomm
&& !strmatch(maybecomm
, "json")
10270 && !strmatch(maybecomm
, "exact-match"))
10271 community
= maybecomm
;
10273 if (argv_find(argv
, argc
, "exact-match", &idx
))
10277 return bgp_show_community(vty
, bgp
, community
,
10278 exact_match
, afi
, safi
, uj
);
10280 return (bgp_show(vty
, bgp
, afi
, safi
,
10281 bgp_show_type_community_all
, NULL
,
10285 return bgp_show(vty
, bgp
, afi
, safi
, sh_type
, NULL
, uj
);
10288 DEFUN (show_ip_bgp_route
,
10289 show_ip_bgp_route_cmd
,
10290 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]]"
10291 "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]",
10295 BGP_INSTANCE_HELP_STR
10297 BGP_SAFI_WITH_LABEL_HELP_STR
10298 "Network in the BGP routing table to display\n"
10300 "Network in the BGP routing table to display\n"
10302 "Display only the bestpath\n"
10303 "Display only multipaths\n"
10306 int prefix_check
= 0;
10308 afi_t afi
= AFI_IP6
;
10309 safi_t safi
= SAFI_UNICAST
;
10310 char *prefix
= NULL
;
10311 struct bgp
*bgp
= NULL
;
10312 enum bgp_path_type path_type
;
10313 bool uj
= use_json(argc
, argv
);
10317 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10320 return CMD_WARNING
;
10324 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
10325 return CMD_WARNING
;
10328 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
10329 if (argv_find(argv
, argc
, "A.B.C.D", &idx
)
10330 || argv_find(argv
, argc
, "X:X::X:X", &idx
))
10332 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
)
10333 || argv_find(argv
, argc
, "X:X::X:X/M", &idx
))
10336 if ((argv
[idx
]->type
== IPV6_TKN
|| argv
[idx
]->type
== IPV6_PREFIX_TKN
)
10337 && afi
!= AFI_IP6
) {
10339 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
10340 return CMD_WARNING
;
10342 if ((argv
[idx
]->type
== IPV4_TKN
|| argv
[idx
]->type
== IPV4_PREFIX_TKN
)
10343 && afi
!= AFI_IP
) {
10345 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
10346 return CMD_WARNING
;
10349 prefix
= argv
[idx
]->arg
;
10351 /* [<bestpath|multipath>] */
10352 if (argv_find(argv
, argc
, "bestpath", &idx
))
10353 path_type
= BGP_PATH_SHOW_BESTPATH
;
10354 else if (argv_find(argv
, argc
, "multipath", &idx
))
10355 path_type
= BGP_PATH_SHOW_MULTIPATH
;
10357 path_type
= BGP_PATH_SHOW_ALL
;
10359 return bgp_show_route(vty
, bgp
, prefix
, afi
, safi
, NULL
, prefix_check
,
10363 DEFUN (show_ip_bgp_regexp
,
10364 show_ip_bgp_regexp_cmd
,
10365 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] regexp REGEX...",
10369 BGP_INSTANCE_HELP_STR
10371 BGP_SAFI_WITH_LABEL_HELP_STR
10372 "Display routes matching the AS path regular expression\n"
10373 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
10375 afi_t afi
= AFI_IP6
;
10376 safi_t safi
= SAFI_UNICAST
;
10377 struct bgp
*bgp
= NULL
;
10380 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10383 return CMD_WARNING
;
10385 // get index of regex
10386 argv_find(argv
, argc
, "regexp", &idx
);
10389 char *regstr
= argv_concat(argv
, argc
, idx
);
10390 int rc
= bgp_show_regexp(vty
, bgp
, (const char *)regstr
, afi
, safi
,
10391 bgp_show_type_regexp
);
10392 XFREE(MTYPE_TMP
, regstr
);
10396 DEFUN (show_ip_bgp_instance_all
,
10397 show_ip_bgp_instance_all_cmd
,
10398 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] [json]",
10402 BGP_INSTANCE_ALL_HELP_STR
10404 BGP_SAFI_WITH_LABEL_HELP_STR
10407 afi_t afi
= AFI_IP
;
10408 safi_t safi
= SAFI_UNICAST
;
10409 struct bgp
*bgp
= NULL
;
10411 bool uj
= use_json(argc
, argv
);
10416 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
10419 return CMD_WARNING
;
10421 bgp_show_all_instances_routes_vty(vty
, afi
, safi
, uj
);
10422 return CMD_SUCCESS
;
10425 static int bgp_show_regexp(struct vty
*vty
, struct bgp
*bgp
, const char *regstr
,
10426 afi_t afi
, safi_t safi
, enum bgp_show_type type
)
10431 if (!config_bgp_aspath_validate(regstr
)) {
10432 vty_out(vty
, "Invalid character in as-path access-list %s\n",
10434 return CMD_WARNING_CONFIG_FAILED
;
10437 regex
= bgp_regcomp(regstr
);
10439 vty_out(vty
, "Can't compile regexp %s\n", regstr
);
10440 return CMD_WARNING
;
10443 rc
= bgp_show(vty
, bgp
, afi
, safi
, type
, regex
, 0);
10444 bgp_regex_free(regex
);
10448 static int bgp_show_prefix_list(struct vty
*vty
, struct bgp
*bgp
,
10449 const char *prefix_list_str
, afi_t afi
,
10450 safi_t safi
, enum bgp_show_type type
)
10452 struct prefix_list
*plist
;
10454 plist
= prefix_list_lookup(afi
, prefix_list_str
);
10455 if (plist
== NULL
) {
10456 vty_out(vty
, "%% %s is not a valid prefix-list name\n",
10458 return CMD_WARNING
;
10461 return bgp_show(vty
, bgp
, afi
, safi
, type
, plist
, 0);
10464 static int bgp_show_filter_list(struct vty
*vty
, struct bgp
*bgp
,
10465 const char *filter
, afi_t afi
, safi_t safi
,
10466 enum bgp_show_type type
)
10468 struct as_list
*as_list
;
10470 as_list
= as_list_lookup(filter
);
10471 if (as_list
== NULL
) {
10472 vty_out(vty
, "%% %s is not a valid AS-path access-list name\n",
10474 return CMD_WARNING
;
10477 return bgp_show(vty
, bgp
, afi
, safi
, type
, as_list
, 0);
10480 static int bgp_show_route_map(struct vty
*vty
, struct bgp
*bgp
,
10481 const char *rmap_str
, afi_t afi
, safi_t safi
,
10482 enum bgp_show_type type
)
10484 struct route_map
*rmap
;
10486 rmap
= route_map_lookup_by_name(rmap_str
);
10488 vty_out(vty
, "%% %s is not a valid route-map name\n", rmap_str
);
10489 return CMD_WARNING
;
10492 return bgp_show(vty
, bgp
, afi
, safi
, type
, rmap
, 0);
10495 static int bgp_show_community(struct vty
*vty
, struct bgp
*bgp
,
10496 const char *comstr
, int exact
, afi_t afi
,
10497 safi_t safi
, bool use_json
)
10499 struct community
*com
;
10502 com
= community_str2com(comstr
);
10504 vty_out(vty
, "%% Community malformed: %s\n", comstr
);
10505 return CMD_WARNING
;
10508 ret
= bgp_show(vty
, bgp
, afi
, safi
,
10509 (exact
? bgp_show_type_community_exact
10510 : bgp_show_type_community
),
10512 community_free(&com
);
10517 static int bgp_show_community_list(struct vty
*vty
, struct bgp
*bgp
,
10518 const char *com
, int exact
, afi_t afi
,
10521 struct community_list
*list
;
10523 list
= community_list_lookup(bgp_clist
, com
, 0, COMMUNITY_LIST_MASTER
);
10524 if (list
== NULL
) {
10525 vty_out(vty
, "%% %s is not a valid community-list name\n", com
);
10526 return CMD_WARNING
;
10529 return bgp_show(vty
, bgp
, afi
, safi
,
10530 (exact
? bgp_show_type_community_list_exact
10531 : bgp_show_type_community_list
),
10535 static int bgp_show_prefix_longer(struct vty
*vty
, struct bgp
*bgp
,
10536 const char *prefix
, afi_t afi
, safi_t safi
,
10537 enum bgp_show_type type
)
10544 ret
= str2prefix(prefix
, p
);
10546 vty_out(vty
, "%% Malformed Prefix\n");
10547 return CMD_WARNING
;
10550 ret
= bgp_show(vty
, bgp
, afi
, safi
, type
, p
, 0);
10556 BGP_STATS_MAXBITLEN
= 0,
10558 BGP_STATS_PREFIXES
,
10560 BGP_STATS_UNAGGREGATEABLE
,
10561 BGP_STATS_MAX_AGGREGATEABLE
,
10562 BGP_STATS_AGGREGATES
,
10564 BGP_STATS_ASPATH_COUNT
,
10565 BGP_STATS_ASPATH_MAXHOPS
,
10566 BGP_STATS_ASPATH_TOTHOPS
,
10567 BGP_STATS_ASPATH_MAXSIZE
,
10568 BGP_STATS_ASPATH_TOTSIZE
,
10569 BGP_STATS_ASN_HIGHEST
,
10573 static const char *table_stats_strs
[] = {
10574 [BGP_STATS_PREFIXES
] = "Total Prefixes",
10575 [BGP_STATS_TOTPLEN
] = "Average prefix length",
10576 [BGP_STATS_RIB
] = "Total Advertisements",
10577 [BGP_STATS_UNAGGREGATEABLE
] = "Unaggregateable prefixes",
10578 [BGP_STATS_MAX_AGGREGATEABLE
] =
10579 "Maximum aggregateable prefixes",
10580 [BGP_STATS_AGGREGATES
] = "BGP Aggregate advertisements",
10581 [BGP_STATS_SPACE
] = "Address space advertised",
10582 [BGP_STATS_ASPATH_COUNT
] = "Advertisements with paths",
10583 [BGP_STATS_ASPATH_MAXHOPS
] = "Longest AS-Path (hops)",
10584 [BGP_STATS_ASPATH_MAXSIZE
] = "Largest AS-Path (bytes)",
10585 [BGP_STATS_ASPATH_TOTHOPS
] = "Average AS-Path length (hops)",
10586 [BGP_STATS_ASPATH_TOTSIZE
] = "Average AS-Path size (bytes)",
10587 [BGP_STATS_ASN_HIGHEST
] = "Highest public ASN",
10588 [BGP_STATS_MAX
] = NULL
,
10591 struct bgp_table_stats
{
10592 struct bgp_table
*table
;
10593 unsigned long long counts
[BGP_STATS_MAX
];
10594 double total_space
;
10598 #define TALLY_SIGFIG 100000
10599 static unsigned long
10600 ravg_tally (unsigned long count
, unsigned long oldavg
, unsigned long newval
)
10602 unsigned long newtot
= (count
-1) * oldavg
+ (newval
* TALLY_SIGFIG
);
10603 unsigned long res
= (newtot
* TALLY_SIGFIG
) / count
;
10604 unsigned long ret
= newtot
/ count
;
10606 if ((res
% TALLY_SIGFIG
) > (TALLY_SIGFIG
/2))
10613 static void bgp_table_stats_rn(struct bgp_node
*rn
, struct bgp_node
*top
,
10614 struct bgp_table_stats
*ts
, unsigned int space
)
10616 struct bgp_node
*prn
= bgp_node_parent_nolock(rn
);
10617 struct bgp_path_info
*pi
;
10622 if (!bgp_node_has_bgp_path_info_data(rn
))
10625 ts
->counts
[BGP_STATS_PREFIXES
]++;
10626 ts
->counts
[BGP_STATS_TOTPLEN
] += rn
->p
.prefixlen
;
10629 ts
->counts
[BGP_STATS_AVGPLEN
]
10630 = ravg_tally (ts
->counts
[BGP_STATS_PREFIXES
],
10631 ts
->counts
[BGP_STATS_AVGPLEN
],
10635 /* check if the prefix is included by any other announcements */
10636 while (prn
&& !bgp_node_has_bgp_path_info_data(prn
))
10637 prn
= bgp_node_parent_nolock(prn
);
10639 if (prn
== NULL
|| prn
== top
) {
10640 ts
->counts
[BGP_STATS_UNAGGREGATEABLE
]++;
10641 /* announced address space */
10643 ts
->total_space
+= pow(2.0, space
- rn
->p
.prefixlen
);
10644 } else if (bgp_node_has_bgp_path_info_data(prn
))
10645 ts
->counts
[BGP_STATS_MAX_AGGREGATEABLE
]++;
10648 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10649 ts
->counts
[BGP_STATS_RIB
]++;
10651 if (CHECK_FLAG(pi
->attr
->flag
,
10652 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE
)))
10653 ts
->counts
[BGP_STATS_AGGREGATES
]++;
10655 /* as-path stats */
10656 if (pi
->attr
->aspath
) {
10657 unsigned int hops
= aspath_count_hops(pi
->attr
->aspath
);
10658 unsigned int size
= aspath_size(pi
->attr
->aspath
);
10659 as_t highest
= aspath_highest(pi
->attr
->aspath
);
10661 ts
->counts
[BGP_STATS_ASPATH_COUNT
]++;
10663 if (hops
> ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
])
10664 ts
->counts
[BGP_STATS_ASPATH_MAXHOPS
] = hops
;
10666 if (size
> ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
])
10667 ts
->counts
[BGP_STATS_ASPATH_MAXSIZE
] = size
;
10669 ts
->counts
[BGP_STATS_ASPATH_TOTHOPS
] += hops
;
10670 ts
->counts
[BGP_STATS_ASPATH_TOTSIZE
] += size
;
10672 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
]
10673 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10674 ts
->counts
[BGP_STATS_ASPATH_AVGHOPS
],
10676 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
]
10677 = ravg_tally (ts
->counts
[BGP_STATS_ASPATH_COUNT
],
10678 ts
->counts
[BGP_STATS_ASPATH_AVGSIZE
],
10681 if (highest
> ts
->counts
[BGP_STATS_ASN_HIGHEST
])
10682 ts
->counts
[BGP_STATS_ASN_HIGHEST
] = highest
;
10687 static int bgp_table_stats_walker(struct thread
*t
)
10689 struct bgp_node
*rn
, *nrn
;
10690 struct bgp_node
*top
;
10691 struct bgp_table_stats
*ts
= THREAD_ARG(t
);
10692 unsigned int space
= 0;
10694 if (!(top
= bgp_table_top(ts
->table
)))
10697 switch (ts
->table
->afi
) {
10699 space
= IPV4_MAX_BITLEN
;
10702 space
= IPV6_MAX_BITLEN
;
10708 ts
->counts
[BGP_STATS_MAXBITLEN
] = space
;
10710 for (rn
= top
; rn
; rn
= bgp_route_next(rn
)) {
10711 if (ts
->table
->safi
== SAFI_MPLS_VPN
) {
10712 struct bgp_table
*table
;
10714 table
= bgp_node_get_bgp_table_info(rn
);
10718 top
= bgp_table_top(table
);
10719 for (nrn
= bgp_table_top(table
); nrn
;
10720 nrn
= bgp_route_next(nrn
))
10721 bgp_table_stats_rn(nrn
, top
, ts
, space
);
10723 bgp_table_stats_rn(rn
, top
, ts
, space
);
10730 static int bgp_table_stats(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
10733 struct bgp_table_stats ts
;
10736 if (!bgp
->rib
[afi
][safi
]) {
10737 vty_out(vty
, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
10739 return CMD_WARNING
;
10742 vty_out(vty
, "BGP %s RIB statistics\n", get_afi_safi_str(afi
, safi
, false));
10744 /* labeled-unicast routes live in the unicast table */
10745 if (safi
== SAFI_LABELED_UNICAST
)
10746 safi
= SAFI_UNICAST
;
10748 memset(&ts
, 0, sizeof(ts
));
10749 ts
.table
= bgp
->rib
[afi
][safi
];
10750 thread_execute(bm
->master
, bgp_table_stats_walker
, &ts
, 0);
10752 for (i
= 0; i
< BGP_STATS_MAX
; i
++) {
10753 if (!table_stats_strs
[i
])
10758 case BGP_STATS_ASPATH_AVGHOPS
:
10759 case BGP_STATS_ASPATH_AVGSIZE
:
10760 case BGP_STATS_AVGPLEN
:
10761 vty_out (vty
, "%-30s: ", table_stats_strs
[i
]);
10762 vty_out (vty
, "%12.2f",
10763 (float)ts
.counts
[i
] / (float)TALLY_SIGFIG
);
10766 case BGP_STATS_ASPATH_TOTHOPS
:
10767 case BGP_STATS_ASPATH_TOTSIZE
:
10768 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10769 vty_out(vty
, "%12.2f",
10771 ? (float)ts
.counts
[i
]
10773 [BGP_STATS_ASPATH_COUNT
]
10776 case BGP_STATS_TOTPLEN
:
10777 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10778 vty_out(vty
, "%12.2f",
10780 ? (float)ts
.counts
[i
]
10782 [BGP_STATS_PREFIXES
]
10785 case BGP_STATS_SPACE
:
10786 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10787 vty_out(vty
, "%12g\n", ts
.total_space
);
10789 if (afi
== AFI_IP6
) {
10790 vty_out(vty
, "%30s: ", "/32 equivalent ");
10791 vty_out(vty
, "%12g\n",
10792 ts
.total_space
* pow(2.0, -128 + 32));
10793 vty_out(vty
, "%30s: ", "/48 equivalent ");
10794 vty_out(vty
, "%12g\n",
10795 ts
.total_space
* pow(2.0, -128 + 48));
10797 vty_out(vty
, "%30s: ", "% announced ");
10798 vty_out(vty
, "%12.2f\n",
10799 ts
.total_space
* 100. * pow(2.0, -32));
10800 vty_out(vty
, "%30s: ", "/8 equivalent ");
10801 vty_out(vty
, "%12.2f\n",
10802 ts
.total_space
* pow(2.0, -32 + 8));
10803 vty_out(vty
, "%30s: ", "/24 equivalent ");
10804 vty_out(vty
, "%12.2f\n",
10805 ts
.total_space
* pow(2.0, -32 + 24));
10809 vty_out(vty
, "%-30s: ", table_stats_strs
[i
]);
10810 vty_out(vty
, "%12llu", ts
.counts
[i
]);
10813 vty_out(vty
, "\n");
10815 return CMD_SUCCESS
;
10827 PCOUNT_PFCNT
, /* the figure we display to users */
10831 static const char *pcount_strs
[] = {
10832 [PCOUNT_ADJ_IN
] = "Adj-in",
10833 [PCOUNT_DAMPED
] = "Damped",
10834 [PCOUNT_REMOVED
] = "Removed",
10835 [PCOUNT_HISTORY
] = "History",
10836 [PCOUNT_STALE
] = "Stale",
10837 [PCOUNT_VALID
] = "Valid",
10838 [PCOUNT_ALL
] = "All RIB",
10839 [PCOUNT_COUNTED
] = "PfxCt counted",
10840 [PCOUNT_PFCNT
] = "Useable",
10841 [PCOUNT_MAX
] = NULL
,
10844 struct peer_pcounts
{
10845 unsigned int count
[PCOUNT_MAX
];
10846 const struct peer
*peer
;
10847 const struct bgp_table
*table
;
10850 static int bgp_peer_count_walker(struct thread
*t
)
10852 struct bgp_node
*rn
;
10853 struct peer_pcounts
*pc
= THREAD_ARG(t
);
10854 const struct peer
*peer
= pc
->peer
;
10856 for (rn
= bgp_table_top(pc
->table
); rn
; rn
= bgp_route_next(rn
)) {
10857 struct bgp_adj_in
*ain
;
10858 struct bgp_path_info
*pi
;
10860 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
)
10861 if (ain
->peer
== peer
)
10862 pc
->count
[PCOUNT_ADJ_IN
]++;
10864 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
10866 if (pi
->peer
!= peer
)
10869 pc
->count
[PCOUNT_ALL
]++;
10871 if (CHECK_FLAG(pi
->flags
, BGP_PATH_DAMPED
))
10872 pc
->count
[PCOUNT_DAMPED
]++;
10873 if (CHECK_FLAG(pi
->flags
, BGP_PATH_HISTORY
))
10874 pc
->count
[PCOUNT_HISTORY
]++;
10875 if (CHECK_FLAG(pi
->flags
, BGP_PATH_REMOVED
))
10876 pc
->count
[PCOUNT_REMOVED
]++;
10877 if (CHECK_FLAG(pi
->flags
, BGP_PATH_STALE
))
10878 pc
->count
[PCOUNT_STALE
]++;
10879 if (CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
10880 pc
->count
[PCOUNT_VALID
]++;
10881 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10882 pc
->count
[PCOUNT_PFCNT
]++;
10884 if (CHECK_FLAG(pi
->flags
, BGP_PATH_COUNTED
)) {
10885 pc
->count
[PCOUNT_COUNTED
]++;
10886 if (CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10888 EC_LIB_DEVELOPMENT
,
10889 "Attempting to count but flags say it is unusable");
10891 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_UNUSEABLE
))
10893 EC_LIB_DEVELOPMENT
,
10894 "Not counted but flags say we should");
10901 static int bgp_peer_counts(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
10902 safi_t safi
, bool use_json
)
10904 struct peer_pcounts pcounts
= {.peer
= peer
};
10906 json_object
*json
= NULL
;
10907 json_object
*json_loop
= NULL
;
10910 json
= json_object_new_object();
10911 json_loop
= json_object_new_object();
10914 if (!peer
|| !peer
->bgp
|| !peer
->afc
[afi
][safi
]
10915 || !peer
->bgp
->rib
[afi
][safi
]) {
10917 json_object_string_add(
10919 "No such neighbor or address family");
10920 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
10921 json_object_free(json
);
10923 vty_out(vty
, "%% No such neighbor or address family\n");
10925 return CMD_WARNING
;
10928 memset(&pcounts
, 0, sizeof(pcounts
));
10929 pcounts
.peer
= peer
;
10930 pcounts
.table
= peer
->bgp
->rib
[afi
][safi
];
10932 /* in-place call via thread subsystem so as to record execution time
10933 * stats for the thread-walk (i.e. ensure this can't be blamed on
10934 * on just vty_read()).
10936 thread_execute(bm
->master
, bgp_peer_count_walker
, &pcounts
, 0);
10939 json_object_string_add(json
, "prefixCountsFor", peer
->host
);
10940 json_object_string_add(json
, "multiProtocol",
10941 get_afi_safi_str(afi
, safi
, true));
10942 json_object_int_add(json
, "pfxCounter",
10943 peer
->pcount
[afi
][safi
]);
10945 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10946 json_object_int_add(json_loop
, pcount_strs
[i
],
10949 json_object_object_add(json
, "ribTableWalkCounters", json_loop
);
10951 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10952 json_object_string_add(json
, "pfxctDriftFor",
10954 json_object_string_add(
10955 json
, "recommended",
10956 "Please report this bug, with the above command output");
10958 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
10959 json
, JSON_C_TO_STRING_PRETTY
));
10960 json_object_free(json
);
10964 && bgp_flag_check(peer
->bgp
, BGP_FLAG_SHOW_HOSTNAME
)) {
10965 vty_out(vty
, "Prefix counts for %s/%s, %s\n",
10966 peer
->hostname
, peer
->host
,
10967 get_afi_safi_str(afi
, safi
, false));
10969 vty_out(vty
, "Prefix counts for %s, %s\n", peer
->host
,
10970 get_afi_safi_str(afi
, safi
, false));
10973 vty_out(vty
, "PfxCt: %" PRIu32
"\n", peer
->pcount
[afi
][safi
]);
10974 vty_out(vty
, "\nCounts from RIB table walk:\n\n");
10976 for (i
= 0; i
< PCOUNT_MAX
; i
++)
10977 vty_out(vty
, "%20s: %-10d\n", pcount_strs
[i
],
10980 if (pcounts
.count
[PCOUNT_PFCNT
] != peer
->pcount
[afi
][safi
]) {
10981 vty_out(vty
, "%s [pcount] PfxCt drift!\n", peer
->host
);
10983 "Please report this bug, with the above command output\n");
10987 return CMD_SUCCESS
;
10990 DEFUN (show_ip_bgp_instance_neighbor_prefix_counts
,
10991 show_ip_bgp_instance_neighbor_prefix_counts_cmd
,
10992 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_CMD_STR
"]] "
10993 "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
10997 BGP_INSTANCE_HELP_STR
11000 "Detailed information on TCP and BGP neighbor connections\n"
11001 "Neighbor to display information about\n"
11002 "Neighbor to display information about\n"
11003 "Neighbor on BGP configured interface\n"
11004 "Display detailed prefix count information\n"
11007 afi_t afi
= AFI_IP6
;
11008 safi_t safi
= SAFI_UNICAST
;
11011 struct bgp
*bgp
= NULL
;
11012 bool uj
= use_json(argc
, argv
);
11017 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11020 return CMD_WARNING
;
11022 argv_find(argv
, argc
, "neighbors", &idx
);
11023 peer
= peer_lookup_in_view(vty
, bgp
, argv
[idx
+ 1]->arg
, uj
);
11025 return CMD_WARNING
;
11027 return bgp_peer_counts(vty
, peer
, afi
, safi
, uj
);
11030 #ifdef KEEP_OLD_VPN_COMMANDS
11031 DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts
,
11032 show_ip_bgp_vpn_neighbor_prefix_counts_cmd
,
11033 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
11038 "Display information about all VPNv4 NLRIs\n"
11039 "Detailed information on TCP and BGP neighbor connections\n"
11040 "Neighbor to display information about\n"
11041 "Neighbor to display information about\n"
11042 "Neighbor on BGP configured interface\n"
11043 "Display detailed prefix count information\n"
11048 bool uj
= use_json(argc
, argv
);
11050 peer
= peer_lookup_in_view(vty
, NULL
, argv
[idx_peer
]->arg
, uj
);
11052 return CMD_WARNING
;
11054 return bgp_peer_counts(vty
, peer
, AFI_IP
, SAFI_MPLS_VPN
, uj
);
11057 DEFUN (show_ip_bgp_vpn_all_route_prefix
,
11058 show_ip_bgp_vpn_all_route_prefix_cmd
,
11059 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
11064 "Display information about all VPNv4 NLRIs\n"
11065 "Network in the BGP routing table to display\n"
11066 "Network in the BGP routing table to display\n"
11070 char *network
= NULL
;
11071 struct bgp
*bgp
= bgp_get_default();
11073 vty_out(vty
, "Can't find default instance\n");
11074 return CMD_WARNING
;
11077 if (argv_find(argv
, argc
, "A.B.C.D", &idx
))
11078 network
= argv
[idx
]->arg
;
11079 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
))
11080 network
= argv
[idx
]->arg
;
11082 vty_out(vty
, "Unable to figure out Network\n");
11083 return CMD_WARNING
;
11086 return bgp_show_route(vty
, bgp
, network
, AFI_IP
, SAFI_MPLS_VPN
, NULL
, 0,
11087 BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11089 #endif /* KEEP_OLD_VPN_COMMANDS */
11091 DEFUN (show_bgp_l2vpn_evpn_route_prefix
,
11092 show_bgp_l2vpn_evpn_route_prefix_cmd
,
11093 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
11098 "Network in the BGP routing table to display\n"
11099 "Network in the BGP routing table to display\n"
11100 "Network in the BGP routing table to display\n"
11101 "Network in the BGP routing table to display\n"
11105 char *network
= NULL
;
11106 int prefix_check
= 0;
11108 if (argv_find(argv
, argc
, "A.B.C.D", &idx
) ||
11109 argv_find(argv
, argc
, "X:X::X:X", &idx
))
11110 network
= argv
[idx
]->arg
;
11111 else if (argv_find(argv
, argc
, "A.B.C.D/M", &idx
) ||
11112 argv_find(argv
, argc
, "A.B.C.D/M", &idx
)) {
11113 network
= argv
[idx
]->arg
;
11116 vty_out(vty
, "Unable to figure out Network\n");
11117 return CMD_WARNING
;
11119 return bgp_show_route(vty
, NULL
, network
, AFI_L2VPN
, SAFI_EVPN
, NULL
,
11120 prefix_check
, BGP_PATH_SHOW_ALL
,
11121 use_json(argc
, argv
));
11124 static void show_adj_route(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11125 safi_t safi
, enum bgp_show_adj_route_type type
,
11126 const char *rmap_name
, bool use_json
,
11129 struct bgp_table
*table
;
11130 struct bgp_adj_in
*ain
;
11131 struct bgp_adj_out
*adj
;
11132 unsigned long output_count
;
11133 unsigned long filtered_count
;
11134 struct bgp_node
*rn
;
11140 struct update_subgroup
*subgrp
;
11141 json_object
*json_scode
= NULL
;
11142 json_object
*json_ocode
= NULL
;
11143 json_object
*json_ar
= NULL
;
11144 struct peer_af
*paf
;
11145 bool route_filtered
;
11148 json_scode
= json_object_new_object();
11149 json_ocode
= json_object_new_object();
11150 json_ar
= json_object_new_object();
11152 json_object_string_add(json_scode
, "suppressed", "s");
11153 json_object_string_add(json_scode
, "damped", "d");
11154 json_object_string_add(json_scode
, "history", "h");
11155 json_object_string_add(json_scode
, "valid", "*");
11156 json_object_string_add(json_scode
, "best", ">");
11157 json_object_string_add(json_scode
, "multipath", "=");
11158 json_object_string_add(json_scode
, "internal", "i");
11159 json_object_string_add(json_scode
, "ribFailure", "r");
11160 json_object_string_add(json_scode
, "stale", "S");
11161 json_object_string_add(json_scode
, "removed", "R");
11163 json_object_string_add(json_ocode
, "igp", "i");
11164 json_object_string_add(json_ocode
, "egp", "e");
11165 json_object_string_add(json_ocode
, "incomplete", "?");
11172 json_object_string_add(json
, "alert", "no BGP");
11173 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11174 json_object_free(json
);
11176 vty_out(vty
, "%% No bgp\n");
11180 /* labeled-unicast routes live in the unicast table */
11181 if (safi
== SAFI_LABELED_UNICAST
)
11182 table
= bgp
->rib
[afi
][SAFI_UNICAST
];
11184 table
= bgp
->rib
[afi
][safi
];
11186 output_count
= filtered_count
= 0;
11187 subgrp
= peer_subgroup(peer
, afi
, safi
);
11189 if (type
== bgp_show_adj_route_advertised
&& subgrp
11190 && CHECK_FLAG(subgrp
->sflags
, SUBGRP_STATUS_DEFAULT_ORIGINATE
)) {
11192 json_object_int_add(json
, "bgpTableVersion",
11194 json_object_string_add(json
, "bgpLocalRouterId",
11195 inet_ntoa(bgp
->router_id
));
11196 json_object_int_add(json
, "defaultLocPrf",
11197 bgp
->default_local_pref
);
11198 json_object_int_add(json
, "localAS", bgp
->as
);
11199 json_object_object_add(json
, "bgpStatusCodes",
11201 json_object_object_add(json
, "bgpOriginCodes",
11203 json_object_string_add(
11204 json
, "bgpOriginatingDefaultNetwork",
11205 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11207 vty_out(vty
, "BGP table version is %" PRIu64
11208 ", local router ID is %s, vrf id ",
11209 table
->version
, inet_ntoa(bgp
->router_id
));
11210 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11211 vty_out(vty
, "%s", VRFID_NONE_STR
);
11213 vty_out(vty
, "%u", bgp
->vrf_id
);
11214 vty_out(vty
, "\n");
11215 vty_out(vty
, "Default local pref %u, ",
11216 bgp
->default_local_pref
);
11217 vty_out(vty
, "local AS %u\n", bgp
->as
);
11218 vty_out(vty
, BGP_SHOW_SCODE_HEADER
);
11219 vty_out(vty
, BGP_SHOW_NCODE_HEADER
);
11220 vty_out(vty
, BGP_SHOW_OCODE_HEADER
);
11222 vty_out(vty
, "Originating default network %s\n\n",
11223 (afi
== AFI_IP
) ? "0.0.0.0/0" : "::/0");
11228 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
11229 if (type
== bgp_show_adj_route_received
11230 || type
== bgp_show_adj_route_filtered
) {
11231 for (ain
= rn
->adj_in
; ain
; ain
= ain
->next
) {
11232 if (ain
->peer
!= peer
)
11237 json_object_int_add(
11238 json
, "bgpTableVersion",
11240 json_object_string_add(
11242 "bgpLocalRouterId",
11245 json_object_int_add(json
,
11247 bgp
->default_local_pref
);
11248 json_object_int_add(json
,
11249 "localAS", bgp
->as
);
11250 json_object_object_add(
11251 json
, "bgpStatusCodes",
11253 json_object_object_add(
11254 json
, "bgpOriginCodes",
11258 "BGP table version is 0, local router ID is %s, vrf id ",
11261 if (bgp
->vrf_id
== VRF_UNKNOWN
)
11267 vty_out(vty
, "\n");
11269 "Default local pref %u, ",
11270 bgp
->default_local_pref
);
11271 vty_out(vty
, "local AS %u\n",
11274 BGP_SHOW_SCODE_HEADER
);
11276 BGP_SHOW_NCODE_HEADER
);
11278 BGP_SHOW_OCODE_HEADER
);
11284 vty_out(vty
, BGP_SHOW_HEADER
);
11288 bgp_attr_dup(&attr
, ain
->attr
);
11289 route_filtered
= false;
11291 /* Filter prefix using distribute list,
11292 * filter list or prefix list
11294 if ((bgp_input_filter(peer
, &rn
->p
, &attr
, afi
,
11295 safi
)) == FILTER_DENY
)
11296 route_filtered
= true;
11298 /* Filter prefix using route-map */
11299 ret
= bgp_input_modifier(peer
, &rn
->p
, &attr
,
11300 afi
, safi
, rmap_name
, NULL
, 0);
11302 if (type
== bgp_show_adj_route_filtered
&&
11303 !route_filtered
&& ret
!= RMAP_DENY
) {
11304 bgp_attr_undup(&attr
, ain
->attr
);
11308 if (type
== bgp_show_adj_route_received
&&
11309 (route_filtered
|| ret
== RMAP_DENY
))
11312 route_vty_out_tmp(vty
, &rn
->p
, &attr
, safi
,
11313 use_json
, json_ar
);
11314 bgp_attr_undup(&attr
, ain
->attr
);
11317 } else if (type
== bgp_show_adj_route_advertised
) {
11318 RB_FOREACH (adj
, bgp_adj_out_rb
, &rn
->adj_out
)
11319 SUBGRP_FOREACH_PEER (adj
->subgroup
, paf
) {
11320 if (paf
->peer
!= peer
|| !adj
->attr
)
11325 json_object_int_add(
11329 json_object_string_add(
11331 "bgpLocalRouterId",
11334 json_object_int_add(
11335 json
, "defaultLocPrf",
11336 bgp
->default_local_pref
11338 json_object_int_add(
11341 json_object_object_add(
11345 json_object_object_add(
11351 "BGP table version is %" PRIu64
11352 ", local router ID is %s, vrf id ",
11365 vty_out(vty
, "\n");
11367 "Default local pref %u, ",
11368 bgp
->default_local_pref
11374 BGP_SHOW_SCODE_HEADER
);
11376 BGP_SHOW_NCODE_HEADER
);
11378 BGP_SHOW_OCODE_HEADER
);
11389 bgp_attr_dup(&attr
, adj
->attr
);
11390 ret
= bgp_output_modifier(
11391 peer
, &rn
->p
, &attr
, afi
, safi
,
11394 if (ret
!= RMAP_DENY
) {
11395 route_vty_out_tmp(vty
, &rn
->p
,
11404 bgp_attr_undup(&attr
, adj
->attr
);
11410 json_object_object_add(json
, "advertisedRoutes", json_ar
);
11411 json_object_int_add(json
, "totalPrefixCounter", output_count
);
11412 json_object_int_add(json
, "filteredPrefixCounter",
11415 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
11416 json
, JSON_C_TO_STRING_PRETTY
));
11417 json_object_free(json
);
11418 } else if (output_count
> 0) {
11419 if (filtered_count
> 0)
11421 "\nTotal number of prefixes %ld (%ld filtered)\n",
11422 output_count
, filtered_count
);
11424 vty_out(vty
, "\nTotal number of prefixes %ld\n",
11429 static int peer_adj_routes(struct vty
*vty
, struct peer
*peer
, afi_t afi
,
11430 safi_t safi
, enum bgp_show_adj_route_type type
,
11431 const char *rmap_name
, bool use_json
)
11433 json_object
*json
= NULL
;
11436 json
= json_object_new_object();
11438 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11440 json_object_string_add(
11442 "No such neighbor or address family");
11443 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11444 json_object_free(json
);
11446 vty_out(vty
, "%% No such neighbor or address family\n");
11448 return CMD_WARNING
;
11451 if ((type
== bgp_show_adj_route_received
11452 || type
== bgp_show_adj_route_filtered
)
11453 && !CHECK_FLAG(peer
->af_flags
[afi
][safi
],
11454 PEER_FLAG_SOFT_RECONFIG
)) {
11456 json_object_string_add(
11458 "Inbound soft reconfiguration not enabled");
11459 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
11460 json_object_free(json
);
11463 "%% Inbound soft reconfiguration not enabled\n");
11465 return CMD_WARNING
;
11468 show_adj_route(vty
, peer
, afi
, safi
, type
, rmap_name
, use_json
, json
);
11470 return CMD_SUCCESS
;
11473 DEFUN (show_ip_bgp_instance_neighbor_advertised_route
,
11474 show_ip_bgp_instance_neighbor_advertised_route_cmd
,
11475 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11476 "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]",
11480 BGP_INSTANCE_HELP_STR
11482 BGP_SAFI_WITH_LABEL_HELP_STR
11483 "Detailed information on TCP and BGP neighbor connections\n"
11484 "Neighbor to display information about\n"
11485 "Neighbor to display information about\n"
11486 "Neighbor on BGP configured interface\n"
11487 "Display the routes advertised to a BGP neighbor\n"
11488 "Display the received routes from neighbor\n"
11489 "Display the filtered routes received from neighbor\n"
11490 "Route-map to modify the attributes\n"
11491 "Name of the route map\n"
11494 afi_t afi
= AFI_IP6
;
11495 safi_t safi
= SAFI_UNICAST
;
11496 char *rmap_name
= NULL
;
11497 char *peerstr
= NULL
;
11498 struct bgp
*bgp
= NULL
;
11500 enum bgp_show_adj_route_type type
= bgp_show_adj_route_advertised
;
11502 bool uj
= use_json(argc
, argv
);
11507 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11510 return CMD_WARNING
;
11512 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11513 argv_find(argv
, argc
, "neighbors", &idx
);
11514 peerstr
= argv
[++idx
]->arg
;
11516 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11518 return CMD_WARNING
;
11520 if (argv_find(argv
, argc
, "advertised-routes", &idx
))
11521 type
= bgp_show_adj_route_advertised
;
11522 else if (argv_find(argv
, argc
, "received-routes", &idx
))
11523 type
= bgp_show_adj_route_received
;
11524 else if (argv_find(argv
, argc
, "filtered-routes", &idx
))
11525 type
= bgp_show_adj_route_filtered
;
11527 if (argv_find(argv
, argc
, "route-map", &idx
))
11528 rmap_name
= argv
[++idx
]->arg
;
11530 return peer_adj_routes(vty
, peer
, afi
, safi
, type
, rmap_name
, uj
);
11533 DEFUN (show_ip_bgp_neighbor_received_prefix_filter
,
11534 show_ip_bgp_neighbor_received_prefix_filter_cmd
,
11535 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
11541 "Address Family modifier\n"
11542 "Detailed information on TCP and BGP neighbor connections\n"
11543 "Neighbor to display information about\n"
11544 "Neighbor to display information about\n"
11545 "Neighbor on BGP configured interface\n"
11546 "Display information received from a BGP neighbor\n"
11547 "Display the prefixlist filter\n"
11550 afi_t afi
= AFI_IP6
;
11551 safi_t safi
= SAFI_UNICAST
;
11552 char *peerstr
= NULL
;
11555 union sockunion su
;
11561 /* show [ip] bgp */
11562 if (argv_find(argv
, argc
, "ip", &idx
))
11564 /* [<ipv4|ipv6> [unicast]] */
11565 if (argv_find(argv
, argc
, "ipv4", &idx
))
11567 if (argv_find(argv
, argc
, "ipv6", &idx
))
11569 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11570 argv_find(argv
, argc
, "neighbors", &idx
);
11571 peerstr
= argv
[++idx
]->arg
;
11573 bool uj
= use_json(argc
, argv
);
11575 ret
= str2sockunion(peerstr
, &su
);
11577 peer
= peer_lookup_by_conf_if(NULL
, peerstr
);
11580 vty_out(vty
, "{}\n");
11583 "%% Malformed address or name: %s\n",
11585 return CMD_WARNING
;
11588 peer
= peer_lookup(NULL
, &su
);
11591 vty_out(vty
, "{}\n");
11593 vty_out(vty
, "No peer\n");
11594 return CMD_WARNING
;
11598 sprintf(name
, "%s.%d.%d", peer
->host
, afi
, safi
);
11599 count
= prefix_bgp_show_prefix_list(NULL
, afi
, name
, uj
);
11602 vty_out(vty
, "Address Family: %s\n",
11603 get_afi_safi_str(afi
, safi
, false));
11604 prefix_bgp_show_prefix_list(vty
, afi
, name
, uj
);
11607 vty_out(vty
, "{}\n");
11609 vty_out(vty
, "No functional output\n");
11612 return CMD_SUCCESS
;
11615 static int bgp_show_neighbor_route(struct vty
*vty
, struct peer
*peer
,
11616 afi_t afi
, safi_t safi
,
11617 enum bgp_show_type type
, bool use_json
)
11619 /* labeled-unicast routes live in the unicast table */
11620 if (safi
== SAFI_LABELED_UNICAST
)
11621 safi
= SAFI_UNICAST
;
11623 if (!peer
|| !peer
->afc
[afi
][safi
]) {
11625 json_object
*json_no
= NULL
;
11626 json_no
= json_object_new_object();
11627 json_object_string_add(
11628 json_no
, "warning",
11629 "No such neighbor or address family");
11630 vty_out(vty
, "%s\n",
11631 json_object_to_json_string(json_no
));
11632 json_object_free(json_no
);
11634 vty_out(vty
, "%% No such neighbor or address family\n");
11635 return CMD_WARNING
;
11638 return bgp_show(vty
, peer
->bgp
, afi
, safi
, type
, &peer
->su
, use_json
);
11641 DEFUN (show_ip_bgp_flowspec_routes_detailed
,
11642 show_ip_bgp_flowspec_routes_detailed_cmd
,
11643 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" flowspec] detail [json]",
11647 BGP_INSTANCE_HELP_STR
11650 "Detailed information on flowspec entries\n"
11653 afi_t afi
= AFI_IP
;
11654 safi_t safi
= SAFI_UNICAST
;
11655 struct bgp
*bgp
= NULL
;
11657 bool uj
= use_json(argc
, argv
);
11662 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11665 return CMD_WARNING
;
11667 return bgp_show(vty
, bgp
, afi
, safi
, bgp_show_type_detail
, NULL
, uj
);
11670 DEFUN (show_ip_bgp_neighbor_routes
,
11671 show_ip_bgp_neighbor_routes_cmd
,
11672 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR
" ["BGP_SAFI_WITH_LABEL_CMD_STR
"]] "
11673 "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]",
11677 BGP_INSTANCE_HELP_STR
11679 BGP_SAFI_WITH_LABEL_HELP_STR
11680 "Detailed information on TCP and BGP neighbor connections\n"
11681 "Neighbor to display information about\n"
11682 "Neighbor to display information about\n"
11683 "Neighbor on BGP configured interface\n"
11684 "Display flap statistics of the routes learned from neighbor\n"
11685 "Display the dampened routes received from neighbor\n"
11686 "Display routes learned from neighbor\n"
11689 char *peerstr
= NULL
;
11690 struct bgp
*bgp
= NULL
;
11691 afi_t afi
= AFI_IP6
;
11692 safi_t safi
= SAFI_UNICAST
;
11694 enum bgp_show_type sh_type
= bgp_show_type_neighbor
;
11696 bool uj
= use_json(argc
, argv
);
11701 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
11704 return CMD_WARNING
;
11706 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
11707 argv_find(argv
, argc
, "neighbors", &idx
);
11708 peerstr
= argv
[++idx
]->arg
;
11710 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
11712 return CMD_WARNING
;
11714 if (argv_find(argv
, argc
, "flap-statistics", &idx
))
11715 sh_type
= bgp_show_type_flap_neighbor
;
11716 else if (argv_find(argv
, argc
, "dampened-routes", &idx
))
11717 sh_type
= bgp_show_type_damp_neighbor
;
11718 else if (argv_find(argv
, argc
, "routes", &idx
))
11719 sh_type
= bgp_show_type_neighbor
;
11721 return bgp_show_neighbor_route(vty
, peer
, afi
, safi
, sh_type
, uj
);
11724 struct bgp_table
*bgp_distance_table
[AFI_MAX
][SAFI_MAX
];
11726 struct bgp_distance
{
11727 /* Distance value for the IP source prefix. */
11730 /* Name of the access-list to be matched. */
11734 DEFUN (show_bgp_afi_vpn_rd_route
,
11735 show_bgp_afi_vpn_rd_route_cmd
,
11736 "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]",
11740 "Address Family modifier\n"
11741 "Display information for a route distinguisher\n"
11742 "Route Distinguisher\n"
11743 "Network in the BGP routing table to display\n"
11744 "Network in the BGP routing table to display\n"
11748 struct prefix_rd prd
;
11749 afi_t afi
= AFI_MAX
;
11752 if (!argv_find_and_parse_afi(argv
, argc
, &idx
, &afi
)) {
11753 vty_out(vty
, "%% Malformed Address Family\n");
11754 return CMD_WARNING
;
11757 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
11759 vty_out(vty
, "%% Malformed Route Distinguisher\n");
11760 return CMD_WARNING
;
11763 return bgp_show_route(vty
, NULL
, argv
[6]->arg
, afi
, SAFI_MPLS_VPN
, &prd
,
11764 0, BGP_PATH_SHOW_ALL
, use_json(argc
, argv
));
11767 static struct bgp_distance
*bgp_distance_new(void)
11769 return XCALLOC(MTYPE_BGP_DISTANCE
, sizeof(struct bgp_distance
));
11772 static void bgp_distance_free(struct bgp_distance
*bdistance
)
11774 XFREE(MTYPE_BGP_DISTANCE
, bdistance
);
11777 static int bgp_distance_set(struct vty
*vty
, const char *distance_str
,
11778 const char *ip_str
, const char *access_list_str
)
11785 struct bgp_node
*rn
;
11786 struct bgp_distance
*bdistance
;
11788 afi
= bgp_node_afi(vty
);
11789 safi
= bgp_node_safi(vty
);
11791 ret
= str2prefix(ip_str
, &p
);
11793 vty_out(vty
, "Malformed prefix\n");
11794 return CMD_WARNING_CONFIG_FAILED
;
11797 distance
= atoi(distance_str
);
11799 /* Get BGP distance node. */
11800 rn
= bgp_node_get(bgp_distance_table
[afi
][safi
], (struct prefix
*)&p
);
11801 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11803 bgp_unlock_node(rn
);
11805 bdistance
= bgp_distance_new();
11806 bgp_node_set_bgp_distance_info(rn
, bdistance
);
11809 /* Set distance value. */
11810 bdistance
->distance
= distance
;
11812 /* Reset access-list configuration. */
11813 if (bdistance
->access_list
) {
11814 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11815 bdistance
->access_list
= NULL
;
11817 if (access_list_str
)
11818 bdistance
->access_list
=
11819 XSTRDUP(MTYPE_AS_LIST
, access_list_str
);
11821 return CMD_SUCCESS
;
11824 static int bgp_distance_unset(struct vty
*vty
, const char *distance_str
,
11825 const char *ip_str
, const char *access_list_str
)
11832 struct bgp_node
*rn
;
11833 struct bgp_distance
*bdistance
;
11835 afi
= bgp_node_afi(vty
);
11836 safi
= bgp_node_safi(vty
);
11838 ret
= str2prefix(ip_str
, &p
);
11840 vty_out(vty
, "Malformed prefix\n");
11841 return CMD_WARNING_CONFIG_FAILED
;
11844 rn
= bgp_node_lookup(bgp_distance_table
[afi
][safi
],
11845 (struct prefix
*)&p
);
11847 vty_out(vty
, "Can't find specified prefix\n");
11848 return CMD_WARNING_CONFIG_FAILED
;
11851 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11852 distance
= atoi(distance_str
);
11854 if (bdistance
->distance
!= distance
) {
11855 vty_out(vty
, "Distance does not match configured\n");
11856 return CMD_WARNING_CONFIG_FAILED
;
11859 XFREE(MTYPE_AS_LIST
, bdistance
->access_list
);
11860 bgp_distance_free(bdistance
);
11862 bgp_node_set_bgp_path_info(rn
, NULL
);
11863 bgp_unlock_node(rn
);
11864 bgp_unlock_node(rn
);
11866 return CMD_SUCCESS
;
11869 /* Apply BGP information to distance method. */
11870 uint8_t bgp_distance_apply(struct prefix
*p
, struct bgp_path_info
*pinfo
,
11871 afi_t afi
, safi_t safi
, struct bgp
*bgp
)
11873 struct bgp_node
*rn
;
11876 struct bgp_distance
*bdistance
;
11877 struct access_list
*alist
;
11878 struct bgp_static
*bgp_static
;
11883 peer
= pinfo
->peer
;
11885 if (pinfo
->attr
->distance
)
11886 return pinfo
->attr
->distance
;
11888 /* Check source address. */
11889 sockunion2hostprefix(&peer
->su
, &q
);
11890 rn
= bgp_node_match(bgp_distance_table
[afi
][safi
], &q
);
11892 bdistance
= bgp_node_get_bgp_distance_info(rn
);
11893 bgp_unlock_node(rn
);
11895 if (bdistance
->access_list
) {
11896 alist
= access_list_lookup(afi
, bdistance
->access_list
);
11898 && access_list_apply(alist
, p
) == FILTER_PERMIT
)
11899 return bdistance
->distance
;
11901 return bdistance
->distance
;
11904 /* Backdoor check. */
11905 rn
= bgp_node_lookup(bgp
->route
[afi
][safi
], p
);
11907 bgp_static
= bgp_node_get_bgp_static_info(rn
);
11908 bgp_unlock_node(rn
);
11910 if (bgp_static
->backdoor
) {
11911 if (bgp
->distance_local
[afi
][safi
])
11912 return bgp
->distance_local
[afi
][safi
];
11914 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11918 if (peer
->sort
== BGP_PEER_EBGP
) {
11919 if (bgp
->distance_ebgp
[afi
][safi
])
11920 return bgp
->distance_ebgp
[afi
][safi
];
11921 return ZEBRA_EBGP_DISTANCE_DEFAULT
;
11923 if (bgp
->distance_ibgp
[afi
][safi
])
11924 return bgp
->distance_ibgp
[afi
][safi
];
11925 return ZEBRA_IBGP_DISTANCE_DEFAULT
;
11929 DEFUN (bgp_distance
,
11931 "distance bgp (1-255) (1-255) (1-255)",
11932 "Define an administrative distance\n"
11934 "Distance for routes external to the AS\n"
11935 "Distance for routes internal to the AS\n"
11936 "Distance for local routes\n")
11938 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11939 int idx_number
= 2;
11940 int idx_number_2
= 3;
11941 int idx_number_3
= 4;
11945 afi
= bgp_node_afi(vty
);
11946 safi
= bgp_node_safi(vty
);
11948 bgp
->distance_ebgp
[afi
][safi
] = atoi(argv
[idx_number
]->arg
);
11949 bgp
->distance_ibgp
[afi
][safi
] = atoi(argv
[idx_number_2
]->arg
);
11950 bgp
->distance_local
[afi
][safi
] = atoi(argv
[idx_number_3
]->arg
);
11951 return CMD_SUCCESS
;
11954 DEFUN (no_bgp_distance
,
11955 no_bgp_distance_cmd
,
11956 "no distance bgp [(1-255) (1-255) (1-255)]",
11958 "Define an administrative distance\n"
11960 "Distance for routes external to the AS\n"
11961 "Distance for routes internal to the AS\n"
11962 "Distance for local routes\n")
11964 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
11968 afi
= bgp_node_afi(vty
);
11969 safi
= bgp_node_safi(vty
);
11971 bgp
->distance_ebgp
[afi
][safi
] = 0;
11972 bgp
->distance_ibgp
[afi
][safi
] = 0;
11973 bgp
->distance_local
[afi
][safi
] = 0;
11974 return CMD_SUCCESS
;
11978 DEFUN (bgp_distance_source
,
11979 bgp_distance_source_cmd
,
11980 "distance (1-255) A.B.C.D/M",
11981 "Define an administrative distance\n"
11982 "Administrative distance\n"
11983 "IP source prefix\n")
11985 int idx_number
= 1;
11986 int idx_ipv4_prefixlen
= 2;
11987 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
11988 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
11989 return CMD_SUCCESS
;
11992 DEFUN (no_bgp_distance_source
,
11993 no_bgp_distance_source_cmd
,
11994 "no distance (1-255) A.B.C.D/M",
11996 "Define an administrative distance\n"
11997 "Administrative distance\n"
11998 "IP source prefix\n")
12000 int idx_number
= 2;
12001 int idx_ipv4_prefixlen
= 3;
12002 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12003 argv
[idx_ipv4_prefixlen
]->arg
, NULL
);
12004 return CMD_SUCCESS
;
12007 DEFUN (bgp_distance_source_access_list
,
12008 bgp_distance_source_access_list_cmd
,
12009 "distance (1-255) A.B.C.D/M WORD",
12010 "Define an administrative distance\n"
12011 "Administrative distance\n"
12012 "IP source prefix\n"
12013 "Access list name\n")
12015 int idx_number
= 1;
12016 int idx_ipv4_prefixlen
= 2;
12018 bgp_distance_set(vty
, argv
[idx_number
]->arg
,
12019 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12020 return CMD_SUCCESS
;
12023 DEFUN (no_bgp_distance_source_access_list
,
12024 no_bgp_distance_source_access_list_cmd
,
12025 "no distance (1-255) A.B.C.D/M WORD",
12027 "Define an administrative distance\n"
12028 "Administrative distance\n"
12029 "IP source prefix\n"
12030 "Access list name\n")
12032 int idx_number
= 2;
12033 int idx_ipv4_prefixlen
= 3;
12035 bgp_distance_unset(vty
, argv
[idx_number
]->arg
,
12036 argv
[idx_ipv4_prefixlen
]->arg
, argv
[idx_word
]->arg
);
12037 return CMD_SUCCESS
;
12040 DEFUN (ipv6_bgp_distance_source
,
12041 ipv6_bgp_distance_source_cmd
,
12042 "distance (1-255) X:X::X:X/M",
12043 "Define an administrative distance\n"
12044 "Administrative distance\n"
12045 "IP source prefix\n")
12047 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, NULL
);
12048 return CMD_SUCCESS
;
12051 DEFUN (no_ipv6_bgp_distance_source
,
12052 no_ipv6_bgp_distance_source_cmd
,
12053 "no distance (1-255) X:X::X:X/M",
12055 "Define an administrative distance\n"
12056 "Administrative distance\n"
12057 "IP source prefix\n")
12059 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, NULL
);
12060 return CMD_SUCCESS
;
12063 DEFUN (ipv6_bgp_distance_source_access_list
,
12064 ipv6_bgp_distance_source_access_list_cmd
,
12065 "distance (1-255) X:X::X:X/M WORD",
12066 "Define an administrative distance\n"
12067 "Administrative distance\n"
12068 "IP source prefix\n"
12069 "Access list name\n")
12071 bgp_distance_set(vty
, argv
[1]->arg
, argv
[2]->arg
, argv
[3]->arg
);
12072 return CMD_SUCCESS
;
12075 DEFUN (no_ipv6_bgp_distance_source_access_list
,
12076 no_ipv6_bgp_distance_source_access_list_cmd
,
12077 "no distance (1-255) X:X::X:X/M WORD",
12079 "Define an administrative distance\n"
12080 "Administrative distance\n"
12081 "IP source prefix\n"
12082 "Access list name\n")
12084 bgp_distance_unset(vty
, argv
[2]->arg
, argv
[3]->arg
, argv
[4]->arg
);
12085 return CMD_SUCCESS
;
12088 DEFUN (bgp_damp_set
,
12090 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12091 "BGP Specific commands\n"
12092 "Enable route-flap dampening\n"
12093 "Half-life time for the penalty\n"
12094 "Value to start reusing a route\n"
12095 "Value to start suppressing a route\n"
12096 "Maximum duration to suppress a stable route\n")
12098 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12099 int idx_half_life
= 2;
12101 int idx_suppress
= 4;
12102 int idx_max_suppress
= 5;
12103 int half
= DEFAULT_HALF_LIFE
* 60;
12104 int reuse
= DEFAULT_REUSE
;
12105 int suppress
= DEFAULT_SUPPRESS
;
12106 int max
= 4 * half
;
12109 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12110 reuse
= atoi(argv
[idx_reuse
]->arg
);
12111 suppress
= atoi(argv
[idx_suppress
]->arg
);
12112 max
= atoi(argv
[idx_max_suppress
]->arg
) * 60;
12113 } else if (argc
== 3) {
12114 half
= atoi(argv
[idx_half_life
]->arg
) * 60;
12118 if (suppress
< reuse
) {
12120 "Suppress value cannot be less than reuse value \n");
12124 return bgp_damp_enable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
), half
,
12125 reuse
, suppress
, max
);
12128 DEFUN (bgp_damp_unset
,
12129 bgp_damp_unset_cmd
,
12130 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
12132 "BGP Specific commands\n"
12133 "Enable route-flap dampening\n"
12134 "Half-life time for the penalty\n"
12135 "Value to start reusing a route\n"
12136 "Value to start suppressing a route\n"
12137 "Maximum duration to suppress a stable route\n")
12139 VTY_DECLVAR_CONTEXT(bgp
, bgp
);
12140 return bgp_damp_disable(bgp
, bgp_node_afi(vty
), bgp_node_safi(vty
));
12143 /* Display specified route of BGP table. */
12144 static int bgp_clear_damp_route(struct vty
*vty
, const char *view_name
,
12145 const char *ip_str
, afi_t afi
, safi_t safi
,
12146 struct prefix_rd
*prd
, int prefix_check
)
12149 struct prefix match
;
12150 struct bgp_node
*rn
;
12151 struct bgp_node
*rm
;
12152 struct bgp_path_info
*pi
;
12153 struct bgp_path_info
*pi_temp
;
12155 struct bgp_table
*table
;
12157 /* BGP structure lookup. */
12159 bgp
= bgp_lookup_by_name(view_name
);
12161 vty_out(vty
, "%% Can't find BGP instance %s\n",
12163 return CMD_WARNING
;
12166 bgp
= bgp_get_default();
12168 vty_out(vty
, "%% No BGP process is configured\n");
12169 return CMD_WARNING
;
12173 /* Check IP address argument. */
12174 ret
= str2prefix(ip_str
, &match
);
12176 vty_out(vty
, "%% address is malformed\n");
12177 return CMD_WARNING
;
12180 match
.family
= afi2family(afi
);
12182 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)
12183 || (safi
== SAFI_EVPN
)) {
12184 for (rn
= bgp_table_top(bgp
->rib
[AFI_IP
][safi
]); rn
;
12185 rn
= bgp_route_next(rn
)) {
12186 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
12188 table
= bgp_node_get_bgp_table_info(rn
);
12191 if ((rm
= bgp_node_match(table
, &match
)) == NULL
)
12195 || rm
->p
.prefixlen
== match
.prefixlen
) {
12196 pi
= bgp_node_get_bgp_path_info(rm
);
12198 if (pi
->extra
&& pi
->extra
->damp_info
) {
12199 pi_temp
= pi
->next
;
12200 bgp_damp_info_free(
12201 pi
->extra
->damp_info
,
12209 bgp_unlock_node(rm
);
12212 if ((rn
= bgp_node_match(bgp
->rib
[afi
][safi
], &match
))
12215 || rn
->p
.prefixlen
== match
.prefixlen
) {
12216 pi
= bgp_node_get_bgp_path_info(rn
);
12218 if (pi
->extra
&& pi
->extra
->damp_info
) {
12219 pi_temp
= pi
->next
;
12220 bgp_damp_info_free(
12221 pi
->extra
->damp_info
,
12229 bgp_unlock_node(rn
);
12233 return CMD_SUCCESS
;
12236 DEFUN (clear_ip_bgp_dampening
,
12237 clear_ip_bgp_dampening_cmd
,
12238 "clear ip bgp dampening",
12242 "Clear route flap dampening information\n")
12244 bgp_damp_info_clean();
12245 return CMD_SUCCESS
;
12248 DEFUN (clear_ip_bgp_dampening_prefix
,
12249 clear_ip_bgp_dampening_prefix_cmd
,
12250 "clear ip bgp dampening A.B.C.D/M",
12254 "Clear route flap dampening information\n"
12257 int idx_ipv4_prefixlen
= 4;
12258 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4_prefixlen
]->arg
,
12259 AFI_IP
, SAFI_UNICAST
, NULL
, 1);
12262 DEFUN (clear_ip_bgp_dampening_address
,
12263 clear_ip_bgp_dampening_address_cmd
,
12264 "clear ip bgp dampening A.B.C.D",
12268 "Clear route flap dampening information\n"
12269 "Network to clear damping information\n")
12272 return bgp_clear_damp_route(vty
, NULL
, argv
[idx_ipv4
]->arg
, AFI_IP
,
12273 SAFI_UNICAST
, NULL
, 0);
12276 DEFUN (clear_ip_bgp_dampening_address_mask
,
12277 clear_ip_bgp_dampening_address_mask_cmd
,
12278 "clear ip bgp dampening A.B.C.D A.B.C.D",
12282 "Clear route flap dampening information\n"
12283 "Network to clear damping information\n"
12287 int idx_ipv4_2
= 5;
12289 char prefix_str
[BUFSIZ
];
12291 ret
= netmask_str2prefix_str(argv
[idx_ipv4
]->arg
, argv
[idx_ipv4_2
]->arg
,
12294 vty_out(vty
, "%% Inconsistent address and mask\n");
12295 return CMD_WARNING
;
12298 return bgp_clear_damp_route(vty
, NULL
, prefix_str
, AFI_IP
, SAFI_UNICAST
,
12302 static void show_bgp_peerhash_entry(struct hash_bucket
*bucket
, void *arg
)
12304 struct vty
*vty
= arg
;
12305 struct peer
*peer
= bucket
->data
;
12306 char buf
[SU_ADDRSTRLEN
];
12308 vty_out(vty
, "\tPeer: %s %s\n", peer
->host
,
12309 sockunion2str(&peer
->su
, buf
, sizeof(buf
)));
12312 DEFUN (show_bgp_peerhash
,
12313 show_bgp_peerhash_cmd
,
12314 "show bgp peerhash",
12317 "Display information about the BGP peerhash\n")
12319 struct list
*instances
= bm
->bgp
;
12320 struct listnode
*node
;
12323 for (ALL_LIST_ELEMENTS_RO(instances
, node
, bgp
)) {
12324 vty_out(vty
, "BGP: %s\n", bgp
->name
);
12325 hash_iterate(bgp
->peerhash
, show_bgp_peerhash_entry
,
12329 return CMD_SUCCESS
;
12332 /* also used for encap safi */
12333 static void bgp_config_write_network_vpn(struct vty
*vty
, struct bgp
*bgp
,
12334 afi_t afi
, safi_t safi
)
12336 struct bgp_node
*prn
;
12337 struct bgp_node
*rn
;
12338 struct bgp_table
*table
;
12340 struct prefix_rd
*prd
;
12341 struct bgp_static
*bgp_static
;
12342 mpls_label_t label
;
12343 char buf
[SU_ADDRSTRLEN
];
12344 char rdbuf
[RD_ADDRSTRLEN
];
12346 /* Network configuration. */
12347 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12348 prn
= bgp_route_next(prn
)) {
12349 table
= bgp_node_get_bgp_table_info(prn
);
12353 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12354 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12355 if (bgp_static
== NULL
)
12359 prd
= (struct prefix_rd
*)&prn
->p
;
12361 /* "network" configuration display. */
12362 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12363 label
= decode_label(&bgp_static
->label
);
12365 vty_out(vty
, " network %s/%d rd %s",
12366 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
12368 p
->prefixlen
, rdbuf
);
12369 if (safi
== SAFI_MPLS_VPN
)
12370 vty_out(vty
, " label %u", label
);
12372 if (bgp_static
->rmap
.name
)
12373 vty_out(vty
, " route-map %s",
12374 bgp_static
->rmap
.name
);
12376 if (bgp_static
->backdoor
)
12377 vty_out(vty
, " backdoor");
12379 vty_out(vty
, "\n");
12384 static void bgp_config_write_network_evpn(struct vty
*vty
, struct bgp
*bgp
,
12385 afi_t afi
, safi_t safi
)
12387 struct bgp_node
*prn
;
12388 struct bgp_node
*rn
;
12389 struct bgp_table
*table
;
12391 struct prefix_rd
*prd
;
12392 struct bgp_static
*bgp_static
;
12393 char buf
[PREFIX_STRLEN
* 2];
12394 char buf2
[SU_ADDRSTRLEN
];
12395 char rdbuf
[RD_ADDRSTRLEN
];
12397 /* Network configuration. */
12398 for (prn
= bgp_table_top(bgp
->route
[afi
][safi
]); prn
;
12399 prn
= bgp_route_next(prn
)) {
12400 table
= bgp_node_get_bgp_table_info(prn
);
12404 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
12405 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12406 if (bgp_static
== NULL
)
12409 char *macrouter
= NULL
;
12412 if (bgp_static
->router_mac
)
12413 macrouter
= prefix_mac2str(
12414 bgp_static
->router_mac
, NULL
, 0);
12415 if (bgp_static
->eth_s_id
)
12416 esi
= esi2str(bgp_static
->eth_s_id
);
12418 prd
= (struct prefix_rd
*)&prn
->p
;
12420 /* "network" configuration display. */
12421 prefix_rd2str(prd
, rdbuf
, sizeof(rdbuf
));
12422 if (p
->u
.prefix_evpn
.route_type
== 5) {
12423 char local_buf
[PREFIX_STRLEN
];
12424 uint8_t family
= is_evpn_prefix_ipaddr_v4((
12425 struct prefix_evpn
*)p
)
12429 &p
->u
.prefix_evpn
.prefix_addr
.ip
.ip
.addr
,
12430 local_buf
, PREFIX_STRLEN
);
12431 sprintf(buf
, "%s/%u", local_buf
,
12432 p
->u
.prefix_evpn
.prefix_addr
.ip_prefix_length
);
12434 prefix2str(p
, buf
, sizeof(buf
));
12437 if (bgp_static
->gatewayIp
.family
== AF_INET
12438 || bgp_static
->gatewayIp
.family
== AF_INET6
)
12439 inet_ntop(bgp_static
->gatewayIp
.family
,
12440 &bgp_static
->gatewayIp
.u
.prefix
, buf2
,
12443 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
12445 p
->u
.prefix_evpn
.prefix_addr
.eth_tag
,
12446 decode_label(&bgp_static
->label
), esi
, buf2
,
12449 XFREE(MTYPE_TMP
, macrouter
);
12450 XFREE(MTYPE_TMP
, esi
);
12455 /* Configuration of static route announcement and aggregate
12457 void bgp_config_write_network(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12460 struct bgp_node
*rn
;
12462 struct bgp_static
*bgp_static
;
12463 struct bgp_aggregate
*bgp_aggregate
;
12464 char buf
[SU_ADDRSTRLEN
];
12466 if ((safi
== SAFI_MPLS_VPN
) || (safi
== SAFI_ENCAP
)) {
12467 bgp_config_write_network_vpn(vty
, bgp
, afi
, safi
);
12471 if (afi
== AFI_L2VPN
&& safi
== SAFI_EVPN
) {
12472 bgp_config_write_network_evpn(vty
, bgp
, afi
, safi
);
12476 /* Network configuration. */
12477 for (rn
= bgp_table_top(bgp
->route
[afi
][safi
]); rn
;
12478 rn
= bgp_route_next(rn
)) {
12479 bgp_static
= bgp_node_get_bgp_static_info(rn
);
12480 if (bgp_static
== NULL
)
12485 vty_out(vty
, " network %s/%d",
12486 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12489 if (bgp_static
->label_index
!= BGP_INVALID_LABEL_INDEX
)
12490 vty_out(vty
, " label-index %u",
12491 bgp_static
->label_index
);
12493 if (bgp_static
->rmap
.name
)
12494 vty_out(vty
, " route-map %s", bgp_static
->rmap
.name
);
12496 if (bgp_static
->backdoor
)
12497 vty_out(vty
, " backdoor");
12499 vty_out(vty
, "\n");
12502 /* Aggregate-address configuration. */
12503 for (rn
= bgp_table_top(bgp
->aggregate
[afi
][safi
]); rn
;
12504 rn
= bgp_route_next(rn
)) {
12505 bgp_aggregate
= bgp_node_get_bgp_aggregate_info(rn
);
12506 if (bgp_aggregate
== NULL
)
12511 vty_out(vty
, " aggregate-address %s/%d",
12512 inet_ntop(p
->family
, &p
->u
.prefix
, buf
, SU_ADDRSTRLEN
),
12515 if (bgp_aggregate
->as_set
)
12516 vty_out(vty
, " as-set");
12518 if (bgp_aggregate
->summary_only
)
12519 vty_out(vty
, " summary-only");
12521 if (bgp_aggregate
->rmap
.name
)
12522 vty_out(vty
, " route-map %s", bgp_aggregate
->rmap
.name
);
12524 vty_out(vty
, "\n");
12528 void bgp_config_write_distance(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
12531 struct bgp_node
*rn
;
12532 struct bgp_distance
*bdistance
;
12534 /* Distance configuration. */
12535 if (bgp
->distance_ebgp
[afi
][safi
] && bgp
->distance_ibgp
[afi
][safi
]
12536 && bgp
->distance_local
[afi
][safi
]
12537 && (bgp
->distance_ebgp
[afi
][safi
] != ZEBRA_EBGP_DISTANCE_DEFAULT
12538 || bgp
->distance_ibgp
[afi
][safi
] != ZEBRA_IBGP_DISTANCE_DEFAULT
12539 || bgp
->distance_local
[afi
][safi
]
12540 != ZEBRA_IBGP_DISTANCE_DEFAULT
)) {
12541 vty_out(vty
, " distance bgp %d %d %d\n",
12542 bgp
->distance_ebgp
[afi
][safi
],
12543 bgp
->distance_ibgp
[afi
][safi
],
12544 bgp
->distance_local
[afi
][safi
]);
12547 for (rn
= bgp_table_top(bgp_distance_table
[afi
][safi
]); rn
;
12548 rn
= bgp_route_next(rn
)) {
12549 bdistance
= bgp_node_get_bgp_distance_info(rn
);
12550 if (bdistance
!= NULL
) {
12551 char buf
[PREFIX_STRLEN
];
12553 vty_out(vty
, " distance %d %s %s\n",
12554 bdistance
->distance
,
12555 prefix2str(&rn
->p
, buf
, sizeof(buf
)),
12556 bdistance
->access_list
? bdistance
->access_list
12562 /* Allocate routing table structure and install commands. */
12563 void bgp_route_init(void)
12568 /* Init BGP distance table. */
12569 FOREACH_AFI_SAFI (afi
, safi
)
12570 bgp_distance_table
[afi
][safi
] = bgp_table_init(NULL
, afi
, safi
);
12572 /* IPv4 BGP commands. */
12573 install_element(BGP_NODE
, &bgp_table_map_cmd
);
12574 install_element(BGP_NODE
, &bgp_network_cmd
);
12575 install_element(BGP_NODE
, &no_bgp_table_map_cmd
);
12577 install_element(BGP_NODE
, &aggregate_address_cmd
);
12578 install_element(BGP_NODE
, &aggregate_address_mask_cmd
);
12579 install_element(BGP_NODE
, &no_aggregate_address_cmd
);
12580 install_element(BGP_NODE
, &no_aggregate_address_mask_cmd
);
12582 /* IPv4 unicast configuration. */
12583 install_element(BGP_IPV4_NODE
, &bgp_table_map_cmd
);
12584 install_element(BGP_IPV4_NODE
, &bgp_network_cmd
);
12585 install_element(BGP_IPV4_NODE
, &no_bgp_table_map_cmd
);
12587 install_element(BGP_IPV4_NODE
, &aggregate_address_cmd
);
12588 install_element(BGP_IPV4_NODE
, &aggregate_address_mask_cmd
);
12589 install_element(BGP_IPV4_NODE
, &no_aggregate_address_cmd
);
12590 install_element(BGP_IPV4_NODE
, &no_aggregate_address_mask_cmd
);
12592 /* IPv4 multicast configuration. */
12593 install_element(BGP_IPV4M_NODE
, &bgp_table_map_cmd
);
12594 install_element(BGP_IPV4M_NODE
, &bgp_network_cmd
);
12595 install_element(BGP_IPV4M_NODE
, &no_bgp_table_map_cmd
);
12596 install_element(BGP_IPV4M_NODE
, &aggregate_address_cmd
);
12597 install_element(BGP_IPV4M_NODE
, &aggregate_address_mask_cmd
);
12598 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_cmd
);
12599 install_element(BGP_IPV4M_NODE
, &no_aggregate_address_mask_cmd
);
12601 /* IPv4 labeled-unicast configuration. */
12602 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_cmd
);
12603 install_element(VIEW_NODE
, &show_ip_bgp_cmd
);
12604 install_element(VIEW_NODE
, &show_ip_bgp_json_cmd
);
12605 install_element(VIEW_NODE
, &show_ip_bgp_route_cmd
);
12606 install_element(VIEW_NODE
, &show_ip_bgp_regexp_cmd
);
12608 install_element(VIEW_NODE
,
12609 &show_ip_bgp_instance_neighbor_advertised_route_cmd
);
12610 install_element(VIEW_NODE
, &show_ip_bgp_neighbor_routes_cmd
);
12611 install_element(VIEW_NODE
,
12612 &show_ip_bgp_neighbor_received_prefix_filter_cmd
);
12613 #ifdef KEEP_OLD_VPN_COMMANDS
12614 install_element(VIEW_NODE
, &show_ip_bgp_vpn_all_route_prefix_cmd
);
12615 #endif /* KEEP_OLD_VPN_COMMANDS */
12616 install_element(VIEW_NODE
, &show_bgp_afi_vpn_rd_route_cmd
);
12617 install_element(VIEW_NODE
,
12618 &show_bgp_l2vpn_evpn_route_prefix_cmd
);
12620 /* BGP dampening clear commands */
12621 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_cmd
);
12622 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_prefix_cmd
);
12624 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_cmd
);
12625 install_element(ENABLE_NODE
, &clear_ip_bgp_dampening_address_mask_cmd
);
12628 install_element(ENABLE_NODE
,
12629 &show_ip_bgp_instance_neighbor_prefix_counts_cmd
);
12630 #ifdef KEEP_OLD_VPN_COMMANDS
12631 install_element(ENABLE_NODE
,
12632 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd
);
12633 #endif /* KEEP_OLD_VPN_COMMANDS */
12635 /* New config IPv6 BGP commands. */
12636 install_element(BGP_IPV6_NODE
, &bgp_table_map_cmd
);
12637 install_element(BGP_IPV6_NODE
, &ipv6_bgp_network_cmd
);
12638 install_element(BGP_IPV6_NODE
, &no_bgp_table_map_cmd
);
12640 install_element(BGP_IPV6_NODE
, &ipv6_aggregate_address_cmd
);
12641 install_element(BGP_IPV6_NODE
, &no_ipv6_aggregate_address_cmd
);
12643 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_network_cmd
);
12645 install_element(BGP_NODE
, &bgp_distance_cmd
);
12646 install_element(BGP_NODE
, &no_bgp_distance_cmd
);
12647 install_element(BGP_NODE
, &bgp_distance_source_cmd
);
12648 install_element(BGP_NODE
, &no_bgp_distance_source_cmd
);
12649 install_element(BGP_NODE
, &bgp_distance_source_access_list_cmd
);
12650 install_element(BGP_NODE
, &no_bgp_distance_source_access_list_cmd
);
12651 install_element(BGP_IPV4_NODE
, &bgp_distance_cmd
);
12652 install_element(BGP_IPV4_NODE
, &no_bgp_distance_cmd
);
12653 install_element(BGP_IPV4_NODE
, &bgp_distance_source_cmd
);
12654 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_cmd
);
12655 install_element(BGP_IPV4_NODE
, &bgp_distance_source_access_list_cmd
);
12656 install_element(BGP_IPV4_NODE
, &no_bgp_distance_source_access_list_cmd
);
12657 install_element(BGP_IPV4M_NODE
, &bgp_distance_cmd
);
12658 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_cmd
);
12659 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_cmd
);
12660 install_element(BGP_IPV4M_NODE
, &no_bgp_distance_source_cmd
);
12661 install_element(BGP_IPV4M_NODE
, &bgp_distance_source_access_list_cmd
);
12662 install_element(BGP_IPV4M_NODE
,
12663 &no_bgp_distance_source_access_list_cmd
);
12664 install_element(BGP_IPV6_NODE
, &bgp_distance_cmd
);
12665 install_element(BGP_IPV6_NODE
, &no_bgp_distance_cmd
);
12666 install_element(BGP_IPV6_NODE
, &ipv6_bgp_distance_source_cmd
);
12667 install_element(BGP_IPV6_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12668 install_element(BGP_IPV6_NODE
,
12669 &ipv6_bgp_distance_source_access_list_cmd
);
12670 install_element(BGP_IPV6_NODE
,
12671 &no_ipv6_bgp_distance_source_access_list_cmd
);
12672 install_element(BGP_IPV6M_NODE
, &bgp_distance_cmd
);
12673 install_element(BGP_IPV6M_NODE
, &no_bgp_distance_cmd
);
12674 install_element(BGP_IPV6M_NODE
, &ipv6_bgp_distance_source_cmd
);
12675 install_element(BGP_IPV6M_NODE
, &no_ipv6_bgp_distance_source_cmd
);
12676 install_element(BGP_IPV6M_NODE
,
12677 &ipv6_bgp_distance_source_access_list_cmd
);
12678 install_element(BGP_IPV6M_NODE
,
12679 &no_ipv6_bgp_distance_source_access_list_cmd
);
12681 install_element(BGP_NODE
, &bgp_damp_set_cmd
);
12682 install_element(BGP_NODE
, &bgp_damp_unset_cmd
);
12683 install_element(BGP_IPV4_NODE
, &bgp_damp_set_cmd
);
12684 install_element(BGP_IPV4_NODE
, &bgp_damp_unset_cmd
);
12686 /* IPv4 Multicast Mode */
12687 install_element(BGP_IPV4M_NODE
, &bgp_damp_set_cmd
);
12688 install_element(BGP_IPV4M_NODE
, &bgp_damp_unset_cmd
);
12690 /* Large Communities */
12691 install_element(VIEW_NODE
, &show_ip_bgp_large_community_list_cmd
);
12692 install_element(VIEW_NODE
, &show_ip_bgp_large_community_cmd
);
12694 /* show bgp ipv4 flowspec detailed */
12695 install_element(VIEW_NODE
, &show_ip_bgp_flowspec_routes_detailed_cmd
);
12697 install_element(VIEW_NODE
, &show_bgp_peerhash_cmd
);
12700 void bgp_route_finish(void)
12705 FOREACH_AFI_SAFI (afi
, safi
) {
12706 bgp_table_unlock(bgp_distance_table
[afi
][safi
]);
12707 bgp_distance_table
[afi
][safi
] = NULL
;