]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Add route-map `match alias` command
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Sun, 18 Jul 2021 09:14:24 +0000 (12:14 +0300)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Wed, 21 Jul 2021 06:26:14 +0000 (09:26 +0300)
Will be handy to filter BGP prefixes by using BGP community alias
instead of numerical community values.

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_routemap.c
bgpd/bgp_routemap_nb.c
bgpd/bgp_routemap_nb.h
bgpd/bgp_routemap_nb_config.c
lib/routemap.h
lib/routemap_cli.c
yang/frr-bgp-route-map.yang

index 529abcbea07b35a393c578e71be6f5448be38c73..5b1044754ebd440a93a9d391ec4fd78a34013e49 100644 (file)
@@ -52,6 +52,7 @@
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_regex.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
 #include "bgpd/bgp_clist.h"
 #include "bgpd/bgp_filter.h"
 #include "bgpd/bgp_mplsvpn.h"
@@ -1179,6 +1180,55 @@ static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
        route_match_vrl_source_vrf_free
 };
 
+/* `match alias` */
+static enum route_map_cmd_result_t
+route_match_alias(void *rule, const struct prefix *prefix, void *object)
+{
+       char *alias = rule;
+       struct bgp_path_info *path = object;
+       char **communities;
+       int num;
+
+       if (path->attr->community) {
+               frrstr_split(path->attr->community->str, " ", &communities,
+                            &num);
+               for (int i = 0; i < num; i++) {
+                       const char *com2alias =
+                               bgp_community2alias(communities[i]);
+                       if (strncmp(alias, com2alias, strlen(com2alias)) == 0)
+                               return RMAP_MATCH;
+               }
+       }
+
+       if (path->attr->lcommunity) {
+               frrstr_split(path->attr->lcommunity->str, " ", &communities,
+                            &num);
+               for (int i = 0; i < num; i++) {
+                       const char *com2alias =
+                               bgp_community2alias(communities[i]);
+                       if (strncmp(alias, com2alias, strlen(com2alias)) == 0)
+                               return RMAP_MATCH;
+               }
+       }
+
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_alias_compile(const char *arg)
+{
+
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_alias_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_alias_cmd = {
+       "alias", route_match_alias, route_match_alias_compile,
+       route_match_alias_free};
+
 /* `match local-preference LOCAL-PREF' */
 
 /* Match function return 1 if match is success else return zero. */
@@ -4597,6 +4647,58 @@ DEFUN_YANG (no_match_local_pref,
        return nb_cli_apply_changes(vty, NULL);
 }
 
+DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
+          MATCH_STR
+          "Match BGP community alias name\n"
+          "BGP community alias name\n")
+{
+       const char *alias = argv[2]->arg;
+       struct community_alias ca1;
+       struct community_alias *lookup_alias;
+
+       const char *xpath =
+               "./match-condition[condition='frr-bgp-route-map:match-alias']";
+       char xpath_value[XPATH_MAXLEN];
+
+       memset(&ca1, 0, sizeof(ca1));
+       strlcpy(ca1.alias, alias, sizeof(ca1.alias));
+       lookup_alias = bgp_ca_alias_lookup(&ca1);
+       if (!lookup_alias) {
+               vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+
+DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
+          NO_STR MATCH_STR
+          "Match BGP community alias name\n"
+          "BGP community alias name\n")
+{
+       int idx_alias = 3;
+       const char *xpath =
+               "./match-condition[condition='frr-bgp-route-map:match-alias']";
+       char xpath_value[XPATH_MAXLEN];
+
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+       if (argc <= idx_alias)
+               return nb_cli_apply_changes(vty, NULL);
+
+       snprintf(xpath_value, sizeof(xpath_value),
+                "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
+       nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
+                             argv[idx_alias]->arg);
+
+       return nb_cli_apply_changes(vty, NULL);
+}
 
 DEFPY_YANG (match_community,
        match_community_cmd,
@@ -6286,6 +6388,7 @@ void bgp_route_map_init(void)
        route_map_no_set_tag_hook(generic_set_delete);
 
        route_map_install_match(&route_match_peer_cmd);
+       route_map_install_match(&route_match_alias_cmd);
        route_map_install_match(&route_match_local_pref_cmd);
 #ifdef HAVE_SCRIPTING
        route_map_install_match(&route_match_script_cmd);
@@ -6370,6 +6473,8 @@ void bgp_route_map_init(void)
        install_element(RMAP_NODE, &no_match_aspath_cmd);
        install_element(RMAP_NODE, &match_local_pref_cmd);
        install_element(RMAP_NODE, &no_match_local_pref_cmd);
+       install_element(RMAP_NODE, &match_alias_cmd);
+       install_element(RMAP_NODE, &no_match_alias_cmd);
        install_element(RMAP_NODE, &match_community_cmd);
        install_element(RMAP_NODE, &no_match_community_cmd);
        install_element(RMAP_NODE, &match_lcommunity_cmd);
index 1254591b87d26b5694f8db6b501591cc76e51522..92164269682aa3f2e4fcbfe357bb31ff7c512c75 100644 (file)
@@ -38,6 +38,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
                                .destroy = lib_route_map_entry_match_condition_rmap_match_condition_local_preference_destroy,
                        }
                },
+               {
+                       .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:alias",
+                       .cbs = {
+                               .modify = lib_route_map_entry_match_condition_rmap_match_condition_alias_modify,
+                               .destroy = lib_route_map_entry_match_condition_rmap_match_condition_alias_destroy,
+                       }
+               },
                {
                        .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:script",
                        .cbs = {
index f0e492eb617da0de9af206d3dcf41c2ca58deb9b..069345b1a48d9d6f6ebf1e6481a0acb4f154e63c 100644 (file)
@@ -29,6 +29,10 @@ extern const struct frr_yang_module_info frr_bgp_route_map_info;
 /* prototypes */
 int lib_route_map_entry_match_condition_rmap_match_condition_local_preference_modify(struct nb_cb_modify_args *args);
 int lib_route_map_entry_match_condition_rmap_match_condition_local_preference_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_alias_modify(
+       struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_alias_destroy(
+       struct nb_cb_destroy_args *args);
 int lib_route_map_entry_match_condition_rmap_match_condition_script_modify(struct nb_cb_modify_args *args);
 int lib_route_map_entry_match_condition_rmap_match_condition_script_destroy(struct nb_cb_destroy_args *args);
 int lib_route_map_entry_match_condition_rmap_match_condition_origin_modify(struct nb_cb_modify_args *args);
index 88e3f6438f547299887441b85406f2a3ad6afc05..45f5c8f4bcd73e665dbd1435087a78aa485a9000 100644 (file)
@@ -159,6 +159,62 @@ lib_route_map_entry_match_condition_rmap_match_condition_local_preference_destro
        return NB_OK;
 }
 
+/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:alias
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_alias_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct routemap_hook_context *rhc;
+       const char *alias;
+       enum rmap_compile_rets ret;
+
+       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);
+               alias = yang_dnode_get_string(args->dnode, NULL);
+
+               /* Set destroy information. */
+               rhc->rhc_mhook = bgp_route_match_delete;
+               rhc->rhc_rule = "alias";
+               rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+               ret = bgp_route_match_add(rhc->rhc_rmi, "alias", alias,
+                                         RMAP_EVENT_MATCH_ADDED, args->errmsg,
+                                         args->errmsg_len);
+
+               if (ret != RMAP_COMPILE_SUCCESS) {
+                       rhc->rhc_mhook = NULL;
+                       return NB_ERR_VALIDATION;
+               }
+
+               break;
+       }
+
+       return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_alias_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_match_destroy(args);
+       }
+
+       return NB_OK;
+}
+
 /*
  * XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:script
  */
index 4a40ec08b9ffdd639c51279070b87b2f8ad531ee..8af3b2c3c03c4ed7b85887e4057f63d69ba604bc 100644 (file)
@@ -270,6 +270,7 @@ DECLARE_QOBJ_TYPE(route_map);
 /* BGP route-map match conditions */
 #define IS_MATCH_LOCAL_PREF(C)                                                 \
        (strmatch(C, "frr-bgp-route-map:match-local-preference"))
+#define IS_MATCH_ALIAS(C) (strmatch(C, "frr-bgp-route-map:match-alias"))
 #define IS_MATCH_ORIGIN(C)                                                     \
        (strmatch(C, "frr-bgp-route-map:match-origin"))
 #define IS_MATCH_RPKI(C) (strmatch(C, "frr-bgp-route-map:rpki"))
index bf982cfa2ba2c0ab4dac52a5234a76976f444536..ec9033b3aaeb3fd881d0cbf2dc74c936bb5347ab 100644 (file)
@@ -634,6 +634,11 @@ void route_map_condition_show(struct vty *vty, struct lyd_node *dnode,
                        yang_dnode_get_string(
                                dnode,
                                "./rmap-match-condition/frr-bgp-route-map:local-preference"));
+       } else if (IS_MATCH_ALIAS(condition)) {
+               vty_out(vty, " match alias %s\n",
+                       yang_dnode_get_string(
+                               dnode,
+                               "./rmap-match-condition/frr-bgp-route-map:alias"));
        } else if (IS_MATCH_ORIGIN(condition)) {
                vty_out(vty, " match origin %s\n",
                        yang_dnode_get_string(
index 1c990b5ed9e01845e9c8c4f884e8e24e70dc3880..e11883a803470e3a1d05a58ed0da45dc31fecb6f 100644 (file)
@@ -36,6 +36,12 @@ module frr-bgp-route-map {
       "Initial revision";
   }
 
+  identity match-alias {
+    base frr-route-map:rmap-match-type;
+    description
+      "Match BGP community alias name";
+  }
+
   identity match-local-preference {
     base frr-route-map:rmap-match-type;
     description
@@ -352,7 +358,14 @@ module frr-bgp-route-map {
       }
     }
 
-    case script { 
+    case alias {
+      when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-alias')";
+      leaf alias {
+        type string;
+      }
+    }
+
+    case script {
       when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-script')";
       leaf script {
         type string;