bgpd: Move 'enforce-first-as' from global to peer

This commit moves the command 'bgp enforce-first-as' from global BGP
instance configuration to peer/neighbor configuration, which can now be
changed by executing '[no] neighbor <neighbor> enforce-first-as'.

End users can now enforce sane first-AS checking on regular sessions
while e.g. disabling the checks on routeserver sessions, which usually
strip away their own AS number from the path.

To ensure backwards-compatibility, a migration routine was added which
automatically sets the 'enforce-first-as' flag on all configured
neighbors if the old global setting was activated. The old global
command immediately disappears after running the migration routine once.

Signed-off-by: Pascal Mathis <mail@pascalmathis.com>
This commit is contained in:
Pascal Mathis 2018-05-17 22:51:35 +02:00
parent 29be7d92cc
commit 47cbc09b63
No known key found for this signature in database
GPG Key ID: E208DBA7BFC9B28C
4 changed files with 72 additions and 16 deletions

View File

@ -1177,7 +1177,6 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
* not right.
* So do the checks later, i.e. here
*/
struct bgp *bgp = peer->bgp;
struct aspath *aspath;
/* Confederation sanity check. */
@ -1192,7 +1191,7 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
}
/* First AS check for EBGP. */
if (bgp != NULL && bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) {
if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
if (peer->sort == BGP_PEER_EBGP
&& !aspath_firstas_check(attr->aspath, peer->as)) {
zlog_err("%s incorrect first AS (must be %u)",

View File

@ -1991,7 +1991,11 @@ DEFUN (no_bgp_fast_external_failover,
}
/* "bgp enforce-first-as" configuration. */
DEFUN (bgp_enforce_first_as,
#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517
CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
#endif
DEFUN_DEPRECATED (bgp_enforce_first_as,
bgp_enforce_first_as_cmd,
"bgp enforce-first-as",
BGP_STR
@ -1999,12 +2003,11 @@ DEFUN (bgp_enforce_first_as,
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp_flag_set(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
bgp_clear_star_soft_in(vty, bgp->name);
return CMD_SUCCESS;
}
DEFUN (no_bgp_enforce_first_as,
DEFUN_DEPRECATED (no_bgp_enforce_first_as,
no_bgp_enforce_first_as_cmd,
"no bgp enforce-first-as",
NO_STR
@ -2013,7 +2016,6 @@ DEFUN (no_bgp_enforce_first_as,
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
bgp_clear_star_soft_in(vty, bgp->name);
return CMD_SUCCESS;
}
@ -3449,7 +3451,7 @@ ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd,
"Peer-group name\n")
static int peer_flag_modify_vty(struct vty *vty, const char *ip_str,
uint16_t flag, int set)
uint32_t flag, int set)
{
int ret;
struct peer *peer;
@ -3481,13 +3483,13 @@ static int peer_flag_modify_vty(struct vty *vty, const char *ip_str,
return bgp_vty_return(vty, ret);
}
static int peer_flag_set_vty(struct vty *vty, const char *ip_str, uint16_t flag)
static int peer_flag_set_vty(struct vty *vty, const char *ip_str, uint32_t flag)
{
return peer_flag_modify_vty(vty, ip_str, flag, 1);
}
static int peer_flag_unset_vty(struct vty *vty, const char *ip_str,
uint16_t flag)
uint32_t flag)
{
return peer_flag_modify_vty(vty, ip_str, flag, 0);
}
@ -4584,6 +4586,36 @@ DEFUN (no_neighbor_disable_connected_check,
PEER_FLAG_DISABLE_CONNECTED_CHECK);
}
/* enforce-first-as */
DEFUN (neighbor_enforce_first_as,
neighbor_enforce_first_as_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Enforce the first AS for EBGP routes\n")
{
int idx_peer = 1;
return peer_flag_set_vty(vty, argv[idx_peer]->arg,
PEER_FLAG_ENFORCE_FIRST_AS);
}
DEFUN (no_neighbor_enforce_first_as,
no_neighbor_enforce_first_as_cmd,
"no neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Enforce the first AS for EBGP routes\n")
{
int idx_peer = 2;
return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
PEER_FLAG_ENFORCE_FIRST_AS);
}
DEFUN (neighbor_description,
neighbor_description_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> description LINE...",
@ -12980,6 +13012,10 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_disable_connected_check_cmd);
install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd);
/* "neighbor enforce-first-as" commands. */
install_element(BGP_NODE, &neighbor_enforce_first_as_cmd);
install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd);
/* "neighbor description" commands. */
install_element(BGP_NODE, &neighbor_description_cmd);
install_element(BGP_NODE, &no_neighbor_description_cmd);

View File

@ -3805,6 +3805,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{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[] = {
@ -6747,6 +6748,14 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
}
}
/* 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
@ -7293,6 +7302,12 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
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;
@ -7328,6 +7343,15 @@ int bgp_config_write(struct vty *vty)
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);
@ -7426,10 +7450,6 @@ int bgp_config_write(struct vty *vty)
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)

View File

@ -826,13 +826,14 @@ struct peer {
#define PEER_FLAG_DISABLE_CONNECTED_CHECK (1 << 6) /* disable-connected-check */
#define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */
#define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */
#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */
#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */
#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */
#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */
#define PEER_FLAG_LONESOUL (1 << 11)
#define PEER_FLAG_DYNAMIC_NEIGHBOR (1 << 12) /* dynamic neighbor */
#define PEER_FLAG_CAPABILITY_ENHE (1 << 13) /* Extended next-hop (rfc 5549)*/
#define PEER_FLAG_IFPEER_V6ONLY (1 << 14) /* if-based peer is v6 only */
#define PEER_FLAG_IS_RFAPI_HD (1 << 15) /* attached to rfapi HD */
#define PEER_FLAG_IS_RFAPI_HD (1 << 15) /* attached to rfapi HD */
#define PEER_FLAG_ENFORCE_FIRST_AS (1 << 16) /* enforce-first-as */
/* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */
char *tx_shutdown_message;