Merge branch 'master' into pim_5549

This commit is contained in:
Donald Sharp 2017-04-05 12:49:17 -04:00 committed by GitHub
commit 096398104b
169 changed files with 3797 additions and 1656 deletions

View File

@ -2,6 +2,16 @@
[TOC]
## General note on this document
This document is "descriptive/post-factual" in that it documents pratices that
are in use; it is not "definitive/pre-factual" in prescribing practices.
This means that when a procedure changes, it is agreed upon, then put into
practice, and then documented here. If this document doesn't match reality,
it's the document that needs to be updated, not reality.
## Git Structure
The master Git for PROJECT resides on Github at
@ -10,20 +20,21 @@ The master Git for PROJECT resides on Github at
![git branches continually merging to the left from 3 lanes; float-right](doc/git_branches.svg
"git branch mechanics")
There are 3 main branches for development and a release branch for each
There is one main branch for development and a release branch for each
major release.
New contributions are done against the head of the Develop branch. The CI
New contributions are done against the head of the master branch. The CI
systems will pick up the Github Pull Requests or the new patch from
Patchwork, run some basic build and functional tests and will merge them
into the branch automatically on success.
Code on the develop branch will then be further tested and reviewed by the
community and merged to master on a regular interval.
Patchwork, run some basic build and functional tests.
For each major release (1.0, 1.1 etc) a new release branch is created based
on the master.
There was an attempt to use a "develop" branch automatically maintained by
the CI system. This is not currently in active use, though the system is
operational. If the "develop" branch is in active use and this paragraph
is still here, this document obviously wasn't updated.
## Programming language, Tools and Libraries
@ -250,16 +261,72 @@ Portions:
### Code styling / format
GNU coding standards apply. Indentation follows the result of invoking GNU
indent (as of 2.2.8a) with the `-nut -nfc1` arguments.
Coding style standards in FRR vary depending on location. Pre-existing
code uses GNU coding standards. New code may use Linux kernel coding style.
GNU coding style apply to the following parts:
* lib/
* zebra/
* bgpd/
* ospfd/
* ospf6d/
* isisd/
* ripd/
* ripngd/
* vtysh/
Linux kernel coding style applies to:
* nhrpd/
* watchfrr/
* pimd/
* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch]
BSD coding style applies to:
* ldpd/
**Whitespace changes in untouched parts of the code are not acceptable in
patches that change actual code.** To change/fix formatting issues, please
create a separate patch that only does formatting changes and nothing else.
It is acceptable to rewrap entire files to Linux kernel style, but this
**MUST** come as a separate patch that does nothing other than this
reformatting.
#### GNU style
For GNU coding style, Indentation follows the result of invoking GNU indent:
```
indent -nut -nfc1 file_for_submission.c
```
Please dont reformat existing files (or only sections modified by your
changes), even if they dont follow the standard. This makes it very hard to
highlight the changes
Originally, tabs were used instead of spaces, with tabs are every 8 columns.
However, tab interoperability issues mean space characters are now preferred for
new changes. We generally only clean up whitespace when code is unmaintainable
due to whitespace issues, to minimise merging conflicts.
#### Linux kernel & BSD style
These styles are documented externally:
* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle).
* [http://man.openbsd.org/style](http://man.openbsd.org/style)
They are relatively similar but differ in details.
pimd deviates from Linux kernel style in using 2 spaces for indentation, with
Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`.
It is acceptable to convert indentation in pimd/ to Linux kernel style, but
please convert an entire file at a time. (Rationale: apart from 2-space
indentation, the styles are sufficiently close to not upset when mixed.)
Unlike GNU style, these styles use tabs, not spaces.
### Compile-Time conditional code
@ -307,4 +374,4 @@ of their debugs.
CLI's are a complicated ugly beast. Additions or changes to the CLI
should use a DEFUN to encapsulate one setting as much as is possible.
Additionally as new DEFUN's are added to the system, documentation
should be provided for the new commands.
should be provided for the new commands.

View File

@ -1,4 +1,4 @@
ChangeLog information for FreeRangeRouting is for now recorded in source-code
ChangeLog information for FRRouting is for now recorded in source-code
management system. Please see:
http://www.freerangerouting.org/
http://www.frrouting.org/

View File

@ -17,3 +17,5 @@ EXTRA_DIST = aclocal.m4 SERVICES REPORTING-BUGS \
tools/zebra.el tools/multiple-bgpd.sh
ACLOCAL_AMFLAGS = -I m4
noinst_HEADERS = defaults.h

View File

@ -1,5 +1,5 @@
This file describes the procedure for reporting FreeRangeRouting bugs. You are not
obliged to follow this format, but it would be great help for FreeRangeRouting developers
This file describes the procedure for reporting FRRouting bugs. You are not
obliged to follow this format, but it would be great help for FRRouting developers
if you report a bug as described below.
Bugs submitted with woefully incomplete information may be summarily
@ -10,10 +10,10 @@ non-response to requests to reconfirm or supply additional
information.
Report bugs on Github Issue Tracker at
https://github.com/freerangerouting/frr/issues
https://github.com/frrouting/frr/issues
Please supply the following information:
1. Your FreeRangeRouting version or if it is from git then the commit reference.
1. Your FRRouting version or if it is from git then the commit reference.
Please try to report bugs against git master or the latest release.
2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any
specific options you compiled Quagga with.

View File

@ -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,15 @@ 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_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
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

View File

@ -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 ();

View File

@ -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 */

View File

@ -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
)

View File

@ -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 */

View File

@ -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"
@ -2937,10 +2934,18 @@ bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type)
bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
bgp->dynamic_neighbors_count = 0;
#if DFLT_BGP_IMPORT_CHECK
bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK);
#endif
#if DFLT_BGP_SHOW_HOSTNAME
bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME);
#endif
#if DFLT_BGP_LOG_NEIGHBOR_CHANGES
bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
#endif
#if DFLT_BGP_DETERMINISTIC_MED
bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
#endif
bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
bgp->as = *as;
@ -7379,8 +7384,11 @@ bgp_config_write (struct vty *vty)
inet_ntoa (bgp->router_id_static), VTY_NEWLINE);
/* BGP log-neighbor-changes. */
if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
!= DFLT_BGP_LOG_NEIGHBOR_CHANGES)
vty_out (vty, " %sbgp log-neighbor-changes%s",
bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no ",
VTY_NEWLINE);
/* BGP configuration. */
if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
@ -7396,8 +7404,11 @@ bgp_config_write (struct vty *vty)
bgp->default_local_pref, VTY_NEWLINE);
/* BGP default show-hostname */
if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE);
if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
!= DFLT_BGP_SHOW_HOSTNAME)
vty_out (vty, " %sbgp default show-hostname%s",
bgp_flag_check (bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no ",
VTY_NEWLINE);
/* BGP default subgroup-pkt-queue-max. */
if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
@ -7440,8 +7451,11 @@ bgp_config_write (struct vty *vty)
vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
/* BGP deterministic-med. */
if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE);
if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
!= DFLT_BGP_DETERMINISTIC_MED)
vty_out (vty, " %sbgp deterministic-med%s",
bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no ",
VTY_NEWLINE);
/* BGP update-delay. */
bgp_config_write_update_delay (vty, bgp);
@ -7517,8 +7531,11 @@ bgp_config_write (struct vty *vty)
}
/* BGP network import check. */
if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE);
if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
!= DFLT_BGP_IMPORT_CHECK)
vty_out (vty, " %sbgp network import-check%s",
bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no ",
VTY_NEWLINE);
/* BGP flag dampening. */
if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
@ -7647,6 +7664,8 @@ bgp_if_finish (struct bgp *bgp)
}
}
extern void bgp_snmp_init (void);
void
bgp_init (void)
{
@ -7695,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();
}

View File

@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h"
#include "routemap.h"
#include "linklist.h"
#include "defaults.h"
#include "bgp_memory.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
@ -1068,12 +1069,13 @@ struct bgp_nlri
#define BGP_EVENTS_MAX 15
/* BGP timers default value. */
/* note: the DFLT_ ones depend on compile-time "defaults" selection */
#define BGP_INIT_START_TIMER 1
#define BGP_DEFAULT_HOLDTIME 9
#define BGP_DEFAULT_KEEPALIVE 3
#define BGP_DEFAULT_HOLDTIME DFLT_BGP_HOLDTIME
#define BGP_DEFAULT_KEEPALIVE DFLT_BGP_KEEPALIVE
#define BGP_DEFAULT_EBGP_ROUTEADV 0
#define BGP_DEFAULT_IBGP_ROUTEADV 0
#define BGP_DEFAULT_CONNECT_RETRY 10
#define BGP_DEFAULT_CONNECT_RETRY DFLT_BGP_TIMERS_CONNECT
/* BGP default local preference. */
#define BGP_DEFAULT_LOCAL_PREF 100

View File

@ -1,5 +1,5 @@
##
## Configure template file for FreeRangeRouting.
## Configure template file for FRRouting.
## autoconf will generate configure script.
##
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
@ -7,9 +7,9 @@
##
AC_PREREQ(2.60)
AC_INIT(frr, 2.1-dev, [https://github.com/freerangerouting/frr/issues])
PACKAGE_URL="https://freerangerouting.org/"
PACKAGE_FULLNAME="FreeRangeRouting"
AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
PACKAGE_FULLNAME="FRRouting"
AC_SUBST(PACKAGE_FULLNAME)
CONFIG_ARGS="$ac_configure_args"
@ -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
@ -66,6 +73,10 @@ LIBS="$LIBS -ltcmalloc_minimal"
esac],[tcmalloc_enabled=false])
dnl Thanks autoconf, but we don't want a default -g -O2. We have our own
dnl flag determination logic.
CFLAGS="${CFLAGS:-}"
dnl --------------------
dnl Check CC and friends
dnl --------------------
@ -78,6 +89,7 @@ AM_PROG_CC_C_O
dnl remove autoconf default "-g -O2"
CFLAGS="$orig_cflags"
AC_PROG_CC_C99
dnl NB: see C11 below
AC_PROG_EGREP
PKG_PROG_PKG_CONFIG
@ -89,7 +101,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
dnl try and enable CFLAGS that are useful for Quagga
dnl - specifically, options to control warnings
AC_USE_SYSTEM_EXTENSIONS()
AC_USE_SYSTEM_EXTENSIONS
AC_DEFUN([AC_C_FLAG], [{
AC_LANG_PUSH(C)
ac_c_flag_save="$CFLAGS"
@ -115,6 +127,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006
dnl need to do this first so we get useful results for the other options
AC_C_FLAG([-diag-error 10006])
dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something
ac_cc="$CC"
CC="${CC% -std=gnu99}"
CC="${CC% -std=c99}"
AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here
if test "z$orig_cflags" = "z"; then
AC_C_FLAG([-g])
@ -170,6 +189,18 @@ AC_LINK_IFELSE(
])
AC_LANG_POP(C)
dnl ----------
dnl Essentials
dnl ----------
AX_PTHREAD([
CC="$PTHREAD_CC"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
], [
AC_MSG_FAILURE([This Quagga version needs pthreads])
])
dnl --------------
dnl Check programs
dnl --------------
@ -352,15 +383,18 @@ AC_SUBST(MPLS_METHOD)
if test "${enable_cumulus}" = "yes" ; then
AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in)
DFLT_NAME="datacenter"
else
DFLT_NAME="traditional"
fi
AC_SUBST(DFLT_NAME)
AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set)
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)
@ -529,6 +563,72 @@ AC_CHECK_HEADERS([stropts.h sys/ksym.h \
linux/version.h asm/types.h \
sys/cdefs.h])
ac_stdatomic_ok=false
AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs])
AC_CHECK_HEADER([stdatomic.h],[
AC_MSG_CHECKING([whether _Atomic qualifier works])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
#include <stdatomic.h>
int main(int argc, char **argv) {
_Atomic int i = 0;
return i;
}
]])], [
AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h])
AC_MSG_RESULT([yes])
ac_stdatomic_ok=true
], [
AC_MSG_RESULT([no])
])
])
AS_IF([$ac_stdatomic_ok], [true], [
AC_MSG_CHECKING([for __atomic_* builtins])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
int main(int argc, char **argv) {
volatile int i = 1;
__atomic_store_n (&i, 0, __ATOMIC_RELEASE);
return __atomic_load_n (&i, __ATOMIC_ACQUIRE);
}
]])], [
AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
dnl FreeBSD 9 has a broken stdatomic.h where _Atomic doesn't work
AC_MSG_CHECKING([for __sync_* builtins])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
int main(int argc, char **argv) {
volatile int i = 1;
__sync_fetch_and_sub (&i, 1);
return __sync_val_compare_and_swap (&i, 0, 1);
}
]])], [
AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins])
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for __sync_swap builtin])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
int main(int argc, char **argv) {
volatile int i = 1;
return __sync_swap (&i, 2);
}
]])], [
AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
])
], [
AC_MSG_RESULT([no])
AC_MSG_FAILURE([stdatomic.h unavailable and $CC has neither __atomic nor __sync builtins])
])
])
])
dnl Utility macro to avoid retyping includes all the time
m4_define([FRR_INCLUDES],
[#ifdef SUNOS_5
@ -1317,8 +1417,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);
@ -1330,7 +1430,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
@ -1346,6 +1445,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
@ -1646,14 +1792,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
@ -1681,6 +1831,7 @@ AC_CONFIG_FILES([Makefile lib/Makefile qpb/Makefile zebra/Makefile ripd/Makefile
snapcraft/Makefile
snapcraft/snapcraft.yaml
lib/version.h
tests/lib/cli/test_cli.refout
doc/defines.texi
doc/bgpd.8
doc/isisd.8
@ -1716,7 +1867,7 @@ AC_CONFIG_FILES([vtysh/extract.pl],[chmod +x vtysh/extract.pl])
AC_OUTPUT
echo "
FreeRangeRouting configuration
FRRouting configuration
------------------------------
FRR version : ${PACKAGE_VERSION}
host operating system : ${host_os}
@ -1728,6 +1879,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}

View File

@ -14,7 +14,7 @@ available forcing you to explicitly type "apt-get install frr" to upgrade it.
* What is frr?
=================
http://www.freerangerouting.org/
http://www.frrouting.org/
FRR is a routing software suite, providing implementations of OSPFv2,
OSPFv3, RIP v1 and v2, RIPng, ISIS, PIM, BGP and LDP for Unix platforms, particularly
FreeBSD and Linux and also NetBSD, to mention a few. FRR is a fork of Quagga

4
debian/copyright vendored
View File

@ -1,7 +1,7 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Frr
Upstream-Contact: maintainers@freerangerouting.org, security@freerangerouting.org
Source: http://www.freerangerouting.org/
Upstream-Contact: maintainers@frrouting.org, security@frrouting.org
Source: http://www.frrouting.org/
Files: *
Copyright: 1996-2003 by the original Zebra authors:

54
defaults.h Normal file
View File

@ -0,0 +1,54 @@
/*
* FRR switchable defaults.
* Copyright (C) 2017 David Lamparter for NetDEF, Inc.
*
* This file is part of FRRouting (FRR).
*
* FRR 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.
*
* FRR 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 FRR; see the file COPYING. If not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _FRR_DEFAULTS_H
#define _FRR_DEFAULTS_H
#include "config.h"
#ifdef HAVE_CUMULUS
#define DFLT_BGP_IMPORT_CHECK 1
#define DFLT_BGP_TIMERS_CONNECT 10
#define DFLT_BGP_HOLDTIME 9
#define DFLT_BGP_KEEPALIVE 3
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1
#define DFLT_BGP_SHOW_HOSTNAME 1
#define DFLT_BGP_DETERMINISTIC_MED 1
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1
#else /* !HAVE_CUMULUS */
#define DFLT_BGP_IMPORT_CHECK 0
#define DFLT_BGP_TIMERS_CONNECT 120
#define DFLT_BGP_HOLDTIME 180
#define DFLT_BGP_KEEPALIVE 60
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0
#define DFLT_BGP_SHOW_HOSTNAME 0
#define DFLT_BGP_DETERMINISTIC_MED 0
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0
#endif /* !HAVE_CUMULUS */
#endif /* _FRR_DEFAULTS_H */

View File

@ -18,7 +18,7 @@ Add packages:
sudo yum install git autoconf automake libtool make gawk readline-devel \
texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \
flex c-ares-devel epel-release
flex c-ares-devel epel-release rpm-build libcap-devel texi2html
Install newer version of bison (CentOS 6 package source is too old) from
CentOS 7
@ -69,7 +69,7 @@ any packages**
sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FreeRangeRouting suite" -d /var/run/frr frr
-c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it
(You may prefer different options on configure statement. These are just
@ -78,7 +78,7 @@ an example.)
You may want to pay special attention to `/usr/lib64` paths and change
them if you are not building on a x86_64 architecture
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \

View File

@ -15,7 +15,7 @@ Add packages:
sudo yum install git autoconf automake libtool make gawk readline-devel \
texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \
bison flex pytest c-ares-devel python-devel
bison flex pytest c-ares-devel python-devel rpm-build
To build from git (in difference to building from distribution tar.gz as created by `make dist`), the python development libraries are needed. (Make sure you've installed EPEL libraries as shown above for this to work)
@ -32,7 +32,7 @@ any packages**
sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FreeRangeRouting suite" -d /var/run/frr frr
-c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it
(You may prefer different options on configure statement. These are just
@ -41,7 +41,7 @@ an example.)
You may want to pay special attention to `/usr/lib64` paths and change
them if you are not building on a x86_64 architecture
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \

View File

@ -32,14 +32,14 @@ any packages**
sudo addgroup --system --gid 92 frr
sudo addgroup --system --gid 85 frrvty
sudo adduser --system --ingroup frr --groups frrvty --home /var/run/frr/ \
--gecos "FRR FreeRangeRouting suite" --shell /bin/false frr
--gecos "FRR FRRouting suite" --shell /bin/false frr
sudo usermode
### Download Source, configure and compile it
(You may prefer different options on configure statement. These are just
an example.)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \

View File

@ -22,7 +22,7 @@ using any packages**
sudo groupadd -g 92 frr
sudo groupadd -r -g 85 frrvt
sudo useradd -u 92 -g 92 -M -r -G frrvt -s /sbin/nologin \
-c "FRR FreeRangeRouting suite" -d /var/run/frr frr
-c "FRR FRRouting suite" -d /var/run/frr frr
### Download Source, configure and compile it
(You may prefer different options on configure statement. These are just
@ -31,7 +31,7 @@ an example.)
You may want to pay special attention to `/usr/lib64` paths and change
them if you are not building on a x86_64 architecture
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \

View File

@ -41,7 +41,7 @@ using any packages**
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
export MAKE=gmake

View File

@ -41,7 +41,7 @@ using any packages**
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
export MAKE=gmake

View File

@ -49,7 +49,7 @@ using any packages**
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
export MAKE=gmake

View File

@ -45,7 +45,7 @@ Get FRR, compile it and install it (from Git)
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
MAKE=gmake

View File

@ -39,7 +39,7 @@ Get FRR, compile it and install it (from Git)
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
MAKE=gmake

View File

@ -87,7 +87,7 @@ any packages**
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
export MAKE=gmake

View File

@ -34,7 +34,7 @@ any packages**
(You may prefer different options on configure statement. These are just
an example)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
export LDFLAGS="-L/usr/local/lib"

View File

@ -72,7 +72,7 @@ any packages**
(You may prefer different options on configure statement. These are just
an example.)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \
@ -102,20 +102,20 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/etc/ldpd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo touch /etc/frr/ldpd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -32,7 +32,7 @@ any packages**
(You may prefer different options on configure statement. These are just
an example.)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \
@ -62,19 +62,19 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -33,7 +33,7 @@ any packages**
(You may prefer different options on configure statement. These are just
an example.)
git clone https://github.com/freerangerouting/frr.git frr
git clone https://github.com/frrouting/frr.git frr
cd frr
./bootstrap.sh
./configure \
@ -63,20 +63,20 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/etc/ldpd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo touch /etc/frr/ldpd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -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

View File

@ -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

View File

@ -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
View 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.

View File

@ -7,7 +7,7 @@
@setfilename frr.info
@c Set variables - sourced from defines.texi
@include defines.texi
@settitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}}
@settitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}}
@c %**end of header
@c automake will automatically generate version.texi
@ -48,16 +48,16 @@ This file documents the Frr Software Routing Suite which manages common
TCP/IP routing protocols.
This is Edition @value{EDITION}, last updated @value{UPDATED} of
@cite{The Frr Manual}, for @uref{http://www.freerangerouting.org/,,@value{PACKAGE_NAME}}
@cite{The Frr Manual}, for @uref{http://www.frrouting.org/,,@value{PACKAGE_NAME}}
Version @value{VERSION}.
@insertcopying
@end ifinfo
@titlepage
@title @uref{http://www.freerangerouting.org,,Frr}
@title @uref{http://www.frrouting.org,,Frr}
@subtitle A routing software package for TCP/IP networks
@subtitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} @value{VERSION}
@subtitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @value{VERSION}
@subtitle @value{UPDATED-MONTH}
@author @value{AUTHORS}
@ -72,9 +72,9 @@ Version @value{VERSION}.
@node Top
@top Frr -- With Virtual Network Control
@uref{http://www.freerangerouting.org,,Frr} is an advanced routing software package
@uref{http://www.frrouting.org,,Frr} is an advanced routing software package
that provides a suite of TCP/IP based routing protocols. This is the Manual
for @value{PACKAGE_STRING}. @uref{http://www.freerangerouting.org,,Frr} is a fork of
for @value{PACKAGE_STRING}. @uref{http://www.frrouting.org,,Frr} is a fork of
@uref{http://www.quagga.net,,Quagga}.
@insertcopying

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,7 +2,7 @@
@chapter Overview
@cindex Overview
@uref{http://www.freerangerouting.org,,Frr} is a routing software package that
@uref{http://www.frrouting.org,,Frr} is a routing software package that
provides TCP/IP based routing services with routing protocols support such
as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+ (@pxref{Supported
RFCs}). Frr also supports special BGP Route Reflector and Route Server
@ -275,12 +275,12 @@ November 1995.}
The official Frr web-site is located at:
@uref{http://www.freerangerouting.org/}
@uref{http://www.frrouting.org/}
and contains further information, as well as links to additional
resources.
@uref{http://www.freerangerouting.org/,Frr} is a fork of Quagga, whose
@uref{http://www.frrouting.org/,Frr} is a fork of Quagga, whose
web-site is located at:
@uref{http://www.quagga.net/}.
@ -298,7 +298,7 @@ comments or suggestions to Frr, please subscribe to:
@uref{http://lists.nox.tf/listinfo/frr-users}.
The @uref{http://www.freerangerouting.org/,,Frr} site has further information on
The @uref{http://www.frrouting.org/,,Frr} site has further information on
the available mailing lists, see:
@uref{http://lists.nox.tf/lists.php}
@ -315,7 +315,7 @@ the available mailing lists, see:
If you think you have found a bug, please send a bug report to:
@uref{http://github.com/freerangerouting/frr/issues}
@uref{http://github.com/frrouting/frr/issues}
When you send a bug report, please be careful about the points below.
@ -334,4 +334,4 @@ arguments to the configure script please note that too.
Bug reports are very important for us to improve the quality of Frr.
Frr is still in the development stage, but please don't hesitate to
send a bug report to @uref{http://github.com/freerangerouting/frr/issues}.
send a bug report to @uref{http://github.com/frrouting/frr/issues}.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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::

View File

@ -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

View File

@ -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

View File

@ -279,6 +279,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
if (bytesread < 0)
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
return ISIS_WARNING;
}
/*
@ -322,10 +326,10 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
addr_len = sizeof (s_addr);
/* we can read directly to the stream */
bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
circuit->interface->mtu, 0,
(struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
stream_recvfrom (circuit->rcv_stream, circuit->fd,
circuit->interface->mtu, 0,
(struct sockaddr *) &s_addr,
(socklen_t *) &addr_len);
if (s_addr.sll_pkttype == PACKET_OUTGOING)
{

View File

@ -68,7 +68,6 @@ remove_excess_adjs (struct list *adjs)
if (candidate->sys_type < adj->sys_type)
{
excess = node;
candidate = adj;
continue;
}
if (candidate->sys_type > adj->sys_type)
@ -78,7 +77,6 @@ remove_excess_adjs (struct list *adjs)
if (comp > 0)
{
excess = node;
candidate = adj;
continue;
}
if (comp < 0)
@ -87,7 +85,6 @@ remove_excess_adjs (struct list *adjs)
if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
{
excess = node;
candidate = adj;
continue;
}
@ -98,7 +95,6 @@ remove_excess_adjs (struct list *adjs)
if (comp > 0)
{
excess = node;
candidate = adj;
continue;
}
}

View File

@ -49,37 +49,48 @@ iface_compare(struct iface *a, struct iface *b)
}
struct iface *
if_new(struct kif *kif)
if_new(const char *name)
{
struct iface *iface;
if ((iface = calloc(1, sizeof(*iface))) == NULL)
fatal("if_new: calloc");
strlcpy(iface->name, kif->ifname, sizeof(iface->name));
LIST_INIT(&iface->addr_list);
if (kif->ifindex)
if_update_info(iface, kif);
strlcpy(iface->name, name, sizeof(iface->name));
/* ipv4 */
iface->ipv4.af = AF_INET;
iface->ipv4.iface = iface;
iface->ipv4.enabled = 0;
iface->ipv4.state = IF_STA_DOWN;
RB_INIT(&iface->ipv4.adj_tree);
/* ipv6 */
iface->ipv6.af = AF_INET6;
iface->ipv6.iface = iface;
iface->ipv6.enabled = 0;
iface->ipv6.state = IF_STA_DOWN;
RB_INIT(&iface->ipv6.adj_tree);
return (iface);
}
void
if_exit(struct iface *iface)
ldpe_if_init(struct iface *iface)
{
log_debug("%s: interface %s", __func__, iface->name);
LIST_INIT(&iface->addr_list);
/* ipv4 */
iface->ipv4.iface = iface;
iface->ipv4.state = IF_STA_DOWN;
RB_INIT(&iface->ipv4.adj_tree);
/* ipv6 */
iface->ipv6.iface = iface;
iface->ipv6.state = IF_STA_DOWN;
RB_INIT(&iface->ipv6.adj_tree);
}
void
ldpe_if_exit(struct iface *iface)
{
struct if_addr *if_addr;

View File

@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
}
struct l2vpn_if *
l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_if *lif;
@ -125,9 +125,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
fatal("l2vpn_if_new: calloc");
lif->l2vpn = l2vpn;
strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname));
lif->ifindex = kif->ifindex;
lif->flags = kif->flags;
strlcpy(lif->ifname, ifname, sizeof(lif->ifname));
return (lif);
}
@ -140,6 +138,14 @@ l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname)
return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
}
void
l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif)
{
lif->ifindex = kif->ifindex;
lif->flags = kif->flags;
memcpy(lif->mac, kif->mac, sizeof(lif->mac));
}
void
l2vpn_if_update(struct l2vpn_if *lif)
{
@ -174,7 +180,7 @@ l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b)
}
struct l2vpn_pw *
l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_pw *pw;
@ -182,8 +188,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
fatal("l2vpn_pw_new: calloc");
pw->l2vpn = l2vpn;
strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname));
pw->ifindex = kif->ifindex;
strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
return (pw);
}
@ -219,6 +224,12 @@ l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
}
void
l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif)
{
pw->ifindex = kif->ifindex;
}
void
l2vpn_pw_init(struct l2vpn_pw *pw)
{
@ -463,37 +474,6 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
}
}
void
l2vpn_sync_pws(int af, union ldpd_addr *addr)
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
struct fec fec;
struct fec_node *fn;
struct fec_nh *fnh;
RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
continue;
l2vpn_pw_fec(pw, &fec);
fn = (struct fec_node *)fec_find(&ft, &fec);
if (fn == NULL)
continue;
fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)
&pw->lsr_id, 0, 0);
if (fnh == NULL)
continue;
if (l2vpn_pw_ok(pw, fnh))
lde_send_change_klabel(fn, fnh);
else
lde_send_delete_klabel(fn, fnh);
}
}
}
void
l2vpn_pw_ctl(pid_t pid)
{

View File

@ -439,13 +439,14 @@ static int
lde_dispatch_parent(struct thread *thread)
{
static struct ldpd_conf *nconf;
struct iface *niface;
struct iface *iface, *niface;
struct tnbr *ntnbr;
struct nbr_params *nnbrp;
static struct l2vpn *nl2vpn;
struct l2vpn_if *nlif;
struct l2vpn_pw *npw;
static struct l2vpn *l2vpn, *nl2vpn;
struct l2vpn_if *lif, *nlif;
struct l2vpn_pw *pw, *npw;
struct imsg imsg;
struct kif *kif;
struct kroute *kr;
int fd = THREAD_FD(thread);
struct imsgev *iev = THREAD_ARG(thread);
@ -468,6 +469,31 @@ lde_dispatch_parent(struct thread *thread)
break;
switch (imsg.hdr.type) {
case IMSG_IFSTATUS:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
sizeof(struct kif))
fatalx("IFSTATUS imsg with wrong len");
kif = imsg.data;
iface = if_lookup_name(ldeconf, kif->ifname);
if (iface) {
if_update_info(iface, kif);
break;
}
RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
lif = l2vpn_if_find(l2vpn, kif->ifname);
if (lif) {
l2vpn_if_update_info(lif, kif);
break;
}
pw = l2vpn_pw_find(l2vpn, kif->ifname);
if (pw) {
l2vpn_pw_update_info(pw, kif);
break;
}
}
break;
case IMSG_NETWORK_ADD:
case IMSG_NETWORK_UPDATE:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
@ -540,12 +566,6 @@ lde_dispatch_parent(struct thread *thread)
fatal(NULL);
memcpy(niface, imsg.data, sizeof(struct iface));
LIST_INIT(&niface->addr_list);
RB_INIT(&niface->ipv4.adj_tree);
RB_INIT(&niface->ipv6.adj_tree);
niface->ipv4.iface = niface;
niface->ipv6.iface = niface;
RB_INSERT(iface_head, &nconf->iface_tree, niface);
break;
case IMSG_RECONF_TNBR:
@ -578,7 +598,6 @@ lde_dispatch_parent(struct thread *thread)
fatal(NULL);
memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
nlif->l2vpn = nl2vpn;
RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
break;
case IMSG_RECONF_L2VPN_PW:
@ -586,7 +605,6 @@ lde_dispatch_parent(struct thread *thread)
fatal(NULL);
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn;
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
break;
case IMSG_RECONF_L2VPN_IPW:
@ -594,11 +612,11 @@ lde_dispatch_parent(struct thread *thread)
fatal(NULL);
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn;
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
break;
case IMSG_RECONF_END:
merge_config(ldeconf, nconf);
ldp_clear_config(nconf);
nconf = NULL;
break;
case IMSG_DEBUG_UPDATE:
@ -725,10 +743,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
sizeof(kr));
if (fn->fec.u.ipv4.prefixlen == 32)
l2vpn_sync_pws(AF_INET, (union ldpd_addr *)
&fn->fec.u.ipv4.prefix);
break;
case FEC_TYPE_IPV6:
memset(&kr, 0, sizeof(kr));
@ -743,10 +757,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
sizeof(kr));
if (fn->fec.u.ipv6.prefixlen == 128)
l2vpn_sync_pws(AF_INET6, (union ldpd_addr *)
&fn->fec.u.ipv6.prefix);
break;
case FEC_TYPE_PWID:
if (fn->local_label == NO_LABEL ||
@ -792,10 +802,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
sizeof(kr));
if (fn->fec.u.ipv4.prefixlen == 32)
l2vpn_sync_pws(AF_INET, (union ldpd_addr *)
&fn->fec.u.ipv4.prefix);
break;
case FEC_TYPE_IPV6:
memset(&kr, 0, sizeof(kr));
@ -810,10 +816,6 @@ lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
sizeof(kr));
if (fn->fec.u.ipv6.prefixlen == 128)
l2vpn_sync_pws(AF_INET6, (union ldpd_addr *)
&fn->fec.u.ipv6.prefix);
break;
case FEC_TYPE_PWID:
pw = (struct l2vpn_pw *) fn->data;

View File

@ -212,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *);
void l2vpn_del(struct l2vpn *);
void l2vpn_init(struct l2vpn *);
void l2vpn_exit(struct l2vpn *);
struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *);
struct l2vpn_if *l2vpn_if_new(struct l2vpn *, const char *);
struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *);
void l2vpn_if_update_info(struct l2vpn_if *, struct kif *);
void l2vpn_if_update(struct l2vpn_if *);
struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *);
struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, const char *);
struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *);
struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *);
struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *);
void l2vpn_pw_update_info(struct l2vpn_pw *, struct kif *);
void l2vpn_pw_init(struct l2vpn_pw *);
void l2vpn_pw_exit(struct l2vpn_pw *);
void l2vpn_pw_reset(struct l2vpn_pw *);
@ -231,7 +233,6 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t,
void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *);
void l2vpn_recv_pw_status_wcard(struct lde_nbr *,
struct notify_msg *);
void l2vpn_sync_pws(int, union ldpd_addr *);
void l2vpn_pw_ctl(pid_t);
void l2vpn_binding_ctl(pid_t);

View File

@ -80,6 +80,5 @@ int ldp_vty_debug(struct vty *, struct vty_arg *[]);
int ldp_vty_show_debugging(struct vty *, struct vty_arg *[]);
void ldp_vty_init(void);
void ldp_vty_if_init(void);
#endif /* _LDP_VTY_H_ */

View File

@ -32,29 +32,15 @@
#include "vty.h"
#include "ldp_vty.h"
static int interface_config_write(struct vty *);
static void ldp_af_iface_config_write(struct vty *, int);
static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *,
struct ldpd_af_conf *);
static void ldp_l2vpn_pw_config_write(struct vty *, struct l2vpn_pw *);
static void ldp_vty_push_node(struct vty *, int, void *);
static void *ldp_vty_get_node(struct vty *, void *, int);
static int ldp_vty_get_af(struct vty *);
static int ldp_iface_is_configured(struct ldpd_conf *, const char *);
static int ldp_vty_nbr_session_holdtime(struct vty *, struct vty_arg *[]);
static int ldp_vty_af_session_holdtime(struct vty *, struct vty_arg *[]);
static struct iface *vty_iface;
static struct l2vpn *vty_l2vpn;
static struct l2vpn_pw *vty_pw;
static struct cmd_node interface_node =
{
INTERFACE_NODE,
"%s(config-if)# ",
1
};
struct cmd_node ldp_node =
{
LDP_NODE,
@ -122,26 +108,6 @@ ldp_get_address(const char *str, int *af, union ldpd_addr *addr)
return (-1);
}
static int
interface_config_write(struct vty *vty)
{
struct listnode *node;
struct interface *ifp;
int write = 0;
for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), node, ifp)) {
vty_out(vty, "!%s", VTY_NEWLINE);
vty_out(vty, "interface %s%s", ifp->name, VTY_NEWLINE);
if (ifp->desc)
vty_out(vty, " description %s%s", ifp->desc,
VTY_NEWLINE);
write++;
}
return (write);
}
static void
ldp_af_iface_config_write(struct vty *vty, int af)
{
@ -419,94 +385,6 @@ ldp_l2vpn_config_write(struct vty *vty)
return (0);
}
void
ldp_vty_push_node(struct vty *vty, int node, void *ptr)
{
if (global.sighup) {
switch (node) {
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
vty_iface = ptr;
break;
case LDP_L2VPN_NODE:
vty_l2vpn = ptr;
break;
case LDP_PSEUDOWIRE_NODE:
vty_pw = ptr;
break;
default:
fatalx("ldp_vty_push_node: unexpected node");
}
vty->node = node;
return;
}
switch (node) {
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
VTY_PUSH_CONTEXT(node, (struct iface *)ptr);
break;
case LDP_L2VPN_NODE:
VTY_PUSH_CONTEXT(node, (struct l2vpn *)ptr);
break;
case LDP_PSEUDOWIRE_NODE:
VTY_PUSH_CONTEXT_SUB(node, (struct l2vpn_pw *)ptr);
break;
default:
fatalx("ldp_vty_push_node: unexpected node");
}
}
void *
ldp_vty_get_node(struct vty *vty, void *parent, int node)
{
struct iface *iface;
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
if (global.sighup) {
switch (node) {
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
return (vty_iface);
case LDP_L2VPN_NODE:
return (vty_l2vpn);
case LDP_PSEUDOWIRE_NODE:
return (vty_pw);
default:
fatalx("ldp_vty_get_node: unexpected node");
}
}
/*
* Since VTY_GET_CONTEXT() returns a pointer to an element of ldpd_conf,
* we have to find the equivalent element inside vty_conf (which should
* always exist as vty_conf is a duplicate of ldpd_conf).
*/
switch (node) {
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
iface = VTY_GET_CONTEXT(iface);
if (iface)
return (if_lookup_name(vty_conf, iface->name));
break;
case LDP_L2VPN_NODE:
l2vpn = VTY_GET_CONTEXT(l2vpn);
if (l2vpn)
return (l2vpn_find(vty_conf, l2vpn->name));
break;
case LDP_PSEUDOWIRE_NODE:
pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
if (pw)
return (l2vpn_pw_find(parent, pw->ifname));
break;
default:
fatalx("ldp_vty_get_node: unexpected node");
}
return (NULL);
}
static int
ldp_vty_get_af(struct vty *vty)
{
@ -684,7 +562,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[])
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
af = ldp_vty_get_af(vty);
iface = ldp_vty_get_node(vty, NULL, vty->node);
iface = VTY_GET_CONTEXT(iface);
VTY_CHECK_CONTEXT(iface);
ia = iface_af_get(iface, af);
@ -692,6 +570,7 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[])
ia->hello_holdtime = 0;
else
ia->hello_holdtime = secs;
ldp_reload(vty_conf);
break;
default:
@ -784,7 +663,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[])
case LDP_IPV4_IFACE_NODE:
case LDP_IPV6_IFACE_NODE:
af = ldp_vty_get_af(vty);
iface = ldp_vty_get_node(vty, NULL, vty->node);
iface = VTY_GET_CONTEXT(iface);
VTY_CHECK_CONTEXT(iface);
ia = iface_af_get(iface, af);
@ -792,6 +671,7 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[])
ia->hello_interval = 0;
else
ia->hello_interval = secs;
ldp_reload(vty_conf);
break;
default:
@ -853,14 +733,14 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING);
}
nbrp = nbr_params_find(vty_conf, lsr_id);
secs = strtol(seconds_str, &ep, 10);
if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) {
vty_out(vty, "%% Invalid holdtime%s", VTY_NEWLINE);
return (CMD_SUCCESS);
}
nbrp = nbr_params_find(vty_conf, lsr_id);
if (disable) {
if (nbrp == NULL)
return (CMD_SUCCESS);
@ -871,6 +751,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[])
if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id);
RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
QOBJ_REG(nbrp, nbr_params);
} else if (nbrp->keepalive == secs)
return (CMD_SUCCESS);
@ -935,8 +816,6 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
int af;
struct iface *iface;
struct iface_af *ia;
struct interface *ifp;
struct kif kif;
const char *ifname;
int disable;
@ -957,7 +836,9 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
ia->enabled = 0;
ia->hello_holdtime = 0;
ia->hello_interval = 0;
ldp_reload(vty_conf);
return (CMD_SUCCESS);
}
@ -968,23 +849,14 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS);
}
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
iface = if_new(&kif);
iface = if_new(ifname);
ia = iface_af_get(iface, af);
ia->enabled = 1;
RB_INSERT(iface_head, &vty_conf->iface_tree, iface);
QOBJ_REG(iface, iface);
ldp_reload(vty_conf);
} else {
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
ia = iface_af_get(iface, af);
if (!ia->enabled) {
ia->enabled = 1;
@ -994,10 +866,10 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
switch (af) {
case AF_INET:
ldp_vty_push_node(vty, LDP_IPV4_IFACE_NODE, iface);
VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE, iface);
break;
case AF_INET6:
ldp_vty_push_node(vty, LDP_IPV6_IFACE_NODE, iface);
VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE, iface);
break;
default:
break;
@ -1065,9 +937,12 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
if (tnbr == NULL)
return (CMD_SUCCESS);
QOBJ_UNREG(tnbr);
RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr);
free(tnbr);
ldp_reload(vty_conf);
return (CMD_SUCCESS);
}
@ -1077,6 +952,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
tnbr = tnbr_new(af, &addr);
tnbr->flags |= F_TNBR_CONFIGURED;
RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr);
QOBJ_REG(tnbr, tnbr);
ldp_reload(vty_conf);
@ -1331,6 +1207,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[])
if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id);
RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
QOBJ_REG(nbrp, nbr_params);
} else if (nbrp->auth.method == AUTH_MD5SIG &&
strcmp(nbrp->auth.md5key, password_str) == 0)
return (CMD_SUCCESS);
@ -1391,6 +1268,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[])
if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id);
RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
QOBJ_REG(nbrp, nbr_params);
}
nbrp->flags |= F_NBRP_GTSM;
@ -1412,6 +1290,8 @@ int
ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_if *lif;
struct l2vpn_pw *pw;
const char *name_str;
int disable;
@ -1424,23 +1304,34 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
if (l2vpn == NULL)
return (CMD_SUCCESS);
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
QOBJ_UNREG(lif);
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
QOBJ_UNREG(pw);
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
QOBJ_UNREG(pw);
QOBJ_UNREG(l2vpn);
RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
l2vpn_del(l2vpn);
ldp_reload(vty_conf);
return (CMD_SUCCESS);
}
if (l2vpn) {
ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn);
VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
return (CMD_SUCCESS);
}
l2vpn = l2vpn_new(name_str);
l2vpn->type = L2VPN_TYPE_VPLS;
RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
QOBJ_REG(l2vpn, l2vpn);
VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
ldp_reload(vty_conf);
ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn);
return (CMD_SUCCESS);
}
@ -1448,16 +1339,13 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
const char *ifname;
int disable;
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
ifname = vty_get_arg_value(args, "ifname");
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
if (disable)
memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname));
else
@ -1471,7 +1359,7 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
char *ep;
int mtu;
const char *mtu_str;
@ -1486,9 +1374,6 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING);
}
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
if (disable)
l2vpn->mtu = DEFAULT_L2VPN_MTU;
else
@ -1502,7 +1387,7 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
int pw_type;
const char *type_str;
int disable;
@ -1515,9 +1400,6 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[])
else
pw_type = PW_TYPE_ETHERNET_TAGGED;
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
if (disable)
l2vpn->pw_type = DEFAULT_PW_TYPE;
else
@ -1531,27 +1413,26 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
struct l2vpn_if *lif;
struct interface *ifp;
struct kif kif;
const char *ifname;
int disable;
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
ifname = vty_get_arg_value(args, "ifname");
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
lif = l2vpn_if_find(l2vpn, ifname);
if (disable) {
if (lif == NULL)
return (CMD_SUCCESS);
QOBJ_UNREG(lif);
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
ldp_reload(vty_conf);
return (CMD_SUCCESS);
}
@ -1563,16 +1444,9 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS);
}
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
lif = l2vpn_if_new(l2vpn, &kif);
lif = l2vpn_if_new(l2vpn, ifname);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
QOBJ_REG(lif, l2vpn_if);
ldp_reload(vty_conf);
@ -1582,32 +1456,34 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
VTY_DECLVAR_CONTEXT(l2vpn, l2vpn);
struct l2vpn_pw *pw;
struct interface *ifp;
struct kif kif;
const char *ifname;
int disable;
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
ifname = vty_get_arg_value(args, "ifname");
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = l2vpn_pw_find(l2vpn, ifname);
if (disable) {
if (pw == NULL)
return (CMD_SUCCESS);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
QOBJ_UNREG(pw);
if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0)
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
else
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw);
ldp_reload(vty_conf);
return (CMD_SUCCESS);
}
if (pw) {
ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw);
VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
return (CMD_SUCCESS);
}
@ -1616,20 +1492,14 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS);
}
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
pw = l2vpn_pw_new(l2vpn, &kif);
pw = l2vpn_pw_new(l2vpn, ifname);
pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
QOBJ_REG(pw, l2vpn_pw);
VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
ldp_reload(vty_conf);
ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw);
return (CMD_SUCCESS);
}
@ -1637,19 +1507,13 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
const char *preference_str;
int disable;
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
preference_str = vty_get_arg_value(args, "preference");
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE);
VTY_CHECK_CONTEXT(pw);
if (disable)
pw->flags |= F_PW_CWORD_CONF;
else {
@ -1667,8 +1531,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
int af;
union ldpd_addr addr;
const char *addr_str;
@ -1683,11 +1546,6 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING);
}
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE);
VTY_CHECK_CONTEXT(pw);
if (disable) {
pw->af = AF_UNSPEC;
memset(&pw->addr, 0, sizeof(pw->addr));
@ -1706,8 +1564,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
struct in_addr lsr_id;
const char *lsr_id_str;
int disable;
@ -1721,11 +1578,6 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING);
}
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE);
VTY_CHECK_CONTEXT(pw);
if (disable)
pw->lsr_id.s_addr = INADDR_ANY;
else
@ -1739,8 +1591,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
char *ep;
uint32_t pwid;
const char *pwid_str;
@ -1755,11 +1606,6 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING);
}
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE);
VTY_CHECK_CONTEXT(pw);
if (disable)
pw->pwid = 0;
else
@ -1773,17 +1619,11 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[])
int
ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[])
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
VTY_DECLVAR_CONTEXT_SUB(l2vpn_pw, pw);
int disable;
disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE);
VTY_CHECK_CONTEXT(l2vpn);
pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE);
VTY_CHECK_CONTEXT(pw);
if (disable)
pw->flags |= F_PW_STATUSTLV_CONF;
else
@ -1794,41 +1634,25 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS);
}
void
ldp_vty_if_init(void)
{
/* Install interface node. */
install_node (&interface_node, interface_config_write);
if_cmd_init ();
}
struct iface *
iface_new_api(struct ldpd_conf *conf, const char *name)
{
const char *ifname = name;
struct iface *iface;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname))
return NULL;
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
iface = if_new(&kif);
iface = if_new(name);
RB_INSERT(iface_head, &conf->iface_tree, iface);
QOBJ_REG(iface, iface);
return (iface);
}
void
iface_del_api(struct ldpd_conf *conf, struct iface *iface)
{
QOBJ_UNREG(iface);
RB_REMOVE(iface_head, &conf->iface_tree, iface);
free(iface);
}
@ -1847,12 +1671,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr)
tnbr = tnbr_new(af, addr);
tnbr->flags |= F_TNBR_CONFIGURED;
RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
QOBJ_REG(tnbr, tnbr);
return (tnbr);
}
void
tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr)
{
QOBJ_UNREG(tnbr);
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr);
}
@ -1867,12 +1693,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id)
nbrp = nbr_params_new(lsr_id);
RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
QOBJ_REG(nbrp, nbr_params);
return (nbrp);
}
void
nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp)
{
QOBJ_UNREG(nbrp);
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
free(nbrp);
}
@ -1888,6 +1716,7 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name)
l2vpn = l2vpn_new(name);
l2vpn->type = L2VPN_TYPE_VPLS;
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
QOBJ_REG(l2vpn, l2vpn);
return (l2vpn);
}
@ -1898,17 +1727,21 @@ l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
struct l2vpn_pw *pw;
while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
QOBJ_UNREG(lif);
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
}
while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
QOBJ_UNREG(pw);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw);
}
while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
QOBJ_UNREG(pw);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw);
}
QOBJ_UNREG(l2vpn);
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
free(l2vpn);
}
@ -1918,28 +1751,20 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
const char *ifname)
{
struct l2vpn_if *lif;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname))
return (NULL);
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
lif = l2vpn_if_new(l2vpn, &kif);
lif = l2vpn_if_new(l2vpn, ifname);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
QOBJ_REG(lif, l2vpn_if);
return (lif);
}
void
l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif)
{
QOBJ_UNREG(lif);
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
}
@ -1949,29 +1774,21 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
const char *ifname)
{
struct l2vpn_pw *pw;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname))
return (NULL);
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
if (ifp) {
kif.ifindex = ifp->ifindex;
kif.flags = ifp->flags;
}
pw = l2vpn_pw_new(l2vpn, &kif);
pw = l2vpn_pw_new(l2vpn, ifname);
pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
QOBJ_REG(pw, l2vpn_pw);
return (pw);
}
void
l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw)
{
QOBJ_UNREG(pw);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw);
}

View File

@ -1049,7 +1049,7 @@ show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
static int
show_lib_detail_msg(struct vty *vty, struct imsg *imsg, struct show_params *params)
{
struct ctl_rt *rt;
struct ctl_rt *rt = NULL;
char dstnet[BUFSIZ];
static int upstream, downstream;
size_t buflen;
@ -1172,7 +1172,7 @@ static int
show_lib_detail_msg_json(struct imsg *imsg, struct show_params *params,
json_object *json)
{
struct ctl_rt *rt;
struct ctl_rt *rt = NULL;
char dstnet[BUFSIZ];
static json_object *json_lib_entry;
static json_object *json_adv_labels;

View File

@ -180,7 +180,7 @@ kif_redistribute(const char *ifname)
continue;
ifp2kif(ifp, &kif);
main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif));
main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
ifc2kaddr(ifp, ifc, &ka);
@ -222,7 +222,7 @@ ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length,
ifp->ifindex, ifp->mtu);
ifp2kif(ifp, &kif);
main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif));
main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
return (0);
}
@ -270,7 +270,7 @@ ldp_interface_status_change(int command, struct zclient *zclient,
debug_zebra_in("interface %s state update", ifp->name);
ifp2kif(ifp, &kif);
main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif));
main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING);
if (link_new) {

View File

@ -56,6 +56,7 @@ static int main_imsg_send_config(struct ldpd_conf *);
static void ldp_config_normalize(struct ldpd_conf *);
static void ldp_config_reset_main(struct ldpd_conf *);
static void ldp_config_reset_af(struct ldpd_conf *, int);
static void ldp_config_reset_l2vpns(struct ldpd_conf *);
static void merge_global(struct ldpd_conf *, struct ldpd_conf *);
static void merge_af(int, struct ldpd_af_conf *,
struct ldpd_af_conf *);
@ -131,9 +132,8 @@ sighup(void)
log_info("SIGHUP received");
/* reset vty_conf */
ldp_clear_config(vty_conf);
vty_conf = config_new_empty();
ldp_config_reset_main(vty_conf);
ldp_config_reset_l2vpns(vty_conf);
/* read configuration file without applying any changes */
global.sighup = 1;
@ -338,20 +338,20 @@ main(int argc, char *argv[])
vrf_init();
access_list_init();
ldp_vty_init();
ldp_vty_if_init();
ldp_zebra_init(master);
/* create base configuration with sane defaults */
ldpd_conf = config_new_empty();
ldp_config_reset_main(ldpd_conf);
QOBJ_REG(ldpd_conf, ldpd_conf);
/*
* Create vty_conf as a duplicate of the main configuration. All
* configuration requests (e.g. CLI) act on vty_conf and then call
* ldp_reload() to merge the changes into ldpd_conf.
*/
vty_conf = ldp_dup_config(ldpd_conf);
vty_conf = config_new_empty();
ldp_config_reset_main(vty_conf);
QOBJ_REG(vty_conf, ldpd_conf);
/* read configuration file and daemonize */
frr_config_fork();
@ -416,7 +416,11 @@ ldpd_shutdown(void)
close(iev_lde->ibuf.fd);
config_clear(ldpd_conf);
QOBJ_UNREG(ldpd_conf);
ldp_config_reset_main(vty_conf);
ldp_config_reset_l2vpns(vty_conf);
QOBJ_UNREG(vty_conf);
free(vty_conf);
log_debug("waiting for children to terminate");
do {
@ -993,16 +997,16 @@ ldp_reload(struct ldpd_conf *xconf)
merge_config(ldpd_conf, xconf);
vty_conf = ldp_dup_config(ldpd_conf);
return (0);
}
static void
ldp_config_normalize(struct ldpd_conf *xconf)
{
struct iface *iface, *itmp;
struct nbr_params *nbrp, *ntmp;
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
struct l2vpn_pw *pw, *ptmp;
if (!(xconf->flags & F_LDPD_ENABLED))
ldp_config_reset_main(xconf);
@ -1011,22 +1015,51 @@ ldp_config_normalize(struct ldpd_conf *xconf)
ldp_config_reset_af(xconf, AF_INET);
if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED))
ldp_config_reset_af(xconf, AF_INET6);
RB_FOREACH_SAFE(iface, iface_head, &xconf->iface_tree, itmp) {
if (iface->ipv4.enabled || iface->ipv6.enabled)
continue;
QOBJ_UNREG(iface);
RB_REMOVE(iface_head, &vty_conf->iface_tree, iface);
free(iface);
}
RB_FOREACH_SAFE(nbrp, nbrp_head, &xconf->nbrp_tree, ntmp) {
if (nbrp->flags & (F_NBRP_KEEPALIVE|F_NBRP_GTSM))
continue;
if (nbrp->auth.method != AUTH_NONE)
continue;
QOBJ_UNREG(nbrp);
RB_REMOVE(nbrp_head, &vty_conf->nbrp_tree, nbrp);
free(nbrp);
}
}
RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (pw->flags & F_PW_STATIC_NBR_ADDR)
continue;
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) {
pw->af = AF_INET;
pw->addr.v4 = pw->lsr_id;
}
pw->af = AF_INET;
pw->addr.v4 = pw->lsr_id;
if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0)
continue;
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
}
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
if (pw->flags & F_PW_STATIC_NBR_ADDR)
continue;
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree,
ptmp) {
if (!(pw->flags & F_PW_STATIC_NBR_ADDR)) {
pw->af = AF_INET;
pw->addr.v4 = pw->lsr_id;
}
pw->af = AF_INET;
pw->addr.v4 = pw->lsr_id;
if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0)
continue;
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
}
}
}
@ -1038,11 +1071,13 @@ ldp_config_reset_main(struct ldpd_conf *conf)
struct nbr_params *nbrp;
while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) {
QOBJ_UNREG(iface);
RB_REMOVE(iface_head, &conf->iface_tree, iface);
free(iface);
}
while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) {
QOBJ_UNREG(nbrp);
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
free(nbrp);
}
@ -1075,6 +1110,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af)
if (tnbr->af != af)
continue;
QOBJ_UNREG(tnbr);
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr);
}
@ -1089,70 +1125,33 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af)
af_conf->flags = 0;
}
struct ldpd_conf *
ldp_dup_config(struct ldpd_conf *conf)
static void
ldp_config_reset_l2vpns(struct ldpd_conf *conf)
{
struct ldpd_conf *xconf;
struct iface *iface, *xi;
struct tnbr *tnbr, *xt;
struct nbr_params *nbrp, *xn;
struct l2vpn *l2vpn, *xl;
struct l2vpn_if *lif, *xf;
struct l2vpn_pw *pw, *xp;
struct l2vpn *l2vpn;
struct l2vpn_if *lif;
struct l2vpn_pw *pw;
#define COPY(a, b) do { \
a = calloc(1, sizeof(*a)); \
if (a == NULL) \
fatal(__func__); \
*a = *b; \
} while (0)
COPY(xconf, conf);
RB_INIT(&xconf->iface_tree);
RB_INIT(&xconf->tnbr_tree);
RB_INIT(&xconf->nbrp_tree);
RB_INIT(&xconf->l2vpn_tree);
RB_FOREACH(iface, iface_head, &conf->iface_tree) {
COPY(xi, iface);
xi->ipv4.iface = xi;
xi->ipv6.iface = xi;
RB_INSERT(iface_head, &xconf->iface_tree, xi);
}
RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) {
COPY(xt, tnbr);
RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt);
}
RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) {
COPY(xn, nbrp);
RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn);
}
RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) {
COPY(xl, l2vpn);
RB_INIT(&xl->if_tree);
RB_INIT(&xl->pw_tree);
RB_INIT(&xl->pw_inactive_tree);
RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl);
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
COPY(xf, lif);
xf->l2vpn = xl;
RB_INSERT(l2vpn_if_head, &xl->if_tree, xf);
while ((l2vpn = RB_ROOT(&conf->l2vpn_tree)) != NULL) {
while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
QOBJ_UNREG(lif);
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
}
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
COPY(xp, pw);
xp->l2vpn = xl;
RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp);
while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
QOBJ_UNREG(pw);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw);
}
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
COPY(xp, pw);
xp->l2vpn = xl;
RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
QOBJ_UNREG(pw);
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw);
}
QOBJ_UNREG(l2vpn);
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
free(l2vpn);
}
#undef COPY
return (xconf);
}
void
@ -1183,6 +1182,13 @@ ldp_clear_config(struct ldpd_conf *xconf)
free(xconf);
}
#define COPY(a, b) do { \
a = malloc(sizeof(*a)); \
if (a == NULL) \
fatal(__func__); \
*a = *b; \
} while (0)
void
merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
{
@ -1193,7 +1199,6 @@ merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
merge_tnbrs(conf, xconf);
merge_nbrps(conf, xconf);
merge_l2vpns(conf, xconf);
free(xconf);
}
static void
@ -1337,31 +1342,34 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
/* find deleted interfaces */
if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
RB_REMOVE(iface_head, &conf->iface_tree, iface);
switch (ldpd_process) {
case PROC_LDE_ENGINE:
break;
case PROC_LDP_ENGINE:
if_exit(iface);
ldpe_if_exit(iface);
break;
case PROC_LDE_ENGINE:
case PROC_MAIN:
QOBJ_UNREG (iface);
break;
}
RB_REMOVE(iface_head, &conf->iface_tree, iface);
free(iface);
}
}
RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
/* find new interfaces */
if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
RB_REMOVE(iface_head, &xconf->iface_tree, xi);
RB_INSERT(iface_head, &conf->iface_tree, xi);
COPY(iface, xi);
RB_INSERT(iface_head, &conf->iface_tree, iface);
if (ldpd_process == PROC_MAIN) {
QOBJ_REG (xi, iface);
switch (ldpd_process) {
case PROC_LDP_ENGINE:
ldpe_if_init(iface);
break;
case PROC_LDE_ENGINE:
break;
case PROC_MAIN:
/* resend addresses to activate new interfaces */
kif_redistribute(xi->name);
kif_redistribute(iface->name);
break;
}
continue;
}
@ -1369,8 +1377,6 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
/* update existing interfaces */
merge_iface_af(&iface->ipv4, &xi->ipv4);
merge_iface_af(&iface->ipv6, &xi->ipv6);
RB_REMOVE(iface_head, &xconf->iface_tree, xi);
free(xi);
}
}
@ -1398,17 +1404,13 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
/* find deleted tnbrs */
if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) {
switch (ldpd_process) {
case PROC_LDE_ENGINE:
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr);
break;
case PROC_LDP_ENGINE:
tnbr->flags &= ~F_TNBR_CONFIGURED;
tnbr_check(conf, tnbr);
break;
case PROC_LDE_ENGINE:
case PROC_MAIN:
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
QOBJ_UNREG (tnbr);
free(tnbr);
break;
}
@ -1417,17 +1419,15 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) {
/* find new tnbrs */
if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
RB_INSERT(tnbr_head, &conf->tnbr_tree, xt);
COPY(tnbr, xt);
RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
switch (ldpd_process) {
case PROC_LDE_ENGINE:
break;
case PROC_LDP_ENGINE:
tnbr_update(xt);
tnbr_update(tnbr);
break;
case PROC_LDE_ENGINE:
case PROC_MAIN:
QOBJ_REG (xt, tnbr);
break;
}
continue;
@ -1436,8 +1436,6 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
/* update existing tnbrs */
if (!(tnbr->flags & F_TNBR_CONFIGURED))
tnbr->flags |= F_TNBR_CONFIGURED;
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
free(xt);
}
}
@ -1452,8 +1450,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
/* find deleted nbrps */
if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
switch (ldpd_process) {
case PROC_LDE_ENGINE:
break;
case PROC_LDP_ENGINE:
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
if (nbr) {
@ -1471,8 +1467,8 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
nbr_establish_connection(nbr);
}
break;
case PROC_LDE_ENGINE:
case PROC_MAIN:
QOBJ_UNREG (nbrp);
break;
}
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
@ -1482,33 +1478,31 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) {
/* find new nbrps */
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
RB_INSERT(nbrp_head, &conf->nbrp_tree, xn);
COPY(nbrp, xn);
RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
switch (ldpd_process) {
case PROC_LDE_ENGINE:
break;
case PROC_LDP_ENGINE:
nbr = nbr_find_ldpid(xn->lsr_id.s_addr);
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
if (nbr) {
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
nbr->auth.method = xn->auth.method;
nbr->auth.method = nbrp->auth.method;
#ifdef __OpenBSD__
if (pfkey_establish(nbr, xn) == -1)
if (pfkey_establish(nbr, nbrp) == -1)
fatalx("pfkey setup failed");
#else
sock_set_md5sig(
(ldp_af_global_get(&global,
nbr->af))->ldp_session_socket,
nbr->af, &nbr->raddr,
xn->auth.md5key);
nbrp->auth.md5key);
#endif
if (nbr_session_active_role(nbr))
nbr_establish_connection(nbr);
}
break;
case PROC_LDE_ENGINE:
case PROC_MAIN:
QOBJ_REG (xn, nbr_params);
break;
}
continue;
@ -1553,8 +1547,6 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
nbr_establish_connection(nbr);
}
}
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
free(xn);
}
}
@ -1562,14 +1554,10 @@ static void
merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
{
struct l2vpn *l2vpn, *ltmp, *xl;
struct l2vpn_if *lif;
struct l2vpn_pw *pw;
RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
/* find deleted l2vpns */
if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
switch (ldpd_process) {
case PROC_LDE_ENGINE:
l2vpn_exit(l2vpn);
@ -1578,58 +1566,35 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
ldpe_l2vpn_exit(l2vpn);
break;
case PROC_MAIN:
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
QOBJ_UNREG (lif);
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
QOBJ_UNREG (pw);
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
QOBJ_UNREG (pw);
QOBJ_UNREG (l2vpn);
break;
}
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
l2vpn_del(l2vpn);
}
}
RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
struct l2vpn_pw *xp, *ptmp;
/* check if the pseudowires should be enabled or disabled */
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
if (xp->lsr_id.s_addr != INADDR_ANY && xp->pwid != 0)
continue;
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
}
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0)
continue;
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp);
}
/* find new l2vpns */
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl);
COPY(l2vpn, xl);
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
RB_INIT(&l2vpn->if_tree);
RB_INIT(&l2vpn->pw_tree);
RB_INIT(&l2vpn->pw_inactive_tree);
switch (ldpd_process) {
case PROC_LDE_ENGINE:
l2vpn_init(xl);
l2vpn_init(l2vpn);
break;
case PROC_LDP_ENGINE:
ldpe_l2vpn_init(xl);
ldpe_l2vpn_init(l2vpn);
break;
case PROC_MAIN:
QOBJ_REG (xl, l2vpn);
break;
}
continue;
}
/* update existing l2vpns */
merge_l2vpn(conf, l2vpn, xl);
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
free(xl);
}
}
@ -1649,8 +1614,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
/* find deleted interfaces */
if ((xf = l2vpn_if_find(xl, lif->ifname)) == NULL) {
if (ldpd_process == PROC_MAIN)
QOBJ_UNREG (lif);
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
}
@ -1658,16 +1621,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) {
/* find new interfaces */
if ((lif = l2vpn_if_find(l2vpn, xf->ifname)) == NULL) {
RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
xf->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN)
QOBJ_REG (xf, l2vpn_if);
continue;
}
COPY(lif, xf);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
lif->l2vpn = l2vpn;
RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
free(xf);
switch (ldpd_process) {
case PROC_LDP_ENGINE:
case PROC_LDE_ENGINE:
break;
case PROC_MAIN:
kif_redistribute(lif->ifname);
break;
}
}
}
/* merge active pseudowires */
@ -1682,7 +1648,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
ldpe_l2vpn_pw_exit(pw);
break;
case PROC_MAIN:
QOBJ_UNREG (pw);
break;
}
@ -1693,19 +1658,19 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
/* find new active pseudowires */
if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) {
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp);
xp->l2vpn = l2vpn;
COPY(pw, xp);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
pw->l2vpn = l2vpn;
switch (ldpd_process) {
case PROC_LDE_ENGINE:
l2vpn_pw_init(xp);
l2vpn_pw_init(pw);
break;
case PROC_LDP_ENGINE:
ldpe_l2vpn_pw_init(xp);
ldpe_l2vpn_pw_init(pw);
break;
case PROC_MAIN:
QOBJ_REG (xp, l2vpn_pw);
kif_redistribute(pw->ifname);
break;
}
continue;
@ -1772,9 +1737,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
l2vpn->pw_type = previous_pw_type;
l2vpn->mtu = previous_mtu;
}
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
free(xp);
}
/* merge inactive pseudowires */
@ -1782,19 +1744,24 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
/* find deleted inactive pseudowires */
if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) {
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
if (ldpd_process == PROC_MAIN)
QOBJ_UNREG (pw);
free(pw);
}
}
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
/* find new inactive pseudowires */
if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) {
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
xp->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN)
QOBJ_REG (xp, l2vpn_pw);
COPY(pw, xp);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
pw->l2vpn = l2vpn;
switch (ldpd_process) {
case PROC_LDE_ENGINE:
case PROC_LDP_ENGINE:
break;
case PROC_MAIN:
kif_redistribute(pw->ifname);
break;
}
continue;
}
@ -1806,9 +1773,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
pw->ifindex = xp->ifindex;
pw->flags = xp->flags;
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
free(xp);
}
l2vpn->pw_type = xl->pw_type;
@ -1852,5 +1816,6 @@ config_clear(struct ldpd_conf *conf)
xconf->trans_pref = conf->trans_pref;
xconf->flags = conf->flags;
merge_config(conf, xconf);
free(xconf);
free(conf);
}

View File

@ -706,7 +706,6 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int);
int ldp_is_dual_stack(struct ldpd_conf *);
in_addr_t ldp_rtr_id_get(struct ldpd_conf *);
int ldp_reload(struct ldpd_conf *);
struct ldpd_conf *ldp_dup_config(struct ldpd_conf *);
void ldp_clear_config(struct ldpd_conf *);
void merge_config(struct ldpd_conf *, struct ldpd_conf *);
struct ldpd_conf *config_new_empty(void);

View File

@ -256,8 +256,8 @@ ldpe_dispatch_main(struct thread *thread)
struct tnbr *ntnbr;
struct nbr_params *nnbrp;
static struct l2vpn *l2vpn, *nl2vpn;
struct l2vpn_if *lif = NULL, *nlif;
struct l2vpn_pw *npw;
struct l2vpn_if *lif, *nlif;
struct l2vpn_pw *pw, *npw;
struct imsg imsg;
int fd = THREAD_FD(thread);
struct imsgev *iev = THREAD_ARG(thread);
@ -305,12 +305,15 @@ ldpe_dispatch_main(struct thread *thread)
RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) {
lif = l2vpn_if_find(l2vpn, kif->ifname);
if (lif) {
lif->flags = kif->flags;
memcpy(lif->mac, kif->mac,
sizeof(lif->mac));
l2vpn_if_update_info(lif, kif);
l2vpn_if_update(lif);
break;
}
pw = l2vpn_pw_find(l2vpn, kif->ifname);
if (pw) {
l2vpn_pw_update_info(pw, kif);
break;
}
}
break;
case IMSG_NEWADDR:
@ -449,12 +452,6 @@ ldpe_dispatch_main(struct thread *thread)
fatal(NULL);
memcpy(niface, imsg.data, sizeof(struct iface));
LIST_INIT(&niface->addr_list);
RB_INIT(&niface->ipv4.adj_tree);
RB_INIT(&niface->ipv6.adj_tree);
niface->ipv4.iface = niface;
niface->ipv6.iface = niface;
RB_INSERT(iface_head, &nconf->iface_tree, niface);
break;
case IMSG_RECONF_TNBR:
@ -487,7 +484,6 @@ ldpe_dispatch_main(struct thread *thread)
fatal(NULL);
memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
nlif->l2vpn = nl2vpn;
RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
break;
case IMSG_RECONF_L2VPN_PW:
@ -495,7 +491,6 @@ ldpe_dispatch_main(struct thread *thread)
fatal(NULL);
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn;
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
break;
case IMSG_RECONF_L2VPN_IPW:
@ -503,11 +498,11 @@ ldpe_dispatch_main(struct thread *thread)
fatal(NULL);
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn;
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
break;
case IMSG_RECONF_END:
merge_config(leconf, nconf);
ldp_clear_config(nconf);
nconf = NULL;
global.conf_seqnum++;
break;

View File

@ -214,8 +214,9 @@ void mapping_list_add(struct mapping_head *, struct map *);
void mapping_list_clr(struct mapping_head *);
/* interface.c */
struct iface *if_new(struct kif *);
void if_exit(struct iface *);
struct iface *if_new(const char *);
void ldpe_if_init(struct iface *);
void ldpe_if_exit(struct iface *);
struct iface *if_lookup(struct ldpd_conf *, unsigned short);
struct iface *if_lookup_name(struct ldpd_conf *, const char *);
void if_update_info(struct iface *, struct kif *);

View File

@ -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,13 +31,30 @@ 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 = \
frratomic.h \
buffer.h checksum.h filter.h getopt.h hash.h \
if.h linklist.h log.h \
graph.h command_match.h \
@ -54,6 +71,8 @@ pkginclude_HEADERS = \
monotime.h \
spf_backoff.h \
srcdest_table.h \
module.h \
hook.h \
libfrr.h \
# end

View File

@ -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 */

View File

@ -41,6 +41,7 @@
#include "vrf.h"
#include "command_match.h"
#include "qobj.h"
#include "defaults.h"
DEFINE_MTYPE( LIB, HOST, "Host config")
DEFINE_MTYPE( LIB, STRVEC, "String vector")
@ -1536,6 +1537,23 @@ DEFUN (show_version,
return CMD_SUCCESS;
}
/* "Set" version ... ignore version tags */
DEFUN (frr_version_defaults,
frr_version_defaults_cmd,
"frr <version|defaults> LINE...",
"FRRouting global parameters\n"
"version configuration was written by\n"
"set of configuration defaults used\n"
"version string\n")
{
if (vty->type == VTY_TERM || vty->type == VTY_SHELL)
/* only print this when the user tries to do run it */
vty_out (vty, "%% NOTE: This command currently does nothing.%s"
"%% It is written to the configuration for future reference.%s",
VTY_NEWLINE, VTY_NEWLINE);
return CMD_SUCCESS;
}
/* Help display function for all node. */
DEFUN (config_help,
config_help_cmd,
@ -1636,6 +1654,37 @@ DEFUN (show_commandtree,
return cmd_list_cmds (vty, argc == 3);
}
static void
vty_write_config (struct vty *vty)
{
size_t i;
struct cmd_node *node;
if (vty->type == VTY_TERM)
{
vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
VTY_NEWLINE);
vty_out (vty, "!%s", VTY_NEWLINE);
}
vty_out (vty, "frr version %s%s", FRR_VER_SHORT, VTY_NEWLINE);
vty_out (vty, "frr defaults %s%s", DFLT_NAME, VTY_NEWLINE);
vty_out (vty, "!%s", VTY_NEWLINE);
for (i = 0; i < vector_active (cmdvec); i++)
if ((node = vector_slot (cmdvec, i)) && node->func
&& (node->vtysh || vty->type != VTY_SHELL))
{
if ((*node->func) (vty))
vty_out (vty, "!%s", VTY_NEWLINE);
}
if (vty->type == VTY_TERM)
{
vty_out (vty, "end%s",VTY_NEWLINE);
}
}
/* Write current configuration into file. */
DEFUN (config_write,
@ -1647,9 +1696,7 @@ DEFUN (config_write,
"Write configuration to terminal\n")
{
int idx_type = 1;
unsigned int i;
int fd, dirfd;
struct cmd_node *node;
char *config_file, *slash;
char *config_file_tmp = NULL;
char *config_file_sav = NULL;
@ -1660,32 +1707,10 @@ DEFUN (config_write,
// if command was 'write terminal' or 'show running-config'
if (argc == 2 && (!strcmp(argv[idx_type]->text, "terminal") ||
!strcmp(argv[0]->text, "show")))
{
if (vty->type == VTY_SHELL_SERV)
{
for (i = 0; i < vector_active (cmdvec); i++)
if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
{
if ((*node->func) (vty))
vty_out (vty, "!%s", VTY_NEWLINE);
}
}
else
{
vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
VTY_NEWLINE);
vty_out (vty, "!%s", VTY_NEWLINE);
for (i = 0; i < vector_active (cmdvec); i++)
if ((node = vector_slot (cmdvec, i)) && node->func)
{
if ((*node->func) (vty))
vty_out (vty, "!%s", VTY_NEWLINE);
}
vty_out (vty, "end%s",VTY_NEWLINE);
}
return CMD_SUCCESS;
}
{
vty_write_config (vty);
return CMD_SUCCESS;
}
if (host.noconfig)
return CMD_SUCCESS;
@ -1749,13 +1774,7 @@ DEFUN (config_write,
vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! ");
vty_time_print (file_vty, 1);
vty_out (file_vty, "!\n");
for (i = 0; i < vector_active (cmdvec); i++)
if ((node = vector_slot (cmdvec, i)) && node->func)
{
if ((*node->func) (file_vty))
vty_out (file_vty, "!\n");
}
vty_write_config (file_vty);
vty_close (file_vty);
if (stat(config_file, &conf_stat) >= 0)
@ -1817,7 +1836,9 @@ DEFUN (copy_runningconf_startupconf,
"Copy running config to... \n"
"Copy running config to startup config (same as write file)\n")
{
return config_write (self, vty, argc, argv);
if (!host.noconfig)
vty_write_config (vty);
return CMD_SUCCESS;
}
/** -- **/
@ -2694,6 +2715,7 @@ cmd_init (int terminal)
install_element (CONFIG_NODE, &hostname_cmd);
install_element (CONFIG_NODE, &no_hostname_cmd);
install_element (CONFIG_NODE, &frr_version_defaults_cmd);
if (terminal > 0)
{

118
lib/frratomic.h Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _FRRATOMIC_H
#define _FRRATOMIC_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef FRR_AUTOCONF_ATOMIC
#error autoconf checks for atomic functions were not properly run
#endif
/* ISO C11 */
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
/* gcc 4.7 and newer */
#elif defined(HAVE___ATOMIC)
#define _Atomic volatile
#define memory_order_relaxed __ATOMIC_RELAXED
#define memory_order_consume __ATOMIC_CONSUME
#define memory_order_acquire __ATOMIC_ACQUIRE
#define memory_order_release __ATOMIC_RELEASE
#define memory_order_acq_rel __ATOMIC_ACQ_REL
#define memory_order_seq_cst __ATOMIC_SEQ_CST
#define atomic_load_explicit __atomic_load_n
#define atomic_store_explicit __atomic_store_n
#define atomic_exchange_explicit __atomic_exchange_n
#define atomic_fetch_add_explicit __atomic_fetch_add
#define atomic_fetch_sub_explicit __atomic_fetch_sub
#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
__atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2)
/* gcc 4.1 and newer,
* clang 3.3 (possibly older)
*
* __sync_swap isn't in gcc's documentation, but clang has it
*
* note __sync_synchronize()
*/
#elif defined(HAVE___SYNC)
#define _Atomic volatile
#define memory_order_relaxed 0
#define memory_order_consume 0
#define memory_order_acquire 0
#define memory_order_release 0
#define memory_order_acq_rel 0
#define memory_order_seq_cst 0
#define atomic_load_explicit(ptr, mem) \
({ __sync_synchronize(); \
typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \
__sync_synchronize(); rval; })
#define atomic_store_explicit(ptr, val, mem) \
({ __sync_synchronize(); \
*(ptr) = (val); \
__sync_synchronize(); (void)0; })
#ifdef HAVE___SYNC_SWAP
#define atomic_exchange_explicit(ptr, val, mem) \
({ __sync_synchronize(); \
typeof(*ptr) rval = __sync_swap((ptr, val), 0); \
__sync_synchronize(); rval; })
#else /* !HAVE___SYNC_SWAP */
#define atomic_exchange_explicit(ptr, val, mem) \
({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \
__sync_synchronize(); \
typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \
do { \
old1 = old2; \
old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \
} while (old1 != old2); \
__sync_synchronize(); \
old2; \
})
#endif /* !HAVE___SYNC_SWAP */
#define atomic_fetch_add_explicit(ptr, val, mem) \
({ __sync_synchronize(); \
typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \
__sync_synchronize(); rval; })
#define atomic_fetch_sub_explicit(ptr, val, mem) \
({ __sync_synchronize(); \
typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \
__sync_synchronize(); rval; })
#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \
typeof(desire) _desire = (desire); \
__sync_synchronize(); \
typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \
__sync_synchronize(); \
bool ret = (rval == *_expect); *_expect = rval; ret; })
#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */
#error no atomic functions...
#endif
#endif /* _FRRATOMIC_H */

56
lib/hook.c Normal file
View 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
View 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 */

View File

@ -229,6 +229,9 @@ struct interface
/* Interface metric */
uint32_t metric;
/* Interface Speed in Mb/s */
uint32_t speed;
/* Interface MTU. */
unsigned int mtu; /* IPv4 MTU */
unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */

View File

@ -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);

View File

@ -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);

View File

@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance,
openlog (progname, syslog_flags, zl->facility);
zlog_default = zl;
#ifdef HAVE_GLIBC_BACKTRACE
/* work around backtrace() using lazily resolved dynamically linked
* symbols, which will otherwise cause funny breakage in the SEGV handler.
* (particularly, the dynamic linker can call malloc(), which uses locks
* in programs linked with -pthread, thus can deadlock.) */
void *bt[4];
backtrace (bt, array_size(bt));
free (backtrace_symbols (bt, 0));
backtrace_symbols_fd (bt, 0, 0);
#endif
}
void
@ -1059,7 +1070,7 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_VNC;
else if (strmatch (s, "vnc-direct"))
return ZEBRA_ROUTE_VNC_DIRECT;
else if (strncmp (s, "n", 1) == 0)
else if (strmatch (s, "nhrp"))
return ZEBRA_ROUTE_NHRP;
}
if (afi == AFI_IP6)
@ -1084,7 +1095,7 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_VNC;
else if (strmatch (s, "vnc-direct"))
return ZEBRA_ROUTE_VNC_DIRECT;
else if (strncmp (s, "n", 1) == 0)
else if (strmatch (s, "nhrp"))
return ZEBRA_ROUTE_NHRP;
}
return -1;

View File

@ -27,119 +27,107 @@ struct memgroup **mg_insert = &mg_first;
DEFINE_MGROUP(LIB, "libfrr")
DEFINE_MTYPE(LIB, TMP, "Temporary memory")
static inline void
mt_count_alloc (struct memtype *mt, size_t size)
static inline void mt_count_alloc(struct memtype *mt, size_t size)
{
mt->n_alloc++;
size_t oldsize;
if (mt->size == 0)
mt->size = size;
else if (mt->size != size)
mt->size = SIZE_VAR;
atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed);
oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed);
if (oldsize == 0)
oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed);
if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR)
atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed);
}
static inline void
mt_count_free (struct memtype *mt)
static inline void mt_count_free(struct memtype *mt)
{
assert(mt->n_alloc);
mt->n_alloc--;
assert(mt->n_alloc);
atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed);
}
static inline void *
mt_checkalloc (struct memtype *mt, void *ptr, size_t size)
static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
{
if (__builtin_expect(ptr == NULL, 0))
{
memory_oom (size, mt->name);
return NULL;
}
mt_count_alloc (mt, size);
return ptr;
if (__builtin_expect(ptr == NULL, 0)) {
memory_oom(size, mt->name);
return NULL;
}
mt_count_alloc(mt, size);
return ptr;
}
void *
qmalloc (struct memtype *mt, size_t size)
void *qmalloc(struct memtype *mt, size_t size)
{
return mt_checkalloc (mt, malloc (size), size);
return mt_checkalloc(mt, malloc(size), size);
}
void *
qcalloc (struct memtype *mt, size_t size)
void *qcalloc(struct memtype *mt, size_t size)
{
return mt_checkalloc (mt, calloc (size, 1), size);
return mt_checkalloc(mt, calloc(size, 1), size);
}
void *
qrealloc (struct memtype *mt, void *ptr, size_t size)
void *qrealloc(struct memtype *mt, void *ptr, size_t size)
{
if (ptr)
mt_count_free (mt);
return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size);
if (ptr)
mt_count_free(mt);
return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size);
}
void *
qstrdup (struct memtype *mt, const char *str)
void *qstrdup(struct memtype *mt, const char *str)
{
return mt_checkalloc (mt, strdup (str), strlen (str) + 1);
return mt_checkalloc(mt, strdup(str), strlen(str) + 1);
}
void
qfree (struct memtype *mt, void *ptr)
void qfree(struct memtype *mt, void *ptr)
{
if (ptr)
mt_count_free (mt);
free (ptr);
if (ptr)
mt_count_free(mt);
free(ptr);
}
int
qmem_walk (qmem_walk_fn *func, void *arg)
int qmem_walk(qmem_walk_fn *func, void *arg)
{
struct memgroup *mg;
struct memtype *mt;
int rv;
struct memgroup *mg;
struct memtype *mt;
int rv;
for (mg = mg_first; mg; mg = mg->next)
{
if ((rv = func (arg, mg, NULL)))
return rv;
for (mt = mg->types; mt; mt = mt->next)
if ((rv = func (arg, mg, mt)))
return rv;
}
return 0;
for (mg = mg_first; mg; mg = mg->next) {
if ((rv = func(arg, mg, NULL)))
return rv;
for (mt = mg->types; mt; mt = mt->next)
if ((rv = func(arg, mg, mt)))
return rv;
}
return 0;
}
struct exit_dump_args
{
const char *prefix;
int error;
struct exit_dump_args {
const char *prefix;
int error;
};
static int
qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt)
static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
{
struct exit_dump_args *eda = arg;
struct exit_dump_args *eda = arg;
if (!mt)
{
fprintf (stderr, "%s: showing active allocations in memory group %s\n",
eda->prefix, mg->name);
}
else if (mt->n_alloc)
{
char size[32];
eda->error++;
snprintf (size, sizeof (size), "%10zu", mt->size);
fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n",
eda->prefix, mt->name, mt->n_alloc,
mt->size == SIZE_VAR ? "(variably sized)" : size);
}
return 0;
if (!mt) {
fprintf(stderr, "%s: showing active allocations in "
"memory group %s\n",
eda->prefix, mg->name);
} else if (mt->n_alloc) {
char size[32];
eda->error++;
snprintf(size, sizeof(size), "%10zu", mt->size);
fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n",
eda->prefix, mt->name, mt->n_alloc,
mt->size == SIZE_VAR ? "(variably sized)" : size);
}
return 0;
}
void
log_memstats_stderr (const char *prefix)
void log_memstats_stderr(const char *prefix)
{
struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
qmem_walk (qmem_exit_walker, &eda);
struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
qmem_walk(qmem_exit_walker, &eda);
}

View File

@ -18,23 +18,22 @@
#define _QUAGGA_MEMORY_H
#include <stdlib.h>
#include <frratomic.h>
#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
#define SIZE_VAR ~0UL
struct memtype
{
struct memtype *next, **ref;
const char *name;
size_t n_alloc;
size_t size;
struct memtype {
struct memtype *next, **ref;
const char *name;
_Atomic size_t n_alloc;
_Atomic size_t size;
};
struct memgroup
{
struct memgroup *next, **ref;
struct memtype *types, **insert;
const char *name;
struct memgroup {
struct memgroup *next, **ref;
struct memtype *types, **insert;
const char *name;
};
#if defined(__clang__)
@ -82,14 +81,14 @@ struct memgroup
* DEFINE_MGROUP(MYDAEMON, "my daemon memory")
* DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
* "this mtype is used in multiple files in mydaemon")
* foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo))
* foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
*
* mydaemon_io.c
* bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar))
* bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
*
* DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
* "this mtype is used only in this file")
* baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz))
* baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
*
* Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
* by not having these as part of the macro arguments)
@ -155,15 +154,15 @@ DECLARE_MGROUP(LIB)
DECLARE_MTYPE(TMP)
extern void *qmalloc (struct memtype *mt, size_t size)
extern void *qmalloc(struct memtype *mt, size_t size)
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
extern void *qcalloc (struct memtype *mt, size_t size)
extern void *qcalloc(struct memtype *mt, size_t size)
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
extern void *qrealloc (struct memtype *mt, void *ptr, size_t size)
extern void *qrealloc(struct memtype *mt, void *ptr, size_t size)
__attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL));
extern void *qstrdup (struct memtype *mt, const char *str)
__attribute__ ((malloc, nonnull (1) _RET_NONNULL));
extern void qfree (struct memtype *mt, void *ptr)
extern void qfree(struct memtype *mt, void *ptr)
__attribute__ ((nonnull (1)));
#define XMALLOC(mtype, size) qmalloc(mtype, size)
@ -183,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
*
* return value: 0: continue, !0: abort walk. qmem_walk will return the
* last value from qmem_walk_fn. */
typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt);
extern int qmem_walk (qmem_walk_fn *func, void *arg);
extern void log_memstats_stderr (const char *);
typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
extern int qmem_walk(qmem_walk_fn *func, void *arg);
extern void log_memstats_stderr(const char *);
extern void memory_oom (size_t size, const char *name);
extern void memory_oom(size_t size, const char *name);
#endif /* _QUAGGA_MEMORY_H */

View File

@ -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
View 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
View 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 */

View File

@ -731,7 +731,7 @@ zprivs_init(struct zebra_privs_t *zprivs)
if (zprivs->user)
{
ngroups = sizeof(groups);
if ( (ngroups = getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups )) < 0 )
if (getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups) < 0)
{
/* cant use log.h here as it depends on vty */
fprintf (stderr, "privs_init: could not getgrouplist for user %s\n",

View File

@ -233,6 +233,18 @@ core_handler(int signo
#endif
)
{
/* make sure we don't hang in here. default for SIGALRM is terminate.
* - if we're in backtrace for more than a second, abort. */
struct sigaction sa_default = { .sa_handler = SIG_DFL };
sigaction (SIGALRM, &sa_default, NULL);
sigset_t sigset;
sigemptyset (&sigset);
sigaddset (&sigset, SIGALRM);
sigprocmask (SIG_UNBLOCK, &sigset, NULL);
alarm (1);
zlog_signal(signo, "aborting..."
#ifdef SA_SIGINFO
, siginfo, program_counter(context)
@ -326,6 +338,11 @@ trap_default_signals(void)
#else
act.sa_handler = sigmap[i].handler;
act.sa_flags = 0;
#endif
#ifdef SA_RESETHAND
/* don't try to print backtraces recursively */
if (sigmap[i].handler == core_handler)
act.sa_flags |= SA_RESETHAND;
#endif
}
if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0)

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -39,8 +39,9 @@
#define FRR_SMUX_NAME "@PACKAGE_NAME@"
#define FRR_PTM_NAME "@PACKAGE_NAME@"
#define FRR_FULL_NAME "FreeRangeRouting"
#define FRR_FULL_NAME "FRRouting"
#define FRR_VERSION "@PACKAGE_VERSION@" GIT_SUFFIX
#define FRR_VER_SHORT "@PACKAGE_VERSION@"
#define FRR_BUG_ADDRESS "@PACKAGE_BUGREPORT@"
#define FRR_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al."
#define FRR_CONFIG_ARGS "@CONFIG_ARGS@"

View File

@ -1003,6 +1003,8 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | metric |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | speed |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ifmtu |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ifmtu6 |
@ -1185,6 +1187,7 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
ifp->ptm_enable = stream_getc (s);
ifp->ptm_status = stream_getc (s);
ifp->metric = stream_getl (s);
ifp->speed = stream_getl (s);
ifp->mtu = stream_getl (s);
ifp->mtu6 = stream_getl (s);
ifp->bandwidth = stream_getl (s);

3
m4/.gitignore vendored
View File

@ -4,4 +4,5 @@ Makefile.in
.arch-ids
*~
*.loT
!ax_pthread.m4
!ax_sys_weak_alias.m4

332
m4/ax_pthread.m4 Normal file
View File

@ -0,0 +1,332 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
#
# 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 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { a = 0; }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD

View File

@ -425,7 +425,6 @@ static void nhrp_handle_registration_request(struct nhrp_packet_parser *p)
nbma_natoa = NULL;
if (natted) {
nbma_natoa = nbma_addr;
nbma_addr = &p->peer->vc->remote.nbma;
}
holdtime = htons(cie->holding_time);

View File

@ -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,13 @@ 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_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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,
)

View File

@ -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*/

View File

@ -29,6 +29,7 @@
#include "table.h"
#include "thread.h"
#include "command.h"
#include "defaults.h"
#include "ospf6_proto.h"
#include "ospf6_message.h"
@ -160,7 +161,10 @@ ospf6_create (void)
o->distance_table = route_table_init ();
/* Enable "log-adjacency-changes" */
#if DFLT_OSPF6_LOG_ADJACENCY_CHANGES
SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
#endif
QOBJ_REG (o, ospf6);
return o;
@ -391,7 +395,6 @@ DEFUN (no_ospf6_log_adjacency_changes_detail,
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
return CMD_SUCCESS;
}
@ -470,21 +473,9 @@ DEFUN (no_ospf6_distance,
DEFUN (ospf6_distance_ospf6,
ospf6_distance_ospf6_cmd,
"distance ospf6 <intra-area (1-255)|inter-area (1-255)|external (1-255)> <intra-area (1-255)|inter-area (1-255)|external (1-255)> <intra-area (1-255)|inter-area (1-255)|external (1-255)>",
"distance ospf6 {intra-area (1-255)|inter-area (1-255)|external (1-255)}",
"Administrative distance\n"
"OSPF6 distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n"
"OSPF6 administrative distance\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
@ -493,53 +484,23 @@ DEFUN (ospf6_distance_ospf6,
"Distance for external routes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
char *intra, *inter, *external;
intra = inter = external = NULL;
int idx = 0;
if (argv_find (argv, argc, "intra-area", &idx))
intra = argv[++idx]->arg;
if (argv_find (argv, argc, "intra-area", &idx))
{
vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (argv_find (argv, argc, "intra-area", &idx))
o->distance_intra = atoi(argv[idx + 1]->arg);
idx = 0;
if (argv_find (argv, argc, "inter-area", &idx))
inter = argv[++idx]->arg;
if (argv_find (argv, argc, "inter-area", &idx))
{
vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
o->distance_inter = atoi(argv[idx + 1]->arg);
idx = 0;
if (argv_find (argv, argc, "external", &idx))
external = argv[++idx]->arg;
if (argv_find (argv, argc, "external", &idx))
{
vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (intra)
o->distance_intra = atoi (intra);
if (inter)
o->distance_inter = atoi (inter);
if (external)
o->distance_external = atoi (external);
o->distance_external = atoi(argv[idx + 1]->arg);
return CMD_SUCCESS;
}
DEFUN (no_ospf6_distance_ospf6,
no_ospf6_distance_ospf6_cmd,
"no distance ospf6 [<intra-area (1-255)|inter-area (1-255)|external (1-255)> <intra-area (1-255)|inter-area (1-255)|external (1-255)> <intra-area (1-255)|inter-area (1-255)|external (1-255)>]",
"no distance ospf6 [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]",
NO_STR
"Administrative distance\n"
"OSPF6 distance\n"
@ -548,70 +509,16 @@ DEFUN (no_ospf6_distance_ospf6,
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n"
"Intra-area routes\n"
"Distance for intra-area routes\n"
"Inter-area routes\n"
"Distance for inter-area routes\n"
"External routes\n"
"Distance for external routes\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
char *intra, *inter, *external;
intra = inter = external = NULL;
if (argc == 3)
{
/* If no arguments are given, clear all distance information */
o->distance_intra = 0;
o->distance_inter = 0;
o->distance_external = 0;
return CMD_SUCCESS;
}
int idx = 0;
if (argv_find (argv, argc, "intra-area", &idx))
intra = argv[++idx]->arg;
if (argv_find (argv, argc, "intra-area", &idx))
{
vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
idx = 0;
if (argv_find (argv, argc, "inter-area", &idx))
inter = argv[++idx]->arg;
if (argv_find (argv, argc, "inter-area", &idx))
{
vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
idx = 0;
if (argv_find (argv, argc, "external", &idx))
external = argv[++idx]->arg;
if (argv_find (argv, argc, "external", &idx))
{
vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (argc < 3) /* should not happen */
return CMD_WARNING;
if (intra)
o->distance_intra = 0;
if (inter)
o->distance_inter = 0;
if (external)
if (argv_find (argv, argc, "intra-area", &idx) || argc == 3)
idx = o->distance_intra = 0;
if (argv_find (argv, argc, "inter-area", &idx) || argc == 3)
idx = o->distance_inter = 0;
if (argv_find (argv, argc, "external", &idx) || argc == 3)
o->distance_external = 0;
return CMD_SUCCESS;
@ -1118,8 +1025,10 @@ config_write_ospf6 (struct vty *vty)
{
if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
vty_out(vty, " log-adjacency-changes detail%s", VTY_NEWLINE);
else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
vty_out(vty, " log-adjacency-changes%s", VTY_NEWLINE);
}
else
else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
{
vty_out(vty, " no log-adjacency-changes%s", VTY_NEWLINE);
}

View File

@ -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);

View File

@ -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,21 @@ 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_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
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)

View File

@ -2,7 +2,7 @@
* OSPFd dump routine (parts used by ospfclient).
* Copyright (C) 1999, 2000 Toshiaki Takada
*
* This file is part of FreeRangeRouting (FRR).
* This file is part of FRRouting (FRR).
*
* FRR 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

View File

@ -2,7 +2,7 @@
* OSPFd dump routine (parts used by ospfclient).
* Copyright (C) 1999 Toshiaki Takada
*
* This file is part of FreeRangeRouting (FRR).
* This file is part of FRRouting (FRR).
*
* FRR 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

View File

@ -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);

Some files were not shown because too many files have changed in this diff Show More