mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
bgpd: update routemap scripting example
- Change from "match command <foo>" to "match script <script>" - Use new scripting API Signed-off-by: Quentin Young <qlyoung@nvidia.com>
This commit is contained in:
parent
1a3a91e211
commit
b4becb063f
@ -60,6 +60,7 @@
|
||||
#include "bgpd/bgp_keepalives.h"
|
||||
#include "bgpd/bgp_network.h"
|
||||
#include "bgpd/bgp_errors.h"
|
||||
#include "bgpd/bgp_script.h"
|
||||
#include "lib/routing_nb.h"
|
||||
#include "bgpd/bgp_nb.h"
|
||||
#include "bgpd/bgp_evpn_mh.h"
|
||||
@ -506,6 +507,8 @@ int main(int argc, char **argv)
|
||||
/* Initializations. */
|
||||
bgp_vrf_init();
|
||||
|
||||
bgp_script_init();
|
||||
|
||||
hook_register(routing_conf_event,
|
||||
routing_control_plane_protocols_name_validate);
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "bgpd/bgp_flowspec_util.h"
|
||||
#include "bgpd/bgp_encap_types.h"
|
||||
#include "bgpd/bgp_mpath.h"
|
||||
#include "bgpd/bgp_script.h"
|
||||
|
||||
#ifdef ENABLE_BGP_VNC
|
||||
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
|
||||
@ -341,8 +342,7 @@ static const struct route_map_rule_cmd route_match_peer_cmd = {
|
||||
|
||||
enum frrlua_rm_status {
|
||||
/*
|
||||
* Script function run failure. This will translate into a
|
||||
* deny
|
||||
* Script function run failure. This will translate into a deny
|
||||
*/
|
||||
LUA_RM_FAILURE = 0,
|
||||
/*
|
||||
@ -350,122 +350,123 @@ enum frrlua_rm_status {
|
||||
*/
|
||||
LUA_RM_NOMATCH,
|
||||
/*
|
||||
* Match was found but no changes were made to the
|
||||
* incoming data.
|
||||
* Match was found but no changes were made to the incoming data.
|
||||
*/
|
||||
LUA_RM_MATCH,
|
||||
/*
|
||||
* Match was found and data was modified, so
|
||||
* figure out what changed
|
||||
* Match was found and data was modified, so figure out what changed
|
||||
*/
|
||||
LUA_RM_MATCH_AND_CHANGE,
|
||||
};
|
||||
|
||||
static enum frrlua_rm_status frrlua_run_rm_rule(lua_State *L, const char *rule)
|
||||
static enum route_map_cmd_result_t
|
||||
route_match_script(void *rule, const struct prefix *prefix, void *object)
|
||||
{
|
||||
int status;
|
||||
const char *scriptname = rule;
|
||||
struct bgp_path_info *path = (struct bgp_path_info *)object;
|
||||
|
||||
lua_getglobal(L, rule);
|
||||
status = lua_pcall(L, 0, 1, 0);
|
||||
if (status) {
|
||||
zlog_debug("Executing Failure with function: %s: %d",
|
||||
rule, status);
|
||||
return LUA_RM_FAILURE;
|
||||
struct frrscript *fs = frrscript_load(scriptname, NULL);
|
||||
|
||||
if (!fs) {
|
||||
zlog_err("Issue loading script rule; defaulting to no match");
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
status = lua_tonumber(L, -1);
|
||||
return status;
|
||||
}
|
||||
enum frrlua_rm_status status_failure = LUA_RM_FAILURE,
|
||||
status_nomatch = LUA_RM_NOMATCH,
|
||||
status_match = LUA_RM_MATCH,
|
||||
status_match_and_change = LUA_RM_MATCH_AND_CHANGE;
|
||||
|
||||
/* Make result values available */
|
||||
struct frrscript_env env[] = {
|
||||
{"integer", "RM_FAILURE", &status_failure},
|
||||
{"integer", "RM_NOMATCH", &status_nomatch},
|
||||
{"integer", "RM_MATCH", &status_match},
|
||||
{"integer", "RM_MATCH_AND_CHANGE", &status_match_and_change},
|
||||
{"integer", "action", &status_failure},
|
||||
{"prefix", "prefix", prefix},
|
||||
{"attr", "attributes", path->attr},
|
||||
{"peer", "peer", path->peer},
|
||||
{}};
|
||||
|
||||
struct frrscript_env results[] = {
|
||||
{"integer", "action"},
|
||||
{"attr", "attributes"},
|
||||
{},
|
||||
};
|
||||
|
||||
int result = frrscript_call(fs, env);
|
||||
|
||||
if (result) {
|
||||
zlog_err("Issue running script rule; defaulting to no match");
|
||||
return RMAP_NOMATCH;
|
||||
}
|
||||
|
||||
enum frrlua_rm_status *lrm_status =
|
||||
frrscript_get_result(fs, &results[0]);
|
||||
|
||||
static enum route_map_cmd_result_t
|
||||
route_match_command(void *rule, const struct prefix *prefix, void *object)
|
||||
{
|
||||
int status = RMAP_NOMATCH;
|
||||
u_int32_t locpref = 0;
|
||||
u_int32_t newlocpref = 0;
|
||||
enum frrlua_rm_status lrm_status;
|
||||
struct bgp_path_info *path = (struct bgp_path_info *)object;
|
||||
lua_State *L = luaL_newstate();;
|
||||
luaL_openlibs(L);
|
||||
|
||||
if (L == NULL)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Setup the prefix information to pass in
|
||||
*/
|
||||
lua_pushprefix(L, prefix);
|
||||
/*
|
||||
* Setup the bgp_path_info information
|
||||
*/
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, path->attr->med);
|
||||
lua_setfield(L, -2, "metric");
|
||||
lua_pushinteger(L, path->attr->nh_ifindex);
|
||||
lua_setfield(L, -2, "ifindex");
|
||||
lua_pushstring(L, path->attr->aspath->str);
|
||||
lua_setfield(L, -2, "aspath");
|
||||
lua_pushinteger(L, path->attr->local_pref);
|
||||
lua_setfield(L, -2, "localpref");
|
||||
zlog_debug("%s %d", path->attr->aspath->str, path->attr->nh_ifindex);
|
||||
lua_setglobal(L, "nexthop");
|
||||
|
||||
zlog_debug("Set up nexthop information");
|
||||
/*
|
||||
* Run the rule
|
||||
*/
|
||||
lrm_status = frrlua_run_rm_rule(L, rule);
|
||||
switch (lrm_status) {
|
||||
switch (*lrm_status) {
|
||||
case LUA_RM_FAILURE:
|
||||
zlog_debug("RM_FAILURE");
|
||||
zlog_err(
|
||||
"Executing route-map match script '%s' failed; defaulting to no match",
|
||||
scriptname);
|
||||
status = RMAP_NOMATCH;
|
||||
break;
|
||||
case LUA_RM_NOMATCH:
|
||||
zlog_debug("RM_NOMATCH");
|
||||
status = RMAP_NOMATCH;
|
||||
break;
|
||||
case LUA_RM_MATCH_AND_CHANGE:
|
||||
zlog_debug("MATCH AND CHANGE");
|
||||
lua_getglobal(L, "nexthop");
|
||||
path->attr->med = frrlua_table_get_integer(L, "metric");
|
||||
/*
|
||||
* This needs to be abstraced with the set function
|
||||
*/
|
||||
status = RMAP_MATCH;
|
||||
zlog_debug("Updating attribute based on script's values");
|
||||
|
||||
uint32_t locpref = 0;
|
||||
struct attr *newattr = frrscript_get_result(fs, &results[1]);
|
||||
|
||||
path->attr->med = newattr->med;
|
||||
|
||||
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
||||
locpref = path->attr->local_pref;
|
||||
newlocpref = frrlua_table_get_integer(L, "localpref");
|
||||
if (newlocpref != locpref) {
|
||||
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
||||
path->attr->local_pref = newlocpref;
|
||||
if (locpref != newattr->local_pref) {
|
||||
SET_FLAG(path->attr->flag,
|
||||
ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
|
||||
path->attr->local_pref = newattr->local_pref;
|
||||
}
|
||||
status = RMAP_MATCH;
|
||||
|
||||
aspath_free(newattr->aspath);
|
||||
XFREE(MTYPE_TMP, newattr);
|
||||
break;
|
||||
case LUA_RM_MATCH:
|
||||
zlog_debug("MATCH ONLY");
|
||||
status = RMAP_MATCH;
|
||||
break;
|
||||
}
|
||||
lua_close(L);
|
||||
|
||||
XFREE(MTYPE_TMP, lrm_status);
|
||||
frrscript_unload(fs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void *route_match_command_compile(const char *arg)
|
||||
static void *route_match_script_compile(const char *arg)
|
||||
{
|
||||
char *command;
|
||||
char *scriptname;
|
||||
|
||||
command = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
return command;
|
||||
scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
|
||||
return scriptname;
|
||||
}
|
||||
|
||||
static void
|
||||
route_match_command_free(void *rule)
|
||||
static void route_match_script_free(void *rule)
|
||||
{
|
||||
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
static const struct route_map_rule_cmd route_match_command_cmd = {
|
||||
"command",
|
||||
route_match_command,
|
||||
route_match_command_compile,
|
||||
route_match_command_free
|
||||
static const struct route_map_rule_cmd route_match_script_cmd = {
|
||||
"script",
|
||||
route_match_script,
|
||||
route_match_script_compile,
|
||||
route_match_script_free
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -4134,27 +4135,26 @@ DEFUN (no_match_peer,
|
||||
}
|
||||
|
||||
#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",
|
||||
DEFUN (match_script,
|
||||
match_script_cmd,
|
||||
"[no] match script WORD",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
"Run a command to match\n"
|
||||
"The command to run\n")
|
||||
"Execute script to determine match\n"
|
||||
"The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
|
||||
{
|
||||
return bgp_route_match_delete(vty, "command", argv[3]->arg,
|
||||
RMAP_EVENT_FILTER_DELETED);
|
||||
bool no = strmatch(argv[0]->text, "no");
|
||||
int i = 0;
|
||||
argv_find(argv, argc, "WORD", &i);
|
||||
const char *script = argv[i]->arg;
|
||||
|
||||
if (no) {
|
||||
return bgp_route_match_delete(vty, "script", script,
|
||||
RMAP_EVENT_FILTER_DELETED);
|
||||
} else {
|
||||
return bgp_route_match_add(vty, "script", script,
|
||||
RMAP_EVENT_FILTER_ADDED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -5671,7 +5671,7 @@ 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);
|
||||
route_map_install_match(&route_match_script_cmd);
|
||||
#endif
|
||||
route_map_install_match(&route_match_ip_address_cmd);
|
||||
route_map_install_match(&route_match_ip_next_hop_cmd);
|
||||
@ -5836,8 +5836,7 @@ void bgp_route_map_init(void)
|
||||
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);
|
||||
install_element(RMAP_NODE, &match_script_cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
188
bgpd/bgp_script.c
Normal file
188
bgpd/bgp_script.c
Normal file
@ -0,0 +1,188 @@
|
||||
/* BGP scripting foo
|
||||
* Copyright (C) 2020 NVIDIA Corporation
|
||||
* Quentin Young
|
||||
*
|
||||
* 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.h>
|
||||
#include <lua.h>
|
||||
|
||||
#include "bgpd.h"
|
||||
#include "bgp_script.h"
|
||||
#include "bgp_debug.h"
|
||||
#include "bgp_aspath.h"
|
||||
#include "frratomic.h"
|
||||
#include "frrscript.h"
|
||||
|
||||
static void lua_pushpeer(lua_State *L, const struct peer *peer)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, peer->as);
|
||||
lua_setfield(L, -2, "remote_as");
|
||||
lua_pushinteger(L, peer->local_as);
|
||||
lua_setfield(L, -2, "local_as");
|
||||
lua_pushinaddr(L, &peer->remote_id);
|
||||
lua_setfield(L, -2, "remote_id");
|
||||
lua_pushinaddr(L, &peer->local_id);
|
||||
lua_setfield(L, -2, "local_id");
|
||||
lua_pushstring(L, lookup_msg(bgp_status_msg, peer->status, NULL));
|
||||
lua_setfield(L, -2, "state");
|
||||
lua_pushstring(L, peer->desc ? peer->desc : "");
|
||||
lua_setfield(L, -2, "description");
|
||||
lua_pushtimet(L, &peer->uptime);
|
||||
lua_setfield(L, -2, "uptime");
|
||||
lua_pushtimet(L, &peer->readtime);
|
||||
lua_setfield(L, -2, "last_readtime");
|
||||
lua_pushtimet(L, &peer->resettime);
|
||||
lua_setfield(L, -2, "last_resettime");
|
||||
lua_pushsockunion(L, peer->su_local);
|
||||
lua_setfield(L, -2, "local_address");
|
||||
lua_pushsockunion(L, peer->su_remote);
|
||||
lua_setfield(L, -2, "remote_address");
|
||||
lua_pushinteger(L, peer->cap);
|
||||
lua_setfield(L, -2, "capabilities");
|
||||
lua_pushinteger(L, peer->flags);
|
||||
lua_setfield(L, -2, "flags");
|
||||
lua_pushstring(L, peer->password ? peer->password : "");
|
||||
lua_setfield(L, -2, "password");
|
||||
|
||||
/* Nested tables here */
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, peer->holdtime);
|
||||
lua_setfield(L, -2, "hold");
|
||||
lua_pushinteger(L, peer->keepalive);
|
||||
lua_setfield(L, -2, "keepalive");
|
||||
lua_pushinteger(L, peer->connect);
|
||||
lua_setfield(L, -2, "connect");
|
||||
lua_pushinteger(L, peer->routeadv);
|
||||
lua_setfield(L, -2, "route_advertisement");
|
||||
}
|
||||
lua_setfield(L, -2, "configured");
|
||||
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, peer->v_holdtime);
|
||||
lua_setfield(L, -2, "hold");
|
||||
lua_pushinteger(L, peer->v_keepalive);
|
||||
lua_setfield(L, -2, "keepalive");
|
||||
lua_pushinteger(L, peer->v_connect);
|
||||
lua_setfield(L, -2, "connect");
|
||||
lua_pushinteger(L, peer->v_routeadv);
|
||||
lua_setfield(L, -2, "route_advertisement");
|
||||
}
|
||||
lua_setfield(L, -2, "negotiated");
|
||||
}
|
||||
lua_setfield(L, -2, "timers");
|
||||
|
||||
lua_newtable(L);
|
||||
{
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->open_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "open_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->open_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "open_out");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->update_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "update_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->update_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "update_out");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->update_time,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "update_time");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->keepalive_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "keepalive_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->keepalive_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "keepalive_out");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->notify_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "notify_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->notify_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "notify_out");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->refresh_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "refresh_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->refresh_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "refresh_out");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->dynamic_cap_in,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "dynamic_cap_in");
|
||||
lua_pushinteger(L, atomic_load_explicit(&peer->dynamic_cap_out,
|
||||
memory_order_relaxed));
|
||||
lua_setfield(L, -2, "dynamic_cap_out");
|
||||
lua_pushinteger(L, peer->established);
|
||||
lua_setfield(L, -2, "times_established");
|
||||
lua_pushinteger(L, peer->dropped);
|
||||
lua_setfield(L, -2, "times_dropped");
|
||||
}
|
||||
lua_setfield(L, -2, "stats");
|
||||
}
|
||||
|
||||
static void lua_pushattr(lua_State *L, const struct attr *attr)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, attr->med);
|
||||
lua_setfield(L, -2, "metric");
|
||||
lua_pushinteger(L, attr->nh_ifindex);
|
||||
lua_setfield(L, -2, "ifindex");
|
||||
lua_pushstring(L, attr->aspath->str);
|
||||
lua_setfield(L, -2, "aspath");
|
||||
lua_pushinteger(L, attr->local_pref);
|
||||
lua_setfield(L, -2, "localpref");
|
||||
}
|
||||
|
||||
static void *lua_toattr(lua_State *L, int idx)
|
||||
{
|
||||
struct attr *attr = XCALLOC(MTYPE_TMP, sizeof(struct attr));
|
||||
|
||||
lua_getfield(L, -1, "metric");
|
||||
attr->med = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "ifindex");
|
||||
attr->nh_ifindex = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "aspath");
|
||||
attr->aspath = aspath_str2aspath(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, -1, "localpref");
|
||||
attr->local_pref = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
struct frrscript_codec frrscript_codecs_bgpd[] = {
|
||||
{.typename = "peer",
|
||||
.encoder = (encoder_func)lua_pushpeer,
|
||||
.decoder = NULL},
|
||||
{.typename = "attr",
|
||||
.encoder = (encoder_func)lua_pushattr,
|
||||
.decoder = lua_toattr},
|
||||
{}};
|
||||
|
||||
void bgp_script_init(void)
|
||||
{
|
||||
frrscript_register_type_codecs(frrscript_codecs_bgpd);
|
||||
}
|
26
bgpd/bgp_script.h
Normal file
26
bgpd/bgp_script.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* BGP scripting foo
|
||||
* Copyright (C) 2020 NVIDIA Corporation
|
||||
* Quentin Young
|
||||
*
|
||||
* 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.h>
|
||||
|
||||
/*
|
||||
* Initialize scripting stuff.
|
||||
*/
|
||||
void bgp_script_init(void);
|
@ -95,6 +95,7 @@ bgpd_libbgp_a_SOURCES = \
|
||||
bgpd/bgp_regex.c \
|
||||
bgpd/bgp_route.c \
|
||||
bgpd/bgp_routemap.c \
|
||||
bgpd/bgp_script.c \
|
||||
bgpd/bgp_table.c \
|
||||
bgpd/bgp_updgrp.c \
|
||||
bgpd/bgp_updgrp_adv.c \
|
||||
@ -174,6 +175,7 @@ noinst_HEADERS += \
|
||||
bgpd/bgp_rd.h \
|
||||
bgpd/bgp_regex.h \
|
||||
bgpd/bgp_route.h \
|
||||
bgpd/bgp_script.h \
|
||||
bgpd/bgp_table.h \
|
||||
bgpd/bgp_updgrp.h \
|
||||
bgpd/bgp_vpn.h \
|
||||
|
Loading…
Reference in New Issue
Block a user