]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #8982 from dlqs/lua-func-stack
authorQuentin Young <qlyoung@users.noreply.github.com>
Mon, 2 Aug 2021 13:51:35 +0000 (13:51 +0000)
committerGitHub <noreply@github.com>
Mon, 2 Aug 2021 13:51:35 +0000 (13:51 +0000)
1  2 
bgpd/bgp_routemap.c
lib/command.c

diff --combined bgpd/bgp_routemap.c
index 61f57d04753132b5a558c6331a7b816bdfd61a83,4b71ba30ce58d997c483a4920e89130ba7c8c718..09dd71c0205db663675e758b911b9a6a659b6ed8
@@@ -52,7 -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"
@@@ -366,38 -365,37 +366,37 @@@ static enum route_map_cmd_result_
  route_match_script(void *rule, const struct prefix *prefix, void *object)
  {
        const char *scriptname = rule;
+       const char *routematch_function = "route_match";
        struct bgp_path_info *path = (struct bgp_path_info *)object;
  
-       struct frrscript *fs = frrscript_load(scriptname, NULL);
+       struct frrscript *fs = frrscript_new(scriptname);
  
-       if (!fs) {
-               zlog_err("Issue loading script rule; defaulting to no match");
+       if (frrscript_load(fs, routematch_function, NULL)) {
+               zlog_err(
+                       "Issue loading script or function; defaulting to no match");
                return RMAP_NOMATCH;
        }
  
-       enum frrlua_rm_status lrm_status = LUA_RM_FAILURE,
-                             status_nomatch = LUA_RM_NOMATCH,
-                             status_match = LUA_RM_MATCH,
-                             status_match_and_change = LUA_RM_MATCH_AND_CHANGE;
        struct attr newattr = *path->attr;
  
        int result = frrscript_call(
-               fs, ("RM_FAILURE", (long long *)&lrm_status),
-               ("RM_NOMATCH", (long long *)&status_nomatch),
-               ("RM_MATCH", (long long *)&status_match),
-               ("RM_MATCH_AND_CHANGE", (long long *)&status_match_and_change),
-               ("action", (long long *)&lrm_status), ("prefix", prefix),
-               ("attributes", &newattr), ("peer", path->peer));
+               fs, routematch_function, ("prefix", prefix),
+               ("attributes", &newattr), ("peer", path->peer),
+               ("RM_FAILURE", LUA_RM_FAILURE), ("RM_NOMATCH", LUA_RM_NOMATCH),
+               ("RM_MATCH", LUA_RM_MATCH),
+               ("RM_MATCH_AND_CHANGE", LUA_RM_MATCH_AND_CHANGE));
  
        if (result) {
                zlog_err("Issue running script rule; defaulting to no match");
                return RMAP_NOMATCH;
        }
  
+       long long *action = frrscript_get_result(fs, routematch_function,
+                                                "action", lua_tointegerp);
        int status = RMAP_NOMATCH;
  
-       switch (lrm_status) {
+       switch (*action) {
        case LUA_RM_FAILURE:
                zlog_err(
                        "Executing route-map match script '%s' failed; defaulting to no match",
                break;
        }
  
-       frrscript_unload(fs);
+       XFREE(MTYPE_SCRIPT_RES, action);
+       frrscript_delete(fs);
  
        return status;
  }
@@@ -1180,55 -1180,6 +1181,55 @@@ static const struct route_map_rule_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 (strcmp(alias, 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 (strcmp(alias, 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. */
@@@ -4647,58 -4598,6 +4648,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,
@@@ -6388,7 -6287,6 +6389,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);
        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);
diff --combined lib/command.c
index fe17c68a8ba57df739f4aca8f2b3223c8a0bef9a,122e18934262368cac139d49a53a3ac502ccb62e..422544b70bc80b1d6434d4a4c54136afcf63e964
@@@ -160,9 -160,6 +160,9 @@@ static bool vty_check_node_for_xpath_de
                || node == BGP_FLOWSPECV6_NODE))
                return false;
  
 +      if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
 +              return false;
 +
        return true;
  }
  
@@@ -2422,28 -2419,30 +2422,30 @@@ DEFUN(find
  }
  
  #if defined(DEV_BUILD) && defined(HAVE_SCRIPTING)
- DEFUN(script,
-       script_cmd,
-       "script SCRIPT",
-       "Test command - execute a script\n"
-       "Script name (same as filename in /etc/frr/scripts/\n")
+ DEFUN(script, script_cmd, "script SCRIPT FUNCTION",
+       "Test command - execute a function in a script\n"
+       "Script name (same as filename in /etc/frr/scripts/)\n"
+       "Function name (in the script)\n")
  {
        struct prefix p;
  
        (void)str2prefix("1.2.3.4/24", &p);
-       struct frrscript *fs = frrscript_load(argv[1]->arg, NULL);
+       struct frrscript *fs = frrscript_new(argv[1]->arg);
  
-       if (fs == NULL) {
-               vty_out(vty, "Script '/etc/frr/scripts/%s.lua' not found\n",
-                       argv[1]->arg);
-       } else {
-               int ret = frrscript_call(fs, ("p", &p));
-               char buf[40];
-               prefix2str(&p, buf, sizeof(buf));
-               vty_out(vty, "p: %s\n", buf);
-               vty_out(vty, "Script result: %d\n", ret);
+       if (frrscript_load(fs, argv[2]->arg, NULL)) {
+               vty_out(vty,
+                       "/etc/frr/scripts/%s.lua or function '%s' not found\n",
+                       argv[1]->arg, argv[2]->arg);
        }
  
+       int ret = frrscript_call(fs, argv[2]->arg, ("p", &p));
+       char buf[40];
+       prefix2str(&p, buf, sizeof(buf));
+       vty_out(vty, "p: %s\n", buf);
+       vty_out(vty, "Script result: %d\n", ret);
+       frrscript_delete(fs);
        return CMD_SUCCESS;
  }
  #endif