#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_mh.h"
#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_orr.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN;
}
+void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl, uint16_t keepalive_probes)
+{
+ bgp->tcp_keepalive_idle = keepalive_idle;
+ bgp->tcp_keepalive_intvl = keepalive_intvl;
+ bgp->tcp_keepalive_probes = keepalive_probes;
+}
+
+void bgp_tcp_keepalive_unset(struct bgp *bgp)
+{
+ bgp->tcp_keepalive_idle = 0;
+ bgp->tcp_keepalive_intvl = 0;
+ bgp->tcp_keepalive_probes = 0;
+}
+
/* BGP confederation configuration. */
void bgp_confederation_id_set(struct bgp *bgp, as_t as)
{
static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
{
struct bgp *bgp;
+ as_t local_as;
bgp = peer->bgp;
+ if (peer->change_local_as)
+ local_as = peer->change_local_as;
+ else
+ local_as = peer->local_as;
+
/* Peer-group */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (peer->as_type == AS_INTERNAL)
else if (peer->as_type == AS_SPECIFIED && peer->as) {
assert(bgp);
- return (bgp->as == peer->as ? BGP_PEER_IBGP
- : BGP_PEER_EBGP);
+ return (local_as == peer->as ? BGP_PEER_IBGP
+ : BGP_PEER_EBGP);
}
else {
/* Normal peer */
if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
- if (peer->local_as == 0)
+ if (local_as == 0)
return BGP_PEER_INTERNAL;
- if (peer->local_as == peer->as) {
+ if (local_as == peer->as) {
if (bgp->as == bgp->confed_id) {
- if (peer->local_as == bgp->as)
+ if (local_as == bgp->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
} else {
- if (peer->local_as == bgp->confed_id)
+ if (local_as == bgp->confed_id)
return BGP_PEER_EBGP;
else
return BGP_PEER_IBGP;
&& (peer->group->conf->as_type != AS_UNSPECIFIED)) {
if (peer->group->conf->as_type
== AS_SPECIFIED) {
- if (peer->local_as
- == peer->group->conf->as)
+ if (local_as == peer->group->conf->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
- return (peer->local_as == 0
- ? BGP_PEER_INTERNAL
- : peer->local_as == peer->as ? BGP_PEER_IBGP
+ return (local_as == 0 ? BGP_PEER_INTERNAL
+ : local_as == peer->as ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
}
}
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
+ afi_t afi;
+ safi_t safi;
enum bgp_peer_sort origtype, newtype;
/* Stop peer. */
/* reflector-client reset */
if (newtype != BGP_PEER_IBGP) {
+
+ FOREACH_AFI_SAFI (afi, safi)
+ UNSET_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ORR_GROUP);
+
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
PEER_FLAG_REFLECTOR_CLIENT);
}
-
- /* local-as reset */
- if (newtype != BGP_PEER_EBGP) {
- peer->change_local_as = 0;
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
/* If peer does not exist, create new one. If peer already exists,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
}
+static void peer_notify_shutdown(struct peer *peer)
+{
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping shutdown notification",
+ peer);
+ return;
+ }
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+}
+
void peer_group_notify_unconfig(struct peer_group *group)
{
struct peer *peer, *other;
/* ebgp-multihop reset */
if (gtype == BGP_PEER_IBGP)
group->conf->ttl = MAXTTL;
-
- /* local-as reset */
- if (gtype != BGP_PEER_EBGP) {
- group->conf->change_local_as = 0;
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
bgp->default_subgroup_pkt_queue_max =
BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
+ bgp_tcp_keepalive_unset(bgp);
bgp_timers_unset(bgp);
bgp->default_min_holdtime = 0;
bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
hook_call(bgp_inst_delete, bgp);
+ THREAD_OFF(bgp->t_condition_check);
THREAD_OFF(bgp->t_startup);
THREAD_OFF(bgp->t_maxmed_onstartup);
THREAD_OFF(bgp->t_update_delay);
gr_info = &bgp->gr_info[afi][safi];
if (!gr_info)
continue;
+ t = gr_info->t_select_deferral;
+ if (t) {
+ void *info = THREAD_ARG(t);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
t = gr_info->t_route_select;
}
/* Inform peers we're going down. */
- for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
- }
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
+ peer_notify_shutdown(peer);
/* Delete static routes (networks). */
bgp_static_delete(bgp);
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
}
+ /* Free any memory allocated to holding routemap references */
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ for (enum vpn_policy_direction dir = 0;
+ dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap[dir] = NULL;
+ }
+ }
+
/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
}
+ bgp_orr_cleanup(bgp);
+
XFREE(MTYPE_BGP, bgp->name);
XFREE(MTYPE_BGP, bgp->name_pretty);
XFREE(MTYPE_BGP, bgp->snmp_stats);
{PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
{PEER_FLAG_TIMER_DELAYOPEN, 0, peer_change_none},
{PEER_FLAG_PASSWORD, 0, peer_change_none},
- {PEER_FLAG_LOCAL_AS, 0, peer_change_none},
- {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
- {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
+ {PEER_FLAG_LOCAL_AS, 0, peer_change_reset},
+ {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_reset},
+ {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_reset},
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
{PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
{PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
{PEER_FLAG_ROLE, 0, peer_change_reset},
{PEER_FLAG_PORT, 0, peer_change_reset},
+ {PEER_FLAG_AIGP, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
{PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
{PEER_FLAG_SOO, 0, peer_change_reset},
+ {PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
{0, 0, 0}};
/* Proper action set. */
if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER;
+ /* Do not remove reflector client when ORR is configured on this peer */
+ if (flag & PEER_FLAG_REFLECTOR_CLIENT && !set &&
+ peer_orr_rrclient_check(peer, afi, safi))
+ return BGP_ERR_PEER_ORR_CONFIGURED;
+
/* Special check for remove-private-AS. */
if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
* being used by a peer has changed (AF specific). Automatically
* initiates inbound or outbound processing as needed.
*/
-static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
- int outbound)
+void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
+ int outbound)
{
if (outbound) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
- enum bgp_peer_sort ptype = peer_sort(peer);
-
- if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
- return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
if (bgp->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
- if (peer->as == as)
- return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
-
/* Save previous flag states. */
old_no_prepend =
!!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
&& old_replace_as == replace_as)
return 0;
peer->change_local_as = as;
+ (void)peer_sort(peer);
/* Check if handling a regular peer. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Send notification or reset peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
- peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
- bgp_session_reset(peer);
-
- /* Skip peer-group mechanics for regular peers. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
return 0;
- }
/*
* Set flag and configuration on all peer-group members, unless they are
COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
replace_as);
member->change_local_as = as;
-
- /* Send notification or stop peer depending on state. */
- if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
- member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
- bgp_notify_send(member, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_CONFIG_CHANGE);
- } else
- BGP_EVENT_ADD(member, BGP_Stop);
}
return 0;
return 0;
}
-static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
- safi_t safi, const char *amap_name,
- struct route_map *amap,
- const char *cmap_name,
- struct route_map *cmap,
- bool condition, bool set)
-{
- struct bgp_filter *filter;
- bool filter_exists = false;
-
- filter = &peer->filter[afi][safi];
-
- /* advertise-map is already configured. */
- if (filter->advmap.aname) {
- filter_exists = true;
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
- }
-
- route_map_counter_decrement(filter->advmap.amap);
-
- /* Removed advertise-map configuration */
- if (!set) {
- memset(&filter->advmap, 0, sizeof(filter->advmap));
-
- /* decrement condition_filter_count delete timer if
- * this is the last advertise-map to be removed.
- */
- if (filter_exists)
- bgp_conditional_adv_disable(peer, afi, safi);
-
- return;
- }
-
- /* Update filter data with newly configured values. */
- filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
- filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
- filter->advmap.amap = amap;
- filter->advmap.cmap = cmap;
- filter->advmap.condition = condition;
- route_map_counter_increment(filter->advmap.amap);
- peer->advmap_config_change[afi][safi] = true;
-
- /* Increment condition_filter_count and/or create timer. */
- if (!filter_exists) {
- filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
- bgp_conditional_adv_enable(peer, afi, safi);
- }
-
- /* Process peer route updates. */
- peer_on_policy_change(peer, afi, safi, 1);
-}
-
-/* Set advertise-map to the peer. */
-int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* Set configuration on peer. */
- peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
- advertise_map, condition_name,
- condition_map, condition, true);
-
- /* Check if handling a regular peer & Skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Set override-flag and process peer route updates. */
- SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
- return 0;
- }
-
- /*
- * Set configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
-
- /* Set configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, true);
- }
-
- return 0;
-}
-
-/* Unset advertise-map from the peer. */
-int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* advertise-map is not configured */
- if (!peer->filter[afi][safi].advmap.aname)
- return 0;
-
- /* Unset override-flag unconditionally. */
- UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
-
- /* Inherit configuration from peer-group if peer is member. */
- if (peer_group_active(peer)) {
- PEER_STR_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.aname,
- MTYPE_BGP_FILTER_NAME);
- PEER_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.amap);
- } else
- peer_advertise_map_filter_update(
- peer, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Check if handling a regular peer and skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s",
- __func__, peer->host,
- get_afi_safi_str(afi, safi, false));
-
- return 0;
- }
-
- /*
- * Remove configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
- /* Remove configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s ",
- __func__, member->host,
- get_afi_safi_str(afi, safi, false));
- }
-
- return 0;
-}
-
static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
{
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
bm->socket_buffer = buffer_size;
bm->wait_for_fib = false;
bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
+ bm->inq_limit = BM_DEFAULT_INQ_LIMIT;
bgp_mac_init();
/* init the rd id space.
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
bgp_close_vrf_socket(bgp);
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
- if (peer_established(peer) || peer->status == OpenSent
- || peer->status == OpenConfirm)
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping unconfig notification",
+ peer);
+ continue;
+ }
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
+ }
}
if (bm->listen_sockets)