mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
bgpd: Add lua match command
Please note this is a Proof of Concept and not actually something that is ready to commit at this point. The file tools/lua.scr contains some documentation on how we expect it to work currently. Additionally not all bgp values have been hooked up into the ability to lua script yet. There is still significant work to be done here: 1) Add the ability to pass in more data and to adjust the return values as appropriate. To set it up: 1) copy tools/lua.scr into /etc/frr (or whereever the config directory is ) 2) Create a route-map match command: ! router bgp 55 neighbor 10.50.11.116 remote-as external ! address-family ipv4 unicast neighbor 10.50.11.116 route-map TEST in exit-address-family ! route-map TEST permit 10 match command mooey ! 3) In the lua.scr file make sure that you have a function named 'mooey' ( as the above example does ): function mooey () zlog_debug(string.format("Family: %d: %s %d ifindex: %d aspath: %s localpref: %d", prefix.family, prefix.route, nexthop.metric, nexthop.ifindex, nexthop.aspath, nexthop.localpref)) nexthop.metric = 33 nexthop.localpref = 13 return 3 end This example script modifies the metric and localpref currently. I've also provided a zlog_debug function in lua to allow some simple debugging. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
634949aef8
commit
1d7c7ace3c
|
@ -28,6 +28,7 @@
|
|||
#include "plist.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "lua.h"
|
||||
#ifdef HAVE_LIBPCREPOSIX
|
||||
#include <pcreposix.h>
|
||||
#else
|
||||
|
@ -330,6 +331,102 @@ struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer,
|
|||
route_match_peer_compile,
|
||||
route_match_peer_free};
|
||||
|
||||
#if defined(HAVE_LUA)
|
||||
static route_map_result_t route_match_command(void *rule,
|
||||
const struct prefix *prefix,
|
||||
route_map_object_t type,
|
||||
void *object)
|
||||
{
|
||||
int status = RMAP_NOMATCH;
|
||||
u_int32_t locpref = 0;
|
||||
u_int32_t newlocpref = 0;
|
||||
enum lua_rm_status lrm_status;
|
||||
struct bgp_info *info = (struct bgp_info *)object;
|
||||
lua_State *L = lua_initialize("/etc/frr/lua.scr");
|
||||
|
||||
if (L == NULL)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Setup the prefix information to pass in
|
||||
*/
|
||||
lua_setup_prefix_table(L, prefix);
|
||||
|
||||
zlog_debug("Set up prefix table");
|
||||
/*
|
||||
* Setup the bgp_info information
|
||||
*/
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, info->attr->med);
|
||||
lua_setfield(L, -2, "metric");
|
||||
lua_pushinteger(L, info->attr->nh_ifindex);
|
||||
lua_setfield(L, -2, "ifindex");
|
||||
lua_pushstring(L, info->attr->aspath->str);
|
||||
lua_setfield(L, -2, "aspath");
|
||||
lua_pushinteger(L, info->attr->local_pref);
|
||||
lua_setfield(L, -2, "localpref");
|
||||
zlog_debug("%s %d", info->attr->aspath->str, info->attr->nh_ifindex);
|
||||
lua_setglobal(L, "nexthop");
|
||||
|
||||
zlog_debug("Set up nexthop information");
|
||||
/*
|
||||
* Run the rule
|
||||
*/
|
||||
lrm_status = lua_run_rm_rule(L, rule);
|
||||
switch (lrm_status) {
|
||||
case LUA_RM_FAILURE:
|
||||
zlog_debug("RM_FAILURE");
|
||||
break;
|
||||
case LUA_RM_NOMATCH:
|
||||
zlog_debug("RM_NOMATCH");
|
||||
break;
|
||||
case LUA_RM_MATCH_AND_CHANGE:
|
||||
zlog_debug("MATCH AND CHANGE");
|
||||
lua_getglobal(L, "nexthop");
|
||||
info->attr->med = get_integer(L, "metric");
|
||||
/*
|
||||
* This needs to be abstraced with the set function
|
||||
*/
|
||||
if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
||||
locpref = info->attr->local_pref;
|
||||
newlocpref = get_integer(L, "localpref");
|
||||
if (newlocpref != locpref) {
|
||||
info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||
info->attr->local_pref = newlocpref;
|
||||
}
|
||||
status = RMAP_MATCH;
|
||||
break;
|
||||
case LUA_RM_MATCH:
|
||||
zlog_debug("MATCH ONLY");
|
||||
status = RMAP_MATCH;
|
||||
break;
|
||||
}
|
||||
lua_close(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void *route_match_command_compile(const char *arg)
|
||||
{
|
||||
char *command;
|
||||
|
||||
command = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
return command;
|
||||
}
|
||||
|
||||
static void
|
||||
route_match_command_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
struct route_map_rule_cmd route_match_command_cmd = {
|
||||
"command",
|
||||
route_match_command,
|
||||
route_match_command_compile,
|
||||
route_match_command_free
|
||||
};
|
||||
#endif
|
||||
|
||||
/* `match ip address IP_ACCESS_LIST' */
|
||||
|
||||
/* Match function should return 1 if match is success else return
|
||||
|
@ -3356,6 +3453,30 @@ DEFUN (no_match_peer,
|
|||
RMAP_EVENT_MATCH_DELETED);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LUA)
|
||||
DEFUN (match_command,
|
||||
match_command_cmd,
|
||||
"match command WORD",
|
||||
MATCH_STR
|
||||
"Run a command to match\n"
|
||||
"The command to run\n")
|
||||
{
|
||||
return bgp_route_match_add(vty, "command", argv[2]->arg,
|
||||
RMAP_EVENT_FILTER_ADDED);
|
||||
}
|
||||
|
||||
DEFUN (no_match_command,
|
||||
no_match_command_cmd,
|
||||
"no match command WORD",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
"Run a command to match\n"
|
||||
"The command to run\n")
|
||||
{
|
||||
return bgp_route_match_delete(vty, "command", argv[3]->arg,
|
||||
RMAP_EVENT_FILTER_DELETED);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* match probability */
|
||||
DEFUN (match_probability,
|
||||
|
@ -4671,6 +4792,9 @@ void bgp_route_map_init(void)
|
|||
|
||||
route_map_install_match(&route_match_peer_cmd);
|
||||
route_map_install_match(&route_match_local_pref_cmd);
|
||||
#if defined(HAVE_LUA)
|
||||
route_map_install_match(&route_match_command_cmd);
|
||||
#endif
|
||||
route_map_install_match(&route_match_ip_address_cmd);
|
||||
route_map_install_match(&route_match_ip_next_hop_cmd);
|
||||
route_map_install_match(&route_match_ip_route_source_cmd);
|
||||
|
@ -4804,6 +4928,10 @@ void bgp_route_map_init(void)
|
|||
install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
|
||||
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
|
||||
install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
|
||||
#if defined(HAVE_LUA)
|
||||
install_element(RMAP_NODE, &match_command_cmd);
|
||||
install_element(RMAP_NODE, &no_match_command_cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bgp_route_map_terminate(void)
|
||||
|
|
29
tools/lua.scr
Normal file
29
tools/lua.scr
Normal file
|
@ -0,0 +1,29 @@
|
|||
-- Route map functionality
|
||||
--
|
||||
-- There are no parameters passed in.
|
||||
-- Currently we set two global tables
|
||||
-- prefix
|
||||
-- .family = The v4 or v6 family we are working in
|
||||
-- .route = the A.B.C.D/X or Z:A:B::D/X string
|
||||
-- nexthop
|
||||
-- .metric = The metric we are going to use
|
||||
-- .ifindex = The outgoing interface
|
||||
-- .aspath = The aspath of the route
|
||||
-- .localpref = The localpref value
|
||||
--
|
||||
-- Valid Return Codes:
|
||||
-- 0 - Some sort of processing failure
|
||||
-- This turns into a implicit DENY
|
||||
-- 1 - No match was found, turns into a DENY
|
||||
-- 2 - Match found, turns into a PERMIT
|
||||
-- 3 - Match found and data structures changed, turns into a PERMIT
|
||||
-- and a reread of the prefix and nexthop tables
|
||||
function mooey ()
|
||||
zlog_debug(string.format("Family: %d: %s %d ifindex: %d aspath: %s localpref: %d",
|
||||
prefix.family, prefix.route,
|
||||
nexthop.metric, nexthop.ifindex, nexthop.aspath, nexthop.localpref))
|
||||
|
||||
nexthop.metric = 33
|
||||
nexthop.localpref = 13
|
||||
return 3
|
||||
end
|
Loading…
Reference in a new issue