struct aspath *aspath_new;
const char *replace = rule;
struct bgp_path_info *path = object;
- as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
- : path->peer->local_as;
+ as_t replace_asn = 0;
+ as_t configured_asn;
+ char *buf;
+ char src_asn[ASN_STRING_MAX_SIZE];
if (path->peer->sort != BGP_PEER_EBGP) {
zlog_warn(
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)
aspath_new = aspath_dup(path->attr->aspath);
else
if (strmatch(replace, "any")) {
path->attr->aspath =
- aspath_replace_all_asn(aspath_new, own_asn);
- } else {
- as_t replace_asn = strtoul(replace, NULL, 10);
-
+ aspath_replace_all_asn(aspath_new, configured_asn);
+ } else
path->attr->aspath = aspath_replace_specific_asn(
- aspath_new, replace_asn, own_asn);
- }
+ aspath_new, replace_asn, configured_asn);
aspath_free(aspath_new);
return nb_cli_apply_changes(vty, NULL);
}
-DEFPY_YANG (set_aspath_replace_asn,
- set_aspath_replace_asn_cmd,
- "set as-path replace <any|ASNUM>$replace",
- SET_STR
- "Transform BGP AS_PATH attribute\n"
- "Replace AS number to local AS number\n"
- "Replace any AS number to local AS number\n"
- "Replace a specific AS number in plain or dotted format to local AS number\n")
+DEFPY_YANG(set_aspath_replace_asn, set_aspath_replace_asn_cmd,
+ "set as-path replace <any|ASNUM>$replace [<ASNUM>$configured_asn]",
+ SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Replace any AS number to local or configured AS number\n"
+ "Replace a specific AS number to local or configured AS number\n"
+ "Define the configured AS number\n")
{
const char *xpath =
"./set-action[action='frr-bgp-route-map:as-path-replace']";
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)) {
vty_out(vty, "%% Invalid AS value %s\n", replace);
return CMD_WARNING_CONFIG_FAILED;
}
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ if (configured_asn_str &&
+ !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),
"%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);
}
-DEFPY_YANG (no_set_aspath_replace_asn,
- no_set_aspath_replace_asn_cmd,
- "no set as-path replace [<any|ASNUM>]",
- NO_STR
- SET_STR
- "Transform BGP AS_PATH attribute\n"
- "Replace AS number to local AS number\n"
- "Replace any AS number to local AS number\n"
- "Replace a specific AS number in plain or dotted format to local AS number\n")
+DEFPY_YANG(no_set_aspath_replace_asn, no_set_aspath_replace_asn_cmd,
+ "no set as-path replace [<any|ASNUM>] [<ASNUM>$configured_asn]",
+ NO_STR SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Replace any AS number to local or configured AS number\n"
+ "Replace a specific AS number to local or configured AS number\n"
+ "Replace AS number with a configured AS number\n"
+ "Define the configured AS number\n")
{
const char *xpath =
"./set-action[action='frr-bgp-route-map:as-path-replace']";
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
pytestmark = [pytest.mark.bgpd]
tgen.stop_topology()
-def test_bgp_maximum_prefix_out():
+def test_bgp_set_aspath_replace_test1():
tgen = get_topogen()
if tgen.routers_have_failure():
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__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))