summaryrefslogtreecommitdiff
path: root/bgpd
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas@opensourcerouting.org>2022-04-25 10:34:36 +0300
committerDonatas Abraitis <donatas@opensourcerouting.org>2022-04-25 14:05:22 +0300
commit77e3d82167b97a1ff4abe59d6e4f12086a61d9f9 (patch)
tree5c68e86eaa6fd6b9734e40928b6bee1390377299 /bgpd
parentc27892b24d21762f3cd4276fa2cca75c958f9b15 (diff)
bgpd: Add `set as-path replace <any|ASN>` cmd for route-maps
``` route-map tstas permit 10 set as-path replace 1 exit ``` Before: ``` donatas-laptop(config-router-af)# do show ip bgp 10.10.10.10/32 BGP routing table entry for 10.10.10.10/32, version 13 Paths: (1 available, best #1, table default) Advertised to non peer-group peers: 192.168.10.65 65000 1 2 3 123 192.168.10.65 from 192.168.10.65 (10.10.10.11) Origin IGP, metric 0, valid, external, best (First path received) Last update: Mon Apr 25 10:39:50 2022 ``` After: ``` donatas-laptop(config-router-af)# do show ip bgp 10.10.10.10/32 BGP routing table entry for 10.10.10.10/32, version 15 Paths: (1 available, best #1, table default) Advertised to non peer-group peers: 192.168.10.65 65000 65010 2 3 123 192.168.10.65 from 192.168.10.65 (10.10.10.11) Origin IGP, metric 0, valid, external, best (First path received) Last update: Mon Apr 25 10:40:16 2022 ``` Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_aspath.c22
-rw-r--r--bgpd/bgp_aspath.h2
-rw-r--r--bgpd/bgp_routemap.c91
-rw-r--r--bgpd/bgp_routemap_nb.c7
-rw-r--r--bgpd/bgp_routemap_nb.h4
-rw-r--r--bgpd/bgp_routemap_nb_config.c52
6 files changed, 178 insertions, 0 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index fd644ebf0a..880e15fadb 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1258,6 +1258,28 @@ struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
return new;
}
+/* Replace all ASNs with our own ASN */
+struct aspath *aspath_replace_all_asn(struct aspath *aspath, as_t our_asn)
+{
+ struct aspath *new;
+ struct assegment *seg;
+
+ new = aspath_dup(aspath);
+ seg = new->segments;
+
+ while (seg) {
+ int i;
+
+ for (i = 0; i < seg->length; i++)
+ seg->as[i] = our_asn;
+
+ seg = seg->next;
+ }
+
+ aspath_str_update(new, false);
+ return new;
+}
+
/* Replace all private ASNs with our own ASN */
struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn,
as_t peer_asn)
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 4b16818167..912db7b254 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -112,6 +112,8 @@ extern bool aspath_single_asn_check(struct aspath *, as_t asn);
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn,
as_t our_asn);
+extern struct aspath *aspath_replace_all_asn(struct aspath *aspath,
+ as_t our_asn);
extern struct aspath *aspath_replace_private_asns(struct aspath *aspath,
as_t asn, as_t peer_asn);
extern struct aspath *aspath_remove_private_asns(struct aspath *aspath,
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 6c303a9e5f..20ee2e4d49 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2174,6 +2174,57 @@ static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
route_aspath_free,
};
+/* `set as-path replace AS-PATH` */
+static void *route_aspath_replace_compile(const char *arg)
+{
+ return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_aspath_replace_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static enum route_map_cmd_result_t
+route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
+{
+ 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;
+
+ if (path->peer->sort != BGP_PEER_EBGP) {
+ zlog_warn(
+ "`set as-path replace` is supported only for EBGP peers");
+ return RMAP_NOOP;
+ }
+
+ if (path->attr->aspath->refcnt)
+ aspath_new = aspath_dup(path->attr->aspath);
+ else
+ aspath_new = path->attr->aspath;
+
+ if (strmatch(replace, "any")) {
+ path->attr->aspath =
+ aspath_replace_all_asn(aspath_new, own_asn);
+ } else {
+ as_t replace_asn = strtoul(replace, NULL, 10);
+
+ path->attr->aspath = aspath_replace_specific_asn(
+ aspath_new, replace_asn, own_asn);
+ }
+
+ return RMAP_OKAY;
+}
+
+static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
+ "as-path replace",
+ route_set_aspath_replace,
+ route_aspath_replace_compile,
+ route_aspath_replace_free,
+};
+
/* `set community COMMUNITY' */
struct rmap_com_set {
struct community *com;
@@ -5389,6 +5440,43 @@ DEFUN_YANG (set_aspath_prepend_lastas,
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG (set_aspath_replace_asn,
+ set_aspath_replace_asn_cmd,
+ "set as-path replace <any|(1-4294967295)>$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 to local AS number\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:as-path-replace']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ 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);
+ 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|(1-4294967295)>]",
+ 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 to local 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 [(1-4294967295)]",
@@ -6727,6 +6815,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_distance_cmd);
route_map_install_set(&route_set_aspath_prepend_cmd);
route_map_install_set(&route_set_aspath_exclude_cmd);
+ route_map_install_set(&route_set_aspath_replace_cmd);
route_map_install_set(&route_set_origin_cmd);
route_map_install_set(&route_set_atomic_aggregate_cmd);
route_map_install_set(&route_set_aggregator_as_cmd);
@@ -6800,10 +6889,12 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
install_element(RMAP_NODE, &set_aspath_exclude_cmd);
+ install_element(RMAP_NODE, &set_aspath_replace_asn_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_replace_asn_cmd);
install_element(RMAP_NODE, &set_origin_cmd);
install_element(RMAP_NODE, &no_set_origin_cmd);
install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index caf1553ec1..585596e1aa 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -297,6 +297,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy,
+ }
+ },
+ {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none",
.cbs = {
.modify = lib_route_map_entry_set_action_rmap_set_action_community_none_modify,
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index e0b3a6926f..a01adf7d5d 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -108,6 +108,10 @@ int lib_route_map_entry_set_action_rmap_set_action_last_as_modify(struct nb_cb_m
int lib_route_map_entry_set_action_rmap_set_action_last_as_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy(
+ struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_community_none_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_community_none_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_community_string_modify(struct nb_cb_modify_args *args);
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 773538ee41..b87877b1e0 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -2209,6 +2209,58 @@ lib_route_map_entry_set_action_rmap_set_action_exclude_as_path_destroy(
/*
* XPath:
+ * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:replace-as-path
+ */
+int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *type;
+ int rv;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ type = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = generic_set_delete;
+ rhc->rhc_rule = "as-path replace";
+ rhc->rhc_event = RMAP_EVENT_SET_DELETED;
+
+ rv = generic_set_add(rhc->rhc_rmi, "as-path replace", type,
+ args->errmsg, args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_replace_as_path_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:community-none
*/
int lib_route_map_entry_set_action_rmap_set_action_community_none_modify(