return true;
}
+/* Replace all ASN instances of the regex rule with our own ASN */
+struct aspath *aspath_replace_regex_asn(struct aspath *aspath,
+ struct as_list *acl_list, as_t our_asn)
+{
+ struct aspath *new;
+ struct assegment *cur_seg;
+ struct as_list *cur_as_list;
+ struct as_filter *cur_as_filter;
+ char str_buf[ASPATH_STR_DEFAULT_LEN];
+ uint32_t i;
+
+ new = aspath_dup(aspath);
+ cur_seg = new->segments;
+
+ while (cur_seg) {
+ cur_as_list = acl_list;
+ while (cur_as_list) {
+ cur_as_filter = cur_as_list->head;
+ while (cur_as_filter) {
+ for (i = 0; i < cur_seg->length; i++) {
+ snprintfrr(str_buf,
+ ASPATH_STR_DEFAULT_LEN,
+ ASN_FORMAT(new->asnotation),
+ &cur_seg->as[i]);
+ if (!regexec(cur_as_filter->reg,
+ str_buf, 0, NULL, 0))
+ cur_seg->as[i] = our_asn;
+ }
+ cur_as_filter = cur_as_filter->next;
+ }
+ cur_as_list = cur_as_list->next;
+ }
+ cur_seg = cur_seg->next;
+ }
+
+ aspath_str_update(new, false);
+ return new;
+}
+
+
/* Replace all instances of the target ASN with our own ASN */
struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn, as_t our_asn)
as_t configured_asn;
char *buf;
char src_asn[ASN_STRING_MAX_SIZE];
+ char *acl_list_name = NULL;
+ uint32_t acl_list_name_len = 0;
+ char *buf_acl_name = NULL;
+ static const char asp_acl[] = "as-path-access-list";
+ struct as_list *aspath_acl = NULL;
if (path->peer->sort != BGP_PEER_EBGP) {
zlog_warn(
"`set as-path replace` is supported only for EBGP peers");
- return RMAP_NOOP;
+ goto end_ko;
}
buf = strchr(replace, ' ');
configured_asn = path->peer->change_local_as
? path->peer->change_local_as
: path->peer->local_as;
+ } else if (!strncmp(replace, asp_acl, strlen(asp_acl))) {
+ /* its as-path-acl-list command get the access list name */
+ while (*buf == ' ')
+ buf++;
+ buf_acl_name = buf;
+ buf = strchr(buf_acl_name, ' ');
+ if (buf)
+ acl_list_name_len = buf - buf_acl_name;
+ else
+ acl_list_name_len = strlen(buf_acl_name);
+
+ buf_acl_name[acl_list_name_len] = 0;
+ /* get the acl-list */
+ aspath_acl = as_list_lookup(buf_acl_name);
+ if (!aspath_acl) {
+ zlog_warn("`set as-path replace`, invalid as-path-access-list name: %s",
+ buf_acl_name);
+ goto end_ko;
+ }
+ acl_list_name = XSTRDUP(MTYPE_TMP, buf_acl_name);
+ buf_acl_name[acl_list_name_len] = ' ';
+
+ if (!buf) {
+ configured_asn = path->peer->change_local_as
+ ? path->peer->change_local_as
+ : path->peer->local_as;
+ } else {
+ while (*buf == ' ')
+ buf++;
+ /* get the configured asn */
+ if (!asn_str2asn(buf, &configured_asn)) {
+ zlog_warn(
+ "`set as-path replace`, invalid configured AS %s",
+ buf);
+ goto end_ko;
+ }
+ }
+
+ replace = buf;
+
} else {
memcpy(src_asn, replace, (size_t)(buf - replace));
src_asn[(size_t)(buf - replace)] = '\0';
zlog_warn(
"`set as-path replace`, invalid configured AS %s",
buf);
- return RMAP_NOOP;
+ goto end_ko;
}
}
- if (!strmatch(replace, "any") && !asn_str2asn(replace, &replace_asn)) {
+ if (replace && !strmatch(replace, "any") &&
+ !asn_str2asn(replace, &replace_asn)) {
zlog_warn("`set as-path replace`, invalid AS %s", replace);
- return RMAP_NOOP;
+ goto end_ko;
}
if (path->attr->aspath->refcnt)
else
aspath_new = path->attr->aspath;
- if (strmatch(replace, "any")) {
+ if (aspath_acl) {
+ path->attr->aspath = aspath_replace_regex_asn(aspath_new,
+ aspath_acl,
+ configured_asn);
+ } else if (strmatch(replace, "any")) {
path->attr->aspath =
aspath_replace_all_asn(aspath_new, configured_asn);
- } else
+ } else {
path->attr->aspath = aspath_replace_specific_asn(
aspath_new, replace_asn, configured_asn);
-
+ }
aspath_free(aspath_new);
+
+ if (acl_list_name)
+ XFREE(MTYPE_TMP, acl_list_name);
return RMAP_OKAY;
+
+end_ko:
+ if (acl_list_name)
+ XFREE(MTYPE_TMP, acl_list_name);
+ return RMAP_NOOP;
+
}
static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG(
+ set_aspath_replace_access_list, set_aspath_replace_access_list_cmd,
+ "set as-path replace as-path-access-list AS_PATH_FILTER_NAME$aspath_filter_name [<ASNUM>$configured_asn]",
+ SET_STR
+ "Transform BGP AS-path attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Specify an as path access list name\n"
+ "AS path access list name\n"
+ "Define the configured AS number\n")
+{
+ char *str;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:as-path-replace']";
+ char xpath_value[XPATH_MAXLEN];
+ as_t as_configured_value;
+ char replace_value[ASN_STRING_MAX_SIZE * 2];
+
+ 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;
+ }
+
+ str = argv_concat(argv, argc, 3);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(replace_value, sizeof(replace_value), "%s %s", aspath_filter_name, str);
+
+ 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, str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_set_aspath_replace_access_list, no_set_aspath_replace_access_list_cmd,
+ "no set as-path replace as-path-access-list [AS_PATH_FILTER_NAME] [<ASNUM>$configured_asn]",
+ NO_STR
+ SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Specify an as path access list name\n"
+ "AS path access list name\n"
+ "Define the configured AS number\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:as-path-replace']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFUN_YANG (no_set_aspath_prepend,
no_set_aspath_prepend_cmd,
"no set as-path prepend [ASNUM]",
install_element(RMAP_NODE, &set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &set_aspath_exclude_access_list_cmd);
install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
+ install_element(RMAP_NODE, &set_aspath_replace_access_list_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_access_list_cmd);
install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
+ install_element(RMAP_NODE, &no_set_aspath_replace_access_list_cmd);
install_element(RMAP_NODE, &set_origin_cmd);
install_element(RMAP_NODE, &no_set_origin_cmd);
install_element(RMAP_NODE, &set_atomic_aggregate_cmd);