diff options
| -rw-r--r-- | bgpd/bgp_vty.c | 44 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 3 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 1 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 26 | ||||
| -rw-r--r-- | tests/bgpd/test_peer_attr.c | 5 | ||||
| -rw-r--r-- | tests/bgpd/test_peer_attr.py | 1 | ||||
| -rw-r--r-- | yang/frr-bgp-neighbor.yang | 2 | 
7 files changed, 72 insertions, 10 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5d6ae589fa..ae2d586de5 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -122,6 +122,10 @@ FRR_CFG_DEFAULT_BOOL(BGP_SOFT_VERSION_CAPABILITY,  	{ .val_bool = true, .match_profile = "datacenter", },  	{ .val_bool = false },  ); +FRR_CFG_DEFAULT_BOOL(BGP_ENFORCE_FIRST_AS, +	{ .val_bool = false, .match_version = "< 9.1", }, +	{ .val_bool = true }, +);  DEFINE_HOOK(bgp_inst_config_write,  		(struct bgp *bgp, struct vty *vty), @@ -615,6 +619,8 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,  		if (DFLT_BGP_SOFT_VERSION_CAPABILITY)  			SET_FLAG((*bgp)->flags,  				 BGP_FLAG_SOFT_VERSION_CAPABILITY); +		if (DFLT_BGP_ENFORCE_FIRST_AS) +			SET_FLAG((*bgp)->flags, BGP_FLAG_ENFORCE_FIRST_AS);  		ret = BGP_SUCCESS;  	} @@ -2828,6 +2834,23 @@ DEFUN(no_bgp_ebgp_requires_policy, no_bgp_ebgp_requires_policy_cmd,  	return CMD_SUCCESS;  } +DEFPY(bgp_enforce_first_as, +      bgp_enforce_first_as_cmd, +      "[no] bgp enforce-first-as", +      NO_STR +      BGP_STR +      "Enforce the first AS for EBGP routes\n") +{ +	VTY_DECLVAR_CONTEXT(bgp, bgp); + +	if (no) +		UNSET_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS); +	else +		SET_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS); + +	return CMD_SUCCESS; +} +  DEFPY(bgp_lu_uses_explicit_null, bgp_lu_uses_explicit_null_cmd,        "[no] bgp labeled-unicast <explicit-null|ipv4-explicit-null|ipv6-explicit-null>$value",        NO_STR BGP_STR @@ -17973,8 +17996,13 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,  			addr);  	/* enforce-first-as */ -	if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS)) -		vty_out(vty, " neighbor %s enforce-first-as\n", addr); +	if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) { +		if (!peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS)) +			vty_out(vty, " no neighbor %s enforce-first-as\n", addr); +	} else { +		if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS)) +			vty_out(vty, " neighbor %s enforce-first-as\n", addr); +	}  	/* update-source */  	if (peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) { @@ -18599,6 +18627,15 @@ int bgp_config_write(struct vty *vty)  					? ""  					: "no "); +		/* bgp enforce-first-as */ +		if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS) != +		    SAVE_BGP_ENFORCE_FIRST_AS) +			vty_out(vty, " %sbgp enforce-first-as\n", +				CHECK_FLAG(bgp->flags, +					   BGP_FLAG_ENFORCE_FIRST_AS) +					? "" +					: "no "); +  		if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV4_EXPLICIT_NULL) &&  		    !!CHECK_FLAG(bgp->flags, BGP_FLAG_LU_IPV6_EXPLICIT_NULL))  			vty_out(vty, " bgp labeled-unicast explicit-null\n"); @@ -19594,6 +19631,9 @@ void bgp_vty_init(void)  	install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd);  	install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd); +	/* bgp enforce-first-as */ +	install_element(BGP_NODE, &bgp_enforce_first_as_cmd); +  	/* bgp labeled-unicast explicit-null */  	install_element(BGP_NODE, &bgp_lu_uses_explicit_null_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 0a01d71968..6ca0b06450 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1919,6 +1919,9 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,  		}  	} +	if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS)) +		SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS); +  	/* auto shutdown if configured */  	if (bgp->autoshutdown)  		peer_flag_set(peer, PEER_FLAG_SHUTDOWN); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 42e4c167f6..bfaa2e5d72 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -516,6 +516,7 @@ struct bgp {  /* For BGP-LU, force IPv6 local prefixes to use ipv6-explicit-null label */  #define BGP_FLAG_LU_IPV6_EXPLICIT_NULL (1ULL << 34)  #define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35) +#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)  	/* BGP default address-families.  	 * New peers inherit enabled afi/safis from bgp instance. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 43572be07e..f7203a599a 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -527,6 +527,27 @@ Reject routes with AS_SET or AS_CONFED_SET types     This command enables rejection of incoming and outgoing routes having AS_SET or AS_CONFED_SET type. +Enforce first AS +---------------- + +.. clicmd:: bgp enforce-first-as + +   To configure a router to deny an update received from an external BGP (eBGP) +   peer that does not list its autonomous system number at the beginning of +   the `AS_PATH` in the incoming update, use the ``bgp enforce-first-as`` command +   in router configuration mode. + +   In order to exclude an arbitrary neighbor from this enforcement, use the +   command ``no neighbor NAME enforce-first-as``. And vice-versa if a global +   enforcement is disabled, you can override this behavior per neighbor too. + +   Default: enabled. + +.. note:: + +   If you have a peering to RS (Route-Server), most likely you MUST disable the +   first AS enforcement. +  Suppress duplicate updates  -------------------------- @@ -1526,7 +1547,10 @@ Configuring Peers     Discard updates received from the specified (eBGP) peer if the AS_PATH     attribute does not contain the PEER's ASN as the first AS_PATH segment. -   Default: disabled. +   You can enable or disable this enforcement globally too using +   ``bgp enforce-first-as`` command. + +   Default: enabled.  .. clicmd:: neighbor PEER extended-optional-parameters diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index bc6eba9069..dd154e3429 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -297,11 +297,6 @@ static struct test_peer_attr test_peer_attrs[] = {  		.type = PEER_AT_GLOBAL_FLAG,  	},  	{ -		.cmd = "enforce-first-as", -		.u.flag = PEER_FLAG_ENFORCE_FIRST_AS, -		.type = PEER_AT_GLOBAL_FLAG, -	}, -	{  		.cmd = "local-as",  		.peer_cmd = "local-as 1",  		.group_cmd = "local-as 2", diff --git a/tests/bgpd/test_peer_attr.py b/tests/bgpd/test_peer_attr.py index eb57618434..bd8b06e2f0 100644 --- a/tests/bgpd/test_peer_attr.py +++ b/tests/bgpd/test_peer_attr.py @@ -15,7 +15,6 @@ TestFlag.okfail("peer\\capability extended-nexthop")  TestFlag.okfail("peer\\description")  TestFlag.okfail("peer\\disable-connected-check")  TestFlag.okfail("peer\\dont-capability-negotiate") -TestFlag.okfail("peer\\enforce-first-as")  TestFlag.okfail("peer\\local-as")  TestFlag.okfail("peer\\local-as 1 no-prepend")  TestFlag.okfail("peer\\local-as 1 no-prepend replace-as") diff --git a/yang/frr-bgp-neighbor.yang b/yang/frr-bgp-neighbor.yang index 5a4c37974f..b199ab9469 100644 --- a/yang/frr-bgp-neighbor.yang +++ b/yang/frr-bgp-neighbor.yang @@ -76,7 +76,7 @@ submodule frr-bgp-neighbor {      leaf enforce-first-as {        type boolean; -      default "false"; +      default "true";        description          "When set to 'true' it will enforce the first AS for EBGP routes.";      }  | 
