#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"
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;
}
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. */
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,
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);
|| node == BGP_FLOWSPECV6_NODE))
return false;
+ if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
+ return false;
+
return true;
}
}
#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