summaryrefslogtreecommitdiff
path: root/bgpd/bgp_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r--bgpd/bgp_route.c2124
1 files changed, 1030 insertions, 1094 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 40ecdbb670..97883418ef 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -28,6 +28,8 @@
#include "lib/json.h"
#include "lib_errors.h"
#include "zclient.h"
+#include "frrdistance.h"
+
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
@@ -77,7 +79,7 @@
#include "bgpd/bgp_route_clippy.c"
DEFINE_HOOK(bgp_snmp_update_stats,
- (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
+ (struct bgp_dest *rn, struct bgp_path_info *pi, bool added),
(rn, pi, added));
DEFINE_HOOK(bgp_rpki_prefix_status,
@@ -85,6 +87,11 @@ DEFINE_HOOK(bgp_rpki_prefix_status,
const struct prefix *prefix),
(peer, attr, prefix));
+DEFINE_HOOK(bgp_route_update,
+ (struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
+ struct bgp_path_info *old_route, struct bgp_path_info *new_route),
+ (bgp, afi, safi, bn, old_route, new_route));
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -113,7 +120,7 @@ DEFINE_HOOK(bgp_process,
(bgp, afi, safi, bn, peer, withdraw));
/** Test if path is suppressed. */
-static bool bgp_path_suppressed(struct bgp_path_info *pi)
+bool bgp_path_suppressed(struct bgp_path_info *pi)
{
if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
return false;
@@ -138,7 +145,9 @@ struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
bgp_dest_set_bgp_table_info(
pdest, bgp_table_init(table->bgp, afi, safi));
else
- bgp_dest_unlock_node(pdest);
+ pdest = bgp_dest_unlock_node(pdest);
+
+ assert(pdest);
table = bgp_dest_get_bgp_table_info(pdest);
}
@@ -188,8 +197,7 @@ static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
sizeof(struct bgp_path_info_extra));
new->label[0] = MPLS_INVALID_LABEL;
new->num_labels = 0;
- new->bgp_fs_pbr = NULL;
- new->bgp_fs_iprule = NULL;
+ new->flowspec = NULL;
return new;
}
@@ -206,8 +214,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
e->damp_info->safi);
e->damp_info = NULL;
- if (e->parent) {
- struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
+ if (e->vrfleak && e->vrfleak->parent) {
+ struct bgp_path_info *bpi =
+ (struct bgp_path_info *)e->vrfleak->parent;
if (bpi->net) {
/* FIXME: since multiple e may have the same e->parent
@@ -227,26 +236,38 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
bpi->net = NULL;
bgp_path_info_unlock(bpi);
}
- bgp_path_info_unlock(e->parent);
- e->parent = NULL;
+ bgp_path_info_unlock(e->vrfleak->parent);
+ e->vrfleak->parent = NULL;
}
- if (e->bgp_orig)
- bgp_unlock(e->bgp_orig);
+ if (e->vrfleak && e->vrfleak->bgp_orig)
+ bgp_unlock(e->vrfleak->bgp_orig);
- if (e->peer_orig)
- peer_unlock(e->peer_orig);
+ if (e->vrfleak && e->vrfleak->peer_orig)
+ peer_unlock(e->vrfleak->peer_orig);
if (e->aggr_suppressors)
list_delete(&e->aggr_suppressors);
- if (e->mh_info)
- bgp_evpn_path_mh_info_free(e->mh_info);
+ if (e->evpn && e->evpn->mh_info)
+ bgp_evpn_path_mh_info_free(e->evpn->mh_info);
+
+ if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_iprule)
+ list_delete(&((*extra)->flowspec->bgp_fs_iprule));
+ if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_pbr)
+ list_delete(&((*extra)->flowspec->bgp_fs_pbr));
+
+ if (e->evpn)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_EVPN, e->evpn);
+ if (e->flowspec)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_FS, e->flowspec);
+ if (e->vrfleak)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, e->vrfleak);
+#ifdef ENABLE_BGP_VNC
+ if (e->vnc)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_VNC, e->vnc);
+#endif
- if ((*extra)->bgp_fs_iprule)
- list_delete(&((*extra)->bgp_fs_iprule));
- if ((*extra)->bgp_fs_pbr)
- list_delete(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
}
@@ -257,6 +278,10 @@ struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
{
if (!pi->extra)
pi->extra = bgp_path_info_extra_new();
+ if (!pi->extra->evpn && pi->net && pi->net->rn->p.family == AF_EVPN)
+ pi->extra->evpn =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_EVPN,
+ sizeof(struct bgp_path_info_extra_evpn));
return pi->extra;
}
@@ -298,6 +323,29 @@ struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
return path;
}
+bool bgp_path_info_nexthop_changed(struct bgp_path_info *pi, struct peer *to,
+ afi_t afi)
+{
+ if (pi->peer->sort == BGP_PEER_IBGP && to->sort == BGP_PEER_IBGP &&
+ !CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_FORCE_NEXTHOP_SELF))
+ /* IBGP RR with no nexthop self force configured */
+ return false;
+
+ if (to->sort == BGP_PEER_IBGP &&
+ !CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_NEXTHOP_SELF))
+ /* IBGP RR with no nexthop self configured */
+ return false;
+
+ if (CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_NEXTHOP_UNCHANGED))
+ /* IBGP or EBGP with nexthop attribute unchanged */
+ return false;
+
+ return true;
+}
+
/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
{
@@ -403,7 +451,8 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
/* Do the actual removal of info from RIB, for use by bgp_process
completion callback *only* */
-void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
+struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
+ struct bgp_path_info *pi)
{
if (pi->next)
pi->next->prev = pi->prev;
@@ -415,7 +464,8 @@ void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
bgp_path_info_mpath_dequeue(pi);
bgp_path_info_unlock(pi);
hook_call(bgp_snmp_update_stats, dest, pi, false);
- bgp_dest_unlock_node(dest);
+
+ return bgp_dest_unlock_node(dest);
}
void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
@@ -522,6 +572,11 @@ void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
{
struct peer *peer;
+ if (!pi) {
+ snprintf(buf, buf_len, "NONE");
+ return;
+ }
+
if (pi->sub_type == BGP_ROUTE_IMPORTED &&
bgp_get_imported_bpi_ultimate(pi))
peer = bgp_get_imported_bpi_ultimate(pi)->peer;
@@ -547,8 +602,9 @@ struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
return info;
for (bpi_ultimate = info;
- bpi_ultimate->extra && bpi_ultimate->extra->parent;
- bpi_ultimate = bpi_ultimate->extra->parent)
+ bpi_ultimate->extra && bpi_ultimate->extra->vrfleak &&
+ bpi_ultimate->extra->vrfleak->parent;
+ bpi_ultimate = bpi_ultimate->extra->vrfleak->parent)
;
return bpi_ultimate;
@@ -556,16 +612,18 @@ struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
*/
-static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
- struct bgp_path_info *exist, int *paths_eq,
- struct bgp_maxpaths_cfg *mpath_cfg, int debug,
- char *pfx_buf, afi_t afi, safi_t safi,
- enum bgp_path_selection_reason *reason)
+int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
+ struct bgp_path_info *exist, int *paths_eq,
+ struct bgp_maxpaths_cfg *mpath_cfg, bool debug,
+ char *pfx_buf, afi_t afi, safi_t safi,
+ enum bgp_path_selection_reason *reason)
{
const struct prefix *new_p;
struct attr *newattr, *existattr;
enum bgp_peer_sort new_sort;
enum bgp_peer_sort exist_sort;
+ enum bgp_peer_sub_sort new_sub_sort;
+ enum bgp_peer_sub_sort exist_sub_sort;
uint32_t new_pref;
uint32_t exist_pref;
uint32_t new_med;
@@ -679,16 +737,6 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
* sticky flag.
*/
if (newattr->sticky != existattr->sticky) {
- if (!debug) {
- prefix2str(new_p, pfx_buf,
- sizeof(*pfx_buf)
- * PREFIX2STR_BUFFER);
- bgp_path_info_path_with_addpath_rx_str(
- new, new_buf, sizeof(new_buf));
- bgp_path_info_path_with_addpath_rx_str(
- exist, exist_buf, sizeof(exist_buf));
- }
-
if (newattr->sticky && !existattr->sticky) {
*reason = bgp_path_selection_evpn_sticky_mac;
if (debug)
@@ -1110,26 +1158,34 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
/* 7. Peer type check. */
new_sort = peer_new->sort;
exist_sort = peer_exist->sort;
+ new_sub_sort = peer_new->sub_sort;
+ exist_sub_sort = peer_exist->sub_sort;
- if (new_sort == BGP_PEER_EBGP
- && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
+ if (new_sort == BGP_PEER_EBGP &&
+ (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED ||
+ exist_sub_sort == BGP_PEER_EBGP_OAD)) {
*reason = bgp_path_selection_peer;
if (debug)
- zlog_debug(
- "%s: %s wins over %s due to eBGP peer > iBGP peer",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s wins over %s due to eBGP peer > %s peer",
+ pfx_buf, new_buf, exist_buf,
+ (exist_sub_sort == BGP_PEER_EBGP_OAD)
+ ? "eBGP-OAD"
+ : "iBGP");
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
return 1;
peer_sort_ret = 1;
}
- if (exist_sort == BGP_PEER_EBGP
- && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
+ if (exist_sort == BGP_PEER_EBGP &&
+ (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED ||
+ new_sub_sort == BGP_PEER_EBGP_OAD)) {
*reason = bgp_path_selection_peer;
if (debug)
- zlog_debug(
- "%s: %s loses to %s due to iBGP peer < eBGP peer",
- pfx_buf, new_buf, exist_buf);
+ zlog_debug("%s: %s loses to %s due to %s peer < eBGP peer",
+ pfx_buf, new_buf, exist_buf,
+ (exist_sub_sort == BGP_PEER_EBGP_OAD)
+ ? "eBGP-OAD"
+ : "iBGP");
if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
return 0;
peer_sort_ret = 0;
@@ -1463,13 +1519,18 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
- struct bgp_path_info *exist, int *paths_eq)
+ struct bgp_path_info *exist, int *paths_eq,
+ bool debug)
{
enum bgp_path_selection_reason reason;
- char pfx_buf[PREFIX2STR_BUFFER];
+ char pfx_buf[PREFIX2STR_BUFFER] = {};
+
+ if (debug)
+ prefix2str(bgp_dest_get_prefix(new->net), pfx_buf,
+ sizeof(pfx_buf));
- return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
- AFI_L2VPN, SAFI_EVPN, &reason);
+ return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, debug,
+ pfx_buf, AFI_L2VPN, SAFI_EVPN, &reason);
}
/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
@@ -1483,8 +1544,10 @@ int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
{
int paths_eq;
int ret;
- ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
- afi, safi, reason);
+ bool debug = false;
+
+ ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, debug,
+ pfx_buf, afi, safi, reason);
if (paths_eq)
ret = 0;
@@ -1996,6 +2059,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
bool nh_reset = false;
uint64_t cum_bw;
+ mpls_label_t label;
if (DISABLE_BGP_ANNOUNCE)
return false;
@@ -2081,7 +2145,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* If it's labeled safi, make sure the route has a valid label. */
if (safi == SAFI_LABELED_UNICAST) {
- mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
+ label = bgp_adv_label(dest, pi, peer, afi, safi);
if (!bgp_is_valid_label(&label)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug("u%" PRIu64 ":s%" PRIu64
@@ -2090,6 +2154,29 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
p, &label);
return false;
}
+ } else if (safi == SAFI_MPLS_VPN &&
+ CHECK_FLAG(pi->flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND) &&
+ pi->mplsvpn.bmnc.nh_label_bind_cache && peer &&
+ pi->peer != peer && pi->sub_type != BGP_ROUTE_IMPORTED &&
+ pi->sub_type != BGP_ROUTE_STATIC &&
+ bgp_mplsvpn_path_uses_valid_mpls_label(pi) &&
+ bgp_path_info_nexthop_changed(pi, peer, afi)) {
+ /* Redistributed mpls vpn route between distinct
+ * peers from 'pi->peer' to 'to',
+ * and an mpls label is used in this path,
+ * and there is a nh label bind entry,
+ * then get appropriate mpls local label
+ * and check its validity
+ */
+ label = bgp_mplsvpn_nh_label_bind_get_label(pi);
+ if (!bgp_is_valid_label(&label)) {
+ if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " %pFX is filtered - no valid label",
+ subgrp->update_group->id, subgrp->id,
+ p);
+ return false;
+ }
}
/* Do not send back route to sender. */
@@ -2101,9 +2188,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* configured for default-originate */
if (CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE)) {
- if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
- return false;
- else if (p->family == AF_INET6 && p->prefixlen == 0)
+ if ((p->family == AF_INET || p->family == AF_INET6) && p->prefixlen == 0)
return false;
}
@@ -2134,10 +2219,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* ORF prefix-list filter check */
- if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
- && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
+ if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) &&
+ CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV))
if (peer->orf_plist[afi][safi]) {
if (prefix_list_apply(peer->orf_plist[afi][safi], p)
== PREFIX_DENY) {
@@ -2159,7 +2242,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* AS path loop check. */
- if (peer->as_path_loop_detection &&
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_AS_LOOP_DETECTION) &&
aspath_loop_check(piattr->aspath, peer->as)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
@@ -2220,6 +2303,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
else
*attr = *piattr;
+ /* don't confuse inbound and outbound setting */
+ RESET_FLAG(attr->rmap_change_flags);
+
/* If local-preference is not set. */
if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
&& (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
@@ -2237,8 +2323,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* Remove MED if its an EBGP peer - will get overwritten by route-maps
*/
- if (peer->sort == BGP_PEER_EBGP
- && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD &&
+ attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
if (from != bgp->peer_self && !transparent
&& !CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MED_UNCHANGED))
@@ -2316,9 +2402,6 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_otc_egress(peer, attr))
return false;
- bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
- bgp_peer_as_override(bgp, afi, safi, peer, attr);
-
if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
filter->advmap.aname &&
route_map_lookup_by_name(filter->advmap.aname)) {
@@ -2355,10 +2438,6 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* Fill temp path_info */
prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
pi, peer, attr);
-
- /* don't confuse inbound and outbound setting */
- RESET_FLAG(attr->rmap_change_flags);
-
/*
* The route reflector is not allowed to modify the attributes
* of the reflected IBGP routes unless explicitly allowed.
@@ -2395,6 +2474,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
}
+ bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
+ bgp_peer_as_override(bgp, afi, safi, peer, attr);
+
/* RFC 8212 to prevent route leaks.
* This specification intends to improve this situation by requiring the
* explicit configuration of both BGP Import and Export Policies for any
@@ -2456,8 +2538,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
return false;
if (bgp_in_graceful_shutdown(bgp)) {
- if (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED) {
+ if (peer->sort == BGP_PEER_IBGP ||
+ peer->sort == BGP_PEER_CONFED ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) {
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
attr->local_pref = BGP_GSHUT_LOCAL_PREF;
} else {
@@ -2587,17 +2670,25 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* If this is an iBGP, send Origin Validation State (OVS)
* extended community (rfc8097).
+ * draft-uttaro-idr-bgp-oad states:
+ * For example, the Origin Validation State Extended Community,
+ * defined as non-transitive in [RFC8097], can be advertised to
+ * peers in the same OAD.
*/
- if (peer->sort == BGP_PEER_IBGP) {
+ if ((peer->sort == BGP_PEER_IBGP ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD) &&
+ peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY_RPKI)) {
enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
if (rpki_state != RPKI_NOT_BEING_USED)
- bgp_attr_set_ecommunity(
- attr, ecommunity_add_origin_validation_state(
- rpki_state,
- bgp_attr_get_ecommunity(attr)));
+ bgp_attr_set_ecommunity(attr,
+ ecommunity_add_origin_validation_state(
+ rpki_state,
+ bgp_attr_get_ecommunity(
+ attr)));
}
/*
@@ -2651,9 +2742,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *pi1;
struct bgp_path_info *pi2;
struct bgp_path_info *nextpi = NULL;
- int paths_eq, do_mpath, debug;
+ int paths_eq, do_mpath;
+ bool debug;
struct list mp_list;
- char pfx_buf[PREFIX2STR_BUFFER];
+ char pfx_buf[PREFIX2STR_BUFFER] = {};
char path_buf[PATH_ADDPATH_STR_BUFFER];
bgp_mp_list_init(&mp_list);
@@ -2685,47 +2777,40 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (pi1->peer != bgp->peer_self &&
!CHECK_FLAG(pi1->peer->sflags,
PEER_STATUS_NSF_WAIT)) {
- if (!peer_established(pi1->peer))
+ if (!peer_established(pi1->peer->connection))
continue;
}
new_select = pi1;
- if (pi1->next) {
- for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
- if (CHECK_FLAG(pi2->flags,
- BGP_PATH_DMED_CHECK))
- continue;
- if (BGP_PATH_HOLDDOWN(pi2))
- continue;
- if (pi2->peer != bgp->peer_self
- && !CHECK_FLAG(
- pi2->peer->sflags,
- PEER_STATUS_NSF_WAIT))
- if (pi2->peer->status
- != Established)
- continue;
-
- if (!aspath_cmp_left(pi1->attr->aspath,
- pi2->attr->aspath)
- && !aspath_cmp_left_confed(
- pi1->attr->aspath,
- pi2->attr->aspath))
- continue;
+ for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
+ if (CHECK_FLAG(pi2->flags, BGP_PATH_DMED_CHECK))
+ continue;
+ if (BGP_PATH_HOLDDOWN(pi2))
+ continue;
+ if (pi2->peer != bgp->peer_self &&
+ !CHECK_FLAG(pi2->peer->sflags,
+ PEER_STATUS_NSF_WAIT) &&
+ !peer_established(pi2->peer->connection))
+ continue;
- if (bgp_path_info_cmp(
- bgp, pi2, new_select,
- &paths_eq, mpath_cfg, debug,
- pfx_buf, afi, safi,
- &dest->reason)) {
- bgp_path_info_unset_flag(
- dest, new_select,
- BGP_PATH_DMED_SELECTED);
- new_select = pi2;
- }
+ if (!aspath_cmp_left(pi1->attr->aspath,
+ pi2->attr->aspath) &&
+ !aspath_cmp_left_confed(pi1->attr->aspath,
+ pi2->attr->aspath))
+ continue;
- bgp_path_info_set_flag(
- dest, pi2, BGP_PATH_DMED_CHECK);
+ if (bgp_path_info_cmp(bgp, pi2, new_select,
+ &paths_eq, mpath_cfg,
+ debug, pfx_buf, afi, safi,
+ &dest->reason)) {
+ bgp_path_info_unset_flag(dest,
+ new_select,
+ BGP_PATH_DMED_SELECTED);
+ new_select = pi2;
}
+
+ bgp_path_info_set_flag(dest, pi2,
+ BGP_PATH_DMED_CHECK);
}
bgp_path_info_set_flag(dest, new_select,
BGP_PATH_DMED_CHECK);
@@ -2758,23 +2843,24 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
/* reap REMOVED routes, if needs be
* selected route must stay for a while longer though
*/
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
- && (pi != old_select))
- bgp_path_info_reap(dest, pi);
-
if (debug)
zlog_debug(
"%s: %pBD(%s) pi from %s in holddown",
__func__, dest, bgp->name_pretty,
pi->peer->host);
+ if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
+ (pi != old_select)) {
+ dest = bgp_path_info_reap(dest, pi);
+ assert(dest);
+ }
+
continue;
}
if (pi->peer && pi->peer != bgp->peer_self
&& !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
- if (!peer_established(pi->peer)) {
-
+ if (!peer_established(pi->peer->connection)) {
if (debug)
zlog_debug(
"%s: %pBD(%s) non self peer %s not estab state",
@@ -2785,9 +2871,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
continue;
}
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
- && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
+ bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
+ (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
if (debug)
zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
dest, bgp->name_pretty,
@@ -2795,8 +2882,6 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
continue;
}
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
-
reason = dest->reason;
if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
debug, pfx_buf, afi, safi,
@@ -2813,11 +2898,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
* qualify as multipaths
*/
if (debug) {
- if (new_select)
- bgp_path_info_path_with_addpath_rx_str(
- new_select, path_buf, sizeof(path_buf));
- else
- snprintf(path_buf, sizeof(path_buf), "NONE");
+ bgp_path_info_path_with_addpath_rx_str(new_select, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pBD(%s): After path selection, newbest is %s oldbest was %s",
dest, bgp->name_pretty, path_buf,
@@ -2825,9 +2907,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
if (do_mpath && new_select) {
- for (pi = bgp_dest_get_bgp_path_info(dest);
- (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
-
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (debug)
bgp_path_info_path_with_addpath_rx_str(
pi, path_buf, sizeof(path_buf));
@@ -2848,7 +2928,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (pi->peer && pi->peer != bgp->peer_self
&& !CHECK_FLAG(pi->peer->sflags,
PEER_STATUS_NSF_WAIT))
- if (!peer_established(pi->peer))
+ if (!peer_established(pi->peer->connection))
continue;
if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
@@ -2894,20 +2974,16 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
*/
void subgroup_process_announce_selected(struct update_subgroup *subgrp,
struct bgp_path_info *selected,
- struct bgp_dest *dest,
- uint32_t addpath_tx_id)
+ struct bgp_dest *dest, afi_t afi,
+ safi_t safi, uint32_t addpath_tx_id)
{
const struct prefix *p;
struct peer *onlypeer;
- struct attr attr;
- afi_t afi;
- safi_t safi;
+ struct attr attr = { 0 }, *pattr = &attr;
struct bgp *bgp;
bool advertise;
p = bgp_dest_get_prefix(dest);
- afi = SUBGRP_AFI(subgrp);
- safi = SUBGRP_SAFI(subgrp);
bgp = SUBGRP_INST(subgrp);
onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
: NULL);
@@ -2928,29 +3004,33 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
* is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
* route
*/
- advertise = bgp_check_advertise(bgp, dest);
+ advertise = bgp_check_advertise(bgp, dest, safi);
if (selected) {
- if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
+ if (subgroup_announce_check(dest, selected, subgrp, p, pattr,
NULL)) {
/* Route is selected, if the route is already installed
* in FIB, then it is advertised
*/
if (advertise) {
- if (!bgp_check_withdrawal(bgp, dest)) {
- struct attr *adv_attr =
- bgp_attr_intern(&attr);
-
- bgp_adj_out_set_subgroup(dest, subgrp,
- adv_attr,
- selected);
- } else
+ if (!bgp_check_withdrawal(bgp, dest, safi)) {
+ if (!bgp_adj_out_set_subgroup(dest,
+ subgrp,
+ pattr,
+ selected))
+ bgp_attr_flush(pattr);
+ } else {
bgp_adj_out_unset_subgroup(
dest, subgrp, 1, addpath_tx_id);
- }
- } else
+ bgp_attr_flush(pattr);
+ }
+ } else
+ bgp_attr_flush(pattr);
+ } else {
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
addpath_tx_id);
+ bgp_attr_flush(pattr);
+ }
}
/* If selected is NULL we must withdraw the path using addpath_tx_id */
@@ -3087,10 +3167,13 @@ static bool bgp_lu_need_null_label(struct bgp *bgp,
need_null_label:
if (label == NULL)
return true;
- if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_EXPLICIT_NULL))
- /* Disable PHP : explicit-null */
- *label = afi == AFI_IP ? MPLS_LABEL_IPV4_EXPLICIT_NULL
- : MPLS_LABEL_IPV6_EXPLICIT_NULL;
+ /* Disable PHP : explicit-null */
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&
+ afi == AFI_IP)
+ *label = MPLS_LABEL_IPV4_EXPLICIT_NULL;
+ else if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL) &&
+ afi == AFI_IP6)
+ *label = MPLS_LABEL_IPV6_EXPLICIT_NULL;
else
/* Enforced PHP popping: implicit-null */
*label = MPLS_LABEL_IMPLICIT_NULL;
@@ -3098,6 +3181,112 @@ need_null_label:
return true;
}
+/* Right now, since we only deal with per-prefix labels, it is not
+ * necessary to do this upon changes to best path. Exceptions:
+ * - label index has changed -> recalculate resulting label
+ * - path_info sub_type changed -> switch to/from null label value
+ * - no valid label (due to removed static label binding) -> get new one
+ */
+static void bgp_lu_handle_label_allocation(struct bgp *bgp,
+ struct bgp_dest *dest,
+ struct bgp_path_info *new_select,
+ struct bgp_path_info *old_select,
+ afi_t afi)
+{
+ mpls_label_t mpls_label_null;
+
+ if (bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
+ if (new_select) {
+ if (!old_select ||
+ bgp_label_index_differs(new_select, old_select) ||
+ new_select->sub_type != old_select->sub_type ||
+ !bgp_is_valid_label(&dest->local_label)) {
+ /* control label imposition for local
+ * routes, aggregate and redistributed
+ * routes
+ */
+ mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
+ if (bgp_lu_need_null_label(bgp, new_select, afi,
+ &mpls_label_null)) {
+ if (CHECK_FLAG(
+ dest->flags,
+ BGP_NODE_REGISTERED_FOR_LABEL) ||
+ CHECK_FLAG(
+ dest->flags,
+ BGP_NODE_LABEL_REQUESTED))
+ bgp_unregister_for_label(dest);
+ dest->local_label = mpls_lse_encode(
+ mpls_label_null, 0, 0, 1);
+ bgp_set_valid_label(&dest->local_label);
+ } else
+ bgp_register_for_label(dest,
+ new_select);
+ }
+ } else if (CHECK_FLAG(dest->flags,
+ BGP_NODE_REGISTERED_FOR_LABEL) ||
+ CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
+ bgp_unregister_for_label(dest);
+ }
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL) ||
+ CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
+ bgp_unregister_for_label(dest);
+ }
+}
+
+static struct interface *
+bgp_label_get_resolved_nh_iface(const struct bgp_path_info *pi)
+{
+ struct nexthop *nh;
+
+ if (pi->nexthop == NULL || pi->nexthop->nexthop == NULL ||
+ !CHECK_FLAG(pi->nexthop->flags, BGP_NEXTHOP_VALID))
+ /* next-hop is not valid */
+ return NULL;
+
+ nh = pi->nexthop->nexthop;
+ if (nh->ifindex == IFINDEX_INTERNAL &&
+ nh->type != NEXTHOP_TYPE_IPV4_IFINDEX &&
+ nh->type != NEXTHOP_TYPE_IPV6_IFINDEX)
+ /* next-hop does not contain valid interface */
+ return NULL;
+
+ return if_lookup_by_index(nh->ifindex, nh->vrf_id);
+}
+
+static void
+bgp_mplsvpn_handle_label_allocation(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *new_select,
+ struct bgp_path_info *old_select, afi_t afi)
+{
+ struct interface *ifp;
+ struct bgp_interface *bgp_ifp;
+
+ if (bgp->allocate_mpls_labels[afi][SAFI_MPLS_VPN] && new_select) {
+ ifp = bgp_label_get_resolved_nh_iface(new_select);
+ if (ifp)
+ bgp_ifp = (struct bgp_interface *)(ifp->info);
+ else
+ bgp_ifp = NULL;
+ if (bgp_ifp &&
+ CHECK_FLAG(bgp_ifp->flags,
+ BGP_INTERFACE_MPLS_L3VPN_SWITCHING) &&
+ bgp_mplsvpn_path_uses_valid_mpls_label(new_select) &&
+ new_select->sub_type != BGP_ROUTE_IMPORTED &&
+ new_select->sub_type != BGP_ROUTE_STATIC)
+ bgp_mplsvpn_nh_label_bind_register_local_label(
+ bgp, dest, new_select);
+ else
+ bgp_mplsvpn_path_nh_label_bind_unlink(new_select);
+ } else {
+ if (new_select)
+ /* no mpls vpn allocation */
+ bgp_mplsvpn_path_nh_label_bind_unlink(new_select);
+ else if (old_select)
+ /* unlink old selection if any */
+ bgp_mplsvpn_path_nh_label_bind_unlink(old_select);
+ }
+}
+
/*
* old_select = The old best path
* new_select = the new best path
@@ -3124,7 +3313,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info *old_select;
struct bgp_path_info_pair old_and_new;
int debug = 0;
- mpls_label_t mpls_label_null;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
if (dest)
@@ -3175,49 +3363,18 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
old_select = old_and_new.old;
new_select = old_and_new.new;
- /* Do we need to allocate or free labels?
- * Right now, since we only deal with per-prefix labels, it is not
- * necessary to do this upon changes to best path. Exceptions:
- * - label index has changed -> recalculate resulting label
- * - path_info sub_type changed -> switch to/from null label value
- * - no valid label (due to removed static label binding) -> get new one
- */
- if (bgp->allocate_mpls_labels[afi][safi]) {
- if (new_select) {
- if (!old_select
- || bgp_label_index_differs(new_select, old_select)
- || new_select->sub_type != old_select->sub_type
- || !bgp_is_valid_label(&dest->local_label)) {
- /* control label imposition for local routes,
- * aggregate and redistributed routes
- */
- mpls_label_null = MPLS_LABEL_IMPLICIT_NULL;
- if (bgp_lu_need_null_label(bgp, new_select, afi,
- &mpls_label_null)) {
- if (CHECK_FLAG(
- dest->flags,
- BGP_NODE_REGISTERED_FOR_LABEL)
- || CHECK_FLAG(
- dest->flags,
- BGP_NODE_LABEL_REQUESTED))
- bgp_unregister_for_label(dest);
- dest->local_label = mpls_lse_encode(
- mpls_label_null, 0, 0, 1);
- bgp_set_valid_label(&dest->local_label);
- } else
- bgp_register_for_label(dest,
- new_select);
- }
- } else if (CHECK_FLAG(dest->flags,
- BGP_NODE_REGISTERED_FOR_LABEL)
- || CHECK_FLAG(dest->flags,
- BGP_NODE_LABEL_REQUESTED)) {
- bgp_unregister_for_label(dest);
- }
- } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
- || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
- bgp_unregister_for_label(dest);
- }
+ if (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)
+ /* label unicast path :
+ * Do we need to allocate or free labels?
+ */
+ bgp_lu_handle_label_allocation(bgp, dest, new_select,
+ old_select, afi);
+ else if (safi == SAFI_MPLS_VPN)
+ /* mpls vpn path:
+ * Do we need to allocate or free labels?
+ */
+ bgp_mplsvpn_handle_label_allocation(bgp, dest, new_select,
+ old_select, afi);
if (debug)
zlog_debug(
@@ -3228,10 +3385,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
/* If best route remains the same and this is not due to user-initiated
* clear, see exactly what needs to be done.
*/
- if (old_select && old_select == new_select
- && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
- && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
- && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
+ if (old_select && old_select == new_select &&
+ !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR) &&
+ !CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_CLEAR) &&
+ !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) &&
+ !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
if (bgp_zebra_has_route_changed(old_select)) {
#ifdef ENABLE_BGP_VNC
vnc_import_bgp_add_route(bgp, p, old_select);
@@ -3244,9 +3402,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type
== BGP_ROUTE_IMPORTED))
-
- bgp_zebra_announce(dest, p, old_select,
- bgp, afi, safi);
+ bgp_zebra_route_install(dest, old_select,
+ bgp, true, NULL,
+ false);
}
}
@@ -3285,20 +3443,23 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
+ /* If the process wants to force deletion this flag will be set
+ */
+ UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_CLEAR);
+
/* bestpath has changed; bump version */
if (old_select || new_select) {
bgp_bump_version(dest);
- if (!bgp->t_rmap_def_originate_eval) {
- bgp_lock(bgp);
+ if (!bgp->t_rmap_def_originate_eval)
event_add_timer(
bm->master,
update_group_refresh_default_originate_route_map,
- bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
+ bgp, bgp->rmap_def_originate_eval_timer,
&bgp->t_rmap_def_originate_eval);
- }
}
+ /* TODO BMP insert rib update hook */
if (old_select)
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
@@ -3311,6 +3472,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
}
+ /* call bmp hook for loc-rib route update / withdraw after flags were
+ * set
+ */
+ if (old_select || new_select) {
+ hook_call(bgp_route_update, bgp, afi, safi, dest, old_select,
+ new_select);
+ }
+
+
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (old_select != new_select) {
@@ -3328,14 +3498,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
}
#endif
- group_announce_route(bgp, afi, safi, dest, new_select);
-
- /* unicast routes must also be annouced to labeled-unicast update-groups
- */
- if (safi == SAFI_UNICAST)
- group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
- new_select);
-
/* FIB update. */
if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
@@ -3351,9 +3513,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
if (old_select &&
is_route_parent_evpn(old_select))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, NULL, false);
- bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
+ bgp_zebra_route_install(dest, new_select, bgp, true,
+ NULL, false);
} else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@@ -3361,21 +3525,32 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, bgp, safi);
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, NULL, false);
}
}
+ group_announce_route(bgp, afi, safi, dest, new_select);
+
+ /* unicast routes must also be annouced to labeled-unicast update-groups
+ */
+ if (safi == SAFI_UNICAST)
+ group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
+ new_select);
+
+
bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
old_select);
/* Clear any route change flags. */
bgp_zebra_clear_route_change_flags(dest);
+ UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
+
/* Reap old select bgp_path_info, if it has been removed */
if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
bgp_path_info_reap(dest, old_select);
- UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
return;
}
@@ -3593,10 +3768,8 @@ void bgp_add_eoiu_mark(struct bgp *bgp)
static void bgp_maximum_prefix_restart_timer(struct event *thread)
{
- struct peer *peer;
-
- peer = EVENT_ARG(thread);
- peer->t_pmax_restart = NULL;
+ struct peer_connection *connection = EVENT_ARG(thread);
+ struct peer *peer = connection->peer;
if (bgp_debug_neighbor_events(peer))
zlog_debug(
@@ -3654,6 +3827,7 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
? bgp_filtered_routes_count(peer, afi, safi)
+ peer->pcount[afi][safi]
: peer->pcount[afi][safi];
+ struct peer_connection *connection = peer->connection;
if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
return false;
@@ -3689,7 +3863,7 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
ndata[6] = (peer->pmax[afi][safi]);
SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
+ bgp_notify_send_with_data(connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_MAX_PREFIX,
ndata, 7);
}
@@ -3708,7 +3882,7 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
"%pBP Maximum-prefix restart timer started for %d secs",
peer, peer->v_pmax_restart);
- BGP_TIMER_ON(peer->t_pmax_restart,
+ BGP_TIMER_ON(connection->t_pmax_restart,
bgp_maximum_prefix_restart_timer,
peer->v_pmax_restart);
}
@@ -4016,7 +4190,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
int aspath_loop_count = 0;
struct bgp_dest *dest;
struct bgp *bgp;
- struct attr new_attr;
+ struct attr new_attr = {};
struct attr *attr_new;
struct bgp_path_info *pi;
struct bgp_path_info *new = NULL;
@@ -4029,7 +4203,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
afi_t nh_afi;
bool force_evpn_import = false;
safi_t orig_safi = safi;
- bool leak_success = true;
int allowas_in = 0;
if (frrtrace_enabled(frr_bgp, process_update)) {
@@ -4050,10 +4223,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (orig_safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
- memset(&new_attr, 0, sizeof(new_attr));
- new_attr.label_index = BGP_INVALID_LABEL_INDEX;
- new_attr.label = MPLS_INVALID_LABEL;
-
bgp = peer->bgp;
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
/* TODO: Check to see if we can get rid of "is_valid_label" */
@@ -4173,6 +4342,31 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
goto filtered;
}
+ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN &&
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT &&
+ !CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
+ vpn_leak_to_vrf_no_retain_filter_check(bgp, attr, afi)) {
+ reason =
+ "no import. Filtered by no bgp retain route-target all";
+ goto filtered;
+ }
+
+ /* If the route has Node Target Extended Communities, check
+ * if it's allowed to be installed locally.
+ */
+ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
+ struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
+
+ if (ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_IP,
+ ECOMMUNITY_NODE_TARGET) &&
+ !ecommunity_node_target_match(ecomm, &peer->local_id)) {
+ reason =
+ "Node-Target Extended Communities do not contain own BGP Identifier;";
+ goto filtered;
+ }
+ }
+
/* RFC 8212 to prevent route leaks.
* This specification intends to improve this situation by requiring the
* explicit configuration of both BGP Import and Export Policies for any
@@ -4238,7 +4432,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
/* remove from RIB previous entry */
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false, NULL,
+ false);
}
if (peer->sort == BGP_PEER_EBGP) {
@@ -4331,12 +4526,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
/* Same attribute comes in. */
- if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
- && same_attr
- && (!has_valid_label
- || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
- num_labels * sizeof(mpls_label_t))
- == 0)) {
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr &&
+ (!has_valid_label ||
+ (bgp_path_info_extra_get(pi) &&
+ bgp_labels_same((const mpls_label_t *)pi->extra->label,
+ pi->extra->num_labels, label,
+ num_labels)))) {
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP
@@ -4521,7 +4716,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Update MPLS label */
if (has_valid_label) {
extra = bgp_path_info_extra_get(pi);
- if (extra->label != label) {
+ if (!bgp_labels_same((const mpls_label_t *)extra->label,
+ extra->num_labels, label,
+ num_labels)) {
memcpy(&extra->label, label,
num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
@@ -4530,49 +4727,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}
- /* Update SRv6 SID */
- if (attr->srv6_l3vpn) {
- extra = bgp_path_info_extra_get(pi);
- if (sid_diff(&extra->sid[0].sid,
- &attr->srv6_l3vpn->sid)) {
- sid_copy(&extra->sid[0].sid,
- &attr->srv6_l3vpn->sid);
- extra->num_sids = 1;
-
- extra->sid[0].loc_block_len = 0;
- extra->sid[0].loc_node_len = 0;
- extra->sid[0].func_len = 0;
- extra->sid[0].arg_len = 0;
- extra->sid[0].transposition_len = 0;
- extra->sid[0].transposition_offset = 0;
-
- if (attr->srv6_l3vpn->loc_block_len != 0) {
- extra->sid[0].loc_block_len =
- attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len =
- attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len =
- attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- attr->srv6_l3vpn
- ->transposition_len;
- extra->sid[0].transposition_offset =
- attr->srv6_l3vpn
- ->transposition_offset;
- }
- }
- } else if (attr->srv6_vpn) {
- extra = bgp_path_info_extra_get(pi);
- if (sid_diff(&extra->sid[0].sid,
- &attr->srv6_vpn->sid)) {
- sid_copy(&extra->sid[0].sid,
- &attr->srv6_vpn->sid);
- extra->num_sids = 1;
- }
- }
-
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
@@ -4609,10 +4763,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Nexthop reachability check - for unicast and
* labeled-unicast.. */
- if (((afi == AFI_IP || afi == AFI_IP6)
- && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
- || (safi == SAFI_EVPN &&
- bgp_evpn_is_prefix_nht_supported(p))) {
+ if (((afi == AFI_IP || afi == AFI_IP6) &&
+ (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST ||
+ (safi == SAFI_MPLS_VPN &&
+ pi->sub_type != BGP_ROUTE_IMPORTED))) ||
+ (safi == SAFI_EVPN &&
+ bgp_evpn_is_prefix_nht_supported(p))) {
if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
&& peer->ttl == BGP_DEFAULT_TTL
&& !CHECK_FLAG(peer->flags,
@@ -4625,31 +4781,40 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct bgp *bgp_nexthop = bgp;
- if (pi->extra && pi->extra->bgp_orig)
- bgp_nexthop = pi->extra->bgp_orig;
+ if (pi->extra && pi->extra->vrfleak &&
+ pi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = pi->extra->vrfleak->bgp_orig;
nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
safi, pi, NULL, connected,
bgp_nht_param_prefix) ||
- CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
+ CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) {
+ if (accept_own)
+ bgp_path_info_set_flag(
+ dest, pi, BGP_PATH_ACCEPT_OWN);
+
bgp_path_info_set_flag(dest, pi,
BGP_PATH_VALID);
- else {
+ } else {
if (BGP_DEBUG(nht, NHT)) {
- zlog_debug("%s(%pI4): NH unresolved",
+ zlog_debug("%s(%pI4): NH unresolved for existing %pFX pi %p flags 0x%x",
__func__,
- (in_addr_t *)&attr_new->nexthop);
+ (in_addr_t *)&attr_new->nexthop,
+ p, pi, pi->flags);
}
bgp_path_info_unset_flag(dest, pi,
BGP_PATH_VALID);
}
} else {
+ /* case mpls-vpn routes with accept-own community
+ * (which have the BGP_ROUTE_IMPORTED subtype)
+ * case other afi/safi not supporting nexthop tracking
+ */
if (accept_own)
bgp_path_info_set_flag(dest, pi,
BGP_PATH_ACCEPT_OWN);
-
bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
}
@@ -4682,10 +4847,23 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* updating
* the attributes for the route in the VNI(s).
*/
- if (safi == SAFI_EVPN &&
- (!same_attr || force_evpn_import) &&
- CHECK_FLAG(pi->flags, BGP_PATH_VALID))
- bgp_evpn_import_route(bgp, afi, safi, p, pi);
+ if (safi == SAFI_EVPN) {
+ if ((!same_attr || force_evpn_import) &&
+ CHECK_FLAG(pi->flags, BGP_PATH_VALID))
+ bgp_evpn_import_route(bgp, afi, safi, p, pi);
+
+ /* If existing path is marked invalid then unimport the
+ * path from EVPN prefix. This will ensure EVPN route
+ * has only valid paths and path refcount maintained in
+ * EVPN nexthop is decremented appropriately.
+ */
+ else if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s unimport EVPN %pFX as pi %p is not VALID",
+ __func__, p, pi);
+ bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
+ }
+ }
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
@@ -4701,7 +4879,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
- leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
+ vpn_leak_to_vrf_update(bgp, pi, prd);
}
#ifdef ENABLE_BGP_VNC
@@ -4716,13 +4894,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
type, sub_type, NULL);
}
#endif
- if ((safi == SAFI_MPLS_VPN) &&
- !CHECK_FLAG(bgp->af_flags[afi][safi],
- BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
- !leak_success) {
- bgp_unlink_nexthop(pi);
- bgp_path_info_delete(dest, pi);
- }
return;
} // End of implicit withdraw
@@ -4746,7 +4917,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Update MPLS label */
if (has_valid_label) {
extra = bgp_path_info_extra_get(new);
- if (extra->label != label) {
+ if (!bgp_labels_same((const mpls_label_t *)extra->label,
+ extra->num_labels, label, num_labels)) {
memcpy(&extra->label, label,
num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
@@ -4755,33 +4927,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}
- /* Update SRv6 SID */
- if (safi == SAFI_MPLS_VPN) {
- extra = bgp_path_info_extra_get(new);
- if (attr->srv6_l3vpn) {
- sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
- extra->num_sids = 1;
-
- extra->sid[0].loc_block_len =
- attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- attr->srv6_l3vpn->transposition_len;
- extra->sid[0].transposition_offset =
- attr->srv6_l3vpn->transposition_offset;
- } else if (attr->srv6_vpn) {
- sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
- extra->num_sids = 1;
- }
- }
-
/* Nexthop reachability check. */
- if (((afi == AFI_IP || afi == AFI_IP6)
- && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
- || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
+ if (((afi == AFI_IP || afi == AFI_IP6) &&
+ (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST ||
+ (safi == SAFI_MPLS_VPN &&
+ new->sub_type != BGP_ROUTE_IMPORTED))) ||
+ (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
&& peer->ttl == BGP_DEFAULT_TTL
&& !CHECK_FLAG(peer->flags,
@@ -4796,18 +4947,25 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
connected, bgp_nht_param_prefix) ||
- CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
+ CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) {
+ if (accept_own)
+ bgp_path_info_set_flag(dest, new,
+ BGP_PATH_ACCEPT_OWN);
+
bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
- else {
+ } else {
if (BGP_DEBUG(nht, NHT))
zlog_debug("%s(%pI4): NH unresolved", __func__,
&attr_new->nexthop);
bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
}
} else {
+ /* case mpls-vpn routes with accept-own community
+ * (which have the BGP_ROUTE_IMPORTED subtype)
+ * case other afi/safi not supporting nexthop tracking
+ */
if (accept_own)
bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
-
bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
}
@@ -4864,7 +5022,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
- leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
+ vpn_leak_to_vrf_update(bgp, new, prd);
}
#ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) {
@@ -4878,13 +5036,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
sub_type, NULL);
}
#endif
- if ((safi == SAFI_MPLS_VPN) &&
- !CHECK_FLAG(bgp->af_flags[afi][safi],
- BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
- !leak_success) {
- bgp_unlink_nexthop(new);
- bgp_path_info_delete(dest, new);
- }
return;
@@ -4987,7 +5138,8 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
*/
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self)
- if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
+ if (!bgp_adj_in_unset(&dest, peer, addpath_id)) {
+ assert(dest);
peer->stat_pfx_dup_withdraw++;
if (bgp_debug_update(peer, p, NULL, 1)) {
@@ -5004,6 +5156,7 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
}
/* Lookup withdrawn route. */
+ assert(dest);
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (pi->peer == peer && pi->type == type
&& pi->sub_type == sub_type
@@ -5046,7 +5199,7 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p,
}
void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
- int withdraw)
+ bool withdraw)
{
struct update_subgroup *subgrp;
subgrp = peer_subgroup(peer, afi, safi);
@@ -5079,7 +5232,7 @@ static void bgp_announce_route_timer_expired(struct event *t)
paf = EVENT_ARG(t);
peer = paf->peer;
- if (!peer_established(peer))
+ if (!peer_established(peer->connection))
return;
if (!peer->afc_nego[paf->afi][paf->safi])
@@ -5495,7 +5648,7 @@ static void bgp_clear_node_complete(struct work_queue *wq)
struct peer *peer = wq->spec.data;
/* Tickle FSM to start moving again */
- BGP_EVENT_ADD(peer, Clearing_Completed);
+ BGP_EVENT_ADD(peer->connection, Clearing_Completed);
peer_unlock(peer); /* bgp_clear_route */
}
@@ -5577,9 +5730,11 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
ain_next = ain->next;
if (ain->peer == peer)
- bgp_adj_in_remove(dest, ain);
+ bgp_adj_in_remove(&dest, ain);
ain = ain_next;
+
+ assert(dest);
}
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
@@ -5587,9 +5742,10 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
if (pi->peer != peer)
continue;
- if (force)
- bgp_path_info_reap(dest, pi);
- else {
+ if (force) {
+ dest = bgp_path_info_reap(dest, pi);
+ assert(dest);
+ } else {
struct bgp_clear_node_queue *cnq;
/* both unlocked in bgp_clear_node_queue_del */
@@ -5684,9 +5840,11 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
ain_next = ain->next;
if (ain->peer == peer)
- bgp_adj_in_remove(dest, ain);
+ bgp_adj_in_remove(&dest, ain);
ain = ain_next;
+
+ assert(dest);
}
}
}
@@ -5855,10 +6013,10 @@ bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
if (peer->sort == BGP_PEER_IBGP)
return true;
- if (peer->sort == BGP_PEER_EBGP
- && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
- || FILTER_LIST_OUT_NAME(filter)
- || DISTRIBUTE_OUT_NAME(filter)))
+ if (peer->sort == BGP_PEER_EBGP &&
+ (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) ||
+ FILTER_LIST_OUT_NAME(filter) || DISTRIBUTE_OUT_NAME(filter) ||
+ UNSUPPRESS_MAP_NAME(filter)))
return true;
return false;
}
@@ -5877,7 +6035,7 @@ bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
}
static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
- safi_t safi)
+ afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
struct bgp_path_info *pi;
@@ -5901,10 +6059,11 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(p, pi, bgp, safi);
+ bgp_zebra_withdraw_actual(dest, pi, bgp);
}
- bgp_path_info_reap(dest, pi);
+ dest = bgp_path_info_reap(dest, pi);
+ assert(dest);
}
}
@@ -5918,7 +6077,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
if (afi == AFI_L2VPN)
continue;
- bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
+ bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST], afi,
SAFI_UNICAST);
/*
* VPN and ENCAP and EVPN tables are two-level (RD is top level)
@@ -5930,10 +6089,12 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ bgp_cleanup_table(bgp, table, afi, safi);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+
+ assert(dest);
}
}
safi = SAFI_ENCAP;
@@ -5941,10 +6102,12 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, safi);
+ bgp_cleanup_table(bgp, table, afi, safi);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+
+ assert(dest);
}
}
}
@@ -5953,10 +6116,12 @@ void bgp_cleanup_routes(struct bgp *bgp)
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
if (table != NULL) {
- bgp_cleanup_table(bgp, table, SAFI_EVPN);
+ bgp_cleanup_table(bgp, table, afi, SAFI_EVPN);
bgp_table_finish(&table);
bgp_dest_set_bgp_table_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+
+ assert(dest);
}
}
}
@@ -5997,7 +6162,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
addpath_id = 0;
addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
- /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
+ /* RFC4271 6.3 The NLRI field in the UPDATE message is checked for
syntactic validity. If the field is syntactically incorrect,
then the Error Subcode is set to Invalid Network Field. */
for (; pnt < lim; pnt += psize) {
@@ -6123,6 +6288,44 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
return BGP_NLRI_PARSE_OK;
}
+static void bgp_nexthop_reachability_check(afi_t afi, safi_t safi,
+ struct bgp_path_info *bpi,
+ const struct prefix *p,
+ struct bgp_dest *dest,
+ struct bgp *bgp,
+ struct bgp *bgp_nexthop)
+{
+ /* Nexthop reachability check. */
+ if (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
+ if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi,
+ bpi, NULL, 0, p))
+ bgp_path_info_set_flag(dest, bpi,
+ BGP_PATH_VALID);
+ else {
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf1[INET6_ADDRSTRLEN];
+
+ inet_ntop(p->family, &p->u.prefix, buf1,
+ sizeof(buf1));
+ zlog_debug("%s(%s): Route not in table, not advertising",
+ __func__, buf1);
+ }
+ bgp_path_info_unset_flag(dest, bpi,
+ BGP_PATH_VALID);
+ }
+ } else {
+ /* Delete the NHT structure if any, if we're toggling between
+ * enabling/disabling import check. We deregister the route
+ * from NHT to avoid overloading NHT and the process interaction
+ */
+ bgp_unlink_nexthop(bpi);
+
+ bgp_path_info_set_flag(dest, bpi, BGP_PATH_VALID);
+ }
+ }
+}
+
static struct bgp_static *bgp_static_new(void)
{
return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
@@ -6134,7 +6337,7 @@ static void bgp_static_free(struct bgp_static *bgp_static)
route_map_counter_decrement(bgp_static->rmap.map);
if (bgp_static->prd_pretty)
- XFREE(MTYPE_BGP, bgp_static->prd_pretty);
+ XFREE(MTYPE_BGP_NAME, bgp_static->prd_pretty);
XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
XFREE(MTYPE_BGP_STATIC, bgp_static);
}
@@ -6151,11 +6354,19 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
route_map_result_t ret;
#ifdef ENABLE_BGP_VNC
int vnc_implicit_withdraw = 0;
+ mpls_label_t label = 0;
#endif
+ uint32_t num_labels = 0;
+ struct bgp *bgp_nexthop = bgp;
assert(bgp_static);
- dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
+ if ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) &&
+ bgp_static->label != MPLS_INVALID_LABEL)
+ num_labels = 1;
+
+ dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
+ &bgp_static->prd);
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
@@ -6178,6 +6389,37 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
}
+ if (safi == SAFI_EVPN || safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
+ if (afi == AFI_IP) {
+ attr.mp_nexthop_global_in = bgp_static->igpnexthop;
+ attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
+ }
+ }
+
+ if (afi == AFI_L2VPN) {
+ if (bgp_static->gatewayIp.family == AF_INET) {
+ SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
+ &bgp_static->gatewayIp.u.prefix4,
+ IPV4_MAX_BYTELEN);
+ } else if (bgp_static->gatewayIp.family == AF_INET6) {
+ SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
+ memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
+ &bgp_static->gatewayIp.u.prefix6,
+ IPV6_MAX_BYTELEN);
+ }
+ memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
+ if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
+ struct bgp_encap_type_vxlan bet;
+ memset(&bet, 0, sizeof(bet));
+ bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
+ bgp_encap_type_vxlan_to_tlv(&bet, &attr);
+ }
+ if (bgp_static->router_mac) {
+ bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
+ }
+ }
+
/* Apply route-map. */
if (bgp_static->rmap.name) {
struct attr attr_tmp = attr;
@@ -6198,7 +6440,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Unintern original. */
aspath_unintern(&attr.aspath);
- bgp_static_withdraw(bgp, p, afi, safi);
+ bgp_static_withdraw(bgp, p, afi, safi, &bgp_static->prd);
bgp_dest_unlock_node(dest);
return;
}
@@ -6238,8 +6480,8 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
else
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
#ifdef ENABLE_BGP_VNC
- if ((afi == AFI_IP || afi == AFI_IP6)
- && (safi == SAFI_UNICAST)) {
+ if ((afi == AFI_IP || afi == AFI_IP6) &&
+ safi == SAFI_UNICAST) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
/*
* Implicit withdraw case.
@@ -6257,60 +6499,43 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
pi->attr = attr_new;
pi->uptime = monotime(NULL);
#ifdef ENABLE_BGP_VNC
- if ((afi == AFI_IP || afi == AFI_IP6)
- && (safi == SAFI_UNICAST)) {
+ if ((afi == AFI_IP || afi == AFI_IP6) &&
+ safi == SAFI_UNICAST) {
if (vnc_implicit_withdraw) {
vnc_import_bgp_add_route(bgp, p, pi);
vnc_import_bgp_exterior_add_route(
bgp, p, pi);
}
+ } else {
+ if (pi->extra)
+ label = decode_label(
+ &pi->extra->label[0]);
}
#endif
+ if (pi->extra && pi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = pi->extra->vrfleak->bgp_orig;
- /* Nexthop reachability check. */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
- && (safi == SAFI_UNICAST
- || safi == SAFI_LABELED_UNICAST)) {
+ bgp_nexthop_reachability_check(afi, safi, pi, p, dest,
+ bgp, bgp_nexthop);
- struct bgp *bgp_nexthop = bgp;
-
- if (pi->extra && pi->extra->bgp_orig)
- bgp_nexthop = pi->extra->bgp_orig;
-
- if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
- afi, safi, pi, NULL,
- 0, p))
- bgp_path_info_set_flag(dest, pi,
- BGP_PATH_VALID);
- else {
- if (BGP_DEBUG(nht, NHT)) {
- char buf1[INET6_ADDRSTRLEN];
- inet_ntop(p->family,
- &p->u.prefix, buf1,
- sizeof(buf1));
- zlog_debug(
- "%s(%s): Route not in table, not advertising",
- __func__, buf1);
- }
- bgp_path_info_unset_flag(
- dest, pi, BGP_PATH_VALID);
- }
- } else {
- /* Delete the NHT structure if any, if we're
- * toggling between
- * enabling/disabling import check. We
- * deregister the route
- * from NHT to avoid overloading NHT and the
- * process interaction
- */
- bgp_unlink_nexthop(pi);
- bgp_path_info_set_flag(dest, pi,
- BGP_PATH_VALID);
- }
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
bgp_process(bgp, dest, afi, safi);
+ if (SAFI_MPLS_VPN == safi &&
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ vpn_leak_to_vrf_update(bgp, pi,
+ &bgp_static->prd);
+ }
+#ifdef ENABLE_BGP_VNC
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
+ safi == SAFI_EVPN)
+ rfapiProcessUpdate(pi->peer, NULL, p,
+ &bgp_static->prd, pi->attr,
+ afi, safi, pi->type,
+ pi->sub_type, &label);
+#endif
+
if (SAFI_UNICAST == safi
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|| bgp->inst_type
@@ -6328,34 +6553,21 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Make new BGP info. */
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
attr_new, dest);
- /* Nexthop reachability check. */
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
- && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
- if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
- p))
- bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
- else {
- if (BGP_DEBUG(nht, NHT)) {
- char buf1[INET6_ADDRSTRLEN];
- inet_ntop(p->family, &p->u.prefix, buf1,
- sizeof(buf1));
- zlog_debug(
- "%s(%s): Route not in table, not advertising",
- __func__, buf1);
- }
- bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
+ SET_FLAG(new->flags, BGP_PATH_VALID);
+ bgp_path_info_extra_get(new);
+ if (num_labels) {
+ new->extra->label[0] = bgp_static->label;
+ new->extra->num_labels = num_labels;
}
- } else {
- /* Delete the NHT structure if any, if we're toggling between
- * enabling/disabling import check. We deregister the route
- * from NHT to avoid overloading NHT and the process interaction
- */
- bgp_unlink_nexthop(new);
-
- bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
+#ifdef ENABLE_BGP_VNC
+ label = decode_label(&bgp_static->label);
+#endif
}
+ bgp_nexthop_reachability_check(afi, safi, new, p, dest, bgp, bgp);
+
/* Aggregate address increment. */
bgp_aggregate_increment(bgp, p, new, afi, safi);
@@ -6368,53 +6580,29 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Process change. */
bgp_process(bgp, dest, afi, safi);
- if (SAFI_UNICAST == safi
- && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
- || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
+ if (SAFI_UNICAST == safi &&
+ (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
}
+ if (SAFI_MPLS_VPN == safi &&
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
+ }
+#ifdef ENABLE_BGP_VNC
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
+ rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd,
+ new->attr, afi, safi, new->type,
+ new->sub_type, &label);
+#endif
+
/* Unintern original. */
aspath_unintern(&attr.aspath);
}
void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
- safi_t safi)
-{
- struct bgp_dest *dest;
- struct bgp_path_info *pi;
-
- dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
-
- /* Check selected route and self inserted route. */
- for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
- && pi->sub_type == BGP_ROUTE_STATIC)
- break;
-
- /* Withdraw static BGP route from routing table. */
- if (pi) {
- if (SAFI_UNICAST == safi
- && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
- || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
- vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
- }
- bgp_aggregate_decrement(bgp, p, pi, afi, safi);
- bgp_unlink_nexthop(pi);
- bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
- }
-
- /* Unlock bgp_node_lookup. */
- bgp_dest_unlock_node(dest);
-}
-
-/*
- * Used for SAFI_MPLS_VPN and SAFI_ENCAP
- */
-static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
- afi_t afi, safi_t safi,
- struct prefix_rd *prd)
+ safi_t safi, struct prefix_rd *prd)
{
struct bgp_dest *dest;
struct bgp_path_info *pi;
@@ -6430,15 +6618,22 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
/* Withdraw static BGP route from routing table. */
if (pi) {
#ifdef ENABLE_BGP_VNC
- rfapiProcessWithdraw(
- pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
- 1); /* Kill, since it is an administrative change */
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+ rfapiProcessWithdraw(pi->peer, NULL, p, prd, pi->attr,
+ afi, safi, pi->type,
+ 1); /* Kill, since it is an administrative change */
#endif
+ if (SAFI_UNICAST == safi &&
+ (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
+ bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
+ vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
+ }
if (SAFI_MPLS_VPN == safi
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
vpn_leak_to_vrf_withdraw(pi);
}
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
+ bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
bgp_process(bgp, dest, afi, safi);
}
@@ -6447,194 +6642,25 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
bgp_dest_unlock_node(dest);
}
-static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
- struct bgp_static *bgp_static, afi_t afi,
- safi_t safi)
-{
- struct bgp_dest *dest;
- struct bgp_path_info *new;
- struct attr *attr_new;
- struct attr attr = {0};
- struct bgp_path_info *pi;
-#ifdef ENABLE_BGP_VNC
- mpls_label_t label = 0;
-#endif
- uint32_t num_labels = 0;
-
- assert(bgp_static);
-
- if (bgp_static->label != MPLS_INVALID_LABEL)
- num_labels = 1;
- dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
- &bgp_static->prd);
-
- bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
-
- attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
-
- if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
- || (safi == SAFI_ENCAP)) {
- if (afi == AFI_IP) {
- attr.mp_nexthop_global_in = bgp_static->igpnexthop;
- attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
- }
- }
- if (afi == AFI_L2VPN) {
- if (bgp_static->gatewayIp.family == AF_INET) {
- SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
- &bgp_static->gatewayIp.u.prefix4,
- IPV4_MAX_BYTELEN);
- } else if (bgp_static->gatewayIp.family == AF_INET6) {
- SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
- memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
- &bgp_static->gatewayIp.u.prefix6,
- IPV6_MAX_BYTELEN);
- }
- memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
- if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
- struct bgp_encap_type_vxlan bet;
- memset(&bet, 0, sizeof(bet));
- bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
- bgp_encap_type_vxlan_to_tlv(&bet, &attr);
- }
- if (bgp_static->router_mac) {
- bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
- }
- }
- /* Apply route-map. */
- if (bgp_static->rmap.name) {
- struct attr attr_tmp = attr;
- struct bgp_path_info rmap_path;
- route_map_result_t ret;
-
- rmap_path.peer = bgp->peer_self;
- rmap_path.attr = &attr_tmp;
-
- SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
-
- ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
-
- bgp->peer_self->rmap_type = 0;
-
- if (ret == RMAP_DENYMATCH) {
- /* Free uninterned attribute. */
- bgp_attr_flush(&attr_tmp);
-
- /* Unintern original. */
- aspath_unintern(&attr.aspath);
- bgp_static_withdraw_safi(bgp, p, afi, safi,
- &bgp_static->prd);
- bgp_dest_unlock_node(dest);
- return;
- }
-
- attr_new = bgp_attr_intern(&attr_tmp);
- } else {
- attr_new = bgp_attr_intern(&attr);
- }
-
- for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
- && pi->sub_type == BGP_ROUTE_STATIC)
- break;
-
- if (pi) {
- if (attrhash_cmp(pi->attr, attr_new)
- && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
- bgp_dest_unlock_node(dest);
- bgp_attr_unintern(&attr_new);
- aspath_unintern(&attr.aspath);
- return;
- } else {
- /* The attribute is changed. */
- bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
-
- /* Rewrite BGP route information. */
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
- bgp_path_info_restore(dest, pi);
- else
- bgp_aggregate_decrement(bgp, p, pi, afi, safi);
- bgp_attr_unintern(&pi->attr);
- pi->attr = attr_new;
- pi->uptime = monotime(NULL);
-#ifdef ENABLE_BGP_VNC
- if (pi->extra)
- label = decode_label(&pi->extra->label[0]);
-#endif
-
- /* Process change. */
- bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
-
- if (SAFI_MPLS_VPN == safi
- && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_update(bgp, pi,
- &bgp_static->prd);
- }
-#ifdef ENABLE_BGP_VNC
- rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
- pi->attr, afi, safi, pi->type,
- pi->sub_type, &label);
-#endif
- bgp_dest_unlock_node(dest);
- aspath_unintern(&attr.aspath);
- return;
- }
- }
-
-
- /* Make new BGP info. */
- new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
- attr_new, dest);
- SET_FLAG(new->flags, BGP_PATH_VALID);
- bgp_path_info_extra_get(new);
- if (num_labels) {
- new->extra->label[0] = bgp_static->label;
- new->extra->num_labels = num_labels;
- }
-#ifdef ENABLE_BGP_VNC
- label = decode_label(&bgp_static->label);
-#endif
-
- /* Aggregate address increment. */
- bgp_aggregate_increment(bgp, p, new, afi, safi);
-
- /* Register new BGP information. */
- bgp_path_info_add(dest, new);
- /* route_node_get lock */
- bgp_dest_unlock_node(dest);
-
- /* Process change. */
- bgp_process(bgp, dest, afi, safi);
-
- if (SAFI_MPLS_VPN == safi
- && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
- }
-#ifdef ENABLE_BGP_VNC
- rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
- safi, new->type, new->sub_type, &label);
-#endif
-
- /* Unintern original. */
- aspath_unintern(&attr.aspath);
-}
-
/* Configure static BGP network. When user don't run zebra, static
route should be installed as valid. */
-static int bgp_static_set(struct vty *vty, const char *negate,
- const char *ip_str, afi_t afi, safi_t safi,
- const char *rmap, int backdoor, uint32_t label_index)
+int bgp_static_set(struct vty *vty, bool negate, const char *ip_str,
+ const char *rd_str, const char *label_str, afi_t afi,
+ safi_t safi, const char *rmap, int backdoor,
+ uint32_t label_index, int evpn_type, const char *esi,
+ const char *gwip, const char *ethtag, const char *routermac)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
struct prefix p;
struct bgp_static *bgp_static;
+ struct prefix_rd prd = {};
+ struct bgp_dest *pdest;
struct bgp_dest *dest;
+ struct bgp_table *table;
uint8_t need_update = 0;
+ mpls_label_t label = MPLS_INVALID_LABEL;
+ struct prefix gw_ip;
/* Convert IP prefix string to struct prefix. */
ret = str2prefix(ip_str, &p);
@@ -6649,8 +6675,69 @@ static int bgp_static_set(struct vty *vty, const char *negate,
apply_mask(&p);
- if (negate) {
+ if (afi == AFI_L2VPN &&
+ (bgp_build_evpn_prefix(evpn_type, ethtag != NULL ? atol(ethtag) : 0,
+ &p))) {
+ vty_out(vty, "%% L2VPN prefix could not be forged\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) {
+ ret = str2prefix_rd(rd_str, &prd);
+ if (!ret) {
+ vty_out(vty, "%% Malformed rd\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (label_str) {
+ unsigned long label_val;
+
+ label_val = strtoul(label_str, NULL, 10);
+ encode_label(label_val, &label);
+ }
+ }
+
+ if (safi == SAFI_EVPN) {
+ if (esi && str2esi(esi, NULL) == 0) {
+ vty_out(vty, "%% Malformed ESI\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (routermac && prefix_str2mac(routermac, NULL) == 0) {
+ vty_out(vty, "%% Malformed Router MAC\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (gwip) {
+ memset(&gw_ip, 0, sizeof(gw_ip));
+ ret = str2prefix(gwip, &gw_ip);
+ if (!ret) {
+ vty_out(vty, "%% Malformed GatewayIp\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if ((gw_ip.family == AF_INET &&
+ is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)&p)) ||
+ (gw_ip.family == AF_INET6 &&
+ is_evpn_prefix_ipaddr_v4(
+ (struct prefix_evpn *)&p))) {
+ vty_out(vty,
+ "%% GatewayIp family differs with IP prefix\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ }
+
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) {
+ pdest = bgp_node_get(bgp->route[afi][safi],
+ (struct prefix *)&prd);
+ if (!bgp_dest_has_bgp_path_info_data(pdest))
+ bgp_dest_set_bgp_table_info(pdest,
+ bgp_table_init(bgp, afi,
+ safi));
+ table = bgp_dest_get_bgp_table_info(pdest);
+ } else {
+ table = bgp->route[afi][safi];
+ }
+
+ if (negate) {
/* Set BGP static route configuration. */
dest = bgp_node_lookup(bgp->route[afi][safi], &p);
@@ -6660,36 +6747,38 @@ static int bgp_static_set(struct vty *vty, const char *negate,
}
bgp_static = bgp_dest_get_bgp_static_info(dest);
+ if (bgp_static) {
+ if ((label_index != BGP_INVALID_LABEL_INDEX) &&
+ (label_index != bgp_static->label_index)) {
+ vty_out(vty,
+ "%% label-index doesn't match static route\n");
+ bgp_dest_unlock_node(dest);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- if ((label_index != BGP_INVALID_LABEL_INDEX)
- && (label_index != bgp_static->label_index)) {
- vty_out(vty,
- "%% label-index doesn't match static route\n");
- bgp_dest_unlock_node(dest);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if ((rmap && bgp_static->rmap.name) &&
+ strcmp(rmap, bgp_static->rmap.name)) {
+ vty_out(vty,
+ "%% route-map name doesn't match static route\n");
+ bgp_dest_unlock_node(dest);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- if ((rmap && bgp_static->rmap.name)
- && strcmp(rmap, bgp_static->rmap.name)) {
- vty_out(vty,
- "%% route-map name doesn't match static route\n");
- bgp_dest_unlock_node(dest);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ /* Update BGP RIB. */
+ if (!bgp_static->backdoor)
+ bgp_static_withdraw(bgp, &p, afi, safi, NULL);
- /* Update BGP RIB. */
- if (!bgp_static->backdoor)
- bgp_static_withdraw(bgp, &p, afi, safi);
+ /* Clear configuration. */
+ bgp_static_free(bgp_static);
+ }
- /* Clear configuration. */
- bgp_static_free(bgp_static);
bgp_dest_set_bgp_static_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+ assert(dest);
bgp_dest_unlock_node(dest);
} else {
+ dest = bgp_node_get(table, &p);
- /* Set BGP static route configuration. */
- dest = bgp_node_get(bgp->route[afi][safi], &p);
bgp_static = bgp_dest_get_bgp_static_info(dest);
if (bgp_static) {
/* Configuration change. */
@@ -6735,6 +6824,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
bgp_static->igpmetric = 0;
bgp_static->igpnexthop.s_addr = INADDR_ANY;
bgp_static->label_index = label_index;
+ bgp_static->label = label;
+ bgp_static->prd = prd;
if (rmap) {
XFREE(MTYPE_ROUTE_MAP_NAME,
@@ -6748,12 +6839,32 @@ static int bgp_static_set(struct vty *vty, const char *negate,
route_map_counter_increment(
bgp_static->rmap.map);
}
+
+ if (safi == SAFI_EVPN) {
+ if (esi) {
+ bgp_static->eth_s_id =
+ XCALLOC(MTYPE_ATTR,
+ sizeof(esi_t));
+ str2esi(esi, bgp_static->eth_s_id);
+ }
+ if (routermac) {
+ bgp_static->router_mac =
+ XCALLOC(MTYPE_ATTR,
+ ETH_ALEN + 1);
+ (void)prefix_str2mac(routermac,
+ bgp_static->router_mac);
+ }
+ if (gwip)
+ prefix_copy(&bgp_static->gatewayIp,
+ &gw_ip);
+ }
+
bgp_dest_set_bgp_static_info(dest, bgp_static);
}
bgp_static->valid = 1;
if (need_update)
- bgp_static_withdraw(bgp, &p, afi, safi);
+ bgp_static_withdraw(bgp, &p, afi, safi, NULL);
if (!bgp_static->backdoor)
bgp_static_update(bgp, &p, bgp_static, afi, safi);
@@ -6787,9 +6898,9 @@ void bgp_static_add(struct bgp *bgp)
bgp_static =
bgp_dest_get_bgp_static_info(
rm);
- bgp_static_update_safi(
- bgp, bgp_dest_get_prefix(rm),
- bgp_static, afi, safi);
+ bgp_static_update(bgp,
+ bgp_dest_get_prefix(rm),
+ bgp_static, afi, safi);
}
} else {
bgp_static_update(
@@ -6830,25 +6941,28 @@ void bgp_static_delete(struct bgp *bgp)
if (!bgp_static)
continue;
- bgp_static_withdraw_safi(
- bgp, bgp_dest_get_prefix(rm),
- AFI_IP, safi,
- (struct prefix_rd *)
- bgp_dest_get_prefix(
- dest));
+ bgp_static_withdraw(bgp,
+ bgp_dest_get_prefix(
+ rm),
+ AFI_IP, safi,
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ dest));
bgp_static_free(bgp_static);
bgp_dest_set_bgp_static_info(rm,
NULL);
- bgp_dest_unlock_node(rm);
+ rm = bgp_dest_unlock_node(rm);
+ assert(rm);
}
} else {
bgp_static = bgp_dest_get_bgp_static_info(dest);
bgp_static_withdraw(bgp,
bgp_dest_get_prefix(dest),
- afi, safi);
+ afi, safi, NULL);
bgp_static_free(bgp_static);
bgp_dest_set_bgp_static_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+ assert(dest);
}
}
}
@@ -6879,9 +6993,9 @@ void bgp_static_redo_import_check(struct bgp *bgp)
bgp_static =
bgp_dest_get_bgp_static_info(
rm);
- bgp_static_update_safi(
- bgp, bgp_dest_get_prefix(rm),
- bgp_static, afi, safi);
+ bgp_static_update(bgp,
+ bgp_dest_get_prefix(rm),
+ bgp_static, afi, safi);
}
} else {
bgp_static = bgp_dest_get_bgp_static_info(dest);
@@ -6941,205 +7055,6 @@ void bgp_purge_static_redist_routes(struct bgp *bgp)
bgp_purge_af_static_redist_routes(bgp, afi, safi);
}
-/*
- * gpz 110624
- * Currently this is used to set static routes for VPN and ENCAP.
- * I think it can probably be factored with bgp_static_set.
- */
-int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
- const char *ip_str, const char *rd_str,
- const char *label_str, const char *rmap_str,
- int evpn_type, const char *esi, const char *gwip,
- const char *ethtag, const char *routermac)
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- int ret;
- struct prefix p;
- struct prefix_rd prd;
- struct bgp_dest *pdest;
- struct bgp_dest *dest;
- struct bgp_table *table;
- struct bgp_static *bgp_static;
- mpls_label_t label = MPLS_INVALID_LABEL;
- struct prefix gw_ip;
-
- /* validate ip prefix */
- ret = str2prefix(ip_str, &p);
- if (!ret) {
- vty_out(vty, "%% Malformed prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask(&p);
- if ((afi == AFI_L2VPN)
- && (bgp_build_evpn_prefix(evpn_type,
- ethtag != NULL ? atol(ethtag) : 0, &p))) {
- vty_out(vty, "%% L2VPN prefix could not be forged\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ret = str2prefix_rd(rd_str, &prd);
- if (!ret) {
- vty_out(vty, "%% Malformed rd\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (label_str) {
- unsigned long label_val;
- label_val = strtoul(label_str, NULL, 10);
- encode_label(label_val, &label);
- }
-
- if (safi == SAFI_EVPN) {
- if (esi && str2esi(esi, NULL) == 0) {
- vty_out(vty, "%% Malformed ESI\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (routermac && prefix_str2mac(routermac, NULL) == 0) {
- vty_out(vty, "%% Malformed Router MAC\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (gwip) {
- memset(&gw_ip, 0, sizeof(gw_ip));
- ret = str2prefix(gwip, &gw_ip);
- if (!ret) {
- vty_out(vty, "%% Malformed GatewayIp\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- if ((gw_ip.family == AF_INET
- && is_evpn_prefix_ipaddr_v6(
- (struct prefix_evpn *)&p))
- || (gw_ip.family == AF_INET6
- && is_evpn_prefix_ipaddr_v4(
- (struct prefix_evpn *)&p))) {
- vty_out(vty,
- "%% GatewayIp family differs with IP prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
- }
- pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
- if (!bgp_dest_has_bgp_path_info_data(pdest))
- bgp_dest_set_bgp_table_info(pdest,
- bgp_table_init(bgp, afi, safi));
- table = bgp_dest_get_bgp_table_info(pdest);
-
- dest = bgp_node_get(table, &p);
-
- if (bgp_dest_has_bgp_path_info_data(dest)) {
- vty_out(vty, "%% Same network configuration exists\n");
- bgp_dest_unlock_node(dest);
- } else {
- /* New configuration. */
- bgp_static = bgp_static_new();
- bgp_static->backdoor = 0;
- bgp_static->valid = 0;
- bgp_static->igpmetric = 0;
- bgp_static->igpnexthop.s_addr = INADDR_ANY;
- bgp_static->label = label;
- bgp_static->prd = prd;
-
- bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);
-
- if (rmap_str) {
- XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
- route_map_counter_decrement(bgp_static->rmap.map);
- bgp_static->rmap.name =
- XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
- bgp_static->rmap.map =
- route_map_lookup_by_name(rmap_str);
- route_map_counter_increment(bgp_static->rmap.map);
- }
-
- if (safi == SAFI_EVPN) {
- if (esi) {
- bgp_static->eth_s_id =
- XCALLOC(MTYPE_ATTR,
- sizeof(esi_t));
- str2esi(esi, bgp_static->eth_s_id);
- }
- if (routermac) {
- bgp_static->router_mac =
- XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
- (void)prefix_str2mac(routermac,
- bgp_static->router_mac);
- }
- if (gwip)
- prefix_copy(&bgp_static->gatewayIp, &gw_ip);
- }
- bgp_dest_set_bgp_static_info(dest, bgp_static);
-
- bgp_static->valid = 1;
- bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
- }
-
- return CMD_SUCCESS;
-}
-
-/* Configure static BGP network. */
-int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
- const char *ip_str, const char *rd_str,
- const char *label_str, int evpn_type, const char *esi,
- const char *gwip, const char *ethtag)
-{
- VTY_DECLVAR_CONTEXT(bgp, bgp);
- int ret;
- struct prefix p;
- struct prefix_rd prd;
- struct bgp_dest *pdest;
- struct bgp_dest *dest;
- struct bgp_table *table;
- struct bgp_static *bgp_static;
- mpls_label_t label = MPLS_INVALID_LABEL;
-
- /* Convert IP prefix string to struct prefix. */
- ret = str2prefix(ip_str, &p);
- if (!ret) {
- vty_out(vty, "%% Malformed prefix\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- apply_mask(&p);
- if ((afi == AFI_L2VPN)
- && (bgp_build_evpn_prefix(evpn_type,
- ethtag != NULL ? atol(ethtag) : 0, &p))) {
- vty_out(vty, "%% L2VPN prefix could not be forged\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- ret = str2prefix_rd(rd_str, &prd);
- if (!ret) {
- vty_out(vty, "%% Malformed rd\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (label_str) {
- unsigned long label_val;
- label_val = strtoul(label_str, NULL, 10);
- encode_label(label_val, &label);
- }
-
- pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
- if (!bgp_dest_has_bgp_path_info_data(pdest))
- bgp_dest_set_bgp_table_info(pdest,
- bgp_table_init(bgp, afi, safi));
- else
- bgp_dest_unlock_node(pdest);
- table = bgp_dest_get_bgp_table_info(pdest);
-
- dest = bgp_node_lookup(table, &p);
-
- if (dest) {
- bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
-
- bgp_static = bgp_dest_get_bgp_static_info(dest);
- bgp_static_free(bgp_static);
- bgp_dest_set_bgp_static_info(dest, NULL);
- bgp_dest_unlock_node(dest);
- bgp_dest_unlock_node(dest);
- } else
- vty_out(vty, "%% Can't find the route\n");
-
- return CMD_SUCCESS;
-}
-
static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
const char *rmap_name)
{
@@ -7245,10 +7160,13 @@ DEFPY(bgp_network,
}
}
- return bgp_static_set(
- vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
- bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
- label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
+ return bgp_static_set(vty, no,
+ address_str ? addr_prefix_str : prefix_str, NULL,
+ NULL, AFI_IP, bgp_node_safi(vty), map_name,
+ backdoor ? 1 : 0,
+ label_index ? (uint32_t)label_index
+ : BGP_INVALID_LABEL_INDEX,
+ 0, NULL, NULL, NULL, NULL);
}
DEFPY(ipv6_bgp_network,
@@ -7263,9 +7181,11 @@ DEFPY(ipv6_bgp_network,
"Label index to associate with the prefix\n"
"Label index value\n")
{
- return bgp_static_set(
- vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
- label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
+ return bgp_static_set(vty, no, prefix_str, NULL, NULL, AFI_IP6,
+ bgp_node_safi(vty), map_name, 0,
+ label_index ? (uint32_t)label_index
+ : BGP_INVALID_LABEL_INDEX,
+ 0, NULL, NULL, NULL, NULL);
}
static struct bgp_aggregate *bgp_aggregate_new(void)
@@ -7400,7 +7320,7 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
asnotation = bgp_get_asnotation(NULL);
- if (!ae)
+ if (!aspath)
ae = aspath_empty(asnotation);
if (!pi)
@@ -7459,8 +7379,9 @@ static void bgp_aggregate_install(
* If the aggregate information has not changed
* no need to re-install it again.
*/
- if (bgp_aggregate_info_same(orig, origin, aspath, community,
- ecommunity, lcommunity)) {
+ if (pi && (!aggregate->rmap.changed &&
+ bgp_aggregate_info_same(pi, origin, aspath, community,
+ ecommunity, lcommunity))) {
bgp_dest_unlock_node(dest);
if (aspath)
@@ -7714,7 +7635,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
*/
aggregate->count = 0;
aggregate->incomplete_origin_count = 0;
- aggregate->incomplete_origin_count = 0;
aggregate->egp_origin_count = 0;
/* ORIGIN attribute: If at least one route among routes that are
@@ -7740,7 +7660,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
/* If suppress fib is enabled and route not installed
* in FIB, skip the route
*/
- if (!bgp_check_advertise(bgp, dest))
+ if (!bgp_check_advertise(bgp, dest, safi))
continue;
match = 0;
@@ -7889,6 +7809,9 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
lcommunity = lcommunity_dup(aggregate->lcommunity);
}
+ /* Unimport suppressed routes from EVPN */
+ bgp_aggr_supp_withdraw_from_evpn(bgp, afi, safi);
+
bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
ecommunity, lcommunity, atomic_aggregate,
aggregate);
@@ -8254,7 +8177,7 @@ void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
/* If suppress fib is enabled and route not installed
* in FIB, do not update the aggregate route
*/
- if (!bgp_check_advertise(bgp, pi->net))
+ if (!bgp_check_advertise(bgp, pi->net, safi))
return;
child = bgp_node_get(table, p);
@@ -8373,7 +8296,8 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
bgp_dest_set_bgp_aggregate_info(dest, NULL);
bgp_free_aggregate_info(aggregate);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+ assert(dest);
bgp_dest_unlock_node(dest);
return CMD_SUCCESS;
@@ -8467,6 +8391,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
aggregate->rmap.name =
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
aggregate->rmap.map = route_map_lookup_by_name(rmap);
+ aggregate->rmap.changed = true;
route_map_counter_increment(aggregate->rmap.map);
}
@@ -8650,6 +8575,11 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
afi_t afi;
route_map_result_t ret;
struct bgp_redist *red;
+ struct interface *ifp;
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
+ bgp->peer_self == NULL)
+ return;
/* Make default attribute. */
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
@@ -8658,12 +8588,16 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
*/
assert(attr.aspath);
+ if (p->family == AF_INET6)
+ UNSET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
+
switch (nhtype) {
case NEXTHOP_TYPE_IFINDEX:
switch (p->family) {
case AF_INET:
attr.nexthop.s_addr = INADDR_ANY;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+ attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
break;
case AF_INET6:
memset(&attr.mp_nexthop_global, 0,
@@ -8676,6 +8610,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
case NEXTHOP_TYPE_IPV4_IFINDEX:
attr.nexthop = nexthop->ipv4;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+ attr.mp_nexthop_global_in = nexthop->ipv4;
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -8687,6 +8622,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
case AF_INET:
attr.nexthop.s_addr = INADDR_ANY;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+ attr.mp_nexthop_global_in.s_addr = INADDR_ANY;
break;
case AF_INET6:
memset(&attr.mp_nexthop_global, 0,
@@ -8699,6 +8635,11 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
}
attr.nh_type = nhtype;
attr.nh_ifindex = ifindex;
+ ifp = if_lookup_by_index(ifindex, bgp->vrf_id);
+ if (ifp && if_is_operative(ifp))
+ SET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
+ else
+ UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
attr.med = metric;
attr.distance = distance;
@@ -8885,8 +8826,10 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
if (!CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
bgp_process(bgp, dest, afi, SAFI_UNICAST);
- else
- bgp_path_info_reap(dest, pi);
+ else {
+ dest = bgp_path_info_reap(dest, pi);
+ assert(dest);
+ }
}
}
}
@@ -9105,6 +9048,9 @@ static void route_vty_short_status_out(struct vty *vty,
vty_out(vty, "i");
else
vty_out(vty, " ");
+
+ /* adding space between next column */
+ vty_out(vty, " ");
}
static char *bgp_nexthop_hostname(struct peer *peer,
@@ -9158,26 +9104,27 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
* If vrf id of nexthop is different from that of prefix,
* set up printable string to append
*/
- if (path->extra && path->extra->bgp_orig) {
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->bgp_orig) {
const char *self = "";
if (nexthop_self)
self = "<";
nexthop_othervrf = true;
- nexthop_vrfid = path->extra->bgp_orig->vrf_id;
+ nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id;
- if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
+ if (path->extra->vrfleak->bgp_orig->vrf_id == VRF_UNKNOWN)
snprintf(vrf_id_str, sizeof(vrf_id_str),
"@%s%s", VRFID_NONE_STR, self);
else
snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
- path->extra->bgp_orig->vrf_id, self);
+ path->extra->vrfleak->bgp_orig->vrf_id, self);
- if (path->extra->bgp_orig->inst_type
- != BGP_INSTANCE_TYPE_DEFAULT)
+ if (path->extra->vrfleak->bgp_orig->inst_type !=
+ BGP_INSTANCE_TYPE_DEFAULT)
- nexthop_vrfname = path->extra->bgp_orig->name;
+ nexthop_vrfname = path->extra->vrfleak->bgp_orig->name;
} else {
const char *self = "";
@@ -9385,9 +9332,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
"link-local");
if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
- &attr->mp_nexthop_local)
- != 0)
- && !attr->mp_nexthop_prefer_global)
+ &attr->mp_nexthop_local) !=
+ 0) &&
+ !CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
json_object_boolean_true_add(
json_nexthop_ll, "used");
else
@@ -9399,10 +9347,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
} else {
/* Display LL if LL/Global both in table unless
* prefer-global is set */
- if (((attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
- && !attr->mp_nexthop_prefer_global)
- || (path->peer->conf_if)) {
+ if (((attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) &&
+ !CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) ||
+ (path->peer->conf_if)) {
if (path->peer->conf_if) {
len = vty_out(vty, "%s",
path->peer->conf_if);
@@ -9487,7 +9436,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
if (json_paths)
json_object_string_addf(json_path, "peerId", "%pSU",
- &path->peer->su);
+ &path->peer->connection->su);
/* Print aspath */
if (attr->aspath) {
@@ -9588,14 +9537,12 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
const struct prefix *p, struct attr *attr, safi_t safi,
bool use_json, json_object *json_ar, bool wide)
{
- json_object *json_status = NULL;
json_object *json_net = NULL;
int len;
char buff[BUFSIZ];
/* Route status display. */
if (use_json) {
- json_status = json_object_new_object();
json_net = json_object_new_object();
} else {
vty_out(vty, " *");
@@ -9662,11 +9609,6 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
attr->aspath->str);
/* Print origin */
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
-#endif
- json_object_string_add(json_net, "bgpOriginCode",
- bgp_origin_str[attr->origin]);
json_object_string_add(
json_net, "origin",
bgp_origin_long_str[attr->origin]);
@@ -9722,20 +9664,11 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
if (use_json) {
struct bgp_path_info *bpi = bgp_dest_get_bgp_path_info(dest);
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
-#endif
- json_object_boolean_true_add(json_status, "*");
- json_object_boolean_true_add(json_status, ">");
json_object_boolean_true_add(json_net, "valid");
json_object_boolean_true_add(json_net, "best");
- if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH)) {
- json_object_boolean_true_add(json_status, "=");
+ if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_MULTIPATH))
json_object_boolean_true_add(json_net, "multipath");
- }
- json_object_object_add(json_net, "appliedStatusSymbols",
- json_status);
json_object_object_addf(json_ar, json_net, "%pFX", p);
} else
vty_out(vty, "\n");
@@ -9818,9 +9751,8 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
}
}
- label = decode_label(&path->extra->label[0]);
-
- if (bgp_is_valid_label(&label)) {
+ if (bgp_is_valid_label(&path->extra->label[0])) {
+ label = decode_label(&path->extra->label[0]);
if (json) {
json_object_int_add(json_out, "notag", label);
json_object_array_add(json, json_out);
@@ -9948,7 +9880,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
{
struct attr *attr = path->attr;
int len;
- char timebuf[BGP_UPTIME_LEN];
+ char timebuf[BGP_UPTIME_LEN] = {};
json_object *json_path = NULL;
if (use_json)
@@ -10007,7 +9939,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
{
struct attr *attr = path->attr;
struct bgp_damp_info *bdi;
- char timebuf[BGP_UPTIME_LEN];
+ char timebuf[BGP_UPTIME_LEN] = {};
int len;
json_object *json_path = NULL;
@@ -10108,7 +10040,7 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
json_peer);
else
json_object_object_addf(json_adv_to, json_peer, "%pSU",
- &peer->su);
+ &peer->connection->su);
} else {
if (*first) {
vty_out(vty, "%s", header);
@@ -10122,12 +10054,12 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
peer->conf_if);
else
vty_out(vty, " %s(%pSU)", peer->hostname,
- &peer->su);
+ &peer->connection->su);
} else {
if (peer->conf_if)
vty_out(vty, " %s", peer->conf_if);
else
- vty_out(vty, " %pSU", &peer->su);
+ vty_out(vty, " %pSU", &peer->connection->su);
}
}
}
@@ -10213,6 +10145,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
char tag_buf[30];
struct attr *attr = path->attr;
time_t tbuf;
+ char timebuf[32];
json_object *json_bestpath = NULL;
json_object *json_cluster_list = NULL;
json_object *json_cluster_list_list = NULL;
@@ -10292,11 +10225,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, "\n");
- if (path->extra && path->extra->parent && !json_paths) {
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->parent && !json_paths) {
struct bgp_path_info *parent_ri;
struct bgp_dest *dest, *pdest;
- parent_ri = (struct bgp_path_info *)path->extra->parent;
+ parent_ri =
+ (struct bgp_path_info *)path->extra->vrfleak->parent;
dest = parent_ri->net;
if (dest && dest->pdest) {
pdest = dest->pdest;
@@ -10551,7 +10486,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (json_paths) {
json_object_string_addf(json_peer, "peerId", "%pSU",
- &path->peer->su);
+ &path->peer->connection->su);
json_object_string_addf(json_peer, "routerId", "%pI4",
&path->peer->remote_id);
@@ -10586,7 +10521,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
path->peer->host);
else
vty_out(vty, " from %pSU",
- &path->peer->su);
+ &path->peer->connection->su);
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
@@ -10599,17 +10534,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/*
* Note when vrfid of nexthop is different from that of prefix
*/
- if (path->extra && path->extra->bgp_orig) {
- vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->bgp_orig) {
+ vrf_id_t nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id;
if (json_paths) {
const char *vn;
- if (path->extra->bgp_orig->inst_type
- == BGP_INSTANCE_TYPE_DEFAULT)
+ if (path->extra->vrfleak->bgp_orig->inst_type ==
+ BGP_INSTANCE_TYPE_DEFAULT)
vn = VRF_DEFAULT_NAME;
else
- vn = path->extra->bgp_orig->name;
+ vn = path->extra->vrfleak->bgp_orig->name;
json_object_string_add(json_path, "nhVrfName", vn);
@@ -10663,7 +10599,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object_boolean_true_add(json_nexthop_ll,
"accessible");
- if (!attr->mp_nexthop_prefer_global)
+ if (!CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
json_object_boolean_true_add(json_nexthop_ll,
"used");
else
@@ -10673,7 +10610,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " (%s) %s\n",
inet_ntop(AF_INET6, &attr->mp_nexthop_local,
buf, INET6_ADDRSTRLEN),
- attr->mp_nexthop_prefer_global
+ CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)
? "(prefer-global)"
: "(used)");
}
@@ -10781,9 +10719,17 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
} else {
if (json_paths)
json_object_string_add(
- json_peer, "type", "external");
+ json_peer, "type",
+ (path->peer->sub_sort ==
+ BGP_PEER_EBGP_OAD)
+ ? "external (oad)"
+ : "external");
else
- vty_out(vty, ", external");
+ vty_out(vty, ", %s",
+ (path->peer->sub_sort ==
+ BGP_PEER_EBGP_OAD)
+ ? "external (oad)"
+ : "external");
}
}
} else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
@@ -11004,13 +10950,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
/* Remote SID */
- if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
+ if ((path->attr->srv6_l3vpn || path->attr->srv6_vpn) &&
+ safi != SAFI_EVPN) {
+ struct in6_addr *sid_tmp =
+ path->attr->srv6_l3vpn ? (&path->attr->srv6_l3vpn->sid)
+ : (&path->attr->srv6_vpn->sid);
if (json_paths)
json_object_string_addf(json_path, "remoteSid", "%pI6",
- &path->extra->sid[0].sid);
+ sid_tmp);
else
- vty_out(vty, " Remote SID: %pI6\n",
- &path->extra->sid[0].sid);
+ vty_out(vty, " Remote SID: %pI6\n", sid_tmp);
}
/* Label Index */
@@ -11100,11 +11049,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_last_update = json_object_new_object();
json_object_int_add(json_last_update, "epoch", tbuf);
json_object_string_add(json_last_update, "string",
- ctime(&tbuf));
+ ctime_r(&tbuf, timebuf));
json_object_object_add(json_path, "lastUpdate",
json_last_update);
} else
- vty_out(vty, " Last update: %s", ctime(&tbuf));
+ vty_out(vty, " Last update: %s", ctime_r(&tbuf, timebuf));
/* Line 10 display PMSI tunnel attribute, if present */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
@@ -11123,10 +11072,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
str, label2vni(&attr->label));
}
- if (path->peer->t_gr_restart &&
+ if (path->peer->connection->t_gr_restart &&
CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
- unsigned long gr_remaining =
- event_timer_remain_second(path->peer->t_gr_restart);
+ unsigned long gr_remaining = event_timer_remain_second(
+ path->peer->connection->t_gr_restart);
if (json_paths) {
json_object_int_add(json_path,
@@ -11202,7 +11151,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi,
safi_t safi, uint16_t show_flags);
-static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
+static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_table *table, enum bgp_show_type type,
void *output_arg, const char *rd, int is_last,
unsigned long *output_cum, unsigned long *total_cum,
@@ -11563,12 +11512,12 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
if (type == bgp_show_type_dampend_paths
|| type == bgp_show_type_damp_neighbor)
damp_route_vty_out(vty, dest_p, pi, display,
- AFI_IP, safi, use_json,
+ afi, safi, use_json,
json_paths);
else if (type == bgp_show_type_flap_statistics
|| type == bgp_show_type_flap_neighbor)
flap_route_vty_out(vty, dest_p, pi, display,
- AFI_IP, safi, use_json,
+ afi, safi, use_json,
json_paths);
else {
if (detail_routes || detail_json) {
@@ -11716,7 +11665,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
total_count);
} else
vty_out(vty,
- "\nDisplayed %ld routes and %ld total paths\n",
+ "\nDisplayed %ld routes and %ld total paths\n",
output_count, total_count);
}
}
@@ -11724,7 +11673,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
return CMD_SUCCESS;
}
-int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
+int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_table *table, struct prefix_rd *prd_match,
enum bgp_show_type type, void *output_arg,
uint16_t show_flags)
@@ -11753,7 +11702,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
memcpy(&prd, dest_p, sizeof(struct prefix_rd));
prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);
- bgp_show_table(vty, bgp, safi, itable, type, output_arg,
+ bgp_show_table(vty, bgp, afi, safi, itable, type, output_arg,
rd, next == NULL, &output_cum,
&total_cum, &json_header_depth,
show_flags, RPKI_NOT_BEING_USED);
@@ -11767,10 +11716,10 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
total_cum);
else
vty_out(vty,
- "\nDisplayed %ld routes and %ld total paths\n",
+ "\nDisplayed %ld routes and %ld total paths\n",
output_cum, total_cum);
} else {
- if (use_json && output_cum == 0)
+ if (use_json && output_cum == 0 && json_header_depth == 0)
vty_out(vty, "{}\n");
}
return CMD_SUCCESS;
@@ -11803,7 +11752,7 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
table = bgp->rib[afi][safi];
/* use MPLS and ENCAP specific shows until they are merged */
if (safi == SAFI_MPLS_VPN) {
- return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
+ return bgp_show_table_rd(vty, bgp, afi, safi, table, NULL, type,
output_arg, show_flags);
}
@@ -11816,7 +11765,7 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (safi == SAFI_EVPN)
return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
- return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
+ return bgp_show_table(vty, bgp, afi, safi, table, type, output_arg, NULL, 1,
NULL, NULL, &json_header_depth, show_flags,
rpki_target_state);
}
@@ -12140,7 +12089,7 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
|| CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
route_vty_out_detail(vty, bgp, bgp_node,
bgp_dest_get_prefix(bgp_node), pi,
- AFI_IP, safi, rpki_curr_state,
+ afi, safi, rpki_curr_state,
json_paths);
}
@@ -12272,7 +12221,9 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
rm_p);
if (type5_pfxlen == match.prefixlen) {
is_exact_pfxlen_match = true;
- bgp_dest_unlock_node(rm);
+ rm = bgp_dest_unlock_node(rm);
+
+ assert(rm);
break;
}
}
@@ -12934,6 +12885,8 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
rpki_target_state = RPKI_VALID;
else if (argv_find(argv, argc, "invalid", &idx))
rpki_target_state = RPKI_INVALID;
+ else if (argv_find(argv, argc, "notfound", &idx))
+ rpki_target_state = RPKI_NOTFOUND;
}
/* Display prefixes with matching version numbers */
@@ -13044,6 +12997,15 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
get_afi_safi_str(afi,
safi,
true));
+
+ /* Adding 'routes' key to make
+ * the json output format valid
+ * for evpn
+ */
+ if (safi == SAFI_EVPN)
+ vty_out(vty,
+ "\"routes\":");
+
} else
vty_out(vty,
"\nFor address family: %s\n",
@@ -13484,7 +13446,7 @@ static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
memset(&ts, 0, sizeof(ts));
ts.table = bgp->rib[afi][safi];
- event_execute(bm->master, bgp_table_stats_walker, &ts, 0);
+ event_execute(bm->master, bgp_table_stats_walker, &ts, 0, NULL);
for (i = 0; i < BGP_STATS_MAX; i++) {
if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
@@ -13670,11 +13632,11 @@ static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
json_bitlen = json_object_new_array();
for (i = 0; i <= bitlen; i++) {
- struct json_object *ind_bit = json_object_new_object();
-
if (!ts.prefix_len_count[i])
continue;
+ struct json_object *ind_bit = json_object_new_object();
+
snprintf(temp_buf, sizeof(temp_buf), "%u", i);
json_object_int_add(ind_bit, temp_buf,
ts.prefix_len_count[i]);
@@ -13841,7 +13803,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
* stats for the thread-walk (i.e. ensure this can't be blamed on
* on just vty_read()).
*/
- event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
+ event_execute(bm->master, bgp_peer_count_walker, &pcounts, 0, NULL);
if (use_json) {
json_object_string_add(json, "prefixCountsFor", peer->host);
@@ -14029,9 +13991,7 @@ DEFUN (show_bgp_l2vpn_evpn_route_prefix,
static void show_adj_route_header(struct vty *vty, struct peer *peer,
struct bgp_table *table, int *header1,
- int *header2, json_object *json,
- json_object *json_scode,
- json_object *json_ocode, bool wide,
+ int *header2, json_object *json, bool wide,
bool detail)
{
uint64_t version = table ? table->version : 0;
@@ -14047,10 +14007,6 @@ static void show_adj_route_header(struct vty *vty, struct peer *peer,
peer->change_local_as
? peer->change_local_as
: peer->local_as);
- json_object_object_add(json, "bgpStatusCodes",
- json_scode);
- json_object_object_add(json, "bgpOriginCodes",
- json_ocode);
} else {
vty_out(vty,
"BGP table version is %" PRIu64
@@ -14087,7 +14043,6 @@ static void
show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
const char *rmap_name, json_object *json, json_object *json_ar,
- json_object *json_scode, json_object *json_ocode,
uint16_t show_flags, int *header1, int *header2, char *rd_str,
const struct prefix *match, unsigned long *output_count,
unsigned long *filtered_count)
@@ -14182,8 +14137,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (ret != RMAP_DENY) {
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide, detail);
if (use_json)
json_net = json_object_new_object();
@@ -14220,10 +14174,6 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
peer->change_local_as
? peer->change_local_as
: peer->local_as);
- json_object_object_add(json, "bgpStatusCodes",
- json_scode);
- json_object_object_add(json, "bgpOriginCodes",
- json_ocode);
json_object_string_add(
json, "bgpOriginatingDefaultNetwork",
(afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
@@ -14262,10 +14212,9 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
for (ain = dest->adj_in; ain; ain = ain->next) {
if (ain->peer != peer)
continue;
-
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide,
+ detail);
if ((safi == SAFI_MPLS_VPN)
|| (safi == SAFI_ENCAP)
@@ -14313,9 +14262,23 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (use_json)
json_net =
json_object_new_object();
+
+ struct bgp_path_info bpi;
+ struct bgp_dest buildit = *dest;
+ struct bgp_dest *pass_in;
+
+ if (route_filtered ||
+ ret == RMAP_DENY) {
+ bpi.attr = &attr;
+ bpi.peer = peer;
+ buildit.info = &bpi;
+
+ pass_in = &buildit;
+ } else
+ pass_in = dest;
bgp_show_path_info(
- NULL /* prefix_rd */, dest, vty,
- bgp, afi, safi, json_net,
+ NULL, pass_in, vty, bgp, afi,
+ safi, json_net,
BGP_PATH_SHOW_ALL, &display,
RPKI_NOT_BEING_USED);
if (use_json)
@@ -14335,10 +14298,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (paf->peer != peer || !adj->attr)
continue;
- show_adj_route_header(
- vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ show_adj_route_header(vty, peer, table,
+ header1, header2,
+ json, wide,
+ detail);
const struct prefix *rn_p =
bgp_dest_get_prefix(dest);
@@ -14402,8 +14365,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
struct bgp_path_info *pi;
show_adj_route_header(vty, peer, table, header1,
- header2, json, json_scode,
- json_ocode, wide, detail);
+ header2, json, wide, detail);
const struct prefix *rn_p = bgp_dest_get_prefix(dest);
@@ -14446,8 +14408,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
struct bgp *bgp;
struct bgp_table *table;
json_object *json = NULL;
- json_object *json_scode = NULL;
- json_object *json_ocode = NULL;
json_object *json_ar = NULL;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -14476,28 +14436,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
if (use_json) {
json = json_object_new_object();
json_ar = json_object_new_object();
- json_scode = json_object_new_object();
- json_ocode = json_object_new_object();
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpStatusCodes` from JSON outputs")
-#endif
- json_object_string_add(json_scode, "suppressed", "s");
- json_object_string_add(json_scode, "damped", "d");
- json_object_string_add(json_scode, "history", "h");
- json_object_string_add(json_scode, "valid", "*");
- json_object_string_add(json_scode, "best", ">");
- json_object_string_add(json_scode, "multipath", "=");
- json_object_string_add(json_scode, "internal", "i");
- json_object_string_add(json_scode, "ribFailure", "r");
- json_object_string_add(json_scode, "stale", "S");
- json_object_string_add(json_scode, "removed", "R");
-
-#if CONFDATE > 20231208
-CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
-#endif
- json_object_string_add(json_ocode, "igp", "i");
- json_object_string_add(json_ocode, "egp", "e");
- json_object_string_add(json_ocode, "incomplete", "?");
}
if (!peer || !peer->afc[afi][safi]) {
@@ -14508,8 +14446,6 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
json_object_free(json_ar);
- json_object_free(json_scode);
- json_object_free(json_ocode);
} else
vty_out(vty, "%% No such neighbor or address family\n");
@@ -14527,8 +14463,6 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
json_object_free(json_ar);
- json_object_free(json_scode);
- json_object_free(json_ocode);
} else
vty_out(vty,
"%% Inbound soft reconfiguration not enabled\n");
@@ -14568,11 +14502,11 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
prefix_rd2str(prd, rd_str, sizeof(rd_str),
bgp->asnotation);
- show_adj_route(
- vty, peer, table, afi, safi, type, rmap_name,
- json, json_routes, json_scode, json_ocode,
- show_flags, &header1, &header2, rd_str, match,
- &output_count_per_rd, &filtered_count_per_rd);
+ show_adj_route(vty, peer, table, afi, safi, type,
+ rmap_name, json, json_routes, show_flags,
+ &header1, &header2, rd_str, match,
+ &output_count_per_rd,
+ &filtered_count_per_rd);
/* Don't include an empty RD in the output! */
if (json_routes && (output_count_per_rd > 0))
@@ -14584,9 +14518,8 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
}
} else
show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
- json, json_ar, json_scode, json_ocode,
- show_flags, &header1, &header2, rd_str, match,
- &output_count, &filtered_count);
+ json, json_ar, show_flags, &header1, &header2,
+ rd_str, match, &output_count, &filtered_count);
if (use_json) {
if (type == bgp_show_adj_route_advertised)
@@ -14598,18 +14531,12 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
json_object_int_add(json, "filteredPrefixCounter",
filtered_count);
- /*
- * These fields only give up ownership to `json` when `header1`
- * is used (set to zero). See code in `show_adj_route` and
- * `show_adj_route_header`.
- */
- if (header1 == 1) {
- json_object_free(json_scode);
- json_object_free(json_ocode);
- }
-
- vty_json(vty, json);
- } else if (output_count > 0) {
+ /*
+ * This is an extremely expensive operation at scale
+ * and non-pretty reduces memory footprint significantly.
+ */
+ vty_json_no_pretty(vty, json);
+ } else if (output_count > 0) {
if (!match && filtered_count > 0)
vty_out(vty,
"\nTotal number of prefixes %ld (%ld filtered)\n",
@@ -14906,39 +14833,46 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
- return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
- RPKI_NOT_BEING_USED);
+ return bgp_show(vty, peer->bgp, afi, safi, type, &peer->connection->su,
+ show_flags, RPKI_NOT_BEING_USED);
}
-DEFUN (show_ip_bgp_flowspec_routes_detailed,
- show_ip_bgp_flowspec_routes_detailed_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- BGP_AFI_HELP_STR
- "SAFI Flowspec\n"
- "Detailed information on flowspec entries\n"
- JSON_STR)
+/*
+ * Used for "detailed" output for cmds like show bgp <afi> <safi> (or)
+ * show bgp <vrf> (or) show bgp <vrf> <afi> <safi>
+ */
+DEFPY(show_ip_bgp_vrf_afi_safi_routes_detailed,
+ show_ip_bgp_vrf_afi_safi_routes_detailed_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf_name] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] detail [json$uj]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Detailed information\n"
+ JSON_STR)
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
struct bgp *bgp = NULL;
int idx = 0;
- bool uj = use_json(argc, argv);
uint16_t show_flags = BGP_SHOW_OPT_ROUTES_DETAIL;
- if (uj) {
- argc--;
+ if (uj)
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
- }
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
if (!idx)
return CMD_WARNING;
+ /* 'vrf all' case to iterate all vrfs & show output per vrf instance */
+ if (vrf_name && strmatch(vrf_name, "all")) {
+ bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
+ return CMD_SUCCESS;
+ }
+ /* All other cases except vrf all */
return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
show_flags, RPKI_NOT_BEING_USED);
}
@@ -15140,7 +15074,8 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
bgp_distance_free(bdistance);
bgp_dest_set_bgp_path_info(dest, NULL);
- bgp_dest_unlock_node(dest);
+ dest = bgp_dest_unlock_node(dest);
+ assert(dest);
bgp_dest_unlock_node(dest);
return CMD_SUCCESS;
@@ -15175,8 +15110,8 @@ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
/* Check source address.
* Note: for aggregate route, peer can have unspec af type.
*/
- if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
- && !sockunion2hostprefix(&peer->su, &q))
+ if (pinfo->sub_type != BGP_ROUTE_AGGREGATE &&
+ !sockunion2hostprefix(&peer->connection->su, &q))
return 0;
dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
@@ -15652,7 +15587,7 @@ static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
struct vty *vty = arg;
struct peer *peer = bucket->data;
- vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
+ vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->connection->su);
}
DEFUN (show_bgp_listeners,
@@ -15679,8 +15614,8 @@ DEFUN (show_bgp_peerhash,
struct bgp *bgp;
for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
- vty_out(vty, "BGP: %s\n", bgp->name);
- hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
+ vty_out(vty, "BGP: %s\n", bgp->name_pretty);
+ hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
vty);
}
@@ -16054,8 +15989,9 @@ void bgp_route_init(void)
install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
- /* show bgp ipv4 flowspec detailed */
- install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
+ /* show bgp vrf <afi> <safi> detailed */
+ install_element(VIEW_NODE,
+ &show_ip_bgp_vrf_afi_safi_routes_detailed_cmd);
install_element(VIEW_NODE, &show_bgp_listeners_cmd);
install_element(VIEW_NODE, &show_bgp_peerhash_cmd);