mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 22:37:49 +00:00
Merge branch 'master' into pim_5549
This commit is contained in:
commit
096398104b
93
COMMUNITY.md
93
COMMUNITY.md
@ -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
|
||||

|
||||
|
||||
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 don’t reformat existing files (or only sections modified by your
|
||||
changes), even if they don’t 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.
|
||||
|
@ -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/
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_dump.h"
|
||||
#include "bgpd/bgp_open.h"
|
||||
#include "bgpd/bgp_advertise.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_memory.h"
|
||||
|
||||
DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DEFINE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
/* Definition of display strings corresponding to FSM events. This should be
|
||||
* kept consistent with the events defined in bgpd.h
|
||||
*/
|
||||
@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer)
|
||||
zlog_debug ("%s remove from all update group", peer->host);
|
||||
update_group_remove_peer_afs(peer);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapBackwardTransition (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_backward_transition, peer);
|
||||
|
||||
/* Reset peer synctime */
|
||||
peer->synctime = 0;
|
||||
@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer)
|
||||
zlog_debug ("%s graceful restart timer stopped", peer->host);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapEstablished (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_established, peer);
|
||||
|
||||
/* Reset uptime, send keepalive, send current table. */
|
||||
peer->uptime = bgp_clock ();
|
||||
|
@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *);
|
||||
*/
|
||||
extern void bgp_adjust_routeadv (struct peer *);
|
||||
|
||||
#include "hook.h"
|
||||
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
#endif /* _QUAGGA_BGP_FSM_H */
|
||||
|
@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "thread.h"
|
||||
#include "smux.h"
|
||||
#include "filter.h"
|
||||
#include "hook.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_table.h"
|
||||
@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
|
||||
/* BGP4-MIB described in RFC1657. */
|
||||
#define BGP4MIB 1,3,6,1,2,1,15
|
||||
@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] =
|
||||
{3, {3, 1, BGPPEERSTATE}}
|
||||
};
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapEstablished (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPESTABLISHED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapBackwardTransition (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPBACKWARDTRANSITION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_snmp_init (void)
|
||||
static int
|
||||
bgp_snmp_init (struct thread_master *tm)
|
||||
{
|
||||
smux_init (bm->master);
|
||||
smux_init (tm);
|
||||
REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
bgp_snmp_module_init (void)
|
||||
{
|
||||
hook_register(peer_established, bgpTrapEstablished);
|
||||
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
|
||||
hook_register(frr_late_init, bgp_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "bgpd_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "bgpd AgentX SNMP module",
|
||||
.init = bgp_snmp_module_init
|
||||
)
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* BGP4 SNMP support
|
||||
Copyright (C) 1999, 2000 Kunihiro Ishiguro
|
||||
|
||||
This file is part of GNU Zebra.
|
||||
|
||||
GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
GNU Zebra is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#ifndef _QUAGGA_BGP_SNMP_H
|
||||
#define _QUAGGA_BGP_SNMP_H
|
||||
|
||||
extern void bgp_snmp_init (void);
|
||||
extern void bgpTrapEstablished (struct peer *);
|
||||
extern void bgpTrapBackwardTransition (struct peer *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_SNMP_H */
|
45
bgpd/bgpd.c
45
bgpd/bgpd.c
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
176
configure.ac
176
configure.ac
@ -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}
|
||||
|
2
debian/README.Debian
vendored
2
debian/README.Debian
vendored
@ -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
4
debian/copyright
vendored
@ -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
54
defaults.h
Normal 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 */
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -18,6 +18,7 @@ daemons.
|
||||
* Config Commands:: Commands used in config files
|
||||
* Terminal Mode Commands:: Common commands used in a VTY
|
||||
* Common Invocation Options:: Starting the daemons
|
||||
* Loadable Module Support:: Using extension modules
|
||||
* Virtual Terminal Interfaces:: Interacting with the daemons
|
||||
@end menu
|
||||
|
||||
@ -372,6 +373,51 @@ Print program version.
|
||||
@end table
|
||||
|
||||
|
||||
@node Loadable Module Support
|
||||
@section Loadable Module Support
|
||||
|
||||
FRR supports loading extension modules at startup. Loading, reloading or
|
||||
unloading modules at runtime is not supported (yet). To load a module, use
|
||||
the following command line option at daemon startup:
|
||||
|
||||
@table @samp
|
||||
@item -M @var{module:options}
|
||||
@itemx --module @var{module:options}
|
||||
|
||||
Load the specified module, optionally passing options to it. If the module
|
||||
name contains a slash (/), it is assumed to be a full pathname to a file to
|
||||
be loaded. If it does not contain a slash, the
|
||||
@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of
|
||||
the given name; first with the daemon name prepended (e.g. @code{zebra_mod}
|
||||
for @code{mod}), then without the daemon name prepended.
|
||||
|
||||
This option is available on all daemons, though some daemons may not have
|
||||
any modules available to be loaded.
|
||||
@end table
|
||||
|
||||
|
||||
@subsection The SNMP Module
|
||||
|
||||
If SNMP is enabled during compile-time and installed as part of the package,
|
||||
the @code{snmp} module can be loaded for the @command{zebra},
|
||||
@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons.
|
||||
|
||||
The module ignores any options passed to it. Refer to @ref{SNMP Support}
|
||||
for information on its usage.
|
||||
|
||||
|
||||
@subsection The FPM Module
|
||||
|
||||
If FPM is enabled during compile-time and installed as part of the package,
|
||||
the @code{fpm} module can be loaded for the @command{zebra} daemon. This
|
||||
provides the Forwarding Plane Manager ("FPM") API.
|
||||
|
||||
The module expects its argument to be either @code{netlink} or
|
||||
@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the
|
||||
default, and @code{protobuf} may not be available if the module was built
|
||||
without protobuf support. Refer to @ref{zebra FIB push interface} for more
|
||||
information.
|
||||
|
||||
|
||||
@node Virtual Terminal Interfaces
|
||||
@section Virtual Terminal Interfaces
|
||||
|
@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B bgpd
|
||||
@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR.
|
||||
\fB\-S\fR, \fB\-\-skip_runas\fR
|
||||
Skip setting the process effective user and group.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBbgpd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -13,6 +13,7 @@
|
||||
@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
|
||||
@set INSTALL_PREFIX_SBIN @CFG_SBIN@
|
||||
@set INSTALL_PREFIX_STATE @CFG_STATE@
|
||||
@set INSTALL_PREFIX_MODULES @CFG_MODULE@
|
||||
@set INSTALL_USER @enable_user@
|
||||
@set INSTALL_GROUP @enable_group@
|
||||
@set INSTALL_VTY_GROUP @enable_vty_group@
|
||||
|
119
doc/dev-modules.md
Normal file
119
doc/dev-modules.md
Normal file
@ -0,0 +1,119 @@
|
||||
# Module and Hook support (developer docs)
|
||||
|
||||
## What it does
|
||||
|
||||
It uses `dlopen()` to load DSOs at startup.
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
* can't load, unload, or reload during runtime. This just needs some work
|
||||
and can probably be done in the future.
|
||||
* doesn't fix any of the "things need to be changed in the code in the library"
|
||||
issues. Most prominently, you can't add a CLI node because CLI nodes are
|
||||
listed in the library...
|
||||
* if your module crashes, the daemon crashes. Should be obvious.
|
||||
* **does not provide a stable API or ABI**. Your module must match a version
|
||||
of FRR and you may have to update it frequently to match changes.
|
||||
* **does not create a license boundary**. Your module will need to link
|
||||
libzebra and include header files from the daemons, meaning it will be
|
||||
GPL-encumbered.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Look for `moduledir` in `configure.ac`, default is normally
|
||||
`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`.
|
||||
|
||||
The daemon's name is prepended when looking for a module, e.g. "snmp" tries
|
||||
to find "zebra_snmp" first when used in zebra. This is just to make it nicer
|
||||
for the user, with the snmp module having the same name everywhere.
|
||||
|
||||
Modules can be packaged separately from FRR. The SNMP and FPM modules are
|
||||
good candidates for this because they have dependencies (net-snmp / protobuf)
|
||||
that are not FRR dependencies. However, any distro packages should have an
|
||||
"exact-match" dependency onto the FRR package. Using a module from a
|
||||
different FRR version will probably blow up nicely.
|
||||
|
||||
For snapcraft (and during development), modules can be loaded with full path
|
||||
(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output
|
||||
files in the .libs directory, so during development you have to use
|
||||
`./zebra -M .libs/zebra_snmp.so`.
|
||||
|
||||
|
||||
## Creating a module
|
||||
|
||||
... best to look at the existing SNMP or FPM modules.
|
||||
|
||||
Basic boilerplate:
|
||||
|
||||
```
|
||||
#include "hook.h"
|
||||
#include "module.h"
|
||||
|
||||
static int
|
||||
module_init (void)
|
||||
{
|
||||
hook_register(frr_late_init, module_late_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "my module",
|
||||
.version = "0.0",
|
||||
.description = "my module",
|
||||
.init = module_init,
|
||||
)
|
||||
```
|
||||
|
||||
The `frr_late_init` hook will be called after the daemon has finished its
|
||||
other startup and is about to enter the main event loop; this is the best
|
||||
place for most initialisation.
|
||||
|
||||
|
||||
## Compiler & Linker magic
|
||||
|
||||
There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility`
|
||||
attributes to restrict it to the current module. If you get a linker error
|
||||
with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be
|
||||
possible, though one way to get it would be to not include libzebra (which
|
||||
provides a fallback definition for the symbol).
|
||||
|
||||
libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable
|
||||
modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use
|
||||
the definition in libzebra; same applies if the main executable doesn't use
|
||||
`FRR_DAEMON_INFO` (e.g. all testcases).
|
||||
|
||||
The deciding factor here is "what dynamic linker unit are you using the symbol
|
||||
from." If you're in a library function and want to know who called you, you
|
||||
can't use `THIS_MODULE` (because that'll just tell you you're in the library).
|
||||
Put a macro around your function that adds `THIS_MODULE` in the *caller's
|
||||
code calling your function*.
|
||||
|
||||
The idea is to use this in the future for module unloading. Hooks already
|
||||
remember which module they were installed by, as groundwork for a function
|
||||
that removes all of a module's installed hooks.
|
||||
|
||||
There's also the `frr_module` symbol in modules, pretty much a standard entry
|
||||
point for loadable modules.
|
||||
|
||||
|
||||
## Hooks
|
||||
|
||||
Hooks are just points in the code where you can register your callback to
|
||||
be called. The parameter list is specific to the hook point. Since there is
|
||||
no stable API, the hook code has some extra type safety checks making sure
|
||||
you get a compiler warning when the hook parameter list doesn't match your
|
||||
callback. Don't ignore these warnings.
|
||||
|
||||
|
||||
## Relation to MTYPE macros
|
||||
|
||||
The MTYPE macros, while primarily designed to decouple MTYPEs from the library
|
||||
and beautify the code, also work very nicely with loadable modules -- both
|
||||
constructors and destructors are executed when loading/unloading modules.
|
||||
|
||||
This means there is absolutely no change required to MTYPEs, you can just use
|
||||
them in a module and they will even clean up themselves when we implement
|
||||
module unloading and an unload happens. In fact, it's impossible to create
|
||||
a bug where unloading fails to de-register a MTYPE.
|
12
doc/frr.texi
12
doc/frr.texi
@ -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 |
@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B isisd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBisisd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ldpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBldpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -385,7 +385,8 @@ ip protocol rip route-map RM1
|
||||
|
||||
Zebra supports a 'FIB push' interface that allows an external
|
||||
component to learn the forwarding information computed by the Frr
|
||||
routing suite.
|
||||
routing suite. This is a loadable module that needs to be enabled
|
||||
at startup as described in @ref{Loadable Module Support}.
|
||||
|
||||
In Frr, the Routing Information Base (RIB) resides inside
|
||||
zebra. Routing protocols communicate their best routes to zebra, and
|
||||
@ -440,9 +441,9 @@ independently.
|
||||
@end itemize
|
||||
|
||||
As mentioned before, zebra encodes routes sent to the FPM in netlink
|
||||
format by default. The format can be controlled via the
|
||||
@code{--fpm_format} command-line option to zebra, which currently
|
||||
takes the values @code{netlink} and @code{protobuf}.
|
||||
format by default. The format can be controlled via the FPM module's
|
||||
load-time option to zebra, which currently takes the values @code{netlink}
|
||||
and @code{protobuf}.
|
||||
|
||||
The zebra FPM interface uses replace semantics. That is, if a 'route
|
||||
add' message for a prefix is followed by another 'route add' message,
|
||||
|
@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B nhrpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBnhrpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospf6d
|
||||
@ -64,6 +67,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospf6d\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospfd
|
||||
@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-a\fR, \fB\-\-apiserver \fR
|
||||
Enable OSPF apiserver. Default is disabled.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospfd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -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}.
|
||||
|
@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B pimd
|
||||
@ -70,6 +73,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBpimd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.TP
|
||||
|
@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBripd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripngd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBripngd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol
|
||||
(@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the
|
||||
routing protocol MIBs available through it.
|
||||
|
||||
Note that SNMP Support needs to be enabled at compile-time and loaded as
|
||||
module on daemon startup. Refer to @ref{Loadable Module Support} on
|
||||
the latter.
|
||||
|
||||
@menu
|
||||
* Getting and installing an SNMP agent::
|
||||
* AgentX configuration::
|
||||
|
@ -108,13 +108,13 @@ Set the logging
|
||||
(LOG_DEBUG), but higher number can be supplied if extra debugging messages
|
||||
are required.
|
||||
.TP
|
||||
.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number
|
||||
.BI \-\-min\-restart\-interval " number
|
||||
Set the minimum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
default value is "60").
|
||||
.TP
|
||||
.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number
|
||||
.BI \-\-max\-restart\-interval " number
|
||||
Set the maximum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
|
@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B zebra
|
||||
@ -86,6 +89,14 @@ maximum before starting zebra.
|
||||
|
||||
Note that this affects Linux only.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR and \fBfpm\fR modules may be
|
||||
available for \fBzebra\fR, if the package was built with SNMP and FPM support
|
||||
respectively. The \fBfpm\fR module takes an additional colon-separated
|
||||
argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR.
|
||||
It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
56
ldpd/l2vpn.c
56
ldpd/l2vpn.c
@ -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)
|
||||
{
|
||||
|
60
ldpd/lde.c
60
ldpd/lde.c
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
333
ldpd/ldpd.c
333
ldpd/ldpd.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
23
ldpd/ldpe.c
23
ldpd/ldpe.c
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
118
lib/frratomic.h
Normal 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
56
lib/hook.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "hook.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry")
|
||||
|
||||
void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
|
||||
struct frrmod_runtime *module, const char *funcname)
|
||||
{
|
||||
struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he));
|
||||
he->hookfn = funcptr;
|
||||
he->hookarg = arg;
|
||||
he->has_arg = has_arg;
|
||||
he->module = module;
|
||||
he->fnname = funcname;
|
||||
|
||||
he->next = hook->entries;
|
||||
hook->entries = he;
|
||||
}
|
||||
|
||||
void _hook_unregister(struct hook *hook, void *funcptr,
|
||||
void *arg, bool has_arg)
|
||||
{
|
||||
struct hookent *he, **prev;
|
||||
|
||||
for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next)
|
||||
if (he->hookfn == funcptr && he->hookarg == arg
|
||||
&& he->has_arg == has_arg)
|
||||
{
|
||||
*prev = he->next;
|
||||
XFREE(MTYPE_HOOK_ENTRY, he);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
187
lib/hook.h
Normal file
187
lib/hook.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_HOOK_H
|
||||
#define _FRR_HOOK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* type-safe subscribable hook points
|
||||
*
|
||||
* where "type-safe" applies to the function pointers used for subscriptions
|
||||
*
|
||||
* overall usage:
|
||||
* - to create a hook:
|
||||
*
|
||||
* mydaemon.h:
|
||||
* #include "hook.h"
|
||||
* DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
*
|
||||
* mydaemon.c:
|
||||
* DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
* ...
|
||||
* hook_call (some_update_event, info)
|
||||
*
|
||||
* Note: the second and third macro args must be the hook function's
|
||||
* parameter list, with the same names for each parameter. The second
|
||||
* macro arg is with types (used for defining things), the third arg is
|
||||
* just the names (used for passing along parameters).
|
||||
*
|
||||
* Do not use parameter names starting with "hook", these can collide with
|
||||
* names used by the hook code itself.
|
||||
*
|
||||
* The return value is always "int" for now; hook_call will sum up the
|
||||
* return values from each registered user. Default is 0.
|
||||
*
|
||||
* There are no pre-defined semantics for the value, in most cases it is
|
||||
* ignored. For success/failure indication, 0 should be success, and
|
||||
* handlers should make sure to only return 0 or 1 (not -1 or other values).
|
||||
*
|
||||
*
|
||||
* - to use a hook / create a handler:
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (struct eventinfo *info) { ... }
|
||||
* hook_register (some_update_event, event_handler);
|
||||
*
|
||||
* or, if you need an argument to be passed along (addonptr will be added
|
||||
* as first argument when calling the handler):
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (void *addonptr, struct eventinfo *info) { ... }
|
||||
* hook_register_arg (some_update_event, event_handler, addonptr);
|
||||
*
|
||||
* (addonptr isn't typesafe, but that should be manageable.)
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - hook_unregister_all_module()
|
||||
* - introspection / CLI / debug
|
||||
* - testcases ;)
|
||||
*
|
||||
* For loadable modules, the idea is that hooks could be automatically
|
||||
* unregistered when a module is unloaded.
|
||||
*
|
||||
* It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK,
|
||||
* which would make it possible for the CLI to show all hooks and all
|
||||
* registered handlers.
|
||||
*/
|
||||
|
||||
struct hookent {
|
||||
struct hookent *next;
|
||||
void *hookfn; /* actually a function pointer */
|
||||
void *hookarg;
|
||||
bool has_arg;
|
||||
struct frrmod_runtime *module;
|
||||
const char *fnname;
|
||||
};
|
||||
|
||||
struct hook {
|
||||
const char *name;
|
||||
struct hookent *entries;
|
||||
};
|
||||
|
||||
/* subscribe/add callback function to a hook
|
||||
*
|
||||
* always use hook_register(), which uses the static inline helper from
|
||||
* DECLARE_HOOK in order to get type safety
|
||||
*/
|
||||
extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg, struct frrmod_runtime *module,
|
||||
const char *funcname);
|
||||
#define hook_register(hookname, func) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), \
|
||||
NULL, false, THIS_MODULE, #func)
|
||||
#define hook_register_arg(hookname, func, arg) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), \
|
||||
arg, true, THIS_MODULE, #func)
|
||||
|
||||
extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg);
|
||||
#define hook_unregister(hookname, func) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), NULL, false)
|
||||
#define hook_unregister_arg(hookname, func, arg) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), arg, true)
|
||||
|
||||
/* invoke hooks
|
||||
* this is private (static) to the file that has the DEFINE_HOOK statement
|
||||
*/
|
||||
#define hook_call(hookname, ...) \
|
||||
hook_call_ ## hookname (__VA_ARGS__)
|
||||
|
||||
/* helpers to add the void * arg */
|
||||
#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__)
|
||||
#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__)
|
||||
|
||||
/* use in header file - declares the hook and its arguments
|
||||
* usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2))
|
||||
* as above, "passlist" must use the same order and same names as "arglist"
|
||||
*
|
||||
* theoretically passlist is not neccessary, but let's keep things simple and
|
||||
* use exact same args on DECLARE and DEFINE.
|
||||
*/
|
||||
#define DECLARE_HOOK(hookname, arglist, passlist) \
|
||||
extern struct hook _hook_ ## hookname; \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_ ## hookname ( \
|
||||
int (*funcptr) arglist) { \
|
||||
return (void *)funcptr; } \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_arg_ ## hookname ( \
|
||||
int (*funcptr) HOOK_ADDDEF arglist) { \
|
||||
return (void *)funcptr; }
|
||||
|
||||
/* use in source file - contains hook-related definitions.
|
||||
*/
|
||||
#define DEFINE_HOOK(hookname, arglist, passlist) \
|
||||
struct hook _hook_ ## hookname = { \
|
||||
.name = #hookname, \
|
||||
.entries = NULL, \
|
||||
}; \
|
||||
static int hook_call_ ## hookname arglist { \
|
||||
int hooksum = 0; \
|
||||
struct hookent *he = _hook_ ## hookname .entries; \
|
||||
void *hookarg; \
|
||||
union { \
|
||||
void *voidptr; \
|
||||
int (*fptr) arglist; \
|
||||
int (*farg) HOOK_ADDDEF arglist; \
|
||||
} hookp; \
|
||||
for (; he; he = he->next) { \
|
||||
hookarg = he->hookarg; \
|
||||
hookp.voidptr = he->hookfn; \
|
||||
if (!he->has_arg) \
|
||||
hooksum += hookp.fptr passlist; \
|
||||
else \
|
||||
hooksum += hookp.farg HOOK_ADDARG passlist; \
|
||||
} \
|
||||
return hooksum; \
|
||||
}
|
||||
|
||||
#endif /* _FRR_HOOK_H */
|
3
lib/if.h
3
lib/if.h
@ -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 */
|
||||
|
38
lib/libfrr.c
38
lib/libfrr.c
@ -28,6 +28,9 @@
|
||||
#include "memory_vty.h"
|
||||
#include "zclient.h"
|
||||
#include "log_int.h"
|
||||
#include "module.h"
|
||||
|
||||
DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
|
||||
const char frr_sysconfdir[] = SYSCONFDIR;
|
||||
const char frr_vtydir[] = DAEMON_VTY_DIR;
|
||||
@ -64,14 +67,16 @@ static const struct option lo_always[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "daemon", no_argument, NULL, 'd' },
|
||||
{ "module", no_argument, NULL, 'M' },
|
||||
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct optspec os_always = {
|
||||
"hvdi:",
|
||||
"hvdM:",
|
||||
" -h, --help Display this help and exit\n"
|
||||
" -v, --version Print program version\n"
|
||||
" -d, --daemon Runs in daemon mode\n"
|
||||
" -M, --module Load specified module\n"
|
||||
" --vty_socket Override vty socket path\n",
|
||||
lo_always
|
||||
};
|
||||
@ -184,12 +189,18 @@ void frr_help_exit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
struct option_chain {
|
||||
struct option_chain *next;
|
||||
const char *arg;
|
||||
};
|
||||
static struct option_chain *modules = NULL, **modnext = &modules;
|
||||
static int errors = 0;
|
||||
|
||||
static int frr_opt(int opt)
|
||||
{
|
||||
static int vty_port_set = 0;
|
||||
static int vty_addr_set = 0;
|
||||
struct option_chain *oc;
|
||||
char *err;
|
||||
|
||||
switch (opt) {
|
||||
@ -203,6 +214,13 @@ static int frr_opt(int opt)
|
||||
case 'd':
|
||||
di->daemon_mode = 1;
|
||||
break;
|
||||
case 'M':
|
||||
oc = XMALLOC(MTYPE_TMP, sizeof(*oc));
|
||||
oc->arg = optarg;
|
||||
oc->next = NULL;
|
||||
*modnext = oc;
|
||||
modnext = &oc->next;
|
||||
break;
|
||||
case 'i':
|
||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||
return 1;
|
||||
@ -295,9 +313,12 @@ int frr_getopt(int argc, char * const argv[], int *longindex)
|
||||
return opt;
|
||||
}
|
||||
|
||||
static struct thread_master *master;
|
||||
struct thread_master *frr_init(void)
|
||||
{
|
||||
struct thread_master *master;
|
||||
struct option_chain *oc;
|
||||
struct frrmod_runtime *module;
|
||||
char moderr[256];
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
@ -307,6 +328,17 @@ struct thread_master *frr_init(void)
|
||||
zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
|
||||
#endif
|
||||
|
||||
frrmod_init(di->module);
|
||||
while (modules) {
|
||||
modules = (oc = modules)->next;
|
||||
module = frrmod_load(oc->arg, moderr, sizeof(moderr));
|
||||
if (!module) {
|
||||
fprintf(stderr, "%s\n", moderr);
|
||||
exit(1);
|
||||
}
|
||||
XFREE(MTYPE_TMP, oc);
|
||||
}
|
||||
|
||||
zprivs_init(di->privs);
|
||||
|
||||
master = thread_master_create();
|
||||
@ -324,6 +356,8 @@ struct thread_master *frr_init(void)
|
||||
|
||||
void frr_config_fork(void)
|
||||
{
|
||||
hook_call(frr_late_init, master);
|
||||
|
||||
if (di->instance) {
|
||||
snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf",
|
||||
frr_sysconfdir, di->name, di->instance);
|
||||
|
15
lib/libfrr.h
15
lib/libfrr.h
@ -26,6 +26,8 @@
|
||||
#include "thread.h"
|
||||
#include "log.h"
|
||||
#include "getopt.h"
|
||||
#include "module.h"
|
||||
#include "hook.h"
|
||||
|
||||
#define FRR_NO_PRIVSEP (1 << 0)
|
||||
#define FRR_NO_TCPVTY (1 << 1)
|
||||
@ -40,6 +42,7 @@ struct frr_daemon_info {
|
||||
const char *name;
|
||||
const char *logname;
|
||||
unsigned short instance;
|
||||
struct frrmod_runtime *module;
|
||||
|
||||
char *vty_addr;
|
||||
int vty_port;
|
||||
@ -67,15 +70,22 @@ struct frr_daemon_info {
|
||||
* i.e. "ZEBRA" or "BGP"
|
||||
*
|
||||
* note that this macro is also a latch-on point for other changes (e.g.
|
||||
* upcoming plugin support) that need to place some per-daemon things. Each
|
||||
* upcoming module support) that need to place some per-daemon things. Each
|
||||
* daemon should have one of these.
|
||||
*/
|
||||
#define FRR_DAEMON_INFO(execname, constname, ...) \
|
||||
static struct frr_daemon_info execname ##_di = { \
|
||||
.name = # execname, \
|
||||
.logname = # constname, \
|
||||
.module = THIS_MODULE, \
|
||||
__VA_ARGS__ \
|
||||
};
|
||||
}; \
|
||||
FRR_COREMOD_SETUP( \
|
||||
.name = # execname, \
|
||||
.description = # execname " daemon", \
|
||||
.version = FRR_VERSION, \
|
||||
) \
|
||||
/* end */
|
||||
|
||||
extern void frr_preinit(struct frr_daemon_info *daemon,
|
||||
int argc, char **argv);
|
||||
@ -86,6 +96,7 @@ extern void frr_help_exit(int status);
|
||||
|
||||
extern struct thread_master *frr_init(void);
|
||||
|
||||
DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
extern void frr_config_fork(void);
|
||||
|
||||
extern void frr_vty_serv(void);
|
||||
|
15
lib/log.c
15
lib/log.c
@ -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;
|
||||
|
146
lib/memory.c
146
lib/memory.c
@ -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);
|
||||
}
|
||||
|
43
lib/memory.h
43
lib/memory.h
@ -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 */
|
||||
|
@ -1,23 +1,22 @@
|
||||
/*
|
||||
* Memory management routine
|
||||
* Memory and dynamic module VTY routine
|
||||
*
|
||||
* Copyright (C) 1998 Kunihiro Ishiguro
|
||||
* Copyright (C) 2016-2017 David Lamparter for NetDEF, Inc.
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
@ -25,9 +24,12 @@
|
||||
#if (defined(GNU_LINUX) && defined(HAVE_MALLINFO))
|
||||
#include <malloc.h>
|
||||
#endif /* HAVE_MALLINFO */
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "module.h"
|
||||
#include "memory_vty.h"
|
||||
|
||||
/* Looking up memory status from vty interface. */
|
||||
@ -110,10 +112,55 @@ DEFUN (show_memory,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_modules,
|
||||
show_modules_cmd,
|
||||
"show modules",
|
||||
"Show running system information\n"
|
||||
"Loaded modules\n")
|
||||
{
|
||||
struct frrmod_runtime *plug = frrmod_list;
|
||||
|
||||
vty_out (vty, "%-12s %-25s %s%s%s",
|
||||
"Module Name", "Version", "Description",
|
||||
VTY_NEWLINE, VTY_NEWLINE);
|
||||
while (plug)
|
||||
{
|
||||
const struct frrmod_info *i = plug->info;
|
||||
|
||||
vty_out (vty, "%-12s %-25s %s%s", i->name, i->version, i->description,
|
||||
VTY_NEWLINE);
|
||||
if (plug->dl_handle)
|
||||
{
|
||||
#ifdef HAVE_DLINFO_ORIGIN
|
||||
char origin[MAXPATHLEN] = "";
|
||||
dlinfo (plug->dl_handle, RTLD_DI_ORIGIN, &origin);
|
||||
# ifdef HAVE_DLINFO_LINKMAP
|
||||
const char *name;
|
||||
struct link_map *lm = NULL;
|
||||
dlinfo (plug->dl_handle, RTLD_DI_LINKMAP, &lm);
|
||||
if (lm)
|
||||
{
|
||||
name = strrchr(lm->l_name, '/');
|
||||
name = name ? name + 1 : lm->l_name;
|
||||
vty_out (vty, "\tfrom: %s/%s%s", origin, name, VTY_NEWLINE);
|
||||
}
|
||||
# else
|
||||
vty_out (vty, "\tfrom: %s %s", origin, plug->load_name, VTY_NEWLINE);
|
||||
# endif
|
||||
#else
|
||||
vty_out (vty, "\tfrom: %s%s", plug->load_name, VTY_NEWLINE);
|
||||
#endif
|
||||
}
|
||||
plug = plug->next;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
memory_init (void)
|
||||
{
|
||||
install_element (VIEW_NODE, &show_memory_cmd);
|
||||
install_element (VIEW_NODE, &show_modules_cmd);
|
||||
}
|
||||
|
||||
/* Stats querying from users */
|
||||
|
159
lib/module.c
Normal file
159
lib/module.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
#include "version.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name")
|
||||
DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments")
|
||||
|
||||
static struct frrmod_info frrmod_default_info = {
|
||||
.name = "libfrr",
|
||||
.version = FRR_VERSION,
|
||||
.description = "libfrr core module",
|
||||
};
|
||||
union _frrmod_runtime_u frrmod_default = {
|
||||
.r.info = &frrmod_default_info,
|
||||
.r.finished_loading = 1,
|
||||
};
|
||||
|
||||
// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
|
||||
// union _frrmod_runtime_u _frrmod_this_module
|
||||
// __attribute__((weak, alias("frrmod_default")));
|
||||
// elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
|
||||
#pragma weak _frrmod_this_module = frrmod_default
|
||||
// else
|
||||
// error need weak symbol support
|
||||
// endif
|
||||
|
||||
struct frrmod_runtime *frrmod_list = &frrmod_default.r;
|
||||
static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
|
||||
static const char *execname = NULL;
|
||||
|
||||
void frrmod_init(struct frrmod_runtime *modinfo)
|
||||
{
|
||||
modinfo->finished_loading = 1;
|
||||
*frrmod_last = modinfo;
|
||||
frrmod_last = &modinfo->next;
|
||||
|
||||
execname = modinfo->info->name;
|
||||
}
|
||||
|
||||
struct frrmod_runtime *frrmod_load(const char *spec,
|
||||
char *err, size_t err_len)
|
||||
{
|
||||
void *handle = NULL;
|
||||
char name[PATH_MAX], fullpath[PATH_MAX], *args;
|
||||
struct frrmod_runtime *rtinfo, **rtinfop;
|
||||
const struct frrmod_info *info;
|
||||
|
||||
snprintf(name, sizeof(name), "%s", spec);
|
||||
args = strchr(name, ':');
|
||||
if (args)
|
||||
*args++ = '\0';
|
||||
|
||||
if (!strchr(name, '/')) {
|
||||
if (!handle && execname) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so",
|
||||
MODULE_PATH, execname, name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
if (!handle) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/%s.so",
|
||||
MODULE_PATH, name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
}
|
||||
if (!handle) {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s", name);
|
||||
handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
if (!handle) {
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"loading module \"%s\" failed: %s",
|
||||
name, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rtinfop = dlsym(handle, "frr_module");
|
||||
if (!rtinfop) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"\"%s\" is not a Quagga module: %s",
|
||||
name, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
rtinfo = *rtinfop;
|
||||
rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
|
||||
rtinfo->dl_handle = handle;
|
||||
if (args)
|
||||
rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
|
||||
info = rtinfo->info;
|
||||
|
||||
if (rtinfo->finished_loading) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"module \"%s\" already loaded",
|
||||
name);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
if (info->init && info->init()) {
|
||||
dlclose(handle);
|
||||
if (err)
|
||||
snprintf(err, err_len,
|
||||
"module \"%s\" initialisation failed",
|
||||
name);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
rtinfo->finished_loading = 1;
|
||||
|
||||
*frrmod_last = rtinfo;
|
||||
frrmod_last = &rtinfo->next;
|
||||
return rtinfo;
|
||||
|
||||
out_fail:
|
||||
if (rtinfo->load_args)
|
||||
XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
|
||||
XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void frrmod_unload(struct frrmod_runtime *module)
|
||||
{
|
||||
}
|
||||
#endif
|
104
lib/module.h
Normal file
104
lib/module.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_MODULE_H
|
||||
#define _FRR_MODULE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
# error module code needs GCC visibility extensions
|
||||
#elif __GNUC__ < 4
|
||||
# error module code needs GCC visibility extensions
|
||||
#else
|
||||
# define DSO_PUBLIC __attribute__ ((visibility ("default")))
|
||||
# define DSO_SELF __attribute__ ((visibility ("protected")))
|
||||
# define DSO_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
|
||||
struct frrmod_runtime;
|
||||
|
||||
struct frrmod_info {
|
||||
/* single-line few-word title */
|
||||
const char *name;
|
||||
/* human-readable version number, should not contain spaces */
|
||||
const char *version;
|
||||
/* one-paragraph description */
|
||||
const char *description;
|
||||
|
||||
int (*init)(void);
|
||||
};
|
||||
|
||||
/* primary entry point structure to be present in loadable module under
|
||||
* "_frrmod_this_module" dlsym() name
|
||||
*
|
||||
* note space for future extensions is reserved below, so other modules
|
||||
* (e.g. memory management, hooks) can add fields
|
||||
*
|
||||
* const members/info are in frrmod_info.
|
||||
*/
|
||||
struct frrmod_runtime {
|
||||
struct frrmod_runtime *next;
|
||||
|
||||
const struct frrmod_info *info;
|
||||
void *dl_handle;
|
||||
bool finished_loading;
|
||||
|
||||
char *load_name;
|
||||
char *load_args;
|
||||
};
|
||||
|
||||
/* space-reserving foo */
|
||||
struct _frrmod_runtime_size {
|
||||
struct frrmod_runtime r;
|
||||
/* this will barf if frrmod_runtime exceeds 1024 bytes ... */
|
||||
uint8_t space[1024 - sizeof(struct frrmod_runtime)];
|
||||
};
|
||||
union _frrmod_runtime_u {
|
||||
struct frrmod_runtime r;
|
||||
struct _frrmod_runtime_size s;
|
||||
};
|
||||
|
||||
extern union _frrmod_runtime_u _frrmod_this_module;
|
||||
#define THIS_MODULE (&_frrmod_this_module.r)
|
||||
|
||||
#define FRR_COREMOD_SETUP(...) \
|
||||
static const struct frrmod_info _frrmod_info = { __VA_ARGS__ }; \
|
||||
DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \
|
||||
.r.info = &_frrmod_info, \
|
||||
};
|
||||
#define FRR_MODULE_SETUP(...) \
|
||||
FRR_COREMOD_SETUP(__VA_ARGS__) \
|
||||
DSO_SELF struct frrmod_runtime *frr_module = &_frrmod_this_module.r;
|
||||
|
||||
extern struct frrmod_runtime *frrmod_list;
|
||||
|
||||
extern void frrmod_init(struct frrmod_runtime *modinfo);
|
||||
extern struct frrmod_runtime *frrmod_load(const char *spec,
|
||||
char *err, size_t err_len);
|
||||
#if 0
|
||||
/* not implemented yet */
|
||||
extern void frrmod_unload(struct frrmod_runtime *module);
|
||||
#endif
|
||||
|
||||
#endif /* _FRR_MODULE_H */
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#if defined HAVE_SNMP && defined SNMP_SMUX
|
||||
#ifdef SNMP_SMUX
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -1445,4 +1445,4 @@ smux_start(void)
|
||||
/* Schedule first connection. */
|
||||
smux_event (SMUX_SCHEDULE, 0);
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
#endif /* SNMP_SMUX */
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -130,4 +129,3 @@ smux_header_table (struct variable *v, oid *name, size_t *length, int exact,
|
||||
|
||||
return MATCH_SUCCEEDED;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
22
lib/thread.c
22
lib/thread.c
@ -1037,28 +1037,6 @@ thread_process_fds_helper (struct thread_master *m, struct thread *thread, threa
|
||||
|
||||
#if defined(HAVE_POLL)
|
||||
|
||||
#if defined(HAVE_SNMP)
|
||||
/* add snmp fds to poll set */
|
||||
static void
|
||||
add_snmp_pollfds(struct thread_master *m, fd_set *snmpfds, int fdsetsize)
|
||||
{
|
||||
int i;
|
||||
m->handler.pfdcountsnmp = m->handler.pfdcount;
|
||||
/* cycle trough fds and add neccessary fds to poll set */
|
||||
for (i=0;i<fdsetsize;++i)
|
||||
{
|
||||
if (FD_ISSET(i, snmpfds))
|
||||
{
|
||||
assert (m->handler.pfdcountsnmp <= m->handler.pfdsize);
|
||||
|
||||
m->handler.pfds[m->handler.pfdcountsnmp].fd = i;
|
||||
m->handler.pfds[m->handler.pfdcountsnmp].events = POLLIN;
|
||||
m->handler.pfdcountsnmp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check poll events */
|
||||
static void
|
||||
check_pollfds(struct thread_master *m, fd_set *readfd, int num)
|
||||
|
@ -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@"
|
||||
|
@ -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
3
m4/.gitignore
vendored
@ -4,4 +4,5 @@ Makefile.in
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
|
||||
!ax_pthread.m4
|
||||
!ax_sys_weak_alias.m4
|
||||
|
332
m4/ax_pthread.m4
Normal file
332
m4/ax_pthread.m4
Normal 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
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -41,12 +41,14 @@
|
||||
#include "ospf6_neighbor.h"
|
||||
#include "ospf6_intra.h"
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_snmp.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names")
|
||||
DEFINE_QOBJ_TYPE(ospf6_interface)
|
||||
DEFINE_HOOK(ospf6_interface_change,
|
||||
(struct ospf6_interface *oi, int state, int old_state),
|
||||
(oi, state, old_state))
|
||||
|
||||
unsigned char conf_debug_ospf6_interface = 0;
|
||||
|
||||
@ -518,16 +520,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == OSPF6_INTERFACE_POINTTOPOINT) ||
|
||||
(next_state == OSPF6_INTERFACE_DROTHER) ||
|
||||
(next_state == OSPF6_INTERFACE_BDR) ||
|
||||
(next_state == OSPF6_INTERFACE_DR) ||
|
||||
(next_state < prev_state))
|
||||
ospf6TrapIfStateChange (oi);
|
||||
#endif
|
||||
|
||||
hook_call(ospf6_interface_change, oi, next_state, prev_state);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define OSPF6_INTERFACE_H
|
||||
|
||||
#include "qobj.h"
|
||||
#include "hook.h"
|
||||
#include "if.h"
|
||||
|
||||
/* Debug option */
|
||||
@ -182,4 +183,8 @@ extern void install_element_ospf6_clear_interface (void);
|
||||
extern int config_write_ospf6_debug_interface (struct vty *vty);
|
||||
extern void install_element_ospf6_debug_interface (void);
|
||||
|
||||
DECLARE_HOOK(ospf6_interface_change,
|
||||
(struct ospf6_interface *oi, int state, int old_state),
|
||||
(oi, state, old_state))
|
||||
|
||||
#endif /* OSPF6_INTERFACE_H */
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "ospf6_neighbor.h"
|
||||
#include "ospf6_intra.h"
|
||||
#include "ospf6_flood.h"
|
||||
#include "ospf6_snmp.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
#include "ospf6_abr.h"
|
||||
@ -47,6 +46,10 @@
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_zebra.h"
|
||||
|
||||
DEFINE_HOOK(ospf6_neighbor_change,
|
||||
(struct ospf6_neighbor *on, int state, int next_state),
|
||||
(on, state, next_state))
|
||||
|
||||
unsigned char conf_debug_ospf6_neighbor = 0;
|
||||
|
||||
const char *ospf6_neighbor_state_str[] =
|
||||
@ -202,13 +205,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e
|
||||
next_state != OSPF6_NEIGHBOR_LOADING))
|
||||
ospf6_maxage_remove (on->ospf6_if->area->ospf6);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
/* Terminal state or regression */
|
||||
if ((next_state == OSPF6_NEIGHBOR_FULL) ||
|
||||
(next_state == OSPF6_NEIGHBOR_TWOWAY) ||
|
||||
(next_state < prev_state))
|
||||
ospf6TrapNbrStateChange (on);
|
||||
#endif
|
||||
hook_call(ospf6_neighbor_change, on, next_state, prev_state);
|
||||
ospf6_bfd_trigger_event(on, prev_state, next_state);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef OSPF6_NEIGHBOR_H
|
||||
#define OSPF6_NEIGHBOR_H
|
||||
|
||||
#include "hook.h"
|
||||
|
||||
/* Debug option */
|
||||
extern unsigned char conf_debug_ospf6_neighbor;
|
||||
#define OSPF6_DEBUG_NEIGHBOR_STATE 0x01
|
||||
@ -179,4 +181,8 @@ extern void ospf6_neighbor_init (void);
|
||||
extern int config_write_ospf6_debug_neighbor (struct vty *vty);
|
||||
extern void install_element_ospf6_debug_neighbor (void);
|
||||
|
||||
DECLARE_HOOK(ospf6_neighbor_change,
|
||||
(struct ospf6_neighbor *on, int state, int next_state),
|
||||
(on, state, next_state))
|
||||
|
||||
#endif /* OSPF6_NEIGHBOR_H */
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -32,6 +30,8 @@
|
||||
#include "vector.h"
|
||||
#include "vrf.h"
|
||||
#include "smux.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_lsa.h"
|
||||
@ -45,7 +45,6 @@
|
||||
#include "ospf6_abr.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_snmp.h"
|
||||
|
||||
/* OSPFv3-MIB */
|
||||
#define OSPFv3MIB 1,3,6,1,2,1,191
|
||||
@ -1139,11 +1138,18 @@ static struct trap_object ospf6IfTrapList[] =
|
||||
{4, {1, 7, 1, OSPFv3IFAREAID}}
|
||||
};
|
||||
|
||||
void
|
||||
ospf6TrapNbrStateChange (struct ospf6_neighbor *on)
|
||||
static int
|
||||
ospf6TrapNbrStateChange (struct ospf6_neighbor *on,
|
||||
int next_state, int prev_state)
|
||||
{
|
||||
oid index[3];
|
||||
|
||||
/* Terminal state or regression */
|
||||
if ((next_state != OSPF6_NEIGHBOR_FULL) &&
|
||||
(next_state != OSPF6_NEIGHBOR_TWOWAY) &&
|
||||
(next_state >= prev_state))
|
||||
return 0;
|
||||
|
||||
index[0] = on->ospf6_if->interface->ifindex;
|
||||
index[1] = on->ospf6_if->instance_id;
|
||||
index[2] = ntohl (on->router_id);
|
||||
@ -1155,13 +1161,23 @@ ospf6TrapNbrStateChange (struct ospf6_neighbor *on)
|
||||
ospf6NbrTrapList,
|
||||
sizeof ospf6NbrTrapList / sizeof (struct trap_object),
|
||||
NBRSTATECHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6TrapIfStateChange (struct ospf6_interface *oi)
|
||||
static int
|
||||
ospf6TrapIfStateChange (struct ospf6_interface *oi,
|
||||
int next_state, int prev_state)
|
||||
{
|
||||
oid index[2];
|
||||
|
||||
/* Terminal state or regression */
|
||||
if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) &&
|
||||
(next_state != OSPF6_INTERFACE_DROTHER) &&
|
||||
(next_state != OSPF6_INTERFACE_BDR) &&
|
||||
(next_state != OSPF6_INTERFACE_DR) &&
|
||||
(next_state >= prev_state))
|
||||
return 0;
|
||||
|
||||
index[0] = oi->interface->ifindex;
|
||||
index[1] = oi->instance_id;
|
||||
|
||||
@ -1172,15 +1188,30 @@ ospf6TrapIfStateChange (struct ospf6_interface *oi)
|
||||
ospf6IfTrapList,
|
||||
sizeof ospf6IfTrapList / sizeof (struct trap_object),
|
||||
IFSTATECHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register OSPFv3-MIB. */
|
||||
void
|
||||
static int
|
||||
ospf6_snmp_init (struct thread_master *master)
|
||||
{
|
||||
smux_init (master);
|
||||
REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SNMP */
|
||||
static int
|
||||
ospf6_snmp_module_init (void)
|
||||
{
|
||||
hook_register(ospf6_interface_change, ospf6TrapIfStateChange);
|
||||
hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange);
|
||||
hook_register(frr_late_init, ospf6_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "ospf6d_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "ospf6d AgentX SNMP module",
|
||||
.init = ospf6_snmp_module_init,
|
||||
)
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* OSPFv3 SNMP support
|
||||
* Copyright (C) 2004 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef OSPF6_SNMP_H
|
||||
#define OSPF6_SNMP_H
|
||||
|
||||
extern void ospf6TrapNbrStateChange (struct ospf6_neighbor *);
|
||||
extern void ospf6TrapIfStateChange (struct ospf6_interface *);
|
||||
extern void ospf6_snmp_init (struct thread_master *);
|
||||
|
||||
#endif /*OSPF6_SNMP_H*/
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -45,10 +45,6 @@
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_bfd.h"
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include "ospf6_snmp.h"
|
||||
#endif /*HAVE_SNMP*/
|
||||
|
||||
char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION;
|
||||
|
||||
struct route_node *
|
||||
@ -1215,10 +1211,6 @@ ospf6_init (void)
|
||||
ospf6_asbr_init ();
|
||||
ospf6_abr_init ();
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
ospf6_snmp_init (master);
|
||||
#endif /*HAVE_SNMP*/
|
||||
|
||||
ospf6_bfd_init();
|
||||
install_node (&debug_node, config_write_ospf6_debug);
|
||||
|
||||
|
@ -6,13 +6,14 @@ DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
|
||||
INSTALL_SDATA=@INSTALL@ -m 600
|
||||
|
||||
noinst_LIBRARIES = libfrrospf.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = ospfd
|
||||
|
||||
libfrrospf_a_SOURCES = \
|
||||
ospfd.c ospf_zebra.c ospf_interface.c ospf_ism.c ospf_neighbor.c \
|
||||
ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \
|
||||
ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \
|
||||
ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \
|
||||
ospf_lsdb.c ospf_asbr.c ospf_routemap.c \
|
||||
ospf_opaque.c ospf_te.c ospf_ri.c ospf_vty.c ospf_api.c ospf_apiserver.c \
|
||||
ospf_bfd.c ospf_memory.c ospf_dump_api.c
|
||||
|
||||
@ -26,13 +27,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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user