mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-12 11:18:59 +00:00
bgpd: add 'set as-path replace' with a configured ASN
There is no route-map set action to replace any ASN, or a part of an ASN, with a configured ASN. The current commit adds a new command to use a configured ASN as replacement, instead of using the local as number. > set as-path replace any 65500 Update the 'bgp_set_aspath_replace' test. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
07a2b9d41e
commit
a3f0a1f5ed
@ -2385,8 +2385,10 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
|
|||||||
struct aspath *aspath_new;
|
struct aspath *aspath_new;
|
||||||
const char *replace = rule;
|
const char *replace = rule;
|
||||||
struct bgp_path_info *path = object;
|
struct bgp_path_info *path = object;
|
||||||
as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
|
as_t replace_asn = 0;
|
||||||
: path->peer->local_as;
|
as_t configured_asn;
|
||||||
|
char *buf;
|
||||||
|
char src_asn[ASN_STRING_MAX_SIZE];
|
||||||
|
|
||||||
if (path->peer->sort != BGP_PEER_EBGP) {
|
if (path->peer->sort != BGP_PEER_EBGP) {
|
||||||
zlog_warn(
|
zlog_warn(
|
||||||
@ -2394,6 +2396,29 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
|
|||||||
return RMAP_NOOP;
|
return RMAP_NOOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf = strchr(replace, ' ');
|
||||||
|
if (!buf) {
|
||||||
|
configured_asn = path->peer->change_local_as
|
||||||
|
? path->peer->change_local_as
|
||||||
|
: path->peer->local_as;
|
||||||
|
} else {
|
||||||
|
memcpy(src_asn, replace, (size_t)(buf - replace));
|
||||||
|
src_asn[(size_t)(buf - replace)] = '\0';
|
||||||
|
replace = src_asn;
|
||||||
|
buf++;
|
||||||
|
if (!asn_str2asn(buf, &configured_asn)) {
|
||||||
|
zlog_warn(
|
||||||
|
"`set as-path replace`, invalid configured AS %s",
|
||||||
|
buf);
|
||||||
|
return RMAP_NOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strmatch(replace, "any") && !asn_str2asn(replace, &replace_asn)) {
|
||||||
|
zlog_warn("`set as-path replace`, invalid AS %s", replace);
|
||||||
|
return RMAP_NOOP;
|
||||||
|
}
|
||||||
|
|
||||||
if (path->attr->aspath->refcnt)
|
if (path->attr->aspath->refcnt)
|
||||||
aspath_new = aspath_dup(path->attr->aspath);
|
aspath_new = aspath_dup(path->attr->aspath);
|
||||||
else
|
else
|
||||||
@ -2401,13 +2426,10 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
|
|||||||
|
|
||||||
if (strmatch(replace, "any")) {
|
if (strmatch(replace, "any")) {
|
||||||
path->attr->aspath =
|
path->attr->aspath =
|
||||||
aspath_replace_all_asn(aspath_new, own_asn);
|
aspath_replace_all_asn(aspath_new, configured_asn);
|
||||||
} else {
|
} else
|
||||||
as_t replace_asn = strtoul(replace, NULL, 10);
|
|
||||||
|
|
||||||
path->attr->aspath = aspath_replace_specific_asn(
|
path->attr->aspath = aspath_replace_specific_asn(
|
||||||
aspath_new, replace_asn, own_asn);
|
aspath_new, replace_asn, configured_asn);
|
||||||
}
|
|
||||||
|
|
||||||
aspath_free(aspath_new);
|
aspath_free(aspath_new);
|
||||||
|
|
||||||
@ -5875,41 +5897,49 @@ DEFUN_YANG (set_aspath_prepend_lastas,
|
|||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG (set_aspath_replace_asn,
|
DEFPY_YANG(set_aspath_replace_asn, set_aspath_replace_asn_cmd,
|
||||||
set_aspath_replace_asn_cmd,
|
"set as-path replace <any|ASNUM>$replace [<ASNUM>$configured_asn]",
|
||||||
"set as-path replace <any|ASNUM>$replace",
|
SET_STR
|
||||||
SET_STR
|
"Transform BGP AS_PATH attribute\n"
|
||||||
"Transform BGP AS_PATH attribute\n"
|
"Replace AS number to local or configured AS number\n"
|
||||||
"Replace AS number to local AS number\n"
|
"Replace any AS number to local or configured AS number\n"
|
||||||
"Replace any AS number to local AS number\n"
|
"Replace a specific AS number to local or configured AS number\n"
|
||||||
"Replace a specific AS number in plain or dotted format to local AS number\n")
|
"Define the configured AS number\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
||||||
char xpath_value[XPATH_MAXLEN];
|
char xpath_value[XPATH_MAXLEN];
|
||||||
as_t as_value;
|
as_t as_value, as_configured_value;
|
||||||
|
char replace_value[ASN_STRING_MAX_SIZE * 2];
|
||||||
|
|
||||||
if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) {
|
if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) {
|
||||||
vty_out(vty, "%% Invalid AS value %s\n", replace);
|
vty_out(vty, "%% Invalid AS value %s\n", replace);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
if (configured_asn_str &&
|
||||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
!asn_str2asn(configured_asn_str, &as_configured_value)) {
|
||||||
|
vty_out(vty, "%% Invalid AS configured value %s\n",
|
||||||
|
configured_asn_str);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
snprintf(xpath_value, sizeof(xpath_value),
|
snprintf(xpath_value, sizeof(xpath_value),
|
||||||
"%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
|
"%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
|
||||||
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
|
snprintf(replace_value, sizeof(replace_value), "%s%s%s", replace,
|
||||||
|
configured_asn_str ? " " : "",
|
||||||
|
configured_asn_str ? configured_asn_str : "");
|
||||||
|
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace_value);
|
||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFPY_YANG (no_set_aspath_replace_asn,
|
DEFPY_YANG(no_set_aspath_replace_asn, no_set_aspath_replace_asn_cmd,
|
||||||
no_set_aspath_replace_asn_cmd,
|
"no set as-path replace [<any|ASNUM>] [<ASNUM>$configured_asn]",
|
||||||
"no set as-path replace [<any|ASNUM>]",
|
NO_STR SET_STR
|
||||||
NO_STR
|
"Transform BGP AS_PATH attribute\n"
|
||||||
SET_STR
|
"Replace AS number to local or configured AS number\n"
|
||||||
"Transform BGP AS_PATH attribute\n"
|
"Replace any AS number to local or configured AS number\n"
|
||||||
"Replace AS number to local AS number\n"
|
"Replace a specific AS number to local or configured AS number\n"
|
||||||
"Replace any AS number to local AS number\n"
|
"Replace AS number with a configured AS number\n"
|
||||||
"Replace a specific AS number in plain or dotted format to local AS number\n")
|
"Define the configured AS number\n")
|
||||||
{
|
{
|
||||||
const char *xpath =
|
const char *xpath =
|
||||||
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
"./set-action[action='frr-bgp-route-map:as-path-replace']";
|
||||||
|
@ -2105,10 +2105,11 @@ Using AS Path in Route Map
|
|||||||
Prepend the existing last AS number (the leftmost ASN) to the AS_PATH.
|
Prepend the existing last AS number (the leftmost ASN) to the AS_PATH.
|
||||||
The no form of this command removes this set operation from the route-map.
|
The no form of this command removes this set operation from the route-map.
|
||||||
|
|
||||||
.. clicmd:: set as-path replace <any|ASN>
|
.. clicmd:: set as-path replace <any|ASN> [<ASN>]
|
||||||
|
|
||||||
Replace a specific AS number to local AS number. ``any`` replaces each
|
Replace a specific AS number to local AS number or a configured AS number.
|
||||||
AS number in the AS-PATH with the local AS number.
|
``any`` replaces each AS number in the AS-PATH with either the local AS
|
||||||
|
number or the configured AS number.
|
||||||
|
|
||||||
.. clicmd:: set as-path exclude all
|
.. clicmd:: set as-path exclude all
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ router bgp 65001
|
|||||||
!
|
!
|
||||||
ip prefix-list p1 seq 5 permit 172.16.255.31/32
|
ip prefix-list p1 seq 5 permit 172.16.255.31/32
|
||||||
!
|
!
|
||||||
|
bgp route-map delay-timer 1
|
||||||
route-map r2 permit 10
|
route-map r2 permit 10
|
||||||
match ip address prefix-list p1
|
match ip address prefix-list p1
|
||||||
set as-path replace 65003
|
set as-path replace 65003
|
||||||
|
@ -24,6 +24,7 @@ sys.path.append(os.path.join(CWD, "../"))
|
|||||||
# pylint: disable=C0413
|
# pylint: disable=C0413
|
||||||
from lib import topotest
|
from lib import topotest
|
||||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
|
||||||
pytestmark = [pytest.mark.bgpd]
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ def teardown_module(mod):
|
|||||||
tgen.stop_topology()
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
def test_bgp_maximum_prefix_out():
|
def test_bgp_set_aspath_replace_test1():
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
|
|
||||||
if tgen.routers_have_failure():
|
if tgen.routers_have_failure():
|
||||||
@ -85,6 +86,40 @@ def test_bgp_maximum_prefix_out():
|
|||||||
assert result is None, "Failed overriding incoming AS-PATH with route-map"
|
assert result is None, "Failed overriding incoming AS-PATH with route-map"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bgp_set_aspath_replace_test2():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
logger.info("Configuring r1 to replace the matching AS with a configured ASN")
|
||||||
|
router = tgen.gears["r1"]
|
||||||
|
router.vtysh_cmd(
|
||||||
|
"configure terminal\nroute-map r2 permit 10\nset as-path replace 65003 65500\n",
|
||||||
|
isjson=False,
|
||||||
|
)
|
||||||
|
router.vtysh_cmd(
|
||||||
|
"configure terminal\nroute-map r2 permit 20\nset as-path replace any 65501\n",
|
||||||
|
isjson=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _bgp_converge(router):
|
||||||
|
output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast json"))
|
||||||
|
expected = {
|
||||||
|
"routes": {
|
||||||
|
"172.16.255.31/32": [{"path": "65002 65500"}],
|
||||||
|
"172.16.255.32/32": [{"path": "65501 65501"}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_converge, router)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
result is None
|
||||||
|
), "Failed overriding incoming AS-PATH with route-map replace with configured ASN"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
sys.exit(pytest.main(args))
|
sys.exit(pytest.main(args))
|
||||||
|
Loading…
Reference in New Issue
Block a user