mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 12:52:49 +00:00
Merge branch 'master'
This commit is contained in:
commit
422f8d0ca9
@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
noinst_LIBRARIES = libbgp.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = bgpd
|
||||
bin_PROGRAMS = bgp_btoa
|
||||
|
||||
@ -75,7 +76,7 @@ libbgp_a_SOURCES = \
|
||||
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
|
||||
bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
|
||||
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
|
||||
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \
|
||||
bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \
|
||||
bgp_mplsvpn.c bgp_nexthop.c \
|
||||
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
|
||||
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
|
||||
@ -89,7 +90,7 @@ noinst_HEADERS = \
|
||||
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
|
||||
bgp_ecommunity.h bgp_lcommunity.h \
|
||||
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
|
||||
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
|
||||
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
|
||||
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
|
||||
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h
|
||||
|
||||
@ -101,6 +102,14 @@ bgp_btoa_SOURCES = bgp_btoa.c
|
||||
bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS)
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += bgpd_snmp.la
|
||||
endif
|
||||
|
||||
bgpd_snmp_la_SOURCES = bgp_snmp.c
|
||||
bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
|
||||
bgpd.conf.vnc.sample
|
||||
|
@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_dump.h"
|
||||
#include "bgpd/bgp_open.h"
|
||||
#include "bgpd/bgp_advertise.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_memory.h"
|
||||
|
||||
DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DEFINE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
/* Definition of display strings corresponding to FSM events. This should be
|
||||
* kept consistent with the events defined in bgpd.h
|
||||
*/
|
||||
@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer)
|
||||
zlog_debug ("%s remove from all update group", peer->host);
|
||||
update_group_remove_peer_afs(peer);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapBackwardTransition (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_backward_transition, peer);
|
||||
|
||||
/* Reset peer synctime */
|
||||
peer->synctime = 0;
|
||||
@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer)
|
||||
zlog_debug ("%s graceful restart timer stopped", peer->host);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapEstablished (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_established, peer);
|
||||
|
||||
/* Reset uptime, send keepalive, send current table. */
|
||||
peer->uptime = bgp_clock ();
|
||||
|
@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *);
|
||||
*/
|
||||
extern void bgp_adjust_routeadv (struct peer *);
|
||||
|
||||
#include "hook.h"
|
||||
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
#endif /* _QUAGGA_BGP_FSM_H */
|
||||
|
@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "thread.h"
|
||||
#include "smux.h"
|
||||
#include "filter.h"
|
||||
#include "hook.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_table.h"
|
||||
@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
|
||||
/* BGP4-MIB described in RFC1657. */
|
||||
#define BGP4MIB 1,3,6,1,2,1,15
|
||||
@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] =
|
||||
{3, {3, 1, BGPPEERSTATE}}
|
||||
};
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapEstablished (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPESTABLISHED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapBackwardTransition (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPBACKWARDTRANSITION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_snmp_init (void)
|
||||
static int
|
||||
bgp_snmp_init (struct thread_master *tm)
|
||||
{
|
||||
smux_init (bm->master);
|
||||
smux_init (tm);
|
||||
REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
bgp_snmp_module_init (void)
|
||||
{
|
||||
hook_register(peer_established, bgpTrapEstablished);
|
||||
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
|
||||
hook_register(frr_late_init, bgp_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "bgpd_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "bgpd AgentX SNMP module",
|
||||
.init = bgp_snmp_module_init
|
||||
)
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* BGP4 SNMP support
|
||||
Copyright (C) 1999, 2000 Kunihiro Ishiguro
|
||||
|
||||
This file is part of GNU Zebra.
|
||||
|
||||
GNU Zebra 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, or (at your option) any
|
||||
later version.
|
||||
|
||||
GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#ifndef _QUAGGA_BGP_SNMP_H
|
||||
#define _QUAGGA_BGP_SNMP_H
|
||||
|
||||
extern void bgp_snmp_init (void);
|
||||
extern void bgpTrapEstablished (struct peer *);
|
||||
extern void bgpTrapBackwardTransition (struct peer *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_SNMP_H */
|
@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_vty.h"
|
||||
#include "bgpd/bgp_mpath.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_memory.h"
|
||||
@ -7667,6 +7664,8 @@ bgp_if_finish (struct bgp *bgp)
|
||||
}
|
||||
}
|
||||
|
||||
extern void bgp_snmp_init (void);
|
||||
|
||||
void
|
||||
bgp_init (void)
|
||||
{
|
||||
@ -7715,10 +7714,6 @@ bgp_init (void)
|
||||
/* Community list initialize. */
|
||||
bgp_clist = community_list_init ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgp_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
/* BFD init */
|
||||
bgp_bfd_init();
|
||||
}
|
||||
|
68
configure.ac
68
configure.ac
@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
|
||||
AC_SUBST(pkgsrcdir)
|
||||
AC_SUBST(pkgsrcrcdir)
|
||||
|
||||
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
|
||||
moduledir="$withval"
|
||||
], [
|
||||
moduledir="\${libdir}/frr/modules"
|
||||
])
|
||||
AC_SUBST([moduledir], [$moduledir])
|
||||
|
||||
AC_ARG_ENABLE(tcmalloc,
|
||||
AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]),
|
||||
[case "${enableval}" in
|
||||
@ -363,9 +370,7 @@ if test "${enable_shell_access}" = "yes"; then
|
||||
AC_DEFINE(HAVE_SHELL_ACCESS,,Allow user to use ssh/telnet/bash)
|
||||
fi
|
||||
|
||||
if test "${enable_fpm}" = "yes"; then
|
||||
AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support)
|
||||
fi
|
||||
AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"])
|
||||
|
||||
if test "x${enable_dev_build}" = "xyes"; then
|
||||
AC_DEFINE(DEV_BUILD,,Build for development)
|
||||
@ -1322,8 +1327,8 @@ if test "${enable_snmp}" != ""; then
|
||||
if test x"$NETSNMP_CONFIG" = x"no"; then
|
||||
AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config])
|
||||
fi
|
||||
LIBS="$LIBS `${NETSNMP_CONFIG} --agent-libs`"
|
||||
CFLAGS="`${NETSNMP_CONFIG} --base-cflags` $CFLAGS"
|
||||
SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`"
|
||||
SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`"
|
||||
AC_MSG_CHECKING([whether we can link to Net-SNMP])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
int main(void);
|
||||
@ -1335,7 +1340,6 @@ int main(void);
|
||||
])],[AC_MSG_RESULT(yes)],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([--enable-snmp given but not usable])])
|
||||
AC_DEFINE(HAVE_SNMP,,SNMP)
|
||||
case "${enable_snmp}" in
|
||||
yes)
|
||||
SNMP_METHOD=agentx
|
||||
@ -1351,6 +1355,53 @@ int main(void);
|
||||
AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd])
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
|
||||
fi
|
||||
AM_CONDITIONAL([SNMP], [test "x${SNMP_METHOD}" != "x"])
|
||||
AC_SUBST(SNMP_LIBS)
|
||||
AC_SUBST(SNMP_CFLAGS)
|
||||
|
||||
dnl ---------------
|
||||
dnl dlopen & dlinfo
|
||||
dnl ---------------
|
||||
AC_SEARCH_LIBS(dlopen, [dl dld], [], [
|
||||
AC_MSG_ERROR([unable to find the dlopen()])
|
||||
])
|
||||
|
||||
AC_CHECK_HEADERS([link.h])
|
||||
|
||||
AC_MSG_CHECKING([for dlinfo(RTLD_DI_ORIGIN)])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_LINK_H
|
||||
#include <link.h>
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
]], [[
|
||||
char origin[1];
|
||||
dlinfo (NULL, RTLD_DI_ORIGIN, &origin);
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_DLINFO_ORIGIN, 1, [Have dlinfo RTLD_DI_ORIGIN])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([for dlinfo(RTLD_DI_LINKMAP)])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_LINK_H
|
||||
#include <link.h>
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
]], [[
|
||||
struct link_map *lm = NULL;
|
||||
dlinfo (NULL, RTLD_DI_LINKMAP, &lm);
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_DLINFO_LINKMAP, 1, [Have dlinfo RTLD_DI_LINKMAP])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
|
||||
dnl ---------------------------
|
||||
dnl sockaddr and netinet checks
|
||||
@ -1651,14 +1702,18 @@ AC_DEFINE_UNQUOTED(VTYSH_BIN_PATH, "$vtysh_bin",path to vtysh binary)
|
||||
CFG_SYSCONF="$sysconfdir"
|
||||
CFG_SBIN="$sbindir"
|
||||
CFG_STATE="$frr_statedir"
|
||||
CFG_MODULE="$moduledir"
|
||||
for I in 1 2 3 4 5 6 7 8 9 10; do
|
||||
eval CFG_SYSCONF="\"$CFG_SYSCONF\""
|
||||
eval CFG_SBIN="\"$CFG_SBIN\""
|
||||
eval CFG_STATE="\"$CFG_STATE\""
|
||||
eval CFG_MODULE="\"$CFG_MODULE\""
|
||||
done
|
||||
AC_SUBST(CFG_SYSCONF)
|
||||
AC_SUBST(CFG_SBIN)
|
||||
AC_SUBST(CFG_STATE)
|
||||
AC_SUBST(CFG_MODULE)
|
||||
AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules)
|
||||
|
||||
dnl ---------------------------
|
||||
dnl Check htonl works correctly
|
||||
@ -1734,6 +1789,7 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
|
||||
state file directory : ${frr_statedir}
|
||||
config file directory : `eval echo \`echo ${sysconfdir}\``
|
||||
example directory : `eval echo \`echo ${exampledir}\``
|
||||
module directory : ${CFG_MODULE}
|
||||
user to run as : ${enable_user}
|
||||
group to run as : ${enable_group}
|
||||
group for vty sockets : ${enable_vty_group}
|
||||
|
@ -18,6 +18,7 @@ daemons.
|
||||
* Config Commands:: Commands used in config files
|
||||
* Terminal Mode Commands:: Common commands used in a VTY
|
||||
* Common Invocation Options:: Starting the daemons
|
||||
* Loadable Module Support:: Using extension modules
|
||||
* Virtual Terminal Interfaces:: Interacting with the daemons
|
||||
@end menu
|
||||
|
||||
@ -372,6 +373,51 @@ Print program version.
|
||||
@end table
|
||||
|
||||
|
||||
@node Loadable Module Support
|
||||
@section Loadable Module Support
|
||||
|
||||
FRR supports loading extension modules at startup. Loading, reloading or
|
||||
unloading modules at runtime is not supported (yet). To load a module, use
|
||||
the following command line option at daemon startup:
|
||||
|
||||
@table @samp
|
||||
@item -M @var{module:options}
|
||||
@itemx --module @var{module:options}
|
||||
|
||||
Load the specified module, optionally passing options to it. If the module
|
||||
name contains a slash (/), it is assumed to be a full pathname to a file to
|
||||
be loaded. If it does not contain a slash, the
|
||||
@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of
|
||||
the given name; first with the daemon name prepended (e.g. @code{zebra_mod}
|
||||
for @code{mod}), then without the daemon name prepended.
|
||||
|
||||
This option is available on all daemons, though some daemons may not have
|
||||
any modules available to be loaded.
|
||||
@end table
|
||||
|
||||
|
||||
@subsection The SNMP Module
|
||||
|
||||
If SNMP is enabled during compile-time and installed as part of the package,
|
||||
the @code{snmp} module can be loaded for the @command{zebra},
|
||||
@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons.
|
||||
|
||||
The module ignores any options passed to it. Refer to @ref{SNMP Support}
|
||||
for information on its usage.
|
||||
|
||||
|
||||
@subsection The FPM Module
|
||||
|
||||
If FPM is enabled during compile-time and installed as part of the package,
|
||||
the @code{fpm} module can be loaded for the @command{zebra} daemon. This
|
||||
provides the Forwarding Plane Manager ("FPM") API.
|
||||
|
||||
The module expects its argument to be either @code{netlink} or
|
||||
@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the
|
||||
default, and @code{protobuf} may not be available if the module was built
|
||||
without protobuf support. Refer to @ref{zebra FIB push interface} for more
|
||||
information.
|
||||
|
||||
|
||||
@node Virtual Terminal Interfaces
|
||||
@section Virtual Terminal Interfaces
|
||||
|
@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B bgpd
|
||||
@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR.
|
||||
\fB\-S\fR, \fB\-\-skip_runas\fR
|
||||
Skip setting the process effective user and group.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBbgpd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -13,6 +13,7 @@
|
||||
@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
|
||||
@set INSTALL_PREFIX_SBIN @CFG_SBIN@
|
||||
@set INSTALL_PREFIX_STATE @CFG_STATE@
|
||||
@set INSTALL_PREFIX_MODULES @CFG_MODULE@
|
||||
@set INSTALL_USER @enable_user@
|
||||
@set INSTALL_GROUP @enable_group@
|
||||
@set INSTALL_VTY_GROUP @enable_vty_group@
|
||||
|
119
doc/dev-modules.md
Normal file
119
doc/dev-modules.md
Normal file
@ -0,0 +1,119 @@
|
||||
# Module and Hook support (developer docs)
|
||||
|
||||
## What it does
|
||||
|
||||
It uses `dlopen()` to load DSOs at startup.
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
* can't load, unload, or reload during runtime. This just needs some work
|
||||
and can probably be done in the future.
|
||||
* doesn't fix any of the "things need to be changed in the code in the library"
|
||||
issues. Most prominently, you can't add a CLI node because CLI nodes are
|
||||
listed in the library...
|
||||
* if your module crashes, the daemon crashes. Should be obvious.
|
||||
* **does not provide a stable API or ABI**. Your module must match a version
|
||||
of FRR and you may have to update it frequently to match changes.
|
||||
* **does not create a license boundary**. Your module will need to link
|
||||
libzebra and include header files from the daemons, meaning it will be
|
||||
GPL-encumbered.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Look for `moduledir` in `configure.ac`, default is normally
|
||||
`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`.
|
||||
|
||||
The daemon's name is prepended when looking for a module, e.g. "snmp" tries
|
||||
to find "zebra_snmp" first when used in zebra. This is just to make it nicer
|
||||
for the user, with the snmp module having the same name everywhere.
|
||||
|
||||
Modules can be packaged separately from FRR. The SNMP and FPM modules are
|
||||
good candidates for this because they have dependencies (net-snmp / protobuf)
|
||||
that are not FRR dependencies. However, any distro packages should have an
|
||||
"exact-match" dependency onto the FRR package. Using a module from a
|
||||
different FRR version will probably blow up nicely.
|
||||
|
||||
For snapcraft (and during development), modules can be loaded with full path
|
||||
(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output
|
||||
files in the .libs directory, so during development you have to use
|
||||
`./zebra -M .libs/zebra_snmp.so`.
|
||||
|
||||
|
||||
## Creating a module
|
||||
|
||||
... best to look at the existing SNMP or FPM modules.
|
||||
|
||||
Basic boilerplate:
|
||||
|
||||
```
|
||||
#include "hook.h"
|
||||
#include "module.h"
|
||||
|
||||
static int
|
||||
module_init (void)
|
||||
{
|
||||
hook_register(frr_late_init, module_late_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "my module",
|
||||
.version = "0.0",
|
||||
.description = "my module",
|
||||
.init = module_init,
|
||||
)
|
||||
```
|
||||
|
||||
The `frr_late_init` hook will be called after the daemon has finished its
|
||||
other startup and is about to enter the main event loop; this is the best
|
||||
place for most initialisation.
|
||||
|
||||
|
||||
## Compiler & Linker magic
|
||||
|
||||
There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility`
|
||||
attributes to restrict it to the current module. If you get a linker error
|
||||
with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be
|
||||
possible, though one way to get it would be to not include libzebra (which
|
||||
provides a fallback definition for the symbol).
|
||||
|
||||
libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable
|
||||
modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use
|
||||
the definition in libzebra; same applies if the main executable doesn't use
|
||||
`FRR_DAEMON_INFO` (e.g. all testcases).
|
||||
|
||||
The deciding factor here is "what dynamic linker unit are you using the symbol
|
||||
from." If you're in a library function and want to know who called you, you
|
||||
can't use `THIS_MODULE` (because that'll just tell you you're in the library).
|
||||
Put a macro around your function that adds `THIS_MODULE` in the *caller's
|
||||
code calling your function*.
|
||||
|
||||
The idea is to use this in the future for module unloading. Hooks already
|
||||
remember which module they were installed by, as groundwork for a function
|
||||
that removes all of a module's installed hooks.
|
||||
|
||||
There's also the `frr_module` symbol in modules, pretty much a standard entry
|
||||
point for loadable modules.
|
||||
|
||||
|
||||
## Hooks
|
||||
|
||||
Hooks are just points in the code where you can register your callback to
|
||||
be called. The parameter list is specific to the hook point. Since there is
|
||||
no stable API, the hook code has some extra type safety checks making sure
|
||||
you get a compiler warning when the hook parameter list doesn't match your
|
||||
callback. Don't ignore these warnings.
|
||||
|
||||
|
||||
## Relation to MTYPE macros
|
||||
|
||||
The MTYPE macros, while primarily designed to decouple MTYPEs from the library
|
||||
and beautify the code, also work very nicely with loadable modules -- both
|
||||
constructors and destructors are executed when loading/unloading modules.
|
||||
|
||||
This means there is absolutely no change required to MTYPEs, you can just use
|
||||
them in a module and they will even clean up themselves when we implement
|
||||
module unloading and an unload happens. In fact, it's impossible to create
|
||||
a bug where unloading fails to de-register a MTYPE.
|
@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B isisd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBisisd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ldpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBldpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -385,7 +385,8 @@ ip protocol rip route-map RM1
|
||||
|
||||
Zebra supports a 'FIB push' interface that allows an external
|
||||
component to learn the forwarding information computed by the Frr
|
||||
routing suite.
|
||||
routing suite. This is a loadable module that needs to be enabled
|
||||
at startup as described in @ref{Loadable Module Support}.
|
||||
|
||||
In Frr, the Routing Information Base (RIB) resides inside
|
||||
zebra. Routing protocols communicate their best routes to zebra, and
|
||||
@ -440,9 +441,9 @@ independently.
|
||||
@end itemize
|
||||
|
||||
As mentioned before, zebra encodes routes sent to the FPM in netlink
|
||||
format by default. The format can be controlled via the
|
||||
@code{--fpm_format} command-line option to zebra, which currently
|
||||
takes the values @code{netlink} and @code{protobuf}.
|
||||
format by default. The format can be controlled via the FPM module's
|
||||
load-time option to zebra, which currently takes the values @code{netlink}
|
||||
and @code{protobuf}.
|
||||
|
||||
The zebra FPM interface uses replace semantics. That is, if a 'route
|
||||
add' message for a prefix is followed by another 'route add' message,
|
||||
|
@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B nhrpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBnhrpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospf6d
|
||||
@ -64,6 +67,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospf6d\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospfd
|
||||
@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-a\fR, \fB\-\-apiserver \fR
|
||||
Enable OSPF apiserver. Default is disabled.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospfd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B pimd
|
||||
@ -70,6 +73,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBpimd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.TP
|
||||
|
@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBripd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripngd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBripngd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol
|
||||
(@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the
|
||||
routing protocol MIBs available through it.
|
||||
|
||||
Note that SNMP Support needs to be enabled at compile-time and loaded as
|
||||
module on daemon startup. Refer to @ref{Loadable Module Support} on
|
||||
the latter.
|
||||
|
||||
@menu
|
||||
* Getting and installing an SNMP agent::
|
||||
* AgentX configuration::
|
||||
|
@ -108,13 +108,13 @@ Set the logging
|
||||
(LOG_DEBUG), but higher number can be supplied if extra debugging messages
|
||||
are required.
|
||||
.TP
|
||||
.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number
|
||||
.BI \-\-min\-restart\-interval " number
|
||||
Set the minimum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
default value is "60").
|
||||
.TP
|
||||
.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number
|
||||
.BI \-\-max\-restart\-interval " number
|
||||
Set the maximum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
|
@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B zebra
|
||||
@ -86,6 +89,14 @@ maximum before starting zebra.
|
||||
|
||||
Note that this affects Linux only.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR and \fBfpm\fR modules may be
|
||||
available for \fBzebra\fR, if the package was built with SNMP and FPM support
|
||||
respectively. The \fBfpm\fR module takes an additional colon-separated
|
||||
argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR.
|
||||
It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -20,7 +20,7 @@ libfrr_la_SOURCES = \
|
||||
command.c \
|
||||
sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \
|
||||
filter.c routemap.c distribute.c stream.c log.c plist.c \
|
||||
zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
|
||||
zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \
|
||||
sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
|
||||
ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
|
||||
imsg-buffer.c imsg.c skiplist.c \
|
||||
@ -31,12 +31,28 @@ libfrr_la_SOURCES = \
|
||||
spf_backoff.c \
|
||||
libfrr.c \
|
||||
strlcpy.c \
|
||||
strlcat.c
|
||||
strlcat.c \
|
||||
module.c \
|
||||
hook.c \
|
||||
# end
|
||||
|
||||
BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h
|
||||
|
||||
libfrr_la_LIBADD = @LIBCAP@
|
||||
|
||||
if SNMP
|
||||
lib_LTLIBRARIES += libfrrsnmp.la
|
||||
endif
|
||||
|
||||
libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
||||
libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
|
||||
libfrrsnmp_la_LIBADD = libfrr.la $(SNMP_LIBS)
|
||||
libfrrsnmp_la_SOURCES = \
|
||||
agentx.c \
|
||||
smux.c \
|
||||
snmp.c \
|
||||
#end
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
buffer.h checksum.h filter.h getopt.h hash.h \
|
||||
if.h linklist.h log.h \
|
||||
@ -54,6 +70,8 @@ pkginclude_HEADERS = \
|
||||
monotime.h \
|
||||
spf_backoff.h \
|
||||
srcdest_table.h \
|
||||
module.h \
|
||||
hook.h \
|
||||
libfrr.h \
|
||||
# end
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#if defined HAVE_SNMP && defined SNMP_AGENTX
|
||||
#ifdef SNMP_AGENTX
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
||||
@ -315,4 +315,4 @@ smux_trap (struct variable *vp, size_t vp_len,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNMP */
|
||||
#endif /* SNMP_AGENTX */
|
||||
|
56
lib/hook.c
Normal file
56
lib/hook.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "hook.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry")
|
||||
|
||||
void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
|
||||
struct frrmod_runtime *module, const char *funcname)
|
||||
{
|
||||
struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he));
|
||||
he->hookfn = funcptr;
|
||||
he->hookarg = arg;
|
||||
he->has_arg = has_arg;
|
||||
he->module = module;
|
||||
he->fnname = funcname;
|
||||
|
||||
he->next = hook->entries;
|
||||
hook->entries = he;
|
||||
}
|
||||
|
||||
void _hook_unregister(struct hook *hook, void *funcptr,
|
||||
void *arg, bool has_arg)
|
||||
{
|
||||
struct hookent *he, **prev;
|
||||
|
||||
for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next)
|
||||
if (he->hookfn == funcptr && he->hookarg == arg
|
||||
&& he->has_arg == has_arg)
|
||||
{
|
||||
*prev = he->next;
|
||||
XFREE(MTYPE_HOOK_ENTRY, he);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
187
lib/hook.h
Normal file
187
lib/hook.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_HOOK_H
|
||||
#define _FRR_HOOK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* type-safe subscribable hook points
|
||||
*
|
||||
* where "type-safe" applies to the function pointers used for subscriptions
|
||||
*
|
||||
* overall usage:
|
||||
* - to create a hook:
|
||||
*
|
||||
* mydaemon.h:
|
||||
* #include "hook.h"
|
||||
* DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
*
|
||||
* mydaemon.c:
|
||||
* DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
* ...
|
||||
* hook_call (some_update_event, info)
|
||||
*
|
||||
* Note: the second and third macro args must be the hook function's
|
||||
* parameter list, with the same names for each parameter. The second
|
||||
* macro arg is with types (used for defining things), the third arg is
|
||||
* just the names (used for passing along parameters).
|
||||
*
|
||||
* Do not use parameter names starting with "hook", these can collide with
|
||||
* names used by the hook code itself.
|
||||
*
|
||||
* The return value is always "int" for now; hook_call will sum up the
|
||||
* return values from each registered user. Default is 0.
|
||||
*
|
||||
* There are no pre-defined semantics for the value, in most cases it is
|
||||
* ignored. For success/failure indication, 0 should be success, and
|
||||
* handlers should make sure to only return 0 or 1 (not -1 or other values).
|
||||
*
|
||||
*
|
||||
* - to use a hook / create a handler:
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (struct eventinfo *info) { ... }
|
||||
* hook_register (some_update_event, event_handler);
|
||||
*
|
||||
* or, if you need an argument to be passed along (addonptr will be added
|
||||
* as first argument when calling the handler):
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (void *addonptr, struct eventinfo *info) { ... }
|
||||
* hook_register_arg (some_update_event, event_handler, addonptr);
|
||||
*
|
||||
* (addonptr isn't typesafe, but that should be manageable.)
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - hook_unregister_all_module()
|
||||
* - introspection / CLI / debug
|
||||
* - testcases ;)
|
||||
*
|
||||
* For loadable modules, the idea is that hooks could be automatically
|
||||
* unregistered when a module is unloaded.
|
||||
*
|
||||
* It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK,
|
||||
* which would make it possible for the CLI to show all hooks and all
|
||||
* registered handlers.
|
||||
*/
|
||||
|
||||
struct hookent {
|
||||
struct hookent *next;
|
||||
void *hookfn; /* actually a function pointer */
|
||||
void *hookarg;
|
||||
bool has_arg;
|
||||
struct frrmod_runtime *module;
|
||||
const char *fnname;
|
||||
};
|
||||
|
||||
struct hook {
|
||||
const char *name;
|
||||
struct hookent *entries;
|
||||
};
|
||||
|
||||
/* subscribe/add callback function to a hook
|
||||
*
|
||||
* always use hook_register(), which uses the static inline helper from
|
||||
* DECLARE_HOOK in order to get type safety
|
||||
*/
|
||||
extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg, struct frrmod_runtime *module,
|
||||
const char *funcname);
|
||||
#define hook_register(hookname, func) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), \
|
||||
NULL, false, THIS_MODULE, #func)
|
||||
#define hook_register_arg(hookname, func, arg) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), \
|
||||
arg, true, THIS_MODULE, #func)
|
||||
|
||||
extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg);
|
||||
#define hook_unregister(hookname, func) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), NULL, false)
|
||||
#define hook_unregister_arg(hookname, func, arg) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), arg, true)
|
||||
|
||||
/* invoke hooks
|
||||
* this is private (static) to the file that has the DEFINE_HOOK statement
|
||||
*/
|
||||
#define hook_call(hookname, ...) \
|
||||
hook_call_ ## hookname (__VA_ARGS__)
|
||||
|
||||
/* helpers to add the void * arg */
|
||||
#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__)
|
||||
#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__)
|
||||
|
||||
/* use in header file - declares the hook and its arguments
|
||||
* usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2))
|
||||
* as above, "passlist" must use the same order and same names as "arglist"
|
||||
*
|
||||
* theoretically passlist is not neccessary, but let's keep things simple and
|
||||
* use exact same args on DECLARE and DEFINE.
|
||||
*/
|
||||
#define DECLARE_HOOK(hookname, arglist, passlist) \
|
||||
extern struct hook _hook_ ## hookname; \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_ ## hookname ( \
|
||||
int (*funcptr) arglist) { \
|
||||
return (void *)funcptr; } \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_arg_ ## hookname ( \
|
||||
int (*funcptr) HOOK_ADDDEF arglist) { \
|
||||
return (void *)funcptr; }
|
||||
|
||||
/* use in source file - contains hook-related definitions.
|
||||
*/
|
||||
#define DEFINE_HOOK(hookname, arglist, passlist) \
|
||||
struct hook _hook_ ## hookname = { \
|
||||
.name = #hookname, \
|
||||
.entries = NULL, \
|
||||
}; \
|
||||
static int hook_call_ ## hookname arglist { \
|
||||
int hooksum = 0; \
|
||||
struct hookent *he = _hook_ ## hookname .entries; \
|
||||
void *hookarg; \
|
||||
union { \
|
||||
void *voidptr; \
|
||||
int (*fptr) arglist; \
|
||||
int (*farg) HOOK_ADDDEF arglist; \
|
||||
} hookp; \
|
||||
for (; he; he = he->next) { \
|
||||
hookarg = he->hookarg; \
|
||||
hookp.voidptr = he->hookfn; \
|
||||
if (!he->has_arg) \
|
||||
hooksum += hookp.fptr passlist; \
|
||||
else \
|
||||
hooksum += hookp.farg HOOK_ADDARG passlist; \
|
||||
} \
|
||||
return hooksum; \
|
||||
}
|
||||
|
||||
#endif /* _FRR_HOOK_H */
|
38
lib/libfrr.c
38
lib/libfrr.c
@ -28,6 +28,9 @@
|
||||
#include "memory_vty.h"
|
||||
#include "zclient.h"
|
||||
#include "log_int.h"
|
||||
#include "module.h"
|
||||
|
||||
DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
|
||||
const char frr_sysconfdir[] = SYSCONFDIR;
|
||||
const char frr_vtydir[] = DAEMON_VTY_DIR;
|
||||
@ -64,14 +67,16 @@ static const struct option lo_always[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "daemon", no_argument, NULL, 'd' },
|
||||
{ "module", no_argument, NULL, 'M' },
|
||||
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct optspec os_always = {
|
||||
"hvdi:",
|
||||
"hvdM:",
|
||||
" -h, --help Display this help and exit\n"
|
||||
" -v, --version Print program version\n"
|
||||
" -d, --daemon Runs in daemon mode\n"
|
||||
" -M, --module Load specified module\n"
|
||||
" --vty_socket Override vty socket path\n",
|
||||
lo_always
|
||||
};
|
||||
@ -184,12 +189,18 @@ void frr_help_exit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
struct option_chain {
|
||||
struct option_chain *next;
|
||||
const char *arg;
|
||||
};
|
||||
static struct option_chain *modules = NULL, **modnext = &modules;
|
||||
static int errors = 0;
|
||||
|
||||
static int frr_opt(int opt)
|
||||
{
|
||||
static int vty_port_set = 0;
|
||||
static int vty_addr_set = 0;
|
||||
struct option_chain *oc;
|
||||
char *err;
|
||||
|
||||
switch (opt) {
|
||||
@ -203,6 +214,13 @@ static int frr_opt(int opt)
|
||||
case 'd':
|
||||
di->daemon_mode = 1;
|
||||
break;
|
||||
case 'M':
|
||||
oc = XMALLOC(MTYPE_TMP, sizeof(*oc));
|
||||
oc->arg = optarg;
|
||||
oc->next = NULL;
|
||||
*modnext = oc;
|
||||
modnext = &oc->next;
|
||||
break;
|
||||
case 'i':
|
||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||
return 1;
|
||||
@ -295,9 +313,12 @@ int frr_getopt(int argc, char * const argv[], int *longindex)
|
||||
return opt;
|
||||
}
|
||||
|
||||
static struct thread_master *master;
|
||||
struct thread_master *frr_init(void)
|
||||
{
|
||||
struct thread_master *master;
|
||||
struct option_chain *oc;
|
||||
struct frrmod_runtime *module;
|
||||
char moderr[256];
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
@ -307,6 +328,17 @@ struct thread_master *frr_init(void)
|
||||
zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
|
||||
#endif
|
||||
|
||||
frrmod_init(di->module);
|
||||
while (modules) {
|
||||
modules = (oc = modules)->next;
|
||||
module = frrmod_load(oc->arg, moderr, sizeof(moderr));
|
||||
if (!module) {
|
||||
fprintf(stderr, "%s\n", moderr);
|
||||
exit(1);
|
||||
}
|
||||
XFREE(MTYPE_TMP, oc);
|
||||
}
|
||||
|
||||
zprivs_init(di->privs);
|
||||
|
||||
master = thread_master_create();
|
||||
@ -324,6 +356,8 @@ struct thread_master *frr_init(void)
|
||||
|
||||
void frr_config_fork(void)
|
||||
{
|
||||
hook_call(frr_late_init, master);
|
||||
|
||||
if (di->instance) {
|
||||
snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf",
|
||||
frr_sysconfdir, di->name, di->instance);
|
||||
|
15
lib/libfrr.h
15
lib/libfrr.h
@ -26,6 +26,8 @@
|
||||
#include "thread.h"
|
||||
#include "log.h"
|
||||
#include "getopt.h"
|
||||
#include "module.h"
|
||||
#include "hook.h"
|
||||
|
||||
#define FRR_NO_PRIVSEP (1 << 0)
|
||||
#define FRR_NO_TCPVTY (1 << 1)
|
||||
@ -40,6 +42,7 @@ struct frr_daemon_info {
|
||||
const char *name;
|
||||
const char *logname;
|
||||
unsigned short instance;
|
||||
struct frrmod_runtime *module;
|
||||
|
||||
char *vty_addr;
|
||||
int vty_port;
|
||||
@ -67,15 +70,22 @@ struct frr_daemon_info {
|
||||
* i.e. "ZEBRA" or "BGP"
|
||||
*
|
||||
* note that this macro is also a latch-on point for other changes (e.g.
|
||||
* upcoming plugin support) that need to place some per-daemon things. Each
|
||||
* upcoming module support) that need to place some per-daemon things. Each
|
||||
* daemon should have one of these.
|
||||
*/
|
||||
#define FRR_DAEMON_INFO(execname, constname, ...) \
|
||||
static struct frr_daemon_info execname ##_di = { \
|
||||
.name = # execname, \
|
||||
.logname = # constname, \
|
||||
.module = THIS_MODULE, \
|
||||
__VA_ARGS__ \
|
||||
};
|
||||
}; \
|
||||
FRR_COREMOD_SETUP( \
|
||||
.name = # execname, \
|
||||
.description = # execname " daemon", \
|
||||
.version = FRR_VERSION, \
|
||||
) \
|
||||
/* end */
|
||||
|
||||
extern void frr_preinit(struct frr_daemon_info *daemon,
|
||||
int argc, char **argv);
|
||||
@ -86,6 +96,7 @@ extern void frr_help_exit(int status);
|
||||
|
||||
extern struct thread_master *frr_init(void);
|
||||
|
||||
DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
extern void frr_config_fork(void);
|
||||
|
||||
extern void frr_vty_serv(void);
|
||||
|
@ -1,23 +1,22 @@
|
||||
/*
|
||||
* Memory management routine
|
||||
* Memory and dynamic module VTY routine
|
||||
*
|
||||
* Copyright (C) 1998 Kunihiro Ishiguro
|
||||
* Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc.
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
* 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.
|
||||
*
|
||||
* GNU Zebra 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, 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.
|
||||
*
|
||||
* GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
@ -25,9 +24,12 @@
|
||||
#if (defined(GNU_LINUX) && defined(HAVE_MALLINFO))
|
||||
#include <malloc.h>
|
||||
#endif /* HAVE_MALLINFO */
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "module.h"
|
||||
#include "memory_vty.h"
|
||||
|
||||
/* Looking up memory status from vty interface. */
|
||||
@ -110,10 +112,55 @@ DEFUN (show_memory,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_modules,
|
||||
show_modules_cmd,
|
||||
"show modules",
|
||||
"Show running system information\n"
|
||||
"Loaded modules\n")
|
||||
{
|
||||
struct frrmod_runtime *plug = frrmod_list;
|
||||
|
||||
vty_out (vty, "%-12s %-25s %s%s%s",
|
||||
"Module Name", "Version", "Description",
|
||||
VTY_NEWLINE, VTY_NEWLINE);
|
||||
while (plug)
|
||||
{
|
||||
const struct frrmod_info *i = plug->info;
|
||||
|
||||
vty_out (vty, "%-12s %-25s %s%s", i->name, i->version, i->description,
|
||||
VTY_NEWLINE);
|
||||
if (plug->dl_handle)
|
||||
{
|
||||
#ifdef HAVE_DLINFO_ORIGIN
|
||||
char origin[MAXPATHLEN] = "";
|
||||
dlinfo (plug->dl_handle, RTLD_DI_ORIGIN, &origin);
|
||||
# ifdef HAVE_DLINFO_LINKMAP
|
||||
const char *name;
|
||||
struct link_map *lm = NULL;
|
||||
dlinfo (plug->dl_handle, RTLD_DI_LINKMAP, &lm);
|
||||
if (lm)
|
||||
{
|
||||
name = strrchr(lm->l_name, '/');
|
||||
name = name ? name + 1 : lm->l_name;
|
||||
vty_out (vty, "\tfrom: %s/%s%s", origin, name, VTY_NEWLINE);
|
||||
}
|
||||
# else
|
||||
vty_out (vty, "\tfrom: %s %s", origin, plug->load_name, VTY_NEWLINE);
|
||||
# endif
|
||||
#else
|
||||
vty_out (vty, "\tfrom: %s%s", plug->load_name, VTY_NEWLINE);
|
||||
#endif
|
||||
}
|
||||
plug = plug->next;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
memory_init (void)
|
||||
{
|
||||
install_element (VIEW_NODE, &show_memory_cmd);
|
||||
install_element (VIEW_NODE, &show_modules_cmd);
|
||||
}
|
||||
|
||||
/* Stats querying from users */
|
||||
|
159
lib/module.c
Normal file
159
lib/module.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
#include "version.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name")
|
||||
DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments")
|
||||
|
||||
static struct frrmod_info frrmod_default_info = {
|
||||
.name = "libfrr",
|
||||
.version = FRR_VERSION,
|
||||
.description = "libfrr core module",
|
||||
};
|
||||
union _frrmod_runtime_u frrmod_default = {
|
||||
.r.info = &frrmod_default_info,
|
||||
.r.finished_loading = 1,
|
||||
};
|
||||
|
||||
// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
|
||||
// union _frrmod_runtime_u _frrmod_this_module
|
||||
// __attribute__((weak, alias("frrmod_default")));
|
||||
// elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
|
||||
#pragma weak _frrmod_this_module = frrmod_default
|
||||
// else
|
||||
// error need weak symbol support
|
||||
// endif
|
||||
|
||||
struct frrmod_runtime *frrmod_list = &frrmod_default.r;
|
||||
static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
|
||||
static const char *execname = NULL;
|
||||
|
||||
void frrmod_init(struct frrmod_runtime *modinfo)
|
||||
{
|
||||
modinfo->finished_loading = 1;
|
||||
*frrmod_last = modinfo;
|
||||
frrmod_last = &modinfo->next;
|
||||
|
||||
execname = modinfo->info->name;
|
||||
}
|
||||
|
||||
struct frrmod_runtime *frrmod_load(const char *spec,
|
||||
char *err, size_t err_len)
|
||||
{
|
||||
void *handle = NULL;
|
||||
char name[PATH_MAX], fullpath[PATH_MAX], *args;
|
||||
struct frrmod_runtime *rtinfo, **rtinfop;
|
||||
const struct frrmod_info *info;
|
||||
|
||||
snprintf(name, sizeof(name), "%s", spec);
|
||||
args = strchr(name, ':');
|
||||
if (args)
|
||||
*args++ = '\0';
|
||||
|
||||
if (!strchr(name, '/')) {
|
||||
if (!handle && execname) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so",
|
||||
MODULE_PATH, execname, name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
if (!handle) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/%s.so",
|
||||
MODULE_PATH, name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
}
|
||||
if (!handle) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s", name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
if (!handle) {
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"loading module \"%s\" failed: %s",
|
||||
name, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtinfop = dlsym(handle, "frr_module");
|
||||
if (!rtinfop) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"\"%s\" is not a Quagga module: %s",
|
||||
name, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
rtinfo = *rtinfop;
|
||||
rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
|
||||
rtinfo->dl_handle = handle;
|
||||
if (args)
|
||||
rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
|
||||
info = rtinfo->info;
|
||||
|
||||
if (rtinfo->finished_loading) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"module \"%s\" already loaded",
|
||||
name);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (info->init && info->init()) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"module \"%s\" initialisation failed",
|
||||
name);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
rtinfo->finished_loading = 1;
|
||||
|
||||
*frrmod_last = rtinfo;
|
||||
frrmod_last = &rtinfo->next;
|
||||
return rtinfo;
|
||||
|
||||
out_fail:
|
||||
if (rtinfo->load_args)
|
||||
XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
|
||||
XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void frrmod_unload(struct frrmod_runtime *module)
|
||||
{
|
||||
}
|
||||
#endif
|
104
lib/module.h
Normal file
104
lib/module.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_MODULE_H
|
||||
#define _FRR_MODULE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
# error module code needs GCC visibility extensions
|
||||
#elif __GNUC__ < 4
|
||||
# error module code needs GCC visibility extensions
|
||||
#else
|
||||
# define DSO_PUBLIC __attribute__ ((visibility ("default")))
|
||||
# define DSO_SELF __attribute__ ((visibility ("protected")))
|
||||
# define DSO_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
|
||||
struct frrmod_runtime;
|
||||
|
||||
struct frrmod_info {
|
||||
/* single-line few-word title */
|
||||
const char *name;
|
||||
/* human-readable version number, should not contain spaces */
|
||||
const char *version;
|
||||
/* one-paragraph description */
|
||||
const char *description;
|
||||
|
||||
int (*init)(void);
|
||||
};
|
||||
|
||||
/* primary entry point structure to be present in loadable module under
|
||||
* "_frrmod_this_module" dlsym() name
|
||||
*
|
||||
* note space for future extensions is reserved below, so other modules
|
||||
* (e.g. memory management, hooks) can add fields
|
||||
*
|
||||
* const members/info are in frrmod_info.
|
||||
*/
|
||||
struct frrmod_runtime {
|
||||
struct frrmod_runtime *next;
|
||||
|
||||
const struct frrmod_info *info;
|
||||
void *dl_handle;
|
||||
bool finished_loading;
|
||||
|
||||
char *load_name;
|
||||
char *load_args;
|
||||
};
|
||||
|
||||
/* space-reserving foo */
|
||||
struct _frrmod_runtime_size {
|
||||
struct frrmod_runtime r;
|
||||
/* this will barf if frrmod_runtime exceeds 1024 bytes ... */
|
||||
uint8_t space[1024 - sizeof(struct frrmod_runtime)];
|
||||
};
|
||||
union _frrmod_runtime_u {
|
||||
struct frrmod_runtime r;
|
||||
struct _frrmod_runtime_size s;
|
||||
};
|
||||
|
||||
extern union _frrmod_runtime_u _frrmod_this_module;
|
||||
#define THIS_MODULE (&_frrmod_this_module.r)
|
||||
|
||||
#define FRR_COREMOD_SETUP(...) \
|
||||
static const struct frrmod_info _frrmod_info = { __VA_ARGS__ }; \
|
||||
DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \
|
||||
.r.info = &_frrmod_info, \
|
||||
};
|
||||
#define FRR_MODULE_SETUP(...) \
|
||||
FRR_COREMOD_SETUP(__VA_ARGS__) \
|
||||
DSO_SELF struct frrmod_runtime *frr_module = &_frrmod_this_module.r;
|
||||
|
||||
extern struct frrmod_runtime *frrmod_list;
|
||||
|
||||
extern void frrmod_init(struct frrmod_runtime *modinfo);
|
||||
extern struct frrmod_runtime *frrmod_load(const char *spec,
|
||||
char *err, size_t err_len);
|
||||
#if 0
|
||||
/* not implemented yet */
|
||||
extern void frrmod_unload(struct frrmod_runtime *module);
|
||||
#endif
|
||||
|
||||
#endif /* _FRR_MODULE_H */
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#if defined HAVE_SNMP && defined SNMP_SMUX
|
||||
#ifdef SNMP_SMUX
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -1445,4 +1445,4 @@ smux_start(void)
|
||||
/* Schedule first connection. */
|
||||
smux_event (SMUX_SCHEDULE, 0);
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
#endif /* SNMP_SMUX */
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -130,4 +129,3 @@ smux_header_table (struct variable *v, oid *name, size_t *length, int exact,
|
||||
|
||||
return MATCH_SUCCEEDED;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
22
lib/thread.c
22
lib/thread.c
@ -1037,28 +1037,6 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa
|
||||
|
||||
#if defined(HAVE_POLL)
|
||||
|
||||
#if defined(HAVE_SNMP)
|
||||
/* add snmp fds to poll set */
|
||||
static void
|
||||
add_snmp_pollfds(struct thread_master *m, fd_set *snmpfds, int fdsetsize)
|
||||
{
|
||||
int i;
|
||||
m->handler.pfdcountsnmp = m->handler.pfdcount;
|
||||
/* cycle trough fds and add neccessary fds to poll set */
|
||||
for (i=0;i<fdsetsize;++i)
|
||||
{
|
||||
if (FD_ISSET(i, snmpfds))
|
||||
{
|
||||
assert (m->handler.pfdcountsnmp <= m->handler.pfdsize);
|
||||
|
||||
m->handler.pfds[m->handler.pfdcountsnmp].fd = i;
|
||||
m->handler.pfds[m->handler.pfdcountsnmp].events = POLLIN;
|
||||
m->handler.pfdcountsnmp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check poll events */
|
||||
static void
|
||||
check_pollfds(struct thread_master *m, fd_set *readfd, int num)
|
||||
|
@ -7,6 +7,7 @@ INSTALL_SDATA=@INSTALL@ -m 600
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
noinst_LIBRARIES = libospf6.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = ospf6d
|
||||
|
||||
libospf6_a_SOURCES = \
|
||||
@ -14,7 +15,7 @@ libospf6_a_SOURCES = \
|
||||
ospf6_network.c ospf6_message.c ospf6_lsa.c ospf6_lsdb.c \
|
||||
ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \
|
||||
ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \
|
||||
ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \
|
||||
ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c \
|
||||
ospf6d.c ospf6_bfd.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
@ -22,7 +23,7 @@ noinst_HEADERS = \
|
||||
ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \
|
||||
ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \
|
||||
ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \
|
||||
ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \
|
||||
ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h \
|
||||
ospf6d.h ospf6_bfd.h
|
||||
|
||||
ospf6d_SOURCES = \
|
||||
@ -30,5 +31,12 @@ ospf6d_SOURCES = \
|
||||
|
||||
ospf6d_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += ospf6d_snmp.la
|
||||
endif
|
||||
ospf6d_snmp_la_SOURCES = ospf6_snmp.c
|
||||
ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
ospf6d_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = ospf6d.conf.sample
|
||||
|
@ -41,12 +41,14 @@
|
||||
#include "ospf6_neighbor.h"
|
||||
#include "ospf6_intra.h"
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_snmp.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names")
|
||||
DEFINE_QOBJ_TYPE(ospf6_interface)
|
||||
DEFINE_HOOK(ospf6_interface_change,
|
||||
(struct ospf6_interface *oi, int state, int old_state),
|
||||
(oi, state, old_state))
|
||||
|
||||
unsigned char conf_debug_ospf6_interface = 0;
|
||||
|
||||
@ -518,16 +520,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == OSPF6_INTERFACE_POINTTOPOINT) ||
|
||||
(next_state == OSPF6_INTERFACE_DROTHER) ||
|
||||
(next_state == OSPF6_INTERFACE_BDR) ||
|
||||
(next_state == OSPF6_INTERFACE_DR) ||
|
||||
(next_state < prev_state))
|
||||
ospf6TrapIfStateChange (oi);
|
||||
#endif
|
||||
|
||||
hook_call(ospf6_interface_change, oi, next_state, prev_state);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define OSPF6_INTERFACE_H
|
||||
|
||||
#include "qobj.h"
|
||||
#include "hook.h"
|
||||
#include "if.h"
|
||||
|
||||
/* Debug option */
|
||||
@ -182,4 +183,8 @@ extern void install_element_ospf6_clear_interface (void);
|
||||
extern int config_write_ospf6_debug_interface (struct vty *vty);
|
||||
extern void install_element_ospf6_debug_interface (void);
|
||||
|
||||
DECLARE_HOOK(ospf6_interface_change,
|
||||
(struct ospf6_interface *oi, int state, int old_state),
|
||||
(oi, state, old_state))
|
||||
|
||||
#endif /* OSPF6_INTERFACE_H */
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "ospf6_neighbor.h"
|
||||
#include "ospf6_intra.h"
|
||||
#include "ospf6_flood.h"
|
||||
#include "ospf6_snmp.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
#include "ospf6_abr.h"
|
||||
@ -47,6 +46,10 @@
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_zebra.h"
|
||||
|
||||
DEFINE_HOOK(ospf6_neighbor_change,
|
||||
(struct ospf6_neighbor *on, int state, int next_state),
|
||||
(on, state, next_state))
|
||||
|
||||
unsigned char conf_debug_ospf6_neighbor = 0;
|
||||
|
||||
const char *ospf6_neighbor_state_str[] =
|
||||
@ -202,13 +205,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e
|
||||
next_state != OSPF6_NEIGHBOR_LOADING))
|
||||
ospf6_maxage_remove (on->ospf6_if->area->ospf6);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == OSPF6_NEIGHBOR_FULL) ||
|
||||
(next_state == OSPF6_NEIGHBOR_TWOWAY) ||
|
||||
(next_state < prev_state))
|
||||
ospf6TrapNbrStateChange (on);
|
||||
#endif
|
||||
hook_call(ospf6_neighbor_change, on, next_state, prev_state);
|
||||
ospf6_bfd_trigger_event(on, prev_state, next_state);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef OSPF6_NEIGHBOR_H
|
||||
#define OSPF6_NEIGHBOR_H
|
||||
|
||||
#include "hook.h"
|
||||
|
||||
/* Debug option */
|
||||
extern unsigned char conf_debug_ospf6_neighbor;
|
||||
#define OSPF6_DEBUG_NEIGHBOR_STATE 0x01
|
||||
@ -179,4 +181,8 @@ extern void ospf6_neighbor_init (void);
|
||||
extern int config_write_ospf6_debug_neighbor (struct vty *vty);
|
||||
extern void install_element_ospf6_debug_neighbor (void);
|
||||
|
||||
DECLARE_HOOK(ospf6_neighbor_change,
|
||||
(struct ospf6_neighbor *on, int state, int next_state),
|
||||
(on, state, next_state))
|
||||
|
||||
#endif /* OSPF6_NEIGHBOR_H */
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -32,6 +30,8 @@
|
||||
#include "vector.h"
|
||||
#include "vrf.h"
|
||||
#include "smux.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_lsa.h"
|
||||
@ -45,7 +45,6 @@
|
||||
#include "ospf6_abr.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_snmp.h"
|
||||
|
||||
/* OSPFv3-MIB */
|
||||
#define OSPFv3MIB 1,3,6,1,2,1,191
|
||||
@ -1139,11 +1138,18 @@ static struct trap_object ospf6IfTrapList[] =
|
||||
{4, {1, 7, 1, OSPFv3IFAREAID}}
|
||||
};
|
||||
|
||||
void
|
||||
ospf6TrapNbrStateChange (struct ospf6_neighbor *on)
|
||||
static int
|
||||
ospf6TrapNbrStateChange (struct ospf6_neighbor *on,
|
||||
int next_state, int prev_state)
|
||||
{
|
||||
oid index[3];
|
||||
|
||||
/* Terminal state or regression */
|
||||
if ((next_state != OSPF6_NEIGHBOR_FULL) &&
|
||||
(next_state != OSPF6_NEIGHBOR_TWOWAY) &&
|
||||
(next_state >= prev_state))
|
||||
return 0;
|
||||
|
||||
index[0] = on->ospf6_if->interface->ifindex;
|
||||
index[1] = on->ospf6_if->instance_id;
|
||||
index[2] = ntohl (on->router_id);
|
||||
@ -1155,13 +1161,23 @@ ospf6TrapNbrStateChange (struct ospf6_neighbor *on)
|
||||
ospf6NbrTrapList,
|
||||
sizeof ospf6NbrTrapList / sizeof (struct trap_object),
|
||||
NBRSTATECHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6TrapIfStateChange (struct ospf6_interface *oi)
|
||||
static int
|
||||
ospf6TrapIfStateChange (struct ospf6_interface *oi,
|
||||
int next_state, int prev_state)
|
||||
{
|
||||
oid index[2];
|
||||
|
||||
/* Terminal state or regression */
|
||||
if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) &&
|
||||
(next_state != OSPF6_INTERFACE_DROTHER) &&
|
||||
(next_state != OSPF6_INTERFACE_BDR) &&
|
||||
(next_state != OSPF6_INTERFACE_DR) &&
|
||||
(next_state >= prev_state))
|
||||
return 0;
|
||||
|
||||
index[0] = oi->interface->ifindex;
|
||||
index[1] = oi->instance_id;
|
||||
|
||||
@ -1172,15 +1188,30 @@ ospf6TrapIfStateChange (struct ospf6_interface *oi)
|
||||
ospf6IfTrapList,
|
||||
sizeof ospf6IfTrapList / sizeof (struct trap_object),
|
||||
IFSTATECHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register OSPFv3-MIB. */
|
||||
void
|
||||
static int
|
||||
ospf6_snmp_init (struct thread_master *master)
|
||||
{
|
||||
smux_init (master);
|
||||
REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNMP */
|
||||
static int
|
||||
ospf6_snmp_module_init (void)
|
||||
{
|
||||
hook_register(ospf6_interface_change, ospf6TrapIfStateChange);
|
||||
hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange);
|
||||
hook_register(frr_late_init, ospf6_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "ospf6d_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "ospf6d AgentX SNMP module",
|
||||
.init = ospf6_snmp_module_init,
|
||||
)
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* OSPFv3 SNMP support
|
||||
* Copyright (C) 2004 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef OSPF6_SNMP_H
|
||||
#define OSPF6_SNMP_H
|
||||
|
||||
extern void ospf6TrapNbrStateChange (struct ospf6_neighbor *);
|
||||
extern void ospf6TrapIfStateChange (struct ospf6_interface *);
|
||||
extern void ospf6_snmp_init (struct thread_master *);
|
||||
|
||||
#endif /*OSPF6_SNMP_H*/
|
||||
|
||||
|
@ -45,10 +45,6 @@
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include "ospf6_snmp.h"
|
||||
#endif /*HAVE_SNMP*/
|
||||
|
||||
char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION;
|
||||
|
||||
struct route_node *
|
||||
@ -1215,10 +1211,6 @@ ospf6_init (void)
|
||||
ospf6_asbr_init ();
|
||||
ospf6_abr_init ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf6_snmp_init (master);
|
||||
#endif /*HAVE_SNMP*/
|
||||
|
||||
ospf6_bfd_init();
|
||||
install_node (&debug_node, config_write_ospf6_debug);
|
||||
|
||||
|
@ -6,13 +6,14 @@ DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
noinst_LIBRARIES = libfrrospf.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = ospfd
|
||||
|
||||
libfrrospf_a_SOURCES = \
|
||||
ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \
|
||||
ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
|
||||
ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
|
||||
ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
|
||||
ospf_lsdb.c ospf_asbr.c ospf_routemap.c \
|
||||
ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \
|
||||
ospf_bfd.c ospf_memory.c ospf_dump_api.c
|
||||
|
||||
@ -26,13 +27,20 @@ ospfdheader_HEADERS = \
|
||||
noinst_HEADERS = \
|
||||
ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \
|
||||
ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \
|
||||
ospf_flood.h ospf_snmp.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \
|
||||
ospf_flood.h ospf_te.h ospf_ri.h ospf_vty.h ospf_apiserver.h \
|
||||
ospf_bfd.h ospf_memory.h
|
||||
|
||||
ospfd_SOURCES = ospf_main.c
|
||||
|
||||
ospfd_LDADD = libfrrospf.a ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += ospfd_snmp.la
|
||||
endif
|
||||
ospfd_snmp_la_SOURCES = ospf_snmp.c
|
||||
ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
ospfd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
EXTRA_DIST = OSPF-MIB.txt OSPF-TRAP-MIB.txt ChangeLog.opaque.txt
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
|
@ -47,11 +47,10 @@
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_network.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "ospfd/ospf_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
DEFINE_QOBJ_TYPE(ospf_interface)
|
||||
DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd))
|
||||
DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd))
|
||||
|
||||
int
|
||||
ospf_if_get_output_cost (struct ospf_interface *oi)
|
||||
@ -993,9 +992,7 @@ void
|
||||
ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data)
|
||||
{
|
||||
listnode_add (ospf->vlinks, vl_data);
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_vl_add (vl_data);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_vl_add, vl_data);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1004,9 +1001,7 @@ ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data)
|
||||
ospf_vl_shutdown (vl_data);
|
||||
ospf_vl_if_delete (vl_data);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_vl_delete (vl_data);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_vl_delete, vl_data);
|
||||
listnode_delete (ospf->vlinks, vl_data);
|
||||
|
||||
ospf_vl_data_free (vl_data);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define _ZEBRA_OSPF_INTERFACE_H
|
||||
|
||||
#include "qobj.h"
|
||||
#include "hook.h"
|
||||
#include "ospfd/ospf_packet.h"
|
||||
#include "ospfd/ospf_spf.h"
|
||||
|
||||
@ -309,4 +310,7 @@ extern u_char ospf_default_iftype (struct interface *ifp);
|
||||
state of the interface. */
|
||||
extern void ospf_if_set_multicast (struct ospf_interface *);
|
||||
|
||||
DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd))
|
||||
DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd))
|
||||
|
||||
#endif /* _ZEBRA_OSPF_INTERFACE_H */
|
||||
|
@ -43,7 +43,10 @@
|
||||
#include "ospfd/ospf_packet.h"
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_snmp.h"
|
||||
|
||||
DEFINE_HOOK(ospf_ism_change,
|
||||
(struct ospf_interface *oi, int state, int oldstate),
|
||||
(oi, state, oldstate))
|
||||
|
||||
/* elect DR and BDR. Refer to RFC2319 section 9.4 */
|
||||
static struct ospf_neighbor *
|
||||
@ -545,19 +548,7 @@ ism_change_state (struct ospf_interface *oi, int state)
|
||||
oi->state = state;
|
||||
oi->state_change++;
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
/* Terminal state or regression */
|
||||
if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) ||
|
||||
(state == ISM_PointToPoint) || (state < old_state))
|
||||
{
|
||||
/* ospfVirtIfStateChange */
|
||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
ospfTrapVirtIfStateChange (oi);
|
||||
/* ospfIfStateChange */
|
||||
else
|
||||
ospfTrapIfStateChange (oi);
|
||||
}
|
||||
#endif
|
||||
hook_call(ospf_ism_change, oi, state, old_state);
|
||||
|
||||
/* Set multicast memberships appropriately for new state. */
|
||||
ospf_if_set_multicast(oi);
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef _ZEBRA_OSPF_ISM_H
|
||||
#define _ZEBRA_OSPF_ISM_H
|
||||
|
||||
#include "hook.h"
|
||||
|
||||
/* OSPF Interface State Machine Status. */
|
||||
#define ISM_DependUpon 0
|
||||
#define ISM_Down 1
|
||||
@ -35,10 +37,6 @@
|
||||
#define ISM_DR 7
|
||||
#define OSPF_ISM_STATE_MAX 8
|
||||
|
||||
/* Because DR/DROther values are exhanged wrt RFC */
|
||||
#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \
|
||||
((x) == ISM_DR) ? ISM_DROther : (x))
|
||||
|
||||
/* OSPF Interface State Machine Event. */
|
||||
#define ISM_NoEvent 0
|
||||
#define ISM_InterfaceUp 1
|
||||
@ -111,4 +109,8 @@ extern int ospf_ism_event (struct thread *);
|
||||
extern void ism_change_status (struct ospf_interface *, int);
|
||||
extern int ospf_hello_timer (struct thread *thread);
|
||||
|
||||
DECLARE_HOOK(ospf_ism_change,
|
||||
(struct ospf_interface *oi, int state, int oldstate),
|
||||
(oi, state, oldstate))
|
||||
|
||||
#endif /* _ZEBRA_OSPF_ISM_H */
|
||||
|
@ -225,9 +225,6 @@ main (int argc, char **argv)
|
||||
ospf_bfd_init();
|
||||
|
||||
ospf_route_map_init ();
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
ospf_opaque_init ();
|
||||
|
||||
/* Need to initialize the default ospf structure, so the interface mode
|
||||
|
@ -48,9 +48,12 @@
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_snmp.h"
|
||||
#include "ospfd/ospf_bfd.h"
|
||||
|
||||
DEFINE_HOOK(ospf_nsm_change,
|
||||
(struct ospf_neighbor *on, int state, int oldstate),
|
||||
(on, state, oldstate))
|
||||
|
||||
static void nsm_clear_adj (struct ospf_neighbor *);
|
||||
|
||||
/* OSPF NSM Timer functions. */
|
||||
@ -838,35 +841,12 @@ ospf_nsm_event (struct thread *thread)
|
||||
/* If state is changed. */
|
||||
if (next_state != nbr->state)
|
||||
{
|
||||
int old_state = nbr->state;
|
||||
|
||||
nsm_notice_state_change (nbr, next_state, event);
|
||||
#ifdef HAVE_SNMP
|
||||
int send_trap_virt = 0;
|
||||
int send_trap = 0;
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == NSM_Full)
|
||||
|| (next_state == NSM_TwoWay)
|
||||
|| (next_state < nbr->state))
|
||||
{
|
||||
/* ospfVirtNbrStateChange */
|
||||
if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
send_trap_virt = 1;
|
||||
/* ospfNbrStateChange trap */
|
||||
else
|
||||
/* To/From FULL, only managed by DR */
|
||||
if (((next_state != NSM_Full) && (nbr->state != NSM_Full))
|
||||
|| (nbr->oi->state == ISM_DR))
|
||||
send_trap = 1;
|
||||
}
|
||||
#endif
|
||||
nsm_change_state (nbr, next_state);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
if (send_trap_virt) {
|
||||
ospfTrapVirtNbrStateChange(nbr);
|
||||
} else if (send_trap) {
|
||||
ospfTrapNbrStateChange(nbr);
|
||||
}
|
||||
#endif
|
||||
hook_call(ospf_nsm_change, nbr, next_state, old_state);
|
||||
}
|
||||
|
||||
/* Make sure timer is set. */
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef _ZEBRA_OSPF_NSM_H
|
||||
#define _ZEBRA_OSPF_NSM_H
|
||||
|
||||
#include "hook.h"
|
||||
|
||||
/* OSPF Neighbor State Machine State. */
|
||||
#define NSM_DependUpon 0
|
||||
#define NSM_Deleted 1
|
||||
@ -86,5 +88,9 @@ extern int ospf_db_summary_isempty (struct ospf_neighbor *);
|
||||
extern int ospf_db_summary_count (struct ospf_neighbor *);
|
||||
extern void ospf_db_summary_clear (struct ospf_neighbor *);
|
||||
|
||||
DECLARE_HOOK(ospf_nsm_change,
|
||||
(struct ospf_neighbor *on, int state, int oldstate),
|
||||
(on, state, oldstate))
|
||||
|
||||
#endif /* _ZEBRA_OSPF_NSM_H */
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -35,6 +34,8 @@
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "smux.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_interface.h"
|
||||
@ -47,7 +48,7 @@
|
||||
#include "ospfd/ospf_flood.h"
|
||||
#include "ospfd/ospf_ism.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_snmp.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
|
||||
/* OSPF2-MIB. */
|
||||
#define OSPF2MIB 1,3,6,1,2,1,14
|
||||
@ -205,6 +206,10 @@
|
||||
#define IPADDRESS ASN_IPADDRESS
|
||||
#define STRING ASN_OCTET_STR
|
||||
|
||||
/* Because DR/DROther values are exhanged wrt RFC */
|
||||
#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \
|
||||
((x) == ISM_DR) ? ISM_DROther : (x))
|
||||
|
||||
/* Declare static local variables for convenience. */
|
||||
SNMP_LOCAL_VARIABLES
|
||||
|
||||
@ -1429,7 +1434,7 @@ ospf_snmp_if_free (struct ospf_snmp_if *osif)
|
||||
XFREE (MTYPE_TMP, osif);
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
ospf_snmp_if_delete (struct interface *ifp)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
@ -1441,12 +1446,13 @@ ospf_snmp_if_delete (struct interface *ifp)
|
||||
{
|
||||
list_delete_node (ospf_snmp_iflist, node);
|
||||
ospf_snmp_if_free (osif);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
ospf_snmp_if_update (struct interface *ifp)
|
||||
{
|
||||
struct listnode *node;
|
||||
@ -1511,6 +1517,7 @@ ospf_snmp_if_update (struct interface *ifp)
|
||||
osif->ifp = ifp;
|
||||
|
||||
listnode_add_after (ospf_snmp_iflist, pn, osif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1914,7 +1921,7 @@ ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact,
|
||||
|
||||
static struct route_table *ospf_snmp_vl_table;
|
||||
|
||||
void
|
||||
static int
|
||||
ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
|
||||
{
|
||||
struct prefix_ls lp;
|
||||
@ -1931,9 +1938,10 @@ ospf_snmp_vl_add (struct ospf_vl_data *vl_data)
|
||||
route_unlock_node (rn);
|
||||
|
||||
rn->info = vl_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
|
||||
{
|
||||
struct prefix_ls lp;
|
||||
@ -1947,10 +1955,11 @@ ospf_snmp_vl_delete (struct ospf_vl_data *vl_data)
|
||||
|
||||
rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp);
|
||||
if (! rn)
|
||||
return;
|
||||
return 0;
|
||||
rn->info = NULL;
|
||||
route_unlock_node (rn);
|
||||
route_unlock_node (rn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ospf_vl_data *
|
||||
@ -2651,7 +2660,7 @@ static struct trap_object ospfVirtIfTrapList[] =
|
||||
{3, {9, 1, OSPFVIRTIFSTATE}}
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
ospfTrapNbrStateChange (struct ospf_neighbor *on)
|
||||
{
|
||||
oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
|
||||
@ -2673,7 +2682,7 @@ ospfTrapNbrStateChange (struct ospf_neighbor *on)
|
||||
NBRSTATECHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ospfTrapVirtNbrStateChange (struct ospf_neighbor *on)
|
||||
{
|
||||
oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
|
||||
@ -2692,7 +2701,29 @@ ospfTrapVirtNbrStateChange (struct ospf_neighbor *on)
|
||||
VIRTNBRSTATECHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
ospf_snmp_nsm_change (struct ospf_neighbor *nbr,
|
||||
int next_state, int old_state)
|
||||
{
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == NSM_Full)
|
||||
|| (next_state == NSM_TwoWay)
|
||||
|| (next_state < old_state))
|
||||
{
|
||||
/* ospfVirtNbrStateChange */
|
||||
if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
ospfTrapVirtNbrStateChange(nbr);
|
||||
/* ospfNbrStateChange trap */
|
||||
else
|
||||
/* To/From FULL, only managed by DR */
|
||||
if (((next_state != NSM_Full) && (nbr->state != NSM_Full))
|
||||
|| (nbr->oi->state == ISM_DR))
|
||||
ospfTrapNbrStateChange(nbr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ospfTrapIfStateChange (struct ospf_interface *oi)
|
||||
{
|
||||
oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
|
||||
@ -2713,7 +2744,7 @@ ospfTrapIfStateChange (struct ospf_interface *oi)
|
||||
IFSTATECHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ospfTrapVirtIfStateChange (struct ospf_interface *oi)
|
||||
{
|
||||
oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)];
|
||||
@ -2731,13 +2762,53 @@ ospfTrapVirtIfStateChange (struct ospf_interface *oi)
|
||||
sizeof ospfVirtIfTrapList / sizeof (struct trap_object),
|
||||
VIRTIFSTATECHANGE);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf_snmp_ism_change (struct ospf_interface *oi,
|
||||
int state, int old_state)
|
||||
{
|
||||
/* Terminal state or regression */
|
||||
if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) ||
|
||||
(state == ISM_PointToPoint) || (state < old_state))
|
||||
{
|
||||
/* ospfVirtIfStateChange */
|
||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
ospfTrapVirtIfStateChange (oi);
|
||||
/* ospfIfStateChange */
|
||||
else
|
||||
ospfTrapIfStateChange (oi);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register OSPF2-MIB. */
|
||||
void
|
||||
ospf_snmp_init ()
|
||||
static int
|
||||
ospf_snmp_init (struct thread_master *tm)
|
||||
{
|
||||
ospf_snmp_iflist = list_new ();
|
||||
ospf_snmp_vl_table = route_table_init ();
|
||||
smux_init (om->master);
|
||||
smux_init (tm);
|
||||
REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
ospf_snmp_module_init (void)
|
||||
{
|
||||
hook_register(ospf_if_update, ospf_snmp_if_update);
|
||||
hook_register(ospf_if_delete, ospf_snmp_if_delete);
|
||||
hook_register(ospf_vl_add, ospf_snmp_vl_add);
|
||||
hook_register(ospf_vl_delete, ospf_snmp_vl_delete);
|
||||
hook_register(ospf_ism_change, ospf_snmp_ism_change);
|
||||
hook_register(ospf_nsm_change, ospf_snmp_nsm_change);
|
||||
|
||||
hook_register(frr_late_init, ospf_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "ospfd_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "ospfd AgentX SNMP module",
|
||||
.init = ospf_snmp_module_init,
|
||||
)
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* OSPFv2 SNMP support
|
||||
* Copyright (C) 2000 IP Infusion Inc.
|
||||
*
|
||||
* Written by Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_OSPF_SNMP_H
|
||||
#define _ZEBRA_OSPF_SNMP_H
|
||||
|
||||
extern void ospf_snmp_if_update (struct interface *);
|
||||
extern void ospf_snmp_if_delete (struct interface *);
|
||||
|
||||
extern void ospf_snmp_vl_add (struct ospf_vl_data *);
|
||||
extern void ospf_snmp_vl_delete (struct ospf_vl_data *);
|
||||
|
||||
extern void ospfTrapIfStateChange (struct ospf_interface *);
|
||||
extern void ospfTrapVirtIfStateChange (struct ospf_interface *);
|
||||
extern void ospfTrapNbrStateChange (struct ospf_neighbor *);
|
||||
extern void ospfTrapVirtNbrStateChange (struct ospf_neighbor *);
|
||||
|
||||
#endif /* _ZEBRA_OSPF_SNMP_H */
|
@ -50,11 +50,11 @@
|
||||
#include "ospfd/ospf_neighbor.h"
|
||||
#include "ospfd/ospf_nsm.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "ospfd/ospf_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "ospfd/ospf_te.h"
|
||||
|
||||
DEFINE_HOOK(ospf_if_update, (struct interface *ifp), (ifp))
|
||||
DEFINE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp))
|
||||
|
||||
/* Zebra structure to hold current status. */
|
||||
struct zclient *zclient = NULL;
|
||||
|
||||
@ -112,9 +112,7 @@ ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length,
|
||||
|
||||
ospf_if_update (NULL, ifp);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_if_update (ifp);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_if_update, ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -143,9 +141,7 @@ ospf_interface_delete (int command, struct zclient *zclient,
|
||||
("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d",
|
||||
ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_if_delete (ifp);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_if_delete, ifp);
|
||||
|
||||
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
|
||||
if (rn->info)
|
||||
@ -277,9 +273,7 @@ ospf_interface_address_add (int command, struct zclient *zclient,
|
||||
|
||||
ospf_if_update (NULL, c->ifp);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_if_update (c->ifp);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_if_update, c->ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -324,9 +318,7 @@ ospf_interface_address_delete (int command, struct zclient *zclient,
|
||||
/* Call interface hook functions to clean up */
|
||||
ospf_if_free (oi);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf_snmp_if_update (c->ifp);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(ospf_if_update, c->ifp);
|
||||
|
||||
connected_free (c);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define _ZEBRA_OSPF_ZEBRA_H
|
||||
|
||||
#include "vty.h"
|
||||
#include "hook.h"
|
||||
|
||||
#define EXTERNAL_METRIC_TYPE_1 0
|
||||
#define EXTERNAL_METRIC_TYPE_2 1
|
||||
@ -79,5 +80,8 @@ extern int ospf_distance_unset (struct vty *, struct ospf *, const char *,
|
||||
const char *, const char *);
|
||||
extern void ospf_zebra_init(struct thread_master *, u_short);
|
||||
|
||||
DECLARE_HOOK(ospf_if_update, (struct interface *ifp), (ifp))
|
||||
DECLARE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp))
|
||||
|
||||
#endif /* _ZEBRA_OSPF_ZEBRA_H */
|
||||
|
||||
|
@ -574,7 +574,6 @@ extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *);
|
||||
extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *);
|
||||
|
||||
extern void ospf_route_map_init (void);
|
||||
extern void ospf_snmp_init (void);
|
||||
|
||||
extern void ospf_master_init (struct thread_master *master);
|
||||
|
||||
|
@ -7,11 +7,12 @@ INSTALL_SDATA=@INSTALL@ -m 600
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
noinst_LIBRARIES = librip.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = ripd
|
||||
|
||||
librip_a_SOURCES = \
|
||||
rip_memory.c \
|
||||
ripd.c rip_zebra.c rip_interface.c rip_debug.c rip_snmp.c \
|
||||
ripd.c rip_zebra.c rip_interface.c rip_debug.c \
|
||||
rip_routemap.c rip_peer.c rip_offset.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
@ -23,6 +24,13 @@ ripd_SOURCES = \
|
||||
|
||||
ripd_LDADD = ../lib/libfrr.la @LIBCAP@
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += ripd_snmp.la
|
||||
endif
|
||||
ripd_snmp_la_SOURCES = rip_snmp.c
|
||||
ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
ripd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = ripd.conf.sample
|
||||
|
||||
|
@ -42,6 +42,9 @@
|
||||
#include "ripd/rip_debug.h"
|
||||
#include "ripd/rip_interface.h"
|
||||
|
||||
DEFINE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc))
|
||||
DEFINE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc))
|
||||
|
||||
/* static prototypes */
|
||||
static void rip_enable_apply (struct interface *);
|
||||
static void rip_passive_interface_apply (struct interface *);
|
||||
@ -673,9 +676,7 @@ rip_interface_address_add (int command, struct zclient *zclient,
|
||||
/* Check if this prefix needs to be redistributed */
|
||||
rip_apply_address_add(ifc);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
rip_ifaddr_add (ifc->ifp, ifc);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(rip_ifaddr_add, ifc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -723,9 +724,7 @@ rip_interface_address_delete (int command, struct zclient *zclient,
|
||||
zlog_debug ("connected address %s/%d is deleted",
|
||||
inet_ntoa (p->u.prefix4), p->prefixlen);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
rip_ifaddr_delete (ifc->ifp, ifc);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(rip_ifaddr_del, ifc);
|
||||
|
||||
/* Chech wether this prefix needs to be removed */
|
||||
rip_apply_address_del(ifc);
|
||||
|
@ -21,16 +21,18 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
#include "if.h"
|
||||
#include "vrf.h"
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "table.h"
|
||||
#include "smux.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "ripd/ripd.h"
|
||||
|
||||
@ -174,24 +176,27 @@ rip2Globals (struct variable *v, oid name[], size_t *length,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
|
||||
static int
|
||||
rip_snmp_ifaddr_add (struct connected *ifc)
|
||||
{
|
||||
struct interface *ifp = ifc->ifp;
|
||||
struct prefix *p;
|
||||
struct route_node *rn;
|
||||
|
||||
p = ifc->address;
|
||||
|
||||
if (p->family != AF_INET)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
rn = route_node_get (rip_ifaddr_table, p);
|
||||
rn->info = ifp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
|
||||
static int
|
||||
rip_snmp_ifaddr_del (struct connected *ifc)
|
||||
{
|
||||
struct interface *ifp = ifc->ifp;
|
||||
struct prefix *p;
|
||||
struct route_node *rn;
|
||||
struct interface *i;
|
||||
@ -199,11 +204,11 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
|
||||
p = ifc->address;
|
||||
|
||||
if (p->family != AF_INET)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
rn = route_node_lookup (rip_ifaddr_table, p);
|
||||
if (! rn)
|
||||
return;
|
||||
return 0;
|
||||
i = rn->info;
|
||||
if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
|
||||
{
|
||||
@ -211,6 +216,7 @@ rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
|
||||
route_unlock_node (rn);
|
||||
route_unlock_node (rn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct interface *
|
||||
@ -582,12 +588,29 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length,
|
||||
}
|
||||
|
||||
/* Register RIPv2-MIB. */
|
||||
void
|
||||
rip_snmp_init ()
|
||||
static int
|
||||
rip_snmp_init (struct thread_master *master)
|
||||
{
|
||||
rip_ifaddr_table = route_table_init ();
|
||||
|
||||
smux_init (master);
|
||||
REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
rip_snmp_module_init (void)
|
||||
{
|
||||
hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add);
|
||||
hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del);
|
||||
|
||||
hook_register(frr_late_init, rip_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "ripd_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "ripd AgentX SNMP module",
|
||||
.init = rip_snmp_module_init,
|
||||
)
|
||||
|
@ -4064,11 +4064,6 @@ rip_init (void)
|
||||
/* Debug related init. */
|
||||
rip_debug_init ();
|
||||
|
||||
/* SNMP init. */
|
||||
#ifdef HAVE_SNMP
|
||||
rip_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
/* Access list install. */
|
||||
access_list_init ();
|
||||
access_list_add_hook (rip_distribute_update_all_wrapper);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define _ZEBRA_RIP_H
|
||||
|
||||
#include "qobj.h"
|
||||
#include "hook.h"
|
||||
#include "rip_memory.h"
|
||||
|
||||
/* RIP version number. */
|
||||
@ -391,7 +392,6 @@ extern void rip_if_init (void);
|
||||
extern void rip_if_down_all (void);
|
||||
extern void rip_route_map_init (void);
|
||||
extern void rip_route_map_reset (void);
|
||||
extern void rip_snmp_init (void);
|
||||
extern void rip_zclient_init(struct thread_master *);
|
||||
extern void rip_zclient_reset (void);
|
||||
extern void rip_offset_init (void);
|
||||
@ -432,8 +432,6 @@ extern void rip_offset_clean (void);
|
||||
extern void rip_info_free (struct rip_info *);
|
||||
extern u_char rip_distance_apply (struct rip_info *);
|
||||
extern void rip_redistribute_clean (void);
|
||||
extern void rip_ifaddr_add (struct interface *, struct connected *);
|
||||
extern void rip_ifaddr_delete (struct interface *, struct connected *);
|
||||
|
||||
extern struct rip_info *rip_ecmp_add (struct rip_info *);
|
||||
extern struct rip_info *rip_ecmp_replace (struct rip_info *);
|
||||
@ -448,4 +446,8 @@ extern struct thread_master *master;
|
||||
/* RIP statistics for SNMP. */
|
||||
extern long rip_global_route_changes;
|
||||
extern long rip_global_queries;
|
||||
|
||||
DECLARE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc))
|
||||
DECLARE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc))
|
||||
|
||||
#endif /* _ZEBRA_RIP_H */
|
||||
|
@ -2010,6 +2010,24 @@ DEFUNSH (VTYSH_ZEBRA,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
show_per_daemon (const char *line, const char *headline)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = CMD_SUCCESS;
|
||||
|
||||
for (i = 0; i < array_size(vtysh_client); i++)
|
||||
if ( vtysh_client[i].fd >= 0 )
|
||||
{
|
||||
fprintf (stdout, headline,
|
||||
vtysh_client[i].name);
|
||||
ret = vtysh_client_execute (&vtysh_client[i], line, stdout);
|
||||
fprintf (stdout,"\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Memory */
|
||||
DEFUN (vtysh_show_memory,
|
||||
vtysh_show_memory_cmd,
|
||||
@ -2017,20 +2035,16 @@ DEFUN (vtysh_show_memory,
|
||||
SHOW_STR
|
||||
"Memory statistics\n")
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = CMD_SUCCESS;
|
||||
char line[] = "show memory\n";
|
||||
|
||||
for (i = 0; i < array_size(vtysh_client); i++)
|
||||
if ( vtysh_client[i].fd >= 0 )
|
||||
{
|
||||
fprintf (stdout, "Memory statistics for %s:\n",
|
||||
vtysh_client[i].name);
|
||||
ret = vtysh_client_execute (&vtysh_client[i], line, stdout);
|
||||
fprintf (stdout,"\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
return show_per_daemon ("show memory\n", "Memory statistics for %s:\n");
|
||||
}
|
||||
|
||||
DEFUN (vtysh_show_modules,
|
||||
vtysh_show_modules_cmd,
|
||||
"show modules",
|
||||
SHOW_STR
|
||||
"Loaded modules\n")
|
||||
{
|
||||
return show_per_daemon ("show modules\n", "Module information for %s:\n");
|
||||
}
|
||||
|
||||
/* Logging commands. */
|
||||
@ -3388,6 +3402,7 @@ vtysh_init_vty (void)
|
||||
#endif
|
||||
|
||||
install_element (VIEW_NODE, &vtysh_show_memory_cmd);
|
||||
install_element (VIEW_NODE, &vtysh_show_modules_cmd);
|
||||
|
||||
install_element (VIEW_NODE, &vtysh_show_work_queues_cmd);
|
||||
install_element (VIEW_NODE, &vtysh_show_work_queues_daemon_cmd);
|
||||
|
@ -19,33 +19,22 @@ mpls_method = @MPLS_METHOD@
|
||||
otherobj = $(ioctl_method) $(ipforward) $(if_method) \
|
||||
$(rt_method) $(rtread_method) $(kernel_method) $(mpls_method)
|
||||
|
||||
if HAVE_NETLINK
|
||||
othersrc = zebra_fpm_netlink.c
|
||||
endif
|
||||
|
||||
if HAVE_PROTOBUF
|
||||
protobuf_srcs = zebra_fpm_protobuf.c
|
||||
endif
|
||||
|
||||
if DEV_BUILD
|
||||
dev_srcs = zebra_fpm_dt.c
|
||||
endif
|
||||
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
sbin_PROGRAMS = zebra
|
||||
|
||||
noinst_PROGRAMS = testzebra
|
||||
module_LTLIBRARIES =
|
||||
|
||||
zebra_SOURCES = \
|
||||
zebra_memory.c \
|
||||
zserv.c main.c interface.c connected.c zebra_rib.c zebra_routemap.c \
|
||||
redistribute.c debug.c rtadv.c zebra_snmp.c zebra_vty.c \
|
||||
irdp_main.c irdp_interface.c irdp_packet.c router-id.c zebra_fpm.c \
|
||||
$(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
|
||||
redistribute.c debug.c rtadv.c zebra_vty.c \
|
||||
irdp_main.c irdp_interface.c irdp_packet.c router-id.c \
|
||||
zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \
|
||||
zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \
|
||||
$(protobuf_srcs) zebra_mroute.c \
|
||||
$(dev_srcs) label_manager.c
|
||||
zebra_mroute.c \
|
||||
label_manager.c \
|
||||
# end
|
||||
|
||||
testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
|
||||
zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \
|
||||
@ -57,17 +46,41 @@ noinst_HEADERS = \
|
||||
zebra_memory.h \
|
||||
connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \
|
||||
interface.h ipforward.h irdp.h router-id.h kernel_socket.h \
|
||||
rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \
|
||||
rt_netlink.h zebra_fpm_private.h zebra_rnh.h \
|
||||
zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \
|
||||
zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \
|
||||
kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h
|
||||
|
||||
zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS)
|
||||
zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP)
|
||||
|
||||
testzebra_LDADD = ../lib/libfrr.la $(LIBCAP)
|
||||
|
||||
zebra_DEPENDENCIES = $(otherobj)
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += zebra_snmp.la
|
||||
endif
|
||||
zebra_snmp_la_SOURCES = zebra_snmp.c
|
||||
zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
zebra_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
if FPM
|
||||
module_LTLIBRARIES += zebra_fpm.la
|
||||
endif
|
||||
zebra_fpm_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
zebra_fpm_la_LIBADD = $(Q_FPM_PB_CLIENT_LDOPTS)
|
||||
zebra_fpm_la_SOURCES = zebra_fpm.c
|
||||
if HAVE_NETLINK
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_netlink.c
|
||||
endif
|
||||
if HAVE_PROTOBUF
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_protobuf.c
|
||||
endif
|
||||
if DEV_BUILD
|
||||
zebra_fpm_la_SOURCES += zebra_fpm_dt.c
|
||||
endif
|
||||
|
||||
|
||||
EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \
|
||||
if_sysctl.c ipforward_proc.c \
|
||||
ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \
|
||||
|
20
zebra/main.c
20
zebra/main.c
@ -43,7 +43,6 @@
|
||||
#include "zebra/router-id.h"
|
||||
#include "zebra/irdp.h"
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/zebra_fpm.h"
|
||||
#include "zebra/zebra_ptm.h"
|
||||
#include "zebra/zebra_ns.h"
|
||||
#include "zebra/redistribute.h"
|
||||
@ -84,7 +83,6 @@ struct option longopts[] =
|
||||
{ "batch", no_argument, NULL, 'b'},
|
||||
{ "allow_delete", no_argument, NULL, 'a'},
|
||||
{ "keep_kernel", no_argument, NULL, 'k'},
|
||||
{ "fpm_format", required_argument, NULL, 'F'},
|
||||
{ "socket", required_argument, NULL, 'z'},
|
||||
{ "ecmp", required_argument, NULL, 'e'},
|
||||
{ "label_socket", no_argument, NULL, 'l'},
|
||||
@ -221,21 +219,18 @@ main (int argc, char **argv)
|
||||
{
|
||||
// int batch_mode = 0;
|
||||
char *zserv_path = NULL;
|
||||
char *fpm_format = NULL;
|
||||
/* Socket to external label manager */
|
||||
char *lblmgr_path = NULL;
|
||||
|
||||
|
||||
frr_preinit(&zebra_di, argc, argv);
|
||||
|
||||
frr_opt_add("bakF:z:e:l:r"
|
||||
frr_opt_add("bakz:e:l:r"
|
||||
#ifdef HAVE_NETLINK
|
||||
"s:"
|
||||
#endif
|
||||
, longopts,
|
||||
" -b, --batch Runs in batch mode\n"
|
||||
" -a, --allow_delete Allow other processes to delete zebra routes\n"
|
||||
" -F, --fpm_format Set fpm format to 'netlink' or 'protobuf'\n"
|
||||
" -z, --socket Set path of zebra socket\n"
|
||||
" -e, --ecmp Specify ECMP to use.\n"
|
||||
" -l, --label_socket Socket to external label manager\n"\
|
||||
@ -266,9 +261,6 @@ main (int argc, char **argv)
|
||||
case 'k':
|
||||
keep_kernel_mode = 1;
|
||||
break;
|
||||
case 'F':
|
||||
fpm_format = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
multipath_num = atoi (optarg);
|
||||
if (multipath_num > MULTIPATH_NUM || multipath_num <= 0)
|
||||
@ -329,16 +321,6 @@ main (int argc, char **argv)
|
||||
/* Initialize NS( and implicitly the VRF module), and make kernel routing socket. */
|
||||
zebra_ns_init ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
zebra_snmp_init ();
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
#ifdef HAVE_FPM
|
||||
zfpm_init (zebrad.master, 1, 0, fpm_format);
|
||||
#else
|
||||
zfpm_init (zebrad.master, 0, 0, fpm_format);
|
||||
#endif
|
||||
|
||||
/* Process the configuration file. Among other configuration
|
||||
* directives we can meet those installing static routes. Such
|
||||
* requests will not be executed immediately, but queued in
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/irdp.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/zebra_fpm.h"
|
||||
|
||||
void rtadv_config_write (struct vty *vty, struct interface *ifp) { return; }
|
||||
void irdp_config_write (struct vty *vty, struct interface *ifp) { return; }
|
||||
@ -35,9 +34,3 @@ void ifstat_update_proc (void) { return; }
|
||||
#ifdef HAVE_NET_RT_IFLIST
|
||||
void ifstat_update_sysctl (void) { return; }
|
||||
#endif
|
||||
|
||||
void
|
||||
zfpm_trigger_update (struct route_node *rn, const char *reason)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define _ZEBRA_RIB_H
|
||||
|
||||
#include "zebra.h"
|
||||
#include "hook.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
@ -490,4 +491,6 @@ rib_tables_iter_cleanup (rib_tables_iter_t *iter)
|
||||
iter->state = RIB_TABLES_ITER_S_DONE;
|
||||
}
|
||||
|
||||
DECLARE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason))
|
||||
|
||||
#endif /*_ZEBRA_RIB_H */
|
||||
|
@ -31,6 +31,10 @@
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
|
||||
/* Thank you, Solaris, for polluting application symbol namespace. */
|
||||
#undef hook_register
|
||||
#undef hook_unregister
|
||||
|
||||
#include <sys/stream.h>
|
||||
#include <sys/tihdr.h>
|
||||
|
||||
|
@ -25,10 +25,12 @@
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "libfrr.h"
|
||||
#include "stream.h"
|
||||
#include "thread.h"
|
||||
#include "network.h"
|
||||
#include "command.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
@ -36,7 +38,6 @@
|
||||
#include "zebra/zebra_vrf.h"
|
||||
|
||||
#include "fpm/fpm.h"
|
||||
#include "zebra_fpm.h"
|
||||
#include "zebra_fpm_private.h"
|
||||
|
||||
/*
|
||||
@ -254,6 +255,8 @@ typedef struct zfpm_glob_t_
|
||||
static zfpm_glob_t zfpm_glob_space;
|
||||
static zfpm_glob_t *zfpm_g = &zfpm_glob_space;
|
||||
|
||||
static int zfpm_trigger_update (struct route_node *rn, const char *reason);
|
||||
|
||||
static int zfpm_read_cb (struct thread *thread);
|
||||
static int zfpm_write_cb (struct thread *thread);
|
||||
|
||||
@ -1296,7 +1299,6 @@ zfpm_start_connect_timer (const char *reason)
|
||||
zfpm_set_state (ZFPM_STATE_ACTIVE, reason);
|
||||
}
|
||||
|
||||
#if defined (HAVE_FPM)
|
||||
/*
|
||||
* zfpm_is_enabled
|
||||
*
|
||||
@ -1307,7 +1309,6 @@ zfpm_is_enabled (void)
|
||||
{
|
||||
return zfpm_g->enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* zfpm_conn_is_up
|
||||
@ -1331,7 +1332,7 @@ zfpm_conn_is_up (void)
|
||||
* The zebra code invokes this function to indicate that we should
|
||||
* send an update to the FPM about the given route_node.
|
||||
*/
|
||||
void
|
||||
static int
|
||||
zfpm_trigger_update (struct route_node *rn, const char *reason)
|
||||
{
|
||||
rib_dest_t *dest;
|
||||
@ -1342,7 +1343,7 @@ zfpm_trigger_update (struct route_node *rn, const char *reason)
|
||||
* all destinations once the connection comes up.
|
||||
*/
|
||||
if (!zfpm_conn_is_up ())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
dest = rib_dest_from_rnode (rn);
|
||||
|
||||
@ -1353,12 +1354,12 @@ zfpm_trigger_update (struct route_node *rn, const char *reason)
|
||||
if (!zfpm_is_table_for_fpm (rib_dest_table (dest)))
|
||||
{
|
||||
zfpm_g->stats.non_fpm_table_triggers++;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) {
|
||||
zfpm_g->stats.redundant_triggers++;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reason)
|
||||
@ -1375,9 +1376,10 @@ zfpm_trigger_update (struct route_node *rn, const char *reason)
|
||||
* Make sure that writes are enabled.
|
||||
*/
|
||||
if (zfpm_g->t_write)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
zfpm_write_on ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1411,7 +1413,6 @@ zfpm_stats_timer_cb (struct thread *t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (HAVE_FPM)
|
||||
/*
|
||||
* zfpm_stop_stats_timer
|
||||
*/
|
||||
@ -1424,7 +1425,6 @@ zfpm_stop_stats_timer (void)
|
||||
zfpm_debug ("Stopping existing stats timer");
|
||||
THREAD_TIMER_OFF (zfpm_g->t_stats);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* zfpm_start_stats_timer
|
||||
@ -1447,7 +1447,6 @@ zfpm_start_stats_timer (void)
|
||||
zfpm_g->last_ivl_stats.counter, VTY_NEWLINE); \
|
||||
} while (0)
|
||||
|
||||
#if defined (HAVE_FPM)
|
||||
/*
|
||||
* zfpm_show_stats
|
||||
*/
|
||||
@ -1600,7 +1599,6 @@ DEFUN ( no_fpm_remote_ip,
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* zfpm_init_message_format
|
||||
@ -1670,7 +1668,7 @@ zfpm_init_message_format (const char *format)
|
||||
* Returns ZERO on success.
|
||||
*/
|
||||
|
||||
int fpm_remote_srv_write (struct vty *vty )
|
||||
static int fpm_remote_srv_write (struct vty *vty)
|
||||
{
|
||||
struct in_addr in;
|
||||
|
||||
@ -1684,6 +1682,15 @@ int fpm_remote_srv_write (struct vty *vty )
|
||||
}
|
||||
|
||||
|
||||
/* Zebra node */
|
||||
static struct cmd_node zebra_node =
|
||||
{
|
||||
ZEBRA_NODE,
|
||||
"",
|
||||
1
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* zfpm_init
|
||||
*
|
||||
@ -1695,17 +1702,12 @@ int fpm_remote_srv_write (struct vty *vty )
|
||||
*
|
||||
* Returns TRUE on success.
|
||||
*/
|
||||
int
|
||||
zfpm_init (struct thread_master *master, int enable, uint16_t port,
|
||||
const char *format)
|
||||
static int
|
||||
zfpm_init (struct thread_master *master)
|
||||
{
|
||||
static int initialized = 0;
|
||||
|
||||
if (initialized) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
int enable = 1;
|
||||
uint16_t port = 0;
|
||||
const char *format = THIS_MODULE->load_args;
|
||||
|
||||
memset (zfpm_g, 0, sizeof (*zfpm_g));
|
||||
zfpm_g->master = master;
|
||||
@ -1717,12 +1719,11 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port,
|
||||
zfpm_stats_init (&zfpm_g->last_ivl_stats);
|
||||
zfpm_stats_init (&zfpm_g->cumulative_stats);
|
||||
|
||||
#if defined (HAVE_FPM)
|
||||
install_node (&zebra_node, fpm_remote_srv_write);
|
||||
install_element (ENABLE_NODE, &show_zebra_fpm_stats_cmd);
|
||||
install_element (ENABLE_NODE, &clear_zebra_fpm_stats_cmd);
|
||||
install_element (CONFIG_NODE, &fpm_remote_ip_cmd);
|
||||
install_element (CONFIG_NODE, &no_fpm_remote_ip_cmd);
|
||||
#endif
|
||||
|
||||
zfpm_init_message_format(format);
|
||||
|
||||
@ -1734,10 +1735,6 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port,
|
||||
|
||||
zfpm_g->enabled = enable;
|
||||
|
||||
if (!enable) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!zfpm_g->fpm_server)
|
||||
zfpm_g->fpm_server = FPM_DEFAULT_IP;
|
||||
|
||||
@ -1751,6 +1748,20 @@ zfpm_init (struct thread_master *master, int enable, uint16_t port,
|
||||
|
||||
zfpm_start_stats_timer ();
|
||||
zfpm_start_connect_timer ("initialized");
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
zebra_fpm_module_init (void)
|
||||
{
|
||||
hook_register(rib_update, zfpm_trigger_update);
|
||||
hook_register(frr_late_init, zfpm_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "zebra_fpm",
|
||||
.version = FRR_VERSION,
|
||||
.description = "zebra FPM (Forwarding Plane Manager) module",
|
||||
.init = zebra_fpm_module_init,
|
||||
)
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Header file exported by the zebra FPM module to zebra.
|
||||
*
|
||||
* Copyright (C) 2012 by Open Source Routing.
|
||||
* Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _ZEBRA_FPM_H
|
||||
#define _ZEBRA_FPM_H
|
||||
|
||||
/*
|
||||
* Externs.
|
||||
*/
|
||||
extern int zfpm_init (struct thread_master *master, int enable, uint16_t port,
|
||||
const char *message_format);
|
||||
extern void zfpm_trigger_update (struct route_node *rn, const char *reason);
|
||||
extern int fpm_remote_srv_write (struct vty *vty);
|
||||
|
||||
#endif /* _ZEBRA_FPM_H */
|
@ -53,7 +53,7 @@ create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
|
||||
}
|
||||
|
||||
fpm__delete_route__init(msg);
|
||||
msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id;
|
||||
msg->vrf_id = zvrf_id(rib_dest_vrf(dest));
|
||||
|
||||
qpb_address_family_set(&msg->address_family, rib_dest_af(dest));
|
||||
|
||||
@ -159,7 +159,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
|
||||
|
||||
fpm__add_route__init(msg);
|
||||
|
||||
msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id;
|
||||
msg->vrf_id = zvrf_id(rib_dest_vrf(dest));
|
||||
|
||||
qpb_address_family_set (&msg->address_family, rib_dest_af(dest));
|
||||
|
||||
|
@ -48,11 +48,12 @@
|
||||
#include "zebra/redistribute.h"
|
||||
#include "zebra/zebra_routemap.h"
|
||||
#include "zebra/debug.h"
|
||||
#include "zebra/zebra_fpm.h"
|
||||
#include "zebra/zebra_rnh.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/connected.h"
|
||||
|
||||
DEFINE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason))
|
||||
|
||||
/* Should we allow non Quagga processes to delete our routes */
|
||||
extern int allow_delete;
|
||||
|
||||
@ -1110,7 +1111,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, struct rib *old)
|
||||
* Make sure we update the FPM any time we send new information to
|
||||
* the kernel.
|
||||
*/
|
||||
zfpm_trigger_update (rn, "installing in kernel");
|
||||
hook_call(rib_update, rn, "installing in kernel");
|
||||
ret = kernel_route_rib (p, src_p, old, rib);
|
||||
|
||||
/* If install succeeds, update FIB flag for nexthops. */
|
||||
@ -1154,7 +1155,7 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
|
||||
* Make sure we update the FPM any time we send new information to
|
||||
* the kernel.
|
||||
*/
|
||||
zfpm_trigger_update (rn, "uninstalling from kernel");
|
||||
hook_call(rib_update, rn, "uninstalling from kernel");
|
||||
ret = kernel_route_rib (p, src_p, rib, NULL);
|
||||
|
||||
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||
@ -1172,7 +1173,7 @@ rib_uninstall (struct route_node *rn, struct rib *rib)
|
||||
if (CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
|
||||
{
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
zfpm_trigger_update (rn, "rib_uninstall");
|
||||
hook_call(rib_update, rn, "rib_uninstall");
|
||||
|
||||
if (! RIB_SYSTEM_ROUTE (rib))
|
||||
rib_uninstall_kernel (rn, rib);
|
||||
@ -1253,7 +1254,7 @@ static void
|
||||
rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
struct rib *new)
|
||||
{
|
||||
zfpm_trigger_update (rn, "new route selected");
|
||||
hook_call(rib_update, rn, "new route selected");
|
||||
|
||||
/* Update real nexthop. This may actually determine if nexthop is active or not. */
|
||||
if (!nexthop_active_update (rn, new, 1))
|
||||
@ -1289,7 +1290,7 @@ static void
|
||||
rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
struct rib *old)
|
||||
{
|
||||
zfpm_trigger_update (rn, "removing existing route");
|
||||
hook_call(rib_update, rn, "removing existing route");
|
||||
|
||||
/* Uninstall from kernel. */
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
@ -1326,7 +1327,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
|
||||
if (new != old ||
|
||||
CHECK_FLAG (new->status, RIB_ENTRY_CHANGED))
|
||||
{
|
||||
zfpm_trigger_update (rn, "updating existing route");
|
||||
hook_call(rib_update, rn, "updating existing route");
|
||||
|
||||
/* Update the nexthop; we could determine here that nexthop is inactive. */
|
||||
if (nexthop_active_update (rn, new, 1))
|
||||
@ -2874,7 +2875,7 @@ rib_close_table (struct route_table *table)
|
||||
continue;
|
||||
|
||||
if (info->safi == SAFI_UNICAST)
|
||||
zfpm_trigger_update (rn, NULL);
|
||||
hook_call(rib_update, rn, NULL);
|
||||
|
||||
if (! RIB_SYSTEM_ROUTE (rib))
|
||||
rib_uninstall_kernel (rn, rib);
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -36,6 +35,9 @@
|
||||
#include "smux.h"
|
||||
#include "table.h"
|
||||
#include "vrf.h"
|
||||
#include "hook.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h"
|
||||
@ -571,10 +573,24 @@ ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
zebra_snmp_init ()
|
||||
static int
|
||||
zebra_snmp_init (struct thread_master *tm)
|
||||
{
|
||||
smux_init (zebrad.master);
|
||||
smux_init (tm);
|
||||
REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
zebra_snmp_module_init (void)
|
||||
{
|
||||
hook_register(frr_late_init, zebra_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "zebra_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "zebra AgentX SNMP module",
|
||||
.init = zebra_snmp_module_init,
|
||||
)
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "zebra/zebra_ptm.h"
|
||||
#include "zebra/rtadv.h"
|
||||
#include "zebra/zebra_mpls.h"
|
||||
#include "zebra/zebra_fpm.h"
|
||||
#include "zebra/zebra_mroute.h"
|
||||
#include "zebra/label_manager.h"
|
||||
|
||||
@ -2851,25 +2850,6 @@ static struct cmd_node forwarding_node =
|
||||
1
|
||||
};
|
||||
|
||||
#ifdef HAVE_FPM
|
||||
/* function to write the fpm config info */
|
||||
static int
|
||||
config_write_fpm (struct vty *vty)
|
||||
{
|
||||
return
|
||||
fpm_remote_srv_write (vty);
|
||||
}
|
||||
|
||||
/* Zebra node */
|
||||
static struct cmd_node zebra_node =
|
||||
{
|
||||
ZEBRA_NODE,
|
||||
"",
|
||||
1
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* Initialisation of zebra and installation of commands. */
|
||||
void
|
||||
zebra_init (void)
|
||||
@ -2880,9 +2860,6 @@ zebra_init (void)
|
||||
/* Install configuration write function. */
|
||||
install_node (&table_node, config_write_table);
|
||||
install_node (&forwarding_node, config_write_forwarding);
|
||||
#ifdef HAVE_FPM
|
||||
install_node (&zebra_node, config_write_fpm);
|
||||
#endif
|
||||
|
||||
install_element (VIEW_NODE, &show_ip_forwarding_cmd);
|
||||
install_element (CONFIG_NODE, &ip_forwarding_cmd);
|
||||
|
@ -149,7 +149,6 @@ extern void route_read (struct zebra_ns *);
|
||||
extern void kernel_init (struct zebra_ns *);
|
||||
extern void kernel_terminate (struct zebra_ns *);
|
||||
extern void zebra_route_map_init (void);
|
||||
extern void zebra_snmp_init (void);
|
||||
extern void zebra_vty_init (void);
|
||||
|
||||
extern int zsend_vrf_add (struct zserv *, struct zebra_vrf *);
|
||||
|
Loading…
Reference in New Issue
Block a user