summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas.abraitis@gmail.com>2021-08-02 21:27:55 +0200
committerDonatas Abraitis <donatas.abraitis@gmail.com>2021-08-18 13:14:52 +0200
commitbb4dcdd13e08a394262e14599278d5c11d7fb197 (patch)
treeda09a043fc17083ee1eb3f1ba3e62bc5f6d7b40b /bgpd
parentMerge pull request #9408 from mobash-rasool/ospfv2-bug-fixes-03 (diff)
downloadfrr-bb4dcdd13e08a394262e14599278d5c11d7fb197.tar.xz
frr-bb4dcdd13e08a394262e14599278d5c11d7fb197.zip
bgpd: Add an ability to set extcommunity to none in route-maps
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_routemap.c104
-rw-r--r--bgpd/bgp_routemap_nb.c7
-rw-r--r--bgpd/bgp_routemap_nb.h4
-rw-r--r--bgpd/bgp_routemap_nb_config.c58
4 files changed, 163 insertions, 10 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 5e566f360..4d23abc71 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2518,26 +2518,40 @@ static const struct route_map_rule_cmd route_set_community_delete_cmd = {
/* `set extcommunity rt COMMUNITY' */
+struct rmap_ecom_set {
+ struct ecommunity *ecom;
+ bool none;
+};
+
/* For community set mechanism. Used by _rt and _soo. */
static enum route_map_cmd_result_t
route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
{
- struct ecommunity *ecom;
+ struct rmap_ecom_set *rcs;
struct ecommunity *new_ecom;
struct ecommunity *old_ecom;
struct bgp_path_info *path;
+ struct attr *attr;
- ecom = rule;
+ rcs = rule;
path = object;
+ attr = path->attr;
- if (!ecom)
+ if (rcs->none) {
+ attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
+ attr->ecommunity = NULL;
+ return RMAP_OKAY;
+ }
+
+ if (!rcs->ecom)
return RMAP_OKAY;
/* We assume additive for Extended Community. */
old_ecom = path->attr->ecommunity;
if (old_ecom) {
- new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), ecom);
+ new_ecom =
+ ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
/* old_ecom->refcnt = 1 => owned elsewhere, e.g.
* bgp_update_receive()
@@ -2546,7 +2560,7 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
if (!old_ecom->refcnt)
ecommunity_free(&old_ecom);
} else
- new_ecom = ecommunity_dup(ecom);
+ new_ecom = ecommunity_dup(rcs->ecom);
/* will be intern()'d or attr_flush()'d by bgp_update_main() */
path->attr->ecommunity = new_ecom;
@@ -2556,24 +2570,55 @@ route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
return RMAP_OKAY;
}
-/* Compile function for set community. */
+static void *route_set_ecommunity_none_compile(const char *arg)
+{
+ struct rmap_ecom_set *rcs;
+ bool none = false;
+
+ if (strncmp(arg, "none", 4) == 0)
+ none = true;
+
+ rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
+ rcs->ecom = NULL;
+ rcs->none = none;
+
+ return rcs;
+}
+
static void *route_set_ecommunity_rt_compile(const char *arg)
{
+ struct rmap_ecom_set *rcs;
struct ecommunity *ecom;
ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
if (!ecom)
return NULL;
- return ecommunity_intern(ecom);
+
+ rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
+ rcs->ecom = ecommunity_intern(ecom);
+ rcs->none = false;
+
+ return rcs;
}
/* Free function for set community. Used by _rt and _soo */
static void route_set_ecommunity_free(void *rule)
{
- struct ecommunity *ecom = rule;
- ecommunity_unintern(&ecom);
+ struct rmap_ecom_set *rcs = rule;
+
+ if (rcs->ecom)
+ ecommunity_unintern(&rcs->ecom);
+
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
}
+static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
+ "extcommunity",
+ route_set_ecommunity,
+ route_set_ecommunity_none_compile,
+ route_set_ecommunity_free,
+};
+
/* Set community rule structure. */
static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
"extcommunity rt",
@@ -2587,13 +2632,18 @@ static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
/* Compile function for set community. */
static void *route_set_ecommunity_soo_compile(const char *arg)
{
+ struct rmap_ecom_set *rcs;
struct ecommunity *ecom;
ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
if (!ecom)
return NULL;
- return ecommunity_intern(ecom);
+ rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
+ rcs->ecom = ecommunity_intern(ecom);
+ rcs->none = false;
+
+ return rcs;
}
/* Set community rule structure. */
@@ -5749,6 +5799,37 @@ ALIAS_YANG (no_set_ecommunity_soo,
"GP extended community attribute\n"
"Site-of-Origin extended community\n")
+DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
+ "set extcommunity none",
+ SET_STR
+ "BGP extended community attribute\n"
+ "No extended community attribute\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
+ 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:extcommunity-none",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
+ "no set extcommunity none",
+ NO_STR SET_STR
+ "BGP extended community attribute\n"
+ "No extended community attribute\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFUN_YANG (set_ecommunity_lb,
set_ecommunity_lb_cmd,
"set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
@@ -6453,6 +6534,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ecommunity_rt_cmd);
route_map_install_set(&route_set_ecommunity_soo_cmd);
route_map_install_set(&route_set_ecommunity_lb_cmd);
+ route_map_install_set(&route_set_ecommunity_none_cmd);
route_map_install_set(&route_set_tag_cmd);
route_map_install_set(&route_set_label_index_cmd);
@@ -6545,6 +6627,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
+ install_element(RMAP_NODE, &set_ecommunity_none_cmd);
+ install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
#ifdef KEEP_OLD_VPN_COMMANDS
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index 921642696..caf1553ec 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -352,6 +352,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:extcommunity-none",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_modify,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_destroy,
+ }
+ },
+ {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-lb",
.cbs = {
.apply_finish = lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish,
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index 069345b1a..e0b3a6926 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -134,6 +134,10 @@ int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_mod
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_destroy(
+ struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_modify(
struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_destroy(
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 398e7323d..a62dc1dfc 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -2691,6 +2691,64 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_spec
/*
* XPath:
+ * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:extcommunity-none
+ */
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ bool none = false;
+ 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);
+ none = yang_dnode_get_bool(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = generic_set_delete;
+ rhc->rhc_rule = "extcommunity";
+ rhc->rhc_event = RMAP_EVENT_SET_DELETED;
+
+ if (none) {
+ rv = generic_set_add(rhc->rhc_rmi, "extcommunity",
+ "none", args->errmsg,
+ args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ return NB_OK;
+ }
+
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_extcommunity_none_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:evpn-gateway-ip-ipv4
*/
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_modify(