#include "table.h"
#include "lib/json.h"
#include "frr_pthread.h"
+#include "bitfield.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_flowspec.h"
-
+#include "bgpd/bgp_labelpool.h"
+#include "bgpd/bgp_pbr.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_QOBJ_TYPE(bgp_master)
static int bgp_check_main_socket(bool create, struct bgp *bgp)
{
static int bgp_server_main_created;
- struct listnode *bgpnode, *nbgpnode;
- struct bgp *bgp_temp;
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF &&
- vrf_is_mapped_on_netns(bgp->vrf_id))
- return 0;
if (create == true) {
if (bgp_server_main_created)
return 0;
}
if (!bgp_server_main_created)
return 0;
- /* only delete socket on some cases */
- for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp_temp)) {
- /* do not count with current bgp */
- if (bgp_temp == bgp)
- continue;
- /* if other instance non VRF, do not delete socket */
- if (bgp_temp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
- return 0;
- /* vrf lite, do not delete socket */
- if (!vrf_is_mapped_on_netns(bgp_temp->vrf_id))
- return 0;
- }
bgp_close();
bgp_server_main_created = 0;
return 0;
return CHECK_FLAG(peer->af_flags[afi][safi], flag);
}
-/* Return true if flag is set for the peer but not the peer-group */
-static int peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag)
+void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
+ uint32_t flag)
{
- struct peer *g_peer = NULL;
+ /* Skip if peer is not a peer-group member. */
+ if (!peer_group_active(peer))
+ return;
- if (peer_af_flag_check(peer, afi, safi, flag)) {
- if (peer_group_active(peer)) {
- g_peer = peer->group->conf;
+ /* Unset override flag to signal inheritance from peer-group. */
+ UNSET_FLAG(peer->af_flags_override[afi][safi], flag);
- /* If this flag is not set for the peer's peer-group
- * then return true */
- if (!peer_af_flag_check(g_peer, afi, safi, flag)) {
- return 1;
- }
- }
+ /* Inherit flag state from peer-group. */
+ if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi], flag))
+ SET_FLAG(peer->af_flags[afi][safi], flag);
+ else
+ UNSET_FLAG(peer->af_flags[afi][safi], flag);
+}
- /* peer is not in a peer-group but the flag is set to return
- true */
- else {
- return 1;
- }
+static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint32_t flag)
+{
+ if (!peer_group_active(peer)) {
+ if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
+ return !peer_af_flag_check(peer, afi, safi, flag);
+ else
+ return !!peer_af_flag_check(peer, afi, safi, flag);
}
- return 0;
+ return !!CHECK_FLAG(peer->af_flags_override[afi][safi], flag);
+}
+
+static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi,
+ uint8_t type, int direct)
+{
+ struct bgp_filter *filter;
+
+ if (peer_group_active(peer))
+ return !!CHECK_FLAG(peer->filter_override[afi][safi][direct],
+ type);
+
+ filter = &peer->filter[afi][safi];
+ switch (type) {
+ case PEER_FT_DISTRIBUTE_LIST:
+ return !!(filter->dlist[direct].name);
+ case PEER_FT_FILTER_LIST:
+ return !!(filter->aslist[direct].name);
+ case PEER_FT_PREFIX_LIST:
+ return !!(filter->plist[direct].name);
+ case PEER_FT_ROUTE_MAP:
+ return !!(filter->map[direct].name);
+ case PEER_FT_UNSUPPRESS_MAP:
+ return !!(filter->usmap.name);
+ default:
+ return false;
+ }
}
/* Reset all address family specific configuration. */
PEER_FLAG_SEND_EXT_COMMUNITY);
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_COMMUNITY);
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
}
/* Clear neighbor default_originate_rmap */
peer = peer_lock(peer); /* initial reference */
peer->password = NULL;
- /* Set default flags. */
+ /* Set default flags. */
FOREACH_AFI_SAFI (afi, safi) {
if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_SEND_EXT_COMMUNITY);
SET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_COMMUNITY);
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ SET_FLAG(peer->af_flags_invert[afi][safi],
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
}
- peer->orf_plist[afi][safi] = NULL;
}
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
FOREACH_AFI_SAFI (afi, safi) {
peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
+ peer_dst->af_flags_invert[afi][safi] =
+ peer_src->af_flags_invert[afi][safi];
peer_dst->allowas_in[afi][safi] =
peer_src->allowas_in[afi][safi];
peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
/* peer af_flags apply */
peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
+ peer->af_flags_invert[afi][safi] = conf->af_flags_invert[afi][safi];
/* maximum-prefix */
peer->pmax[afi][safi] = conf->pmax[afi][safi];
if (safi == SAFI_FLOWSPEC) {
/* connect to table manager */
- bgp_zebra_init_tm_connect();
+ bgp_zebra_init_tm_connect(bgp);
}
return ret;
}
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
FOREACH_AFI_SAFI (afi, safi) {
- bgp->route[afi][safi] = bgp_table_init(afi, safi);
- bgp->aggregate[afi][safi] = bgp_table_init(afi, safi);
- bgp->rib[afi][safi] = bgp_table_init(afi, safi);
+ bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
/* Enable maximum-paths */
bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
#endif /* ENABLE_BGP_VNC */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ bgp->vpn_policy[afi].bgp = bgp;
+ bgp->vpn_policy[afi].afi = afi;
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
MPLS_LABEL_NONE;
+
+ bgp->vpn_policy[afi].import_vrf = list_new();
+ bgp->vpn_policy[afi].export_vrf = list_new();
}
if (name) {
bgp->name = XSTRDUP(MTYPE_BGP, name);
bgp->restart_time, &bgp->t_startup);
}
+ /* printable name we can use in debug messages */
+ if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
+ bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
+ } else {
+ const char *n;
+ int len;
+
+ if (bgp->name)
+ n = bgp->name;
+ else
+ n = "?";
+
+ len = 4 + 1 + strlen(n) + 1; /* "view foo\0" */
+
+ bgp->name_pretty = XCALLOC(MTYPE_BGP, len);
+ snprintf(bgp->name_pretty, len, "%s %s",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+ ? "VRF"
+ : "VIEW",
+ n);
+ }
+
atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
memory_order_relaxed);
atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
QOBJ_REG(bgp, bgp);
update_bgp_group_init(bgp);
+
+ /* assign a unique rd id for auto derivation of vrf's RD */
+ bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
+
bgp_evpn_init(bgp);
+ bgp_pbr_init(bgp);
return bgp;
}
/* Create BGP server socket, if listen mode not disabled */
if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
return 0;
- if (bgp->name && bgp->inst_type == BGP_INSTANCE_TYPE_VRF && vrf) {
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
/*
* suppress vrf socket
*/
if (create == FALSE) {
- if (vrf_is_mapped_on_netns(vrf->vrf_id))
- bgp_close_vrf_socket(bgp);
- else
- ret = bgp_check_main_socket(create, bgp);
- return ret;
+ bgp_close_vrf_socket(bgp);
+ return 0;
}
+ if (vrf == NULL)
+ return BGP_ERR_INVALID_VALUE;
/* do nothing
* if vrf_id did not change
*/
*/
if (vrf->vrf_id == VRF_UNKNOWN)
return 0;
- /* if BGP VRF instance requested
- * if backend is NETNS, create BGP server socket in the NETNS
- */
- if (vrf_is_mapped_on_netns(bgp->vrf_id)) {
- ret = bgp_socket(bgp, bm->port, bm->address);
- if (ret < 0)
- return BGP_ERR_INVALID_VALUE;
- return 0;
- }
- }
- /* if BGP VRF instance requested or VRF lite backend
- * if BGP non VRF instance, create it
- * if not already done
- */
- return bgp_check_main_socket(create, bgp);
+ ret = bgp_socket(bgp, bm->port, bm->address);
+ if (ret < 0)
+ return BGP_ERR_INVALID_VALUE;
+ return 0;
+ } else
+ return bgp_check_main_socket(create, bgp);
}
/* Called from VTY commands. */
rmap = &bgp->table_map[afi][safi];
if (rmap->name)
XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+
+ /*
+ * Yes this is per AFI, but
+ * the list_delete_and_null nulls the pointer
+ * and we'll not leak anything on going down
+ * and the if test will fail on the second safi.
+ */
+ if (bgp->vpn_policy[afi].import_vrf)
+ list_delete_and_null(&bgp->vpn_policy[afi].import_vrf);
+ if (bgp->vpn_policy[afi].export_vrf)
+ list_delete_and_null(&bgp->vpn_policy[afi].export_vrf);
}
bgp_scan_finish(bgp);
bgp_address_destroy(bgp);
bgp_tip_hash_destroy(bgp);
- bgp_evpn_cleanup(bgp);
+ /* release the auto RD id */
+ bf_release_index(bm->rd_idspace, bgp->vrf_rd_id);
+ bgp_evpn_cleanup(bgp);
+ bgp_pbr_cleanup(bgp);
if (bgp->name)
XFREE(MTYPE_BGP, bgp->name);
+ if (bgp->name_pretty)
+ XFREE(MTYPE_BGP, bgp->name_pretty);
XFREE(MTYPE_BGP, bgp);
}
struct listnode *bgpnode, *nbgpnode;
for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
- /* Skip VRFs Lite only, this function will not be
- * invoked without an instance
- * when examining VRFs.
- */
- if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
- && !vrf_is_mapped_on_netns(bgp->vrf_id))
- continue;
-
peer = hash_lookup(bgp->peerhash, &tmp_peer);
-
if (peer)
break;
}
{PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
{PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
{PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
+ {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
{PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
{PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
- // PEER_FLAG_DEFAULT_ORIGINATE
+ {PEER_FLAG_DEFAULT_ORIGINATE, 0, peer_change_none},
{PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
{PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
{PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
{PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
{PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
- // PEER_FLAG_MAX_PREFIX
- // PEER_FLAG_MAX_PREFIX_WARNING
+ {PEER_FLAG_MAX_PREFIX, 0, peer_change_none},
+ {PEER_FLAG_MAX_PREFIX_WARNING, 0, peer_change_none},
{PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
{PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
{PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
}
static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag, int set)
+ uint32_t flag, bool set)
{
int found;
int size;
+ int addpath_tx_used;
+ bool invert;
struct listnode *node, *nnode;
struct peer_group *group;
struct peer_flag_action action;
struct peer *tmp_peer;
struct bgp *bgp;
- int addpath_tx_used;
memset(&action, 0, sizeof(struct peer_flag_action));
size = sizeof peer_af_flag_action_list
/ sizeof(struct peer_flag_action);
+ invert = CHECK_FLAG(peer->af_flags_invert[afi][safi], flag);
found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
flag);
/* When current flag configuration is same as requested one. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag) == flag)
+ if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
+ if (invert)
+ UNSET_FLAG(peer->af_flags_override[afi][safi],
+ flag);
+ else
+ SET_FLAG(peer->af_flags_override[afi][safi],
+ flag);
return 0;
- if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag))
+ }
+
+ if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
+ if (invert)
+ SET_FLAG(peer->af_flags_override[afi][safi],
+ flag);
+ else
+ UNSET_FLAG(peer->af_flags_override[afi][safi],
+ flag);
return 0;
+ }
}
- if (set)
- SET_FLAG(peer->af_flags[afi][safi], flag);
- else
- UNSET_FLAG(peer->af_flags[afi][safi], flag);
+ /* Set/unset flag or inherit from peer-group if appropriate. */
+ if (invert) {
+ if (!set)
+ UNSET_FLAG(peer->af_flags[afi][safi], flag);
+ else if (peer_group_active(peer))
+ peer_af_flag_inherit(peer, afi, safi, flag);
+ else
+ SET_FLAG(peer->af_flags[afi][safi], flag);
+ } else {
+ if (set)
+ SET_FLAG(peer->af_flags[afi][safi], flag);
+ else if (peer_group_active(peer))
+ peer_af_flag_inherit(peer, afi, safi, flag);
+ else
+ UNSET_FLAG(peer->af_flags[afi][safi], flag);
+ }
/* Execute action when peer is established. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
/* Peer group member updates. */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
group = peer->group;
-
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
+ if (CHECK_FLAG(tmp_peer->af_flags_override[afi][safi],
+ flag))
+ continue;
+
if (set
- && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag)
- == flag)
+ && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag))
continue;
if (!set
}
}
}
+ } else {
+ if (set != invert)
+ SET_FLAG(peer->af_flags_override[afi][safi], flag);
+ else
+ UNSET_FLAG(peer->af_flags_override[afi][safi], flag);
}
/* Track if addpath TX is in use */
int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
const char *rmap)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
- if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
- || (rmap && !peer->default_rmap[afi][safi].name)
- || (rmap
- && strcmp(rmap, peer->default_rmap[afi][safi].name) != 0)) {
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_DEFAULT_ORIGINATE);
-
- if (rmap) {
+ /* Set flag and configuration on peer. */
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE);
+ if (rmap) {
+ if (!peer->default_rmap[afi][safi].name
+ || strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) {
if (peer->default_rmap[afi][safi].name)
XFREE(MTYPE_ROUTE_MAP_NAME,
peer->default_rmap[afi][safi].name);
+
peer->default_rmap[afi][safi].name =
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
peer->default_rmap[afi][safi].map =
route_map_lookup_by_name(rmap);
}
+ } else if (!rmap) {
+ if (peer->default_rmap[afi][safi].name)
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ peer->default_rmap[afi][safi].name);
+
+ peer->default_rmap[afi][safi].name = NULL;
+ peer->default_rmap[afi][safi].map = NULL;
}
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Update peer route announcements. */
if (peer->status == Established && peer->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
bgp_default_originate(peer, afi, safi, 0);
bgp_announce_route(peer, afi, safi);
}
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- /* peer-group member updates. */
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_DEFAULT_ORIGINATE);
+ /*
+ * Set flag and configuration on all peer-group members, unless they are
+ * explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_DEFAULT_ORIGINATE))
+ continue;
+ /* Set flag and configuration on peer-group member. */
+ SET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_DEFAULT_ORIGINATE);
if (rmap) {
- if (peer->default_rmap[afi][safi].name)
+ if (member->default_rmap[afi][safi].name)
XFREE(MTYPE_ROUTE_MAP_NAME,
- peer->default_rmap[afi][safi].name);
- peer->default_rmap[afi][safi].name =
+ member->default_rmap[afi][safi].name);
+
+ member->default_rmap[afi][safi].name =
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
- peer->default_rmap[afi][safi].map =
+ member->default_rmap[afi][safi].map =
route_map_lookup_by_name(rmap);
}
- if (peer->status == Established && peer->afc_nego[afi][safi]) {
- update_group_adjust_peer(peer_af_find(peer, afi, safi));
- bgp_default_originate(peer, afi, safi, 0);
- bgp_announce_route(peer, afi, safi);
+ /* Update peer route announcements. */
+ if (member->status == Established
+ && member->afc_nego[afi][safi]) {
+ update_group_adjust_peer(
+ peer_af_find(member, afi, safi));
+ bgp_default_originate(member, afi, safi, 0);
+ bgp_announce_route(member, afi, safi);
}
}
+
return 0;
}
int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_DEFAULT_ORIGINATE)) {
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_DEFAULT_ORIGINATE);
-
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ peer_af_flag_inherit(peer, afi, safi,
+ PEER_FLAG_DEFAULT_ORIGINATE);
+ PEER_STR_ATTR_INHERIT(MTYPE_ROUTE_MAP_NAME, peer,
+ default_rmap[afi][safi].name);
+ PEER_ATTR_INHERIT(peer, default_rmap[afi][safi].map);
+ } else {
+ /* Otherwise remove flag and configuration from peer. */
+ peer_af_flag_unset(peer, afi, safi,
+ PEER_FLAG_DEFAULT_ORIGINATE);
if (peer->default_rmap[afi][safi].name)
XFREE(MTYPE_ROUTE_MAP_NAME,
peer->default_rmap[afi][safi].name);
peer->default_rmap[afi][safi].map = NULL;
}
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Update peer route announcements. */
if (peer->status == Established && peer->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
bgp_default_originate(peer, afi, safi, 1);
bgp_announce_route(peer, afi, safi);
}
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- /* peer-group member updates. */
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
+ /*
+ * Remove flag and configuration from all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_DEFAULT_ORIGINATE))
+ continue;
+
+ /* Remove flag and configuration on peer-group member. */
UNSET_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_DEFAULT_ORIGINATE);
-
if (peer->default_rmap[afi][safi].name)
XFREE(MTYPE_ROUTE_MAP_NAME,
peer->default_rmap[afi][safi].name);
peer->default_rmap[afi][safi].name = NULL;
peer->default_rmap[afi][safi].map = NULL;
+ /* Update peer route announcements. */
if (peer->status == Established && peer->afc_nego[afi][safi]) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
bgp_default_originate(peer, afi, safi, 1);
bgp_announce_route(peer, afi, safi);
}
}
+
return 0;
}
/* neighbor weight. */
int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, uint16_t weight)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
+ /* Set flag and configuration on peer. */
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
if (peer->weight[afi][safi] != weight) {
peer->weight[afi][safi] = weight;
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
peer_on_policy_change(peer, afi, safi, 0);
}
+ /* Skip peer-group mechanics for regular peers. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
return 0;
- /* peer-group member updates. */
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (peer->weight[afi][safi] != weight) {
- peer->weight[afi][safi] = weight;
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
- peer_on_policy_change(peer, afi, safi, 0);
+ /*
+ * Set flag and configuration on all peer-group members, unless they are
+ * explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_WEIGHT))
+ continue;
+
+ /* Set flag and configuration on peer-group member. */
+ SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
+ if (member->weight[afi][safi] != weight) {
+ member->weight[afi][safi] = weight;
+ peer_on_policy_change(member, afi, safi, 0);
}
}
+
return 0;
}
int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
- /* not the peer-group itself but a peer in a peer-group */
+ if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+ return 0;
+
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- group = peer->group;
+ peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT);
+ PEER_ATTR_INHERIT(peer, weight[afi][safi]);
- /* inherit weight from the peer-group */
- if (CHECK_FLAG(group->conf->af_flags[afi][safi],
- PEER_FLAG_WEIGHT)) {
- peer->weight[afi][safi] =
- group->conf->weight[afi][safi];
- peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
- peer_on_policy_change(peer, afi, safi, 0);
- } else {
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_WEIGHT)) {
- peer->weight[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_WEIGHT);
- peer_on_policy_change(peer, afi, safi, 0);
- }
- }
+ peer_on_policy_change(peer, afi, safi, 0);
+ return 0;
}
- else {
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) {
- peer->weight[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
- peer_on_policy_change(peer, afi, safi, 0);
- }
+ /* Remove flag and configuration from peer. */
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
+ peer->weight[afi][safi] = 0;
+ peer_on_policy_change(peer, afi, safi, 0);
- /* peer-group member updates. */
- group = peer->group;
+ /* Skip peer-group mechanics for regular peers. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ return 0;
- if (group) {
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
- peer)) {
- if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_WEIGHT)) {
- peer->weight[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_WEIGHT);
- peer_on_policy_change(peer, afi, safi,
- 0);
- }
- }
- }
+ /*
+ * Remove flag and configuration from all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_WEIGHT))
+ continue;
+
+ /* Skip peers where flag is already disabled. */
+ if (!CHECK_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT))
+ continue;
+
+ /* Remove flag and configuration on peer-group member. */
+ UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
+ member->weight[afi][safi] = 0;
+ peer_on_policy_change(member, afi, safi, 0);
}
+
return 0;
}
int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
int allow_num, int origin)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
+ if (!origin && (allow_num < 1 || allow_num > 10))
+ return BGP_ERR_INVALID_VALUE;
+
+ /* Set flag and configuration on peer. */
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
if (origin) {
- if (peer->allowas_in[afi][safi]
- || CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN)
+ if (peer->allowas_in[afi][safi] != 0
|| !CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- peer->allowas_in[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN);
peer_af_flag_set(peer, afi, safi,
PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ peer->allowas_in[afi][safi] = 0;
peer_on_policy_change(peer, afi, safi, 0);
}
-
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
- return 0;
-
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (peer->allowas_in[afi][safi]
- || CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN)
- || !CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- peer->allowas_in[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN);
- peer_af_flag_set(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN);
- peer_on_policy_change(peer, afi, safi, 0);
- }
- }
} else {
- if (allow_num < 1 || allow_num > 10)
- return BGP_ERR_INVALID_VALUE;
-
if (peer->allowas_in[afi][safi] != allow_num
|| CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- peer->allowas_in[afi][safi] = allow_num;
- peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+
peer_af_flag_unset(peer, afi, safi,
PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ peer->allowas_in[afi][safi] = allow_num;
peer_on_policy_change(peer, afi, safi, 0);
}
+ }
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ /* Skip peer-group mechanics for regular peers. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ return 0;
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (peer->allowas_in[afi][safi] != allow_num
- || CHECK_FLAG(peer->af_flags[afi][safi],
+ /*
+ * Set flag and configuration on all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_ALLOWAS_IN))
+ continue;
+
+ /* Set flag and configuration on peer-group member. */
+ SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
+ if (origin) {
+ if (member->allowas_in[afi][safi] != 0
+ || !CHECK_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
+ SET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ member->allowas_in[afi][safi] = 0;
+ peer_on_policy_change(peer, afi, safi, 0);
+ }
+ } else {
+ if (member->allowas_in[afi][safi] != allow_num
+ || CHECK_FLAG(member->af_flags[afi][safi],
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- peer->allowas_in[afi][safi] = allow_num;
- peer_af_flag_set(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN);
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ UNSET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ member->allowas_in[afi][safi] = allow_num;
peer_on_policy_change(peer, afi, safi, 0);
}
}
int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
{
- struct peer_group *group;
- struct peer *tmp_peer;
+ struct peer *member;
struct listnode *node, *nnode;
- /* If this is a peer-group we must first clear the flags for all of the
- * peer-group members
- */
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
- if (CHECK_FLAG(tmp_peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN)
- || CHECK_FLAG(tmp_peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- tmp_peer->allowas_in[afi][safi] = 0;
- peer_af_flag_unset(tmp_peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN);
- peer_af_flag_unset(tmp_peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN);
- peer_on_policy_change(tmp_peer, afi, safi, 0);
- }
- }
- }
+ /* Skip peer if flag is already disabled. */
+ if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
+ return 0;
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)
- || CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- peer->allowas_in[afi][safi] = 0;
- peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
- peer_af_flag_unset(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+ peer_af_flag_inherit(peer, afi, safi,
+ PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ PEER_ATTR_INHERIT(peer, allowas_in[afi][safi]);
peer_on_policy_change(peer, afi, safi, 0);
+
+ return 0;
+ }
+
+ /* Remove flag and configuration from peer. */
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ peer->allowas_in[afi][safi] = 0;
+ peer_on_policy_change(peer, afi, safi, 0);
+
+ /* Skip peer-group mechanics if handling a regular peer. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ return 0;
+
+ /*
+ * Remove flags and configuration from all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_ALLOWAS_IN))
+ continue;
+
+ /* Skip peers where flag is already disabled. */
+ if (!CHECK_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN))
+ continue;
+
+ /* Remove flags and configuration on peer-group member. */
+ UNSET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN);
+ UNSET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_ALLOWAS_IN_ORIGIN);
+ member->allowas_in[afi][safi] = 0;
+ peer_on_policy_change(member, afi, safi, 0);
}
return 0;
int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
const char *name)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
+ /* Set configuration on peer. */
filter = &peer->filter[afi][safi];
-
if (filter->plist[direct].name)
return BGP_ERR_PEER_FILTER_CONFLICT;
-
if (filter->dlist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->dlist[direct].alist = access_list_lookup(afi, name);
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_DISTRIBUTE_LIST);
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Set configuration on all peer-group members, un less they are
+ * explicitely 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][direct],
+ PEER_FT_DISTRIBUTE_LIST))
+ continue;
+ /* Set configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->dlist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->dlist[direct].name);
filter->dlist[direct].name =
XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->dlist[direct].alist = access_list_lookup(afi, name);
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct bgp_filter *gfilter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
- filter = &peer->filter[afi][safi];
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_DISTRIBUTE_LIST);
- /* apply peer-group filter */
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- gfilter = &peer->group->conf->filter[afi][safi];
-
- if (gfilter->dlist[direct].name) {
- if (filter->dlist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME,
- filter->dlist[direct].name);
- filter->dlist[direct].name =
- XSTRDUP(MTYPE_BGP_FILTER_NAME,
- gfilter->dlist[direct].name);
- filter->dlist[direct].alist =
- gfilter->dlist[direct].alist;
- peer_on_policy_change(peer, afi, safi,
- (direct == FILTER_OUT) ? 1 : 0);
- return 0;
- }
+ PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
+ filter[afi][safi].dlist[direct].name);
+ PEER_ATTR_INHERIT(peer, filter[afi][safi].dlist[direct].alist);
+ } else {
+ /* Otherwise remove configuration from peer. */
+ filter = &peer->filter[afi][safi];
+ if (filter->dlist[direct].name)
+ XFREE(MTYPE_BGP_FILTER_NAME,
+ filter->dlist[direct].name);
+ filter->dlist[direct].name = NULL;
+ filter->dlist[direct].alist = NULL;
}
- if (filter->dlist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
- filter->dlist[direct].name = NULL;
- filter->dlist[direct].alist = NULL;
-
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_DISTRIBUTE_LIST))
+ continue;
+ /* Remove configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->dlist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->dlist[direct].name);
filter->dlist[direct].name = NULL;
filter->dlist[direct].alist = NULL;
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
const char *name)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
+ /* Set configuration on peer. */
filter = &peer->filter[afi][safi];
-
if (filter->dlist[direct].name)
return BGP_ERR_PEER_FILTER_CONFLICT;
-
if (filter->plist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->plist[direct].plist = prefix_list_lookup(afi, name);
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_PREFIX_LIST);
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_PREFIX_LIST))
+ continue;
+ /* Set configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->plist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->plist[direct].name);
filter->plist[direct].name =
XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->plist[direct].plist = prefix_list_lookup(afi, name);
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
+
return 0;
}
int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
int direct)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct bgp_filter *gfilter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
- filter = &peer->filter[afi][safi];
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_PREFIX_LIST);
- /* apply peer-group filter */
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- gfilter = &peer->group->conf->filter[afi][safi];
-
- if (gfilter->plist[direct].name) {
- if (filter->plist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME,
- filter->plist[direct].name);
- filter->plist[direct].name =
- XSTRDUP(MTYPE_BGP_FILTER_NAME,
- gfilter->plist[direct].name);
- filter->plist[direct].plist =
- gfilter->plist[direct].plist;
- peer_on_policy_change(peer, afi, safi,
- (direct == FILTER_OUT) ? 1 : 0);
- return 0;
- }
+ PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
+ filter[afi][safi].plist[direct].name);
+ PEER_ATTR_INHERIT(peer, filter[afi][safi].plist[direct].plist);
+ } else {
+ /* Otherwise remove configuration from peer. */
+ filter = &peer->filter[afi][safi];
+ if (filter->plist[direct].name)
+ XFREE(MTYPE_BGP_FILTER_NAME,
+ filter->plist[direct].name);
+ filter->plist[direct].name = NULL;
+ filter->plist[direct].plist = NULL;
}
- if (filter->plist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
- filter->plist[direct].name = NULL;
- filter->plist[direct].plist = NULL;
-
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_PREFIX_LIST))
+ continue;
+ /* Remove configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->plist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->plist[direct].name);
filter->plist[direct].name = NULL;
filter->plist[direct].plist = NULL;
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
const char *name)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
+ /* Set configuration on peer. */
filter = &peer->filter[afi][safi];
-
if (filter->aslist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->aslist[direct].aslist = as_list_lookup(name);
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_FILTER_LIST);
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_FILTER_LIST))
+ continue;
+ /* Set configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->aslist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->aslist[direct].name);
filter->aslist[direct].name =
XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->aslist[direct].aslist = as_list_lookup(name);
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
+
return 0;
}
int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct bgp_filter *gfilter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE;
- filter = &peer->filter[afi][safi];
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_FILTER_LIST);
- /* apply peer-group filter */
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- gfilter = &peer->group->conf->filter[afi][safi];
-
- if (gfilter->aslist[direct].name) {
- if (filter->aslist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME,
- filter->aslist[direct].name);
- filter->aslist[direct].name =
- XSTRDUP(MTYPE_BGP_FILTER_NAME,
- gfilter->aslist[direct].name);
- filter->aslist[direct].aslist =
- gfilter->aslist[direct].aslist;
- peer_on_policy_change(peer, afi, safi,
- (direct == FILTER_OUT) ? 1 : 0);
- return 0;
- }
+ PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
+ filter[afi][safi].aslist[direct].name);
+ PEER_ATTR_INHERIT(peer,
+ filter[afi][safi].aslist[direct].aslist);
+ } else {
+ /* Otherwise remove configuration from peer. */
+ filter = &peer->filter[afi][safi];
+ if (filter->aslist[direct].name)
+ XFREE(MTYPE_BGP_FILTER_NAME,
+ filter->aslist[direct].name);
+ filter->aslist[direct].name = NULL;
+ filter->aslist[direct].aslist = NULL;
}
- if (filter->aslist[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
- filter->aslist[direct].name = NULL;
- filter->aslist[direct].aslist = NULL;
-
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
peer_on_policy_change(peer, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_FILTER_LIST))
+ continue;
+ /* Remove configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->aslist[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME,
filter->aslist[direct].name);
filter->aslist[direct].name = NULL;
filter->aslist[direct].aslist = NULL;
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == FILTER_OUT) ? 1 : 0);
}
int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
const char *name)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != RMAP_IN && direct != RMAP_OUT)
return BGP_ERR_INVALID_VALUE;
+ /* Set configuration on peer. */
filter = &peer->filter[afi][safi];
-
if (filter->map[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
-
filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->map[direct].map = route_map_lookup_by_name(name);
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][direct],
+ PEER_FT_ROUTE_MAP);
peer_on_policy_change(peer, afi, safi,
(direct == RMAP_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_ROUTE_MAP))
+ continue;
+ /* Set configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->map[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->map[direct].map = route_map_lookup_by_name(name);
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == RMAP_OUT) ? 1 : 0);
}
return 0;
/* Unset route-map from the peer. */
int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct bgp_filter *gfilter;
- struct peer_group *group;
struct listnode *node, *nnode;
if (direct != RMAP_IN && direct != RMAP_OUT)
return BGP_ERR_INVALID_VALUE;
- filter = &peer->filter[afi][safi];
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][direct], PEER_FT_ROUTE_MAP);
- /* apply peer-group filter */
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- gfilter = &peer->group->conf->filter[afi][safi];
-
- if (gfilter->map[direct].name) {
- if (filter->map[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME,
- filter->map[direct].name);
- filter->map[direct].name =
- XSTRDUP(MTYPE_BGP_FILTER_NAME,
- gfilter->map[direct].name);
- filter->map[direct].map = gfilter->map[direct].map;
- peer_on_policy_change(peer, afi, safi,
- (direct == RMAP_OUT) ? 1 : 0);
- return 0;
- }
+ PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
+ filter[afi][safi].map[direct].name);
+ PEER_ATTR_INHERIT(peer, filter[afi][safi].map[direct].map);
+ } else {
+ /* Otherwise remove configuration from peer. */
+ filter = &peer->filter[afi][safi];
+ if (filter->map[direct].name)
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+ filter->map[direct].name = NULL;
+ filter->map[direct].map = NULL;
}
- if (filter->map[direct].name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
- filter->map[direct].name = NULL;
- filter->map[direct].map = NULL;
-
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
peer_on_policy_change(peer, afi, safi,
(direct == RMAP_OUT) ? 1 : 0);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitely 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][direct],
+ PEER_FT_ROUTE_MAP))
+ continue;
+ /* Remove configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->map[direct].name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
filter->map[direct].name = NULL;
filter->map[direct].map = NULL;
- peer_on_policy_change(peer, afi, safi,
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi,
(direct == RMAP_OUT) ? 1 : 0);
}
+
return 0;
}
int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
const char *name)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
+ /* Set configuration on peer. */
filter = &peer->filter[afi][safi];
-
if (filter->usmap.name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
-
filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->usmap.map = route_map_lookup_by_name(name);
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][0],
+ PEER_FT_UNSUPPRESS_MAP);
peer_on_policy_change(peer, afi, safi, 1);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitely 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][0],
+ PEER_FT_UNSUPPRESS_MAP))
+ continue;
+ /* Set configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->usmap.name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
filter->usmap.map = route_map_lookup_by_name(name);
- peer_on_policy_change(peer, afi, safi, 1);
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi, 1);
}
+
return 0;
}
/* Unset route-map from the peer. */
int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
{
+ struct peer *member;
struct bgp_filter *filter;
- struct peer_group *group;
struct listnode *node, *nnode;
- filter = &peer->filter[afi][safi];
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][0], PEER_FT_UNSUPPRESS_MAP);
- if (filter->usmap.name)
- XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
- filter->usmap.name = NULL;
- filter->usmap.map = NULL;
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ PEER_STR_ATTR_INHERIT(MTYPE_BGP_FILTER_NAME, peer,
+ filter[afi][safi].usmap.name);
+ PEER_ATTR_INHERIT(peer, filter[afi][safi].usmap.map);
+ } else {
+ /* Otherwise remove configuration from peer. */
+ filter = &peer->filter[afi][safi];
+ if (filter->usmap.name)
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
+ filter->usmap.name = NULL;
+ filter->usmap.map = NULL;
+ }
+ /* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
peer_on_policy_change(peer, afi, safi, 1);
+
+ /* Skip peer-group mechanics for regular peers. */
return 0;
}
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- filter = &peer->filter[afi][safi];
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitely 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][0],
+ PEER_FT_UNSUPPRESS_MAP))
+ continue;
+ /* Remove configuration on peer-group member. */
+ filter = &member->filter[afi][safi];
if (filter->usmap.name)
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
filter->usmap.name = NULL;
filter->usmap.map = NULL;
- peer_on_policy_change(peer, afi, safi, 1);
+
+ /* Process peer route updates. */
+ peer_on_policy_change(member, afi, safi, 1);
}
+
return 0;
}
uint32_t max, uint8_t threshold, int warning,
uint16_t restart)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
- peer->pmax[afi][safi] = max;
- peer->pmax_threshold[afi][safi] = threshold;
- peer->pmax_restart[afi][safi] = restart;
+ /* Set flags and configuration on peer. */
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
if (warning)
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
else
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
+ peer_af_flag_unset(peer, afi, safi,
+ PEER_FLAG_MAX_PREFIX_WARNING);
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX);
- peer->pmax[afi][safi] = max;
- peer->pmax_threshold[afi][safi] = threshold;
- peer->pmax_restart[afi][safi] = restart;
- if (warning)
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
- else
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
+ peer->pmax[afi][safi] = max;
+ peer->pmax_threshold[afi][safi] = threshold;
+ peer->pmax_restart[afi][safi] = restart;
- if ((peer->status == Established)
- && (peer->afc[afi][safi]))
- bgp_maximum_prefix_overflow(peer, afi, safi, 1);
- }
- } else {
- if ((peer->status == Established) && (peer->afc[afi][safi]))
+ /* Check if handling a regular peer. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Re-check if peer violates maximum-prefix. */
+ if ((peer->status == Established) && (peer->afc[afi][safi])) {
bgp_maximum_prefix_overflow(peer, afi, safi, 1);
+ }
+
+ /* Skip peer-group mechanics for regular peers. */
+ return 0;
+ }
+
+ /*
+ * Set flags and configuration on all peer-group members, unless they
+ * are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_MAX_PREFIX))
+ continue;
+
+ /* Set flag and configuration on peer-group member. */
+ member->pmax[afi][safi] = max;
+ member->pmax_threshold[afi][safi] = threshold;
+ member->pmax_restart[afi][safi] = restart;
+ if (warning)
+ SET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_WARNING);
+ else
+ UNSET_FLAG(member->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_WARNING);
+
+ /* Re-check if peer violates maximum-prefix. */
+ if ((member->status == Established) && (member->afc[afi][safi]))
+ bgp_maximum_prefix_overflow(member, afi, safi, 1);
}
return 0;
int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
{
- struct peer_group *group;
+ struct peer *member;
struct listnode *node, *nnode;
- /* apply peer-group config */
+ /* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
- if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX))
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX);
- else
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX);
-
- if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING))
- SET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
- else
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING);
+ peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
+ peer_af_flag_inherit(peer, afi, safi,
+ PEER_FLAG_MAX_PREFIX_WARNING);
+ PEER_ATTR_INHERIT(peer, pmax[afi][safi]);
+ PEER_ATTR_INHERIT(peer, pmax_threshold[afi][safi]);
+ PEER_ATTR_INHERIT(peer, pmax_restart[afi][safi]);
- peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
- peer->pmax_threshold[afi][safi] =
- peer->group->conf->pmax_threshold[afi][safi];
- peer->pmax_restart[afi][safi] =
- peer->group->conf->pmax_restart[afi][safi];
return 0;
}
- UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
- UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+ /* Remove flags and configuration from peer. */
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
peer->pmax[afi][safi] = 0;
peer->pmax_threshold[afi][safi] = 0;
peer->pmax_restart[afi][safi] = 0;
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
- return 0;
+ /*
+ * Remove flags and configuration from all peer-group members, unless
+ * they are explicitely overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->af_flags_override[afi][safi],
+ PEER_FLAG_MAX_PREFIX))
+ continue;
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
- UNSET_FLAG(peer->af_flags[afi][safi],
+ /* Remove flag and configuration on peer-group member. */
+ UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+ UNSET_FLAG(member->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING);
- peer->pmax[afi][safi] = 0;
- peer->pmax_threshold[afi][safi] = 0;
- peer->pmax_restart[afi][safi] = 0;
+ member->pmax[afi][safi] = 0;
+ member->pmax_threshold[afi][safi] = 0;
+ member->pmax_restart[afi][safi] = 0;
}
+
return 0;
}
afi_t afi, safi_t safi)
{
struct bgp_filter *filter;
- struct bgp_filter *gfilter = NULL;
char *addr;
- int in = FILTER_IN;
- int out = FILTER_OUT;
addr = peer->host;
filter = &peer->filter[afi][safi];
- if (peer_group_active(peer))
- gfilter = &peer->group->conf->filter[afi][safi];
-
/* distribute-list. */
- if (filter->dlist[in].name)
- if (!gfilter || !gfilter->dlist[in].name
- || strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
- != 0) {
- vty_out(vty, " neighbor %s distribute-list %s in\n",
- addr, filter->dlist[in].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s distribute-list %s in\n", addr,
+ filter->dlist[FILTER_IN].name);
- if (filter->dlist[out].name && !gfilter) {
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
+ FILTER_OUT))
vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
- filter->dlist[out].name);
- }
+ filter->dlist[FILTER_OUT].name);
/* prefix-list. */
- if (filter->plist[in].name)
- if (!gfilter || !gfilter->plist[in].name
- || strcmp(filter->plist[in].name, gfilter->plist[in].name)
- != 0) {
- vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
- filter->plist[in].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
+ filter->plist[FILTER_IN].name);
- if (filter->plist[out].name)
- if (!gfilter || !gfilter->plist[out].name
- || strcmp(filter->plist[out].name, gfilter->plist[out].name)
- != 0) {
- vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
- filter->plist[out].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
+ FILTER_OUT))
+ vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
+ filter->plist[FILTER_OUT].name);
/* route-map. */
- if (filter->map[RMAP_IN].name)
- if (!gfilter || !gfilter->map[RMAP_IN].name
- || strcmp(filter->map[RMAP_IN].name,
- gfilter->map[RMAP_IN].name)
- != 0) {
- vty_out(vty, " neighbor %s route-map %s in\n", addr,
- filter->map[RMAP_IN].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP, RMAP_IN))
+ vty_out(vty, " neighbor %s route-map %s in\n", addr,
+ filter->map[RMAP_IN].name);
- if (filter->map[RMAP_OUT].name)
- if (!gfilter || !gfilter->map[RMAP_OUT].name
- || strcmp(filter->map[RMAP_OUT].name,
- gfilter->map[RMAP_OUT].name)
- != 0) {
- vty_out(vty, " neighbor %s route-map %s out\n", addr,
- filter->map[RMAP_OUT].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP,
+ RMAP_OUT))
+ vty_out(vty, " neighbor %s route-map %s out\n", addr,
+ filter->map[RMAP_OUT].name);
/* unsuppress-map */
- if (filter->usmap.name && !gfilter) {
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_UNSUPPRESS_MAP, 0))
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
filter->usmap.name);
- }
/* filter-list. */
- if (filter->aslist[in].name)
- if (!gfilter || !gfilter->aslist[in].name
- || strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
- != 0) {
- vty_out(vty, " neighbor %s filter-list %s in\n", addr,
- filter->aslist[in].name);
- }
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
+ FILTER_IN))
+ vty_out(vty, " neighbor %s filter-list %s in\n", addr,
+ filter->aslist[FILTER_IN].name);
- if (filter->aslist[out].name && !gfilter) {
+ if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
+ FILTER_OUT))
vty_out(vty, " neighbor %s filter-list %s out\n", addr,
- filter->aslist[out].name);
- }
+ filter->aslist[FILTER_OUT].name);
}
/* BGP peer configuration display function. */
}
}
+ /* enforce-first-as */
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
+ if (!peer_group_active(peer)
+ || !CHECK_FLAG(g_peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
+ vty_out(vty, " neighbor %s enforce-first-as\n", addr);
+ }
+ }
+
/* update-source */
if (peer->update_if) {
if (!peer_group_active(peer) || !g_peer->update_if
{
struct peer *g_peer = NULL;
char *addr;
+ bool flag_scomm, flag_secomm, flag_slcomm;
/* Skip dynamic neighbors. */
if (peer_dynamic_neighbor(peer))
}
/* send-community print. */
- if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
- if (peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY)
- && peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY)
- && peergroup_af_flag_check(
- peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY)) {
- vty_out(vty, " neighbor %s send-community all\n",
- addr);
- } else if (peergroup_af_flag_check(
- peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY)) {
- vty_out(vty, " neighbor %s send-community large\n",
- addr);
- } else if (peergroup_af_flag_check(
- peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY)) {
- vty_out(vty, " neighbor %s send-community extended\n",
- addr);
- } else if (peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY)) {
- vty_out(vty, " neighbor %s send-community\n", addr);
- }
- } else {
- if (!peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY)
- && (!g_peer || peer_af_flag_check(g_peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY))
- && !peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY)
- && (!g_peer
- || peer_af_flag_check(g_peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY))
- && !peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY)
- && (!g_peer || peer_af_flag_check(
- g_peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY))) {
+ flag_scomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_COMMUNITY);
+ flag_secomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_EXT_COMMUNITY);
+ flag_slcomm = peergroup_af_flag_check(peer, afi, safi,
+ PEER_FLAG_SEND_LARGE_COMMUNITY);
+
+ if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
+ if (flag_scomm && flag_secomm && flag_slcomm) {
vty_out(vty, " no neighbor %s send-community all\n",
addr);
} else {
- if (!peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY)
- && (!g_peer
- || peer_af_flag_check(
- g_peer, afi, safi,
- PEER_FLAG_SEND_LARGE_COMMUNITY))) {
+ if (flag_scomm)
vty_out(vty,
- " no neighbor %s send-community large\n",
+ " no neighbor %s send-community\n",
addr);
- }
-
- if (!peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY)
- && (!g_peer
- || peer_af_flag_check(
- g_peer, afi, safi,
- PEER_FLAG_SEND_EXT_COMMUNITY))) {
+ if (flag_secomm)
vty_out(vty,
" no neighbor %s send-community extended\n",
addr);
- }
- if (!peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY)
- && (!g_peer || peer_af_flag_check(
- g_peer, afi, safi,
- PEER_FLAG_SEND_COMMUNITY))) {
+ if (flag_slcomm)
vty_out(vty,
- " no neighbor %s send-community\n",
+ " no neighbor %s send-community large\n",
+ addr);
+ }
+ } else {
+ if (flag_scomm && flag_secomm && flag_slcomm) {
+ vty_out(vty, " neighbor %s send-community all\n",
+ addr);
+ } else if (flag_scomm && flag_secomm) {
+ vty_out(vty, " neighbor %s send-community both\n",
+ addr);
+ } else {
+ if (flag_scomm)
+ vty_out(vty, " neighbor %s send-community\n",
+ addr);
+ if (flag_secomm)
+ vty_out(vty,
+ " neighbor %s send-community extended\n",
+ addr);
+ if (flag_slcomm)
+ vty_out(vty,
+ " neighbor %s send-community large\n",
addr);
- }
}
}
/* Default information */
if (peergroup_af_flag_check(peer, afi, safi,
- PEER_FLAG_DEFAULT_ORIGINATE)
- || (g_peer
- && ((peer->default_rmap[afi][safi].name
- && !g_peer->default_rmap[afi][safi].name)
- || (!peer->default_rmap[afi][safi].name
- && g_peer->default_rmap[afi][safi].name)
- || (peer->default_rmap[afi][safi].name
- && strcmp(peer->default_rmap[afi][safi].name,
- g_peer->default_rmap[afi][safi].name))))) {
+ PEER_FLAG_DEFAULT_ORIGINATE)) {
vty_out(vty, " neighbor %s default-originate", addr);
+
if (peer->default_rmap[afi][safi].name)
vty_out(vty, " route-map %s",
peer->default_rmap[afi][safi].name);
+
vty_out(vty, "\n");
}
}
/* maximum-prefix. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
- if (!peer_group_active(peer)
- || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
- || g_peer->pmax_threshold[afi][safi]
- != peer->pmax_threshold[afi][safi]
- || CHECK_FLAG(g_peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING)
- != CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_WARNING)) {
- vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
- peer->pmax[afi][safi]);
- if (peer->pmax_threshold[afi][safi]
- != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
- vty_out(vty, " %u",
- peer->pmax_threshold[afi][safi]);
- if (CHECK_FLAG(peer->af_flags[afi][safi],
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX)) {
+ vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
+ peer->pmax[afi][safi]);
+
+ if (peer->pmax_threshold[afi][safi]
+ != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
+ vty_out(vty, " %u", peer->pmax_threshold[afi][safi]);
+ if (peer_af_flag_check(peer, afi, safi,
PEER_FLAG_MAX_PREFIX_WARNING))
- vty_out(vty, " warning-only");
- if (peer->pmax_restart[afi][safi])
- vty_out(vty, " restart %u",
- peer->pmax_restart[afi][safi]);
- vty_out(vty, "\n");
- }
+ vty_out(vty, " warning-only");
+ if (peer->pmax_restart[afi][safi])
+ vty_out(vty, " restart %u",
+ peer->pmax_restart[afi][safi]);
+
+ vty_out(vty, "\n");
+ }
/* Route server client. */
if (peergroup_af_flag_check(peer, afi, safi,
}
/* allowas-in <1-10> */
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
- if (!peer_group_active(peer)
- || !peer_af_flag_check(g_peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN)
- || peer->allowas_in[afi][safi]
- != g_peer->allowas_in[afi][safi]) {
- if (peer->allowas_in[afi][safi] == 3) {
- vty_out(vty, " neighbor %s allowas-in\n",
- addr);
- } else {
- vty_out(vty, " neighbor %s allowas-in %d\n",
- addr, peer->allowas_in[afi][safi]);
- }
- }
- }
-
- /* allowas-in origin */
- else if (peer_af_flag_check(peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
- if (!peer_group_active(peer)
- || !peer_af_flag_check(g_peer, afi, safi,
- PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
vty_out(vty, " neighbor %s allowas-in origin\n", addr);
+ } else if (peer->allowas_in[afi][safi] == 3) {
+ vty_out(vty, " neighbor %s allowas-in\n", addr);
+ } else {
+ vty_out(vty, " neighbor %s allowas-in %d\n", addr,
+ peer->allowas_in[afi][safi]);
}
}
/* weight */
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
- if (!peer_group_active(peer)
- || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
- || peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
- if (peer->weight[afi][safi]) {
- vty_out(vty, " neighbor %s weight %lu\n", addr,
- peer->weight[afi][safi]);
- }
- }
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
+ vty_out(vty, " neighbor %s weight %lu\n", addr,
+ peer->weight[afi][safi]);
/* Filter. */
bgp_config_write_filter(vty, peer, afi, safi);
if (safi == SAFI_EVPN)
bgp_config_write_evpn_info(vty, bgp, afi, safi);
+ if (safi == SAFI_FLOWSPEC)
+ bgp_fs_config_write_pbr(vty, bgp, afi, safi);
+
if (safi == SAFI_UNICAST) {
bgp_vpn_policy_config_write_afi(vty, bgp, afi);
if (CHECK_FLAG(bgp->af_flags[afi][safi],
vty_out(vty, " import vpn\n");
}
+ if (CHECK_FLAG(bgp->af_flags[afi][safi],
+ BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+ struct listnode *node;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(
+ bgp->vpn_policy[afi].import_vrf, node,
+ name))
+ vty_out(vty, " import vrf %s\n", name);
+ }
}
vty_endframe(vty, " exit-address-family\n");
}
+/* clang-format off */
+#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517
+CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
+#endif
+/* clang-format on */
+
int bgp_config_write(struct vty *vty)
{
int write = 0;
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
continue;
+ /* Migrate deprecated 'bgp enforce-first-as'
+ * config to 'neighbor * enforce-first-as' configs
+ */
+ if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) {
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS);
+ bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
+ }
+
/* Router bgp ASN */
vty_out(vty, "router bgp %u", bgp->as);
vty_out(vty, "\n");
}
- /* BGP enforce-first-as. */
- if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS))
- vty_out(vty, " bgp enforce-first-as\n");
-
/* BGP deterministic-med. */
if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
!= DFLT_BGP_DETERMINISTIC_MED)
/* Enable multiple instances by default. */
bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
+ /* mpls label dynamic allocation pool */
+ bgp_lp_init(bm->master, &bm->labelpool);
+
QOBJ_REG(bm, bgp_master);
}
frr_pthread_finish();
}
-void bgp_init(void)
+void bgp_init(unsigned short instance)
{
/* allocates some vital data structures used by peer commands in
bgp_pthreads_init();
/* Init zebra. */
- bgp_zebra_init(bm->master);
+ bgp_zebra_init(bm->master, instance);
#if ENABLE_BGP_VNC
vnc_zebra_init(bm->master);
if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update);
+
+ bgp_lp_finish();
}