mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-02-01 15:35:00 +00:00
Merge pull request #9440 from dlqs/dplanehook2
This commit is contained in:
commit
0c124f75db
@ -1,22 +1,31 @@
|
||||
.. _scripting:
|
||||
.. _scripting-user:
|
||||
|
||||
*********
|
||||
Scripting
|
||||
*********
|
||||
|
||||
The behavior of FRR may be extended or customized using its built-in scripting
|
||||
capabilities.
|
||||
capabilities. The scripting language is Lua 5.3. This guide assumes Lua
|
||||
knowledge. For more information on Lua, consult the Lua 5.3 reference manual, or
|
||||
*Programming in Lua* (note that the free version covers only Lua 5.0).
|
||||
|
||||
Some configuration commands accept the name of a Lua script to call to perform
|
||||
some task or make some decision. These scripts have their environments
|
||||
populated with some set of inputs, and are expected to populate some set of
|
||||
output variables, which are read by FRR after the script completes. The names
|
||||
and expected contents of these scripts are documented alongside the commands
|
||||
that support them.
|
||||
https://www.lua.org/manual/5.3/
|
||||
|
||||
These scripts live in :file:`/etc/frr/scripts/` by default. This is
|
||||
configurable at compile time via ``--with-scriptdir``. It may be
|
||||
overriden at runtime with the ``--scriptdir`` daemon option.
|
||||
http://www.lua.org/pil/contents.html
|
||||
|
||||
Scripting
|
||||
=========
|
||||
|
||||
.. seealso:: Developer docs for scripting
|
||||
|
||||
How to use
|
||||
----------
|
||||
|
||||
1. Identify the Lua function name. See :ref:`lua-hook-calls`.
|
||||
|
||||
2. Write the Lua script
|
||||
|
||||
3. Configure FRR to use the Lua script
|
||||
|
||||
In order to use scripting, FRR must be built with ``--enable-scripting``.
|
||||
|
||||
@ -26,3 +35,51 @@ In order to use scripting, FRR must be built with ``--enable-scripting``.
|
||||
contents of a script that is in use without restarting FRR. Not all
|
||||
scripting locations may behave this way; refer to the documentation for the
|
||||
particular location.
|
||||
|
||||
|
||||
Example: on_rib_process_dplane_results
|
||||
--------------------------------------
|
||||
|
||||
This example shows how to write a Lua script that logs changes when a route is
|
||||
added.
|
||||
|
||||
First, identify the Lua hook call to attach a Lua function to: this will be the
|
||||
name of the Lua function. In this case, since the hook call is
|
||||
`on_rib_process_dplane_results`:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
function on_rib_process_dplane_results(ctx)
|
||||
log.info(ctx.rinfo.zd_dest.network)
|
||||
return {}
|
||||
|
||||
|
||||
The documentation for :ref:`on-rib-process-dplane-results` tells us its
|
||||
arguments. Here, the destination prefix for a route is being logged out.
|
||||
|
||||
Scripts live in :file:`/etc/frr/scripts/` by default. This is configurable at
|
||||
compile time via ``--with-scriptdir``. It may be overriden at runtime with the
|
||||
``--scriptdir`` daemon option.
|
||||
|
||||
The documentation for :ref:`on-rib-process-dplane-results` indicates that the
|
||||
``script`` command should be used to set the script. Assuming that the above
|
||||
function was created in :file:`/etc/frr/scripts/my_dplane_script.lua`, the
|
||||
following vtysh command sets the script for the hook call:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
script on_rib_process_dplane_results my_dplane_script
|
||||
|
||||
|
||||
After the script is set, when the hook call is hit, FRR will look for a
|
||||
*on_rib_process_dplane_results* function in
|
||||
:file:`/etc/frr/scripts/my_dplane_script.lua` and run it with the ``ctx`` object
|
||||
as its argument.
|
||||
|
||||
|
||||
.. _lua-hook-calls:
|
||||
|
||||
Available Lua hook calls
|
||||
========================
|
||||
|
||||
:ref:`on-rib-process-dplane-results`
|
||||
|
||||
@ -1416,3 +1416,199 @@ Debugging
|
||||
|
||||
Nexthop and nexthop-group events.
|
||||
|
||||
Scripting
|
||||
=========
|
||||
|
||||
.. clicmd:: zebra on-rib-process script SCRIPT
|
||||
|
||||
Set a Lua script for :ref:`on-rib-process-dplane-results` hook call.
|
||||
SCRIPT is the basename of the script, without `.lua`.
|
||||
|
||||
Data structures
|
||||
---------------
|
||||
|
||||
.. _const-struct-zebra-dplane-ctx:
|
||||
|
||||
const struct zebra_dplane_ctx
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
* integer zd_op
|
||||
* integer zd_status
|
||||
* integer zd_provider
|
||||
* integer zd_vrf_id
|
||||
* integer zd_table_id
|
||||
* integer zd_ifname
|
||||
* integer zd_ifindex
|
||||
* table rinfo (if zd_op is DPLANE_OP_ROUTE*, DPLANE_NH_*)
|
||||
|
||||
* prefix zd_dest
|
||||
* prefix zd_src
|
||||
* integer zd_afi
|
||||
* integer zd_safi
|
||||
* integer zd_type
|
||||
* integer zd_old_type
|
||||
* integer zd_tag
|
||||
* integer zd_old_tag
|
||||
* integer zd_metric
|
||||
* integer zd_old_metric
|
||||
* integer zd_instance
|
||||
* integer zd_old_instance
|
||||
* integer zd_distance
|
||||
* integer zd_old_distance
|
||||
* integer zd_mtu
|
||||
* integer zd_nexthop_mtu
|
||||
* table nhe
|
||||
|
||||
* integer id
|
||||
* integer old_id
|
||||
* integer afi
|
||||
* integer vrf_id
|
||||
* integer type
|
||||
* nexthop_group ng
|
||||
* nh_grp
|
||||
* integer nh_grp_count
|
||||
|
||||
* integer zd_nhg_id
|
||||
* nexthop_group zd_ng
|
||||
* nexthop_group backup_ng
|
||||
* nexthop_group zd_old_ng
|
||||
* nexthop_group old_backup_ng
|
||||
|
||||
* integer label (if zd_op is DPLANE_OP_LSP_*)
|
||||
* table pw (if zd_op is DPLANE_OP_PW_*)
|
||||
|
||||
* integer type
|
||||
* integer af
|
||||
* integer status
|
||||
* integer flags
|
||||
* integer local_label
|
||||
* integer remote_label
|
||||
|
||||
* table macinfo (if zd_op is DPLANE_OP_MAC_*)
|
||||
|
||||
* integer vid
|
||||
* integer br_ifindex
|
||||
* ethaddr mac
|
||||
* integer vtep_ip
|
||||
* integer is_sticky
|
||||
* integer nhg_id
|
||||
* integer update_flags
|
||||
|
||||
* table rule (if zd_op is DPLANE_OP_RULE_*)
|
||||
|
||||
* integer sock
|
||||
* integer unique
|
||||
* integer seq
|
||||
* string ifname
|
||||
* integer priority
|
||||
* integer old_priority
|
||||
* integer table
|
||||
* integer old_table
|
||||
* integer filter_bm
|
||||
* integer old_filter_bm
|
||||
* integer fwmark
|
||||
* integer old_fwmark
|
||||
* integer dsfield
|
||||
* integer old_dsfield
|
||||
* integer ip_proto
|
||||
* integer old_ip_proto
|
||||
* prefix src_ip
|
||||
* prefix old_src_ip
|
||||
* prefix dst_ip
|
||||
* prefix old_dst_ip
|
||||
|
||||
* table iptable (if zd_op is DPLANE_OP_IPTABLE_*)
|
||||
|
||||
* integer sock
|
||||
* integer vrf_id
|
||||
* integer unique
|
||||
* integer type
|
||||
* integer filter_bm
|
||||
* integer fwmark
|
||||
* integer action
|
||||
* integer pkt_len_min
|
||||
* integer pkt_len_max
|
||||
* integer tcp_flags
|
||||
* integer dscp_value
|
||||
* integer fragment
|
||||
* integer protocol
|
||||
* integer nb_interface
|
||||
* integer flow_label
|
||||
* integer family
|
||||
* string ipset_name
|
||||
|
||||
* table ipset (if zd_op is DPLANE_OP_IPSET_*)
|
||||
* integer sock
|
||||
* integer vrf_id
|
||||
* integer unique
|
||||
* integer type
|
||||
* integer family
|
||||
* string ipset_name
|
||||
|
||||
* table neigh (if zd_op is DPLANE_OP_NEIGH_*)
|
||||
|
||||
* ipaddr ip_addr
|
||||
* table link
|
||||
|
||||
* ethaddr mac
|
||||
* ipaddr ip_addr
|
||||
|
||||
* integer flags
|
||||
* integer state
|
||||
* integer update_flags
|
||||
|
||||
* table br_port (if zd_op is DPLANE_OP_BR_PORT_UPDATE)
|
||||
|
||||
* integer sph_filter_cnt
|
||||
* integer flags
|
||||
* integer backup_nhg_id
|
||||
|
||||
* table neightable (if zd_op is DPLANE_OP_NEIGH_TABLE_UPDATE)
|
||||
|
||||
* integer family
|
||||
* integer app_probes
|
||||
* integer ucast_probes
|
||||
* integer mcast_probes
|
||||
|
||||
* table gre (if zd_op is DPLANE_OP_GRE_SET)**
|
||||
|
||||
* integer link_ifindex
|
||||
* integer mtu
|
||||
|
||||
|
||||
.. _const-struct-nh-grp:
|
||||
|
||||
const struct nh_grp
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
* integer id
|
||||
* integer weight
|
||||
|
||||
|
||||
.. _zebra-hook-calls:
|
||||
|
||||
Zebra Hook calls
|
||||
----------------
|
||||
|
||||
.. _on-rib-process-dplane-results:
|
||||
|
||||
on_rib_process_dplane_results
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Called when RIB processes dataplane events.
|
||||
Set script location with the ``zebra on-rib-process script SCRIPT`` command.
|
||||
|
||||
**Arguments**
|
||||
|
||||
* :ref:`const struct zebra_dplane_ctx<const-struct-zebra-dplane-ctx>` ctx
|
||||
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
function on_rib_process_dplane_results(ctx)
|
||||
log.info(ctx.rinfo.zd_dest.network)
|
||||
return {}
|
||||
|
||||
67
lib/frrlua.c
67
lib/frrlua.c
@ -223,6 +223,21 @@ void *lua_toin6addr(lua_State *L, int idx)
|
||||
return in6addr;
|
||||
}
|
||||
|
||||
void lua_pushipaddr(lua_State *L, const struct ipaddr *addr)
|
||||
{
|
||||
if (IS_IPADDR_V4(addr))
|
||||
lua_pushinaddr(L, &addr->ipaddr_v4);
|
||||
else
|
||||
lua_pushin6addr(L, &addr->ipaddr_v6);
|
||||
}
|
||||
|
||||
void lua_pushethaddr(lua_State *L, const struct ethaddr *addr)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, *(addr->octet));
|
||||
lua_setfield(L, -2, "octet");
|
||||
}
|
||||
|
||||
void lua_pushsockunion(lua_State *L, const union sockunion *su)
|
||||
{
|
||||
char buf[SU_ADDRSTRLEN];
|
||||
@ -297,6 +312,58 @@ void *lua_tointegerp(lua_State *L, int idx)
|
||||
return num;
|
||||
}
|
||||
|
||||
void lua_pushnexthop(lua_State *L, const struct nexthop *nexthop)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, nexthop->vrf_id);
|
||||
lua_setfield(L, -2, "vrf_id");
|
||||
lua_pushinteger(L, nexthop->ifindex);
|
||||
lua_setfield(L, -2, "ifindex");
|
||||
lua_pushinteger(L, nexthop->type);
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushinteger(L, nexthop->flags);
|
||||
lua_setfield(L, -2, "flags");
|
||||
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
|
||||
lua_pushinteger(L, nexthop->bh_type);
|
||||
lua_setfield(L, -2, "bh_type");
|
||||
} else if (nexthop->type == NEXTHOP_TYPE_IPV4) {
|
||||
lua_pushinaddr(L, &nexthop->gate.ipv4);
|
||||
lua_setfield(L, -2, "gate");
|
||||
} else if (nexthop->type == NEXTHOP_TYPE_IPV6) {
|
||||
lua_pushin6addr(L, &nexthop->gate.ipv6);
|
||||
lua_setfield(L, -2, "gate");
|
||||
}
|
||||
lua_pushinteger(L, nexthop->nh_label_type);
|
||||
lua_setfield(L, -2, "nh_label_type");
|
||||
lua_pushinteger(L, nexthop->weight);
|
||||
lua_setfield(L, -2, "weight");
|
||||
lua_pushinteger(L, nexthop->backup_num);
|
||||
lua_setfield(L, -2, "backup_num");
|
||||
lua_pushinteger(L, *(nexthop->backup_idx));
|
||||
lua_setfield(L, -2, "backup_idx");
|
||||
if (nexthop->nh_encap_type == NET_VXLAN) {
|
||||
lua_pushinteger(L, nexthop->nh_encap.vni);
|
||||
lua_setfield(L, -2, "vni");
|
||||
}
|
||||
lua_pushinteger(L, nexthop->nh_encap_type);
|
||||
lua_setfield(L, -2, "nh_encap_type");
|
||||
lua_pushinteger(L, nexthop->srte_color);
|
||||
lua_setfield(L, -2, "srte_color");
|
||||
}
|
||||
|
||||
void lua_pushnexthop_group(lua_State *L, const struct nexthop_group *ng)
|
||||
{
|
||||
lua_newtable(L);
|
||||
struct nexthop *nexthop;
|
||||
int i = 0;
|
||||
|
||||
for (ALL_NEXTHOPS_PTR(ng, nexthop)) {
|
||||
lua_pushnexthop(L, nexthop);
|
||||
lua_seti(L, -2, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void lua_decode_stringp(lua_State *L, int idx, char *str)
|
||||
{
|
||||
strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
|
||||
|
||||
@ -100,6 +100,10 @@ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr);
|
||||
|
||||
void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *addr);
|
||||
|
||||
void lua_pushipaddr(lua_State *L, const struct ipaddr *addr);
|
||||
|
||||
void lua_pushethaddr(lua_State *L, const struct ethaddr *addr);
|
||||
|
||||
/*
|
||||
* Converts the Lua value at idx to an in6_addr.
|
||||
*
|
||||
@ -138,6 +142,10 @@ void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su);
|
||||
*/
|
||||
void *lua_tosockunion(lua_State *L, int idx);
|
||||
|
||||
void lua_pushnexthop_group(lua_State *L, const struct nexthop_group *ng);
|
||||
|
||||
void lua_pushnexthop(lua_State *L, const struct nexthop *nexthop);
|
||||
|
||||
/*
|
||||
* Converts an int to a Lua value and pushes it on the stack.
|
||||
*/
|
||||
|
||||
@ -32,6 +32,92 @@
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, SCRIPT, "Scripting");
|
||||
|
||||
/*
|
||||
* Script name hash utilities
|
||||
*/
|
||||
|
||||
struct frrscript_names_head frrscript_names_hash;
|
||||
|
||||
/*
|
||||
* Wrapper for frrscript_names_add
|
||||
* Use this to register hook calls when a daemon starts up
|
||||
*/
|
||||
int frrscript_names_add_function_name(const char *function_name)
|
||||
{
|
||||
struct frrscript_names_entry *insert =
|
||||
XCALLOC(MTYPE_SCRIPT, sizeof(*insert));
|
||||
strlcpy(insert->function_name, function_name,
|
||||
sizeof(insert->function_name));
|
||||
|
||||
if (frrscript_names_add(&frrscript_names_hash, insert)) {
|
||||
zlog_warn(
|
||||
"Failed to add hook call function name to script_names");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void frrscript_names_destroy(void)
|
||||
{
|
||||
struct frrscript_names_entry *ne;
|
||||
|
||||
while ((ne = frrscript_names_pop(&frrscript_names_hash)))
|
||||
XFREE(MTYPE_SCRIPT, ne);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a function_name, set its script_name. function_names and script_names
|
||||
* are one-to-one. Each set will wipe the previous script_name.
|
||||
* Return 0 if set was successful, else 1.
|
||||
*
|
||||
* script_name is the base name of the file, without .lua.
|
||||
*/
|
||||
int frrscript_names_set_script_name(const char *function_name,
|
||||
const char *script_name)
|
||||
{
|
||||
struct frrscript_names_entry lookup;
|
||||
|
||||
strlcpy(lookup.function_name, function_name,
|
||||
sizeof(lookup.function_name));
|
||||
struct frrscript_names_entry *snhe =
|
||||
frrscript_names_find(&frrscript_names_hash, &lookup);
|
||||
if (!snhe)
|
||||
return 1;
|
||||
strlcpy(snhe->script_name, script_name, sizeof(snhe->script_name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a function_name, get its script_name.
|
||||
* Return NULL if function_name not found.
|
||||
*
|
||||
* script_name is the base name of the file, without .lua.
|
||||
*/
|
||||
char *frrscript_names_get_script_name(const char *function_name)
|
||||
{
|
||||
struct frrscript_names_entry lookup;
|
||||
|
||||
strlcpy(lookup.function_name, function_name,
|
||||
sizeof(lookup.function_name));
|
||||
struct frrscript_names_entry *snhe =
|
||||
frrscript_names_find(&frrscript_names_hash, &lookup);
|
||||
if (!snhe)
|
||||
return NULL;
|
||||
return snhe->script_name;
|
||||
}
|
||||
|
||||
uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe)
|
||||
{
|
||||
return string_hash_make(snhe->function_name);
|
||||
}
|
||||
|
||||
int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
|
||||
const struct frrscript_names_entry *snhe2)
|
||||
{
|
||||
return strncmp(snhe1->function_name, snhe2->function_name,
|
||||
sizeof(snhe1->function_name));
|
||||
}
|
||||
|
||||
/* Codecs */
|
||||
|
||||
struct frrscript_codec frrscript_codecs_lib[] = {
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
#ifdef HAVE_SCRIPTING
|
||||
|
||||
#include <lua.h>
|
||||
#include <nexthop.h>
|
||||
#include <nexthop_group.h>
|
||||
#include "frrlua.h"
|
||||
#include "bgpd/bgp_script.h" // for peer and attr encoders/decoders
|
||||
|
||||
@ -31,6 +33,43 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
extern struct zebra_dplane_ctx ctx;
|
||||
extern void lua_pushzebra_dplane_ctx(lua_State *L,
|
||||
const struct zebra_dplane_ctx *ctx);
|
||||
extern void lua_decode_zebra_dplane_ctx(lua_State *L, int idx,
|
||||
struct zebra_dplane_ctx *ctx);
|
||||
|
||||
/*
|
||||
* Script name hash
|
||||
*/
|
||||
PREDECL_HASH(frrscript_names);
|
||||
|
||||
struct frrscript_names_entry {
|
||||
/* Name of a Lua hook call */
|
||||
char function_name[MAXPATHLEN];
|
||||
|
||||
/* Lua script in which to look for it */
|
||||
char script_name[MAXPATHLEN];
|
||||
|
||||
struct frrscript_names_item item;
|
||||
};
|
||||
|
||||
extern struct frrscript_names_head frrscript_names_hash;
|
||||
|
||||
int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
|
||||
const struct frrscript_names_entry *snhe2);
|
||||
uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe);
|
||||
|
||||
DECLARE_HASH(frrscript_names, struct frrscript_names_entry, item,
|
||||
frrscript_names_hash_cmp, frrscript_names_hash_key);
|
||||
|
||||
int frrscript_names_add_function_name(const char *function_name);
|
||||
void frrscript_names_destroy(void);
|
||||
int frrscript_names_set_script_name(const char *function_name,
|
||||
const char *script_name);
|
||||
char *frrscript_names_get_script_name(const char *function_name);
|
||||
|
||||
typedef void (*encoder_func)(lua_State *, const void *);
|
||||
typedef void *(*decoder_func)(lua_State *, int);
|
||||
|
||||
@ -171,7 +210,12 @@ time_t * : lua_pushtimet, \
|
||||
char * : lua_pushstring_wrapper, \
|
||||
struct attr * : lua_pushattr, \
|
||||
struct peer * : lua_pushpeer, \
|
||||
const struct prefix * : lua_pushprefix \
|
||||
const struct prefix * : lua_pushprefix, \
|
||||
const struct ipaddr * : lua_pushipaddr, \
|
||||
const struct ethaddr * : lua_pushethaddr, \
|
||||
const struct nexthop_group * : lua_pushnexthop_group, \
|
||||
const struct nexthop * : lua_pushnexthop, \
|
||||
struct zebra_dplane_ctx * : lua_pushzebra_dplane_ctx \
|
||||
)((L), (value))
|
||||
|
||||
#define DECODE_ARGS_WITH_STATE(L, value) \
|
||||
@ -187,7 +231,12 @@ time_t * : lua_decode_timet, \
|
||||
char * : lua_decode_stringp, \
|
||||
struct attr * : lua_decode_attr, \
|
||||
struct peer * : lua_decode_noop, \
|
||||
const struct prefix * : lua_decode_noop \
|
||||
const struct prefix * : lua_decode_noop, \
|
||||
const struct ipaddr * : lua_decode_noop, \
|
||||
const struct ethaddr * : lua_decode_noop, \
|
||||
const struct nexthop_group * : lua_decode_noop, \
|
||||
const struct nexthop * : lua_decode_noop, \
|
||||
struct zebra_dplane_ctx * : lua_decode_noop \
|
||||
)((L), -1, (value))
|
||||
|
||||
/*
|
||||
|
||||
@ -383,6 +383,9 @@ typedef uint32_t route_tag_t;
|
||||
#define ROUTE_TAG_MAX UINT32_MAX
|
||||
#define ROUTE_TAG_PRI PRIu32
|
||||
|
||||
/* Name of hook calls */
|
||||
#define ZEBRA_ON_RIB_PROCESS_HOOK_CALL "on_rib_process_dplane_results"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -116,6 +116,7 @@ zebra_zebra_SOURCES = \
|
||||
zebra/zebra_routemap.c \
|
||||
zebra/zebra_routemap_nb.c \
|
||||
zebra/zebra_routemap_nb_config.c \
|
||||
zebra/zebra_script.c \
|
||||
zebra/zebra_srte.c \
|
||||
zebra/zebra_vrf.c \
|
||||
zebra/zebra_vty.c \
|
||||
@ -185,6 +186,7 @@ noinst_HEADERS += \
|
||||
zebra/zebra_routemap.h \
|
||||
zebra/zebra_routemap_nb.h \
|
||||
zebra/zebra_router.h \
|
||||
zebra/zebra_script.h \
|
||||
zebra/zebra_srte.h \
|
||||
zebra/zebra_vrf.h \
|
||||
zebra/zebra_vxlan.h \
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include "nexthop_group_private.h"
|
||||
#include "frr_pthread.h"
|
||||
#include "printfrr.h"
|
||||
#include "frrscript.h"
|
||||
|
||||
#include "zebra/zebra_router.h"
|
||||
#include "zebra/connected.h"
|
||||
@ -57,6 +58,7 @@
|
||||
#include "zebra/zapi_msg.h"
|
||||
#include "zebra/zebra_dplane.h"
|
||||
#include "zebra/zebra_evpn_mh.h"
|
||||
#include "zebra/zebra_script.h"
|
||||
|
||||
DEFINE_MGROUP(ZEBRA, "zebra");
|
||||
|
||||
@ -4135,7 +4137,31 @@ static int rib_process_dplane_results(struct thread *thread)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
char *script_name = frrscript_names_get_script_name(
|
||||
ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
|
||||
|
||||
int ret = 1;
|
||||
struct frrscript *fs;
|
||||
|
||||
if (script_name) {
|
||||
fs = frrscript_new(script_name);
|
||||
if (fs)
|
||||
ret = frrscript_load(
|
||||
fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
|
||||
NULL);
|
||||
}
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
|
||||
while (ctx) {
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
if (ret == 0)
|
||||
frrscript_call(fs,
|
||||
ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
|
||||
("ctx", ctx));
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
|
||||
switch (dplane_ctx_get_op(ctx)) {
|
||||
case DPLANE_OP_ROUTE_INSTALL:
|
||||
case DPLANE_OP_ROUTE_UPDATE:
|
||||
|
||||
@ -255,6 +255,10 @@ void zebra_router_terminate(void)
|
||||
hash_free(zrouter.ipset_entry_hash);
|
||||
hash_clean(zrouter.iptable_hash, zebra_pbr_iptable_free);
|
||||
hash_free(zrouter.iptable_hash);
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
zebra_script_destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool zebra_router_notify_on_ack(void)
|
||||
@ -296,4 +300,8 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
|
||||
|
||||
zrouter.asic_offloaded = asic_offload;
|
||||
zrouter.notify_on_ack = notify_on_ack;
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
zebra_script_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
415
zebra/zebra_script.c
Normal file
415
zebra/zebra_script.c
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* frrscript encoders and decoders for data structures in Zebra
|
||||
* Copyright (C) 2021 Donald Lee
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "zebra_script.h"
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
|
||||
void zebra_script_init(void)
|
||||
{
|
||||
frrscript_names_add_function_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
|
||||
}
|
||||
|
||||
void zebra_script_destroy(void)
|
||||
{
|
||||
frrscript_names_destroy();
|
||||
}
|
||||
|
||||
void lua_pushnh_grp(lua_State *L, const struct nh_grp *nh_grp)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, nh_grp->id);
|
||||
lua_setfield(L, -2, "id");
|
||||
lua_pushinteger(L, nh_grp->weight);
|
||||
lua_setfield(L, -2, "weight");
|
||||
}
|
||||
|
||||
void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, dplane_ctx_get_op(ctx));
|
||||
lua_setfield(L, -2, "zd_op");
|
||||
lua_pushinteger(L, dplane_ctx_get_status(ctx));
|
||||
lua_setfield(L, -2, "zd_status");
|
||||
lua_pushinteger(L, dplane_ctx_get_provider(ctx));
|
||||
lua_setfield(L, -2, "zd_provider");
|
||||
lua_pushinteger(L, dplane_ctx_get_vrf(ctx));
|
||||
lua_setfield(L, -2, "zd_vrf_id");
|
||||
lua_pushinteger(L, dplane_ctx_get_table(ctx));
|
||||
lua_setfield(L, -2, "zd_table_id");
|
||||
lua_pushstring(L, dplane_ctx_get_ifname(ctx));
|
||||
lua_setfield(L, -2, "zd_ifname");
|
||||
lua_pushinteger(L, dplane_ctx_get_ifindex(ctx));
|
||||
lua_setfield(L, -2, "zd_ifindex");
|
||||
|
||||
switch (dplane_ctx_get_op(ctx)) {
|
||||
case DPLANE_OP_ROUTE_INSTALL:
|
||||
case DPLANE_OP_ROUTE_UPDATE:
|
||||
case DPLANE_OP_ROUTE_DELETE:
|
||||
case DPLANE_OP_ROUTE_NOTIFY:
|
||||
case DPLANE_OP_NH_INSTALL:
|
||||
case DPLANE_OP_NH_UPDATE:
|
||||
case DPLANE_OP_NH_DELETE:
|
||||
/* rinfo */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushprefix(L, dplane_ctx_get_dest(ctx));
|
||||
lua_setfield(L, -2, "zd_dest");
|
||||
const struct prefix *src_pfx = dplane_ctx_get_src(ctx);
|
||||
|
||||
if (src_pfx) {
|
||||
lua_pushprefix(L, src_pfx);
|
||||
lua_setfield(L, -2, "zd_src");
|
||||
}
|
||||
lua_pushinteger(L, dplane_ctx_get_afi(ctx));
|
||||
lua_setfield(L, -2, "zd_afi");
|
||||
lua_pushinteger(L, dplane_ctx_get_safi(ctx));
|
||||
lua_setfield(L, -2, "zd_safi");
|
||||
lua_pushinteger(L, dplane_ctx_get_type(ctx));
|
||||
lua_setfield(L, -2, "zd_type");
|
||||
lua_pushinteger(L, dplane_ctx_get_old_type(ctx));
|
||||
lua_setfield(L, -2, "zd_old_type");
|
||||
lua_pushinteger(L, dplane_ctx_get_tag(ctx));
|
||||
lua_setfield(L, -2, "zd_tag");
|
||||
lua_pushinteger(L, dplane_ctx_get_old_tag(ctx));
|
||||
lua_setfield(L, -2, "zd_old_tag");
|
||||
lua_pushinteger(L, dplane_ctx_get_metric(ctx));
|
||||
lua_setfield(L, -2, "zd_metric");
|
||||
lua_pushinteger(L, dplane_ctx_get_old_metric(ctx));
|
||||
lua_setfield(L, -2, "zd_old_metric");
|
||||
lua_pushinteger(L, dplane_ctx_get_instance(ctx));
|
||||
lua_setfield(L, -2, "zd_instance");
|
||||
lua_pushinteger(L, dplane_ctx_get_old_instance(ctx));
|
||||
lua_setfield(L, -2, "zd_old_instance");
|
||||
lua_pushinteger(L, dplane_ctx_get_distance(ctx));
|
||||
lua_setfield(L, -2, "zd_distance");
|
||||
lua_pushinteger(L, dplane_ctx_get_old_distance(ctx));
|
||||
lua_setfield(L, -2, "zd_old_distance");
|
||||
lua_pushinteger(L, dplane_ctx_get_mtu(ctx));
|
||||
lua_setfield(L, -2, "zd_mtu");
|
||||
lua_pushinteger(L, dplane_ctx_get_nh_mtu(ctx));
|
||||
lua_setfield(L, -2, "zd_nexthop_mtu");
|
||||
/* nhe */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, dplane_ctx_get_nhe_id(ctx));
|
||||
lua_setfield(L, -2, "id");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_get_old_nhe_id(ctx));
|
||||
lua_setfield(L, -2, "old_id");
|
||||
lua_pushinteger(L, dplane_ctx_get_nhe_afi(ctx));
|
||||
lua_setfield(L, -2, "afi");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_get_nhe_vrf_id(ctx));
|
||||
lua_setfield(L, -2, "vrf_id");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_get_nhe_type(ctx));
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushnexthop_group(
|
||||
L, dplane_ctx_get_nhe_ng(ctx));
|
||||
lua_setfield(L, -2, "ng");
|
||||
lua_pushnh_grp(L,
|
||||
dplane_ctx_get_nhe_nh_grp(ctx));
|
||||
lua_setfield(L, -2, "nh_grp");
|
||||
lua_pushinteger(
|
||||
L,
|
||||
dplane_ctx_get_nhe_nh_grp_count(ctx));
|
||||
lua_setfield(L, -2, "nh_grp_count");
|
||||
}
|
||||
lua_setfield(L, -2, "nhe");
|
||||
lua_pushinteger(L, dplane_ctx_get_nhg_id(ctx));
|
||||
lua_setfield(L, -2, "zd_nhg_id");
|
||||
lua_pushnexthop_group(L, dplane_ctx_get_ng(ctx));
|
||||
lua_setfield(L, -2, "zd_ng");
|
||||
lua_pushnexthop_group(L, dplane_ctx_get_backup_ng(ctx));
|
||||
lua_setfield(L, -2, "backup_ng");
|
||||
lua_pushnexthop_group(L, dplane_ctx_get_old_ng(ctx));
|
||||
lua_setfield(L, -2, "zd_old_ng");
|
||||
lua_pushnexthop_group(
|
||||
L, dplane_ctx_get_old_backup_ng(ctx));
|
||||
lua_setfield(L, -2, "old_backup_ng");
|
||||
}
|
||||
lua_setfield(L, -2, "rinfo");
|
||||
break;
|
||||
case DPLANE_OP_LSP_INSTALL:
|
||||
case DPLANE_OP_LSP_UPDATE:
|
||||
case DPLANE_OP_LSP_DELETE:
|
||||
case DPLANE_OP_LSP_NOTIFY:
|
||||
lua_pushinteger(L, (int)dplane_ctx_get_in_label(ctx));
|
||||
lua_setfield(L, -2, "label");
|
||||
break;
|
||||
case DPLANE_OP_PW_INSTALL:
|
||||
case DPLANE_OP_PW_UNINSTALL:
|
||||
/* pw*/
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_type(ctx));
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_af(ctx));
|
||||
lua_setfield(L, -2, "af");
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_status(ctx));
|
||||
lua_setfield(L, -2, "status");
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_flags(ctx));
|
||||
lua_setfield(L, -2, "flags");
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_local_label(ctx));
|
||||
lua_setfield(L, -2, "local_label");
|
||||
lua_pushinteger(L, dplane_ctx_get_pw_remote_label(ctx));
|
||||
lua_setfield(L, -2, "remote_label");
|
||||
}
|
||||
lua_setfield(L, -2, "pw");
|
||||
break;
|
||||
case DPLANE_OP_SYS_ROUTE_ADD:
|
||||
case DPLANE_OP_SYS_ROUTE_DELETE:
|
||||
/* nothing to encode */
|
||||
break;
|
||||
case DPLANE_OP_MAC_INSTALL:
|
||||
case DPLANE_OP_MAC_DELETE:
|
||||
/* macinfo */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, dplane_ctx_mac_get_vlan(ctx));
|
||||
lua_setfield(L, -2, "vid");
|
||||
lua_pushinteger(L, dplane_ctx_mac_get_br_ifindex(ctx));
|
||||
lua_setfield(L, -2, "br_ifindex");
|
||||
lua_pushethaddr(L, dplane_ctx_mac_get_addr(ctx));
|
||||
lua_setfield(L, -2, "mac");
|
||||
lua_pushinaddr(L, dplane_ctx_mac_get_vtep_ip(ctx));
|
||||
lua_setfield(L, -2, "vtep_ip");
|
||||
lua_pushinteger(L, dplane_ctx_mac_is_sticky(ctx));
|
||||
lua_setfield(L, -2, "is_sticky");
|
||||
lua_pushinteger(L, dplane_ctx_mac_get_nhg_id(ctx));
|
||||
lua_setfield(L, -2, "nhg_id");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_mac_get_update_flags(ctx));
|
||||
lua_setfield(L, -2, "update_flags");
|
||||
}
|
||||
lua_setfield(L, -2, "macinfo");
|
||||
break;
|
||||
case DPLANE_OP_RULE_ADD:
|
||||
case DPLANE_OP_RULE_DELETE:
|
||||
case DPLANE_OP_RULE_UPDATE:
|
||||
/* rule */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_sock(ctx));
|
||||
lua_setfield(L, -2, "sock");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_unique(ctx));
|
||||
lua_setfield(L, -2, "unique");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_seq(ctx));
|
||||
lua_setfield(L, -2, "seq");
|
||||
lua_pushstring(L, dplane_ctx_rule_get_ifname(ctx));
|
||||
lua_setfield(L, -2, "ifname");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_priority(ctx));
|
||||
lua_setfield(L, -2, "priority");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_rule_get_old_priority(ctx));
|
||||
lua_setfield(L, -2, "old_priority");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_table(ctx));
|
||||
lua_setfield(L, -2, "table");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_old_table(ctx));
|
||||
lua_setfield(L, -2, "old_table");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_filter_bm(ctx));
|
||||
lua_setfield(L, -2, "filter_bm");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_rule_get_old_filter_bm(ctx));
|
||||
lua_setfield(L, -2, "old_filter_bm");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_fwmark(ctx));
|
||||
lua_setfield(L, -2, "fwmark");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_old_fwmark(ctx));
|
||||
lua_setfield(L, -2, "old_fwmark");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_dsfield(ctx));
|
||||
lua_setfield(L, -2, "dsfield");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_rule_get_old_dsfield(ctx));
|
||||
lua_setfield(L, -2, "old_dsfield");
|
||||
lua_pushinteger(L, dplane_ctx_rule_get_ipproto(ctx));
|
||||
lua_setfield(L, -2, "ip_proto");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_rule_get_old_ipproto(ctx));
|
||||
lua_setfield(L, -2, "old_ip_proto");
|
||||
lua_pushprefix(L, dplane_ctx_rule_get_src_ip(ctx));
|
||||
lua_setfield(L, -2, "src_ip");
|
||||
lua_pushprefix(L, dplane_ctx_rule_get_old_src_ip(ctx));
|
||||
lua_setfield(L, -2, "old_src_ip");
|
||||
lua_pushprefix(L, dplane_ctx_rule_get_dst_ip(ctx));
|
||||
lua_setfield(L, -2, "dst_ip");
|
||||
lua_pushprefix(L, dplane_ctx_rule_get_old_dst_ip(ctx));
|
||||
lua_setfield(L, -2, "old_dst_ip");
|
||||
}
|
||||
lua_setfield(L, -2, "rule");
|
||||
break;
|
||||
case DPLANE_OP_IPTABLE_ADD:
|
||||
case DPLANE_OP_IPTABLE_DELETE:
|
||||
struct zebra_pbr_iptable iptable;
|
||||
|
||||
dplane_ctx_get_pbr_iptable(ctx, &iptable);
|
||||
/* iptable */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, iptable.sock);
|
||||
lua_setfield(L, -2, "sock");
|
||||
lua_pushinteger(L, iptable.vrf_id);
|
||||
lua_setfield(L, -2, "vrf_id");
|
||||
lua_pushinteger(L, iptable.unique);
|
||||
lua_setfield(L, -2, "unique");
|
||||
lua_pushinteger(L, iptable.type);
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushinteger(L, iptable.filter_bm);
|
||||
lua_setfield(L, -2, "filter_bm");
|
||||
lua_pushinteger(L, iptable.fwmark);
|
||||
lua_setfield(L, -2, "fwmark");
|
||||
lua_pushinteger(L, iptable.action);
|
||||
lua_setfield(L, -2, "action");
|
||||
lua_pushinteger(L, iptable.pkt_len_min);
|
||||
lua_setfield(L, -2, "pkt_len_min");
|
||||
lua_pushinteger(L, iptable.pkt_len_max);
|
||||
lua_setfield(L, -2, "pkt_len_max");
|
||||
lua_pushinteger(L, iptable.tcp_flags);
|
||||
lua_setfield(L, -2, "tcp_flags");
|
||||
lua_pushinteger(L, iptable.dscp_value);
|
||||
lua_setfield(L, -2, "dscp_value");
|
||||
lua_pushinteger(L, iptable.fragment);
|
||||
lua_setfield(L, -2, "fragment");
|
||||
lua_pushinteger(L, iptable.protocol);
|
||||
lua_setfield(L, -2, "protocol");
|
||||
lua_pushinteger(L, iptable.nb_interface);
|
||||
lua_setfield(L, -2, "nb_interface");
|
||||
lua_pushinteger(L, iptable.flow_label);
|
||||
lua_setfield(L, -2, "flow_label");
|
||||
lua_pushinteger(L, iptable.family);
|
||||
lua_setfield(L, -2, "family");
|
||||
lua_pushstring(L, iptable.ipset_name);
|
||||
lua_setfield(L, -2, "ipset_name");
|
||||
}
|
||||
lua_setfield(L, -2, "iptable");
|
||||
break;
|
||||
case DPLANE_OP_IPSET_ADD:
|
||||
case DPLANE_OP_IPSET_DELETE:
|
||||
case DPLANE_OP_IPSET_ENTRY_ADD:
|
||||
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
||||
struct zebra_pbr_ipset ipset;
|
||||
|
||||
dplane_ctx_get_pbr_ipset(ctx, &ipset);
|
||||
/* ipset */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, ipset.sock);
|
||||
lua_setfield(L, -2, "sock");
|
||||
lua_pushinteger(L, ipset.vrf_id);
|
||||
lua_setfield(L, -2, "vrf_id");
|
||||
lua_pushinteger(L, ipset.unique);
|
||||
lua_setfield(L, -2, "unique");
|
||||
lua_pushinteger(L, ipset.type);
|
||||
lua_setfield(L, -2, "type");
|
||||
lua_pushinteger(L, ipset.family);
|
||||
lua_setfield(L, -2, "family");
|
||||
lua_pushstring(L, ipset.ipset_name);
|
||||
lua_setfield(L, -2, "ipset_name");
|
||||
}
|
||||
lua_setfield(L, -2, "ipset");
|
||||
break;
|
||||
case DPLANE_OP_ADDR_INSTALL:
|
||||
case DPLANE_OP_ADDR_UNINSTALL:
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_INSTALL:
|
||||
case DPLANE_OP_NEIGH_UPDATE:
|
||||
case DPLANE_OP_NEIGH_DELETE:
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_NEIGH_IP_INSTALL:
|
||||
case DPLANE_OP_NEIGH_IP_DELETE:
|
||||
/* neigh */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushipaddr(L, dplane_ctx_neigh_get_ipaddr(ctx));
|
||||
lua_setfield(L, -2, "ip_addr");
|
||||
/* link */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushethaddr(L,
|
||||
dplane_ctx_neigh_get_mac(ctx));
|
||||
lua_setfield(L, -2, "mac");
|
||||
lua_pushipaddr(
|
||||
L, dplane_ctx_neigh_get_link_ip(ctx));
|
||||
lua_setfield(L, -2, "ip_addr");
|
||||
}
|
||||
lua_setfield(L, -2, "link");
|
||||
lua_pushinteger(L, dplane_ctx_neigh_get_flags(ctx));
|
||||
lua_setfield(L, -2, "flags");
|
||||
lua_pushinteger(L, dplane_ctx_neigh_get_state(ctx));
|
||||
lua_setfield(L, -2, "state");
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_neigh_get_update_flags(ctx));
|
||||
lua_setfield(L, -2, "update_flags");
|
||||
}
|
||||
lua_setfield(L, -2, "neigh");
|
||||
break;
|
||||
case DPLANE_OP_VTEP_ADD:
|
||||
case DPLANE_OP_VTEP_DELETE:
|
||||
break;
|
||||
case DPLANE_OP_BR_PORT_UPDATE:
|
||||
/* br_port */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(
|
||||
L, dplane_ctx_get_br_port_sph_filter_cnt(ctx));
|
||||
lua_setfield(L, -2, "sph_filter_cnt");
|
||||
lua_pushinteger(L, dplane_ctx_get_br_port_flags(ctx));
|
||||
lua_setfield(L, -2, "flags");
|
||||
lua_pushinteger(
|
||||
L, dplane_ctx_get_br_port_backup_nhg_id(ctx));
|
||||
lua_setfield(L, -2, "backup_nhg_id");
|
||||
}
|
||||
lua_setfield(L, -2, "br_port");
|
||||
break;
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
/* neightable */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_neightable_get_family(ctx));
|
||||
lua_setfield(L, -2, "family");
|
||||
lua_pushinteger(
|
||||
L, dplane_ctx_neightable_get_app_probes(ctx));
|
||||
lua_setfield(L, -2, "app_probes");
|
||||
lua_pushinteger(
|
||||
L, dplane_ctx_neightable_get_mcast_probes(ctx));
|
||||
lua_setfield(L, -2, "ucast_probes");
|
||||
lua_pushinteger(
|
||||
L, dplane_ctx_neightable_get_ucast_probes(ctx));
|
||||
lua_setfield(L, -2, "mcast_probes");
|
||||
}
|
||||
lua_setfield(L, -2, "neightable");
|
||||
break;
|
||||
case DPLANE_OP_GRE_SET:
|
||||
/* gre */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L,
|
||||
dplane_ctx_gre_get_link_ifindex(ctx));
|
||||
lua_setfield(L, -2, "link_ifindex");
|
||||
lua_pushinteger(L, dplane_ctx_gre_get_mtu(ctx));
|
||||
lua_setfield(L, -2, "mtu");
|
||||
}
|
||||
lua_setfield(L, -2, "gre");
|
||||
case DPLANE_OP_NONE:
|
||||
} /* Dispatch by op code */
|
||||
}
|
||||
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
41
zebra/zebra_script.h
Normal file
41
zebra/zebra_script.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* frrscript encoders and decoders for data structures in Zebra
|
||||
* Copyright (C) 2021 Donald Lee
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_SCRIPT_H
|
||||
#define _ZEBRA_SCRIPT_H
|
||||
|
||||
#include "zebra.h"
|
||||
#include "zebra/zebra_dplane.h"
|
||||
#include "zebra/zebra_pbr.h"
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
|
||||
#include "frrlua.h"
|
||||
|
||||
void zebra_script_init(void);
|
||||
|
||||
void zebra_script_destroy(void);
|
||||
|
||||
void lua_pushnh_grp(lua_State *L, const struct nh_grp *nh_grp);
|
||||
|
||||
void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx);
|
||||
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
|
||||
#endif /* _ZEBRA_SCRIPT_H */
|
||||
@ -60,6 +60,7 @@
|
||||
#include "zebra/zebra_nb.h"
|
||||
#include "zebra/kernel_netlink.h"
|
||||
#include "zebra/table_manager.h"
|
||||
#include "zebra/zebra_script.h"
|
||||
|
||||
extern int allow_delete;
|
||||
|
||||
@ -4323,6 +4324,30 @@ DEFUN(ip_table_range, ip_table_range_cmd,
|
||||
return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
|
||||
DEFUN(zebra_on_rib_process_script, zebra_on_rib_process_script_cmd,
|
||||
"zebra on-rib-process script SCRIPT",
|
||||
ZEBRA_STR
|
||||
"on_rib_process_dplane_results hook call\n"
|
||||
"Set a script\n"
|
||||
"Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
|
||||
{
|
||||
|
||||
if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
|
||||
argv[3]->arg)
|
||||
== 0) {
|
||||
vty_out(vty, "Successfully added script %s for hook call %s\n",
|
||||
argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
|
||||
} else {
|
||||
vty_out(vty, "Failed to add script %s for hook call %s\n",
|
||||
argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
|
||||
/* IP node for static routes. */
|
||||
static int zebra_ip_config(struct vty *vty);
|
||||
static struct cmd_node ip_node = {
|
||||
@ -4479,5 +4504,9 @@ void zebra_vty_init(void)
|
||||
install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
|
||||
#endif /* HAVE_NETLINK */
|
||||
|
||||
#ifdef HAVE_SCRIPTING
|
||||
install_element(CONFIG_NODE, &zebra_on_rib_process_script_cmd);
|
||||
#endif /* HAVE_SCRIPTING */
|
||||
|
||||
install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user