Merge remote-tracking branch 'origin/master' into EIGRP

This commit is contained in:
Donald Sharp 2017-04-05 20:52:32 -04:00
commit 97133f7915
257 changed files with 8482 additions and 2974 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600
AM_CFLAGS = $(WERROR)
noinst_LIBRARIES = libbgp.a
module_LTLIBRARIES =
sbin_PROGRAMS = bgpd
bin_PROGRAMS = bgp_btoa
@ -75,7 +76,7 @@ libbgp_a_SOURCES = \
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \
bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \
bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
@ -89,7 +90,7 @@ noinst_HEADERS = \
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
bgp_ecommunity.h bgp_lcommunity.h \
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h
@ -101,6 +102,15 @@ bgp_btoa_SOURCES = bgp_btoa.c
bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS)
if SNMP
module_LTLIBRARIES += bgpd_snmp.la
endif
bgpd_snmp_la_SOURCES = bgp_snmp.c
bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
examplesdir = $(exampledir)
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
bgpd.conf.vnc.sample

View File

@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_dump.h"
#include "bgpd/bgp_open.h"
#include "bgpd/bgp_advertise.h"
#ifdef HAVE_SNMP
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_memory.h"
DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
DEFINE_HOOK(peer_established, (struct peer *peer), (peer))
/* Definition of display strings corresponding to FSM events. This should be
* kept consistent with the events defined in bgpd.h
*/
@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer)
zlog_debug ("%s remove from all update group", peer->host);
update_group_remove_peer_afs(peer);
#ifdef HAVE_SNMP
bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */
hook_call(peer_backward_transition, peer);
/* Reset peer synctime */
peer->synctime = 0;
@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer)
zlog_debug ("%s graceful restart timer stopped", peer->host);
}
#ifdef HAVE_SNMP
bgpTrapEstablished (peer);
#endif /* HAVE_SNMP */
hook_call(peer_established, peer);
/* Reset uptime, send keepalive, send current table. */
peer->uptime = bgp_clock ();

View File

@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *);
*/
extern void bgp_adjust_routeadv (struct peer *);
#include "hook.h"
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
#endif /* _QUAGGA_BGP_FSM_H */

View File

@ -262,7 +262,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst)
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
continue;
ifp = if_lookup_by_name_vrf (name, bgp->vrf_id);
ifp = if_lookup_by_name (name, bgp->vrf_id);
if (ifp)
{
*bgp_inst = bgp;
@ -544,7 +544,7 @@ bgp_update_source (struct peer *peer)
/* Source is specified with interface name. */
if (peer->update_if)
{
ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id);
ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id);
if (! ifp)
return -1;
@ -617,7 +617,7 @@ bgp_connect (struct peer *peer)
}
if (peer->conf_if || peer->ifname)
ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname);
ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id);
if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s [Event] Connect start to %s fd %d",

View File

@ -415,7 +415,7 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
vty_out(vty, " gate %s, if %s%s",
inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
sizeof (buf)),
ifindex2ifname(nexthop->ifindex),
ifindex2ifname(nexthop->ifindex, bgp->vrf_id),
VTY_NEWLINE);
break;
case NEXTHOP_TYPE_IPV4:
@ -425,13 +425,13 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail)
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out (vty, " if %s%s",
ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE);
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
vty_out (vty, " gate %s, if %s%s",
inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
sizeof (buf)),
ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE);
break;
default:
vty_out (vty, " invalid nexthop type %u%s",

View File

@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include <zebra.h>
#ifdef HAVE_SNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "thread.h"
#include "smux.h"
#include "filter.h"
#include "hook.h"
#include "libfrr.h"
#include "version.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_snmp.h"
/* BGP4-MIB described in RFC1657. */
#define BGP4MIB 1,3,6,1,2,1,15
@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] =
{3, {3, 1, BGPPEERSTATE}}
};
void
static int
bgpTrapEstablished (struct peer *peer)
{
int ret;
@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer)
ret = inet_aton (peer->host, &addr);
if (ret == 0)
return;
return 0;
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer)
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
BGPESTABLISHED);
return 0;
}
void
static int
bgpTrapBackwardTransition (struct peer *peer)
{
int ret;
@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer)
ret = inet_aton (peer->host, &addr);
if (ret == 0)
return;
return 0;
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer)
index, IN_ADDR_SIZE,
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
BGPBACKWARDTRANSITION);
return 0;
}
void
bgp_snmp_init (void)
static int
bgp_snmp_init (struct thread_master *tm)
{
smux_init (bm->master);
smux_init (tm);
REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
return 0;
}
#endif /* HAVE_SNMP */
static int
bgp_snmp_module_init (void)
{
hook_register(peer_established, bgpTrapEstablished);
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
hook_register(frr_late_init, bgp_snmp_init);
return 0;
}
FRR_MODULE_SETUP(
.name = "bgpd_snmp",
.version = FRR_VERSION,
.description = "bgpd AgentX SNMP module",
.init = bgp_snmp_module_init
)

View File

@ -1,28 +0,0 @@
/* BGP4 SNMP support
Copyright (C) 1999, 2000 Kunihiro Ishiguro
This file is part of GNU Zebra.
GNU Zebra is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
GNU Zebra is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Zebra; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#ifndef _QUAGGA_BGP_SNMP_H
#define _QUAGGA_BGP_SNMP_H
extern void bgp_snmp_init (void);
extern void bgpTrapEstablished (struct peer *);
extern void bgpTrapBackwardTransition (struct peer *);
#endif /* _QUAGGA_BGP_SNMP_H */

View File

@ -806,7 +806,7 @@ DEFUN (no_auto_summary,
}
/* "router bgp" commands. */
DEFUN (router_bgp,
DEFUN_NOSH (router_bgp,
router_bgp_cmd,
"router bgp [(1-4294967295) [<view|vrf> WORD]]",
ROUTER_STR
@ -5647,7 +5647,7 @@ DEFUN (no_neighbor_addpath_tx_bestpath_per_as,
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS);
}
DEFUN (address_family_ipv4_safi,
DEFUN_NOSH (address_family_ipv4_safi,
address_family_ipv4_safi_cmd,
"address-family ipv4 [<unicast|multicast|vpn|encap>]",
"Enter Address Family command mode\n"
@ -5680,7 +5680,7 @@ DEFUN (address_family_ipv4_safi,
return CMD_SUCCESS;
}
DEFUN (address_family_ipv6_safi,
DEFUN_NOSH (address_family_ipv6_safi,
address_family_ipv6_safi_cmd,
"address-family ipv6 [<unicast|multicast|vpn|encap>]",
"Enter Address Family command mode\n"
@ -5714,7 +5714,7 @@ DEFUN (address_family_ipv6_safi,
}
#ifdef KEEP_OLD_VPN_COMMANDS
DEFUN (address_family_vpnv4,
DEFUN_NOSH (address_family_vpnv4,
address_family_vpnv4_cmd,
"address-family vpnv4 [unicast]",
"Enter Address Family command mode\n"
@ -5725,7 +5725,7 @@ DEFUN (address_family_vpnv4,
return CMD_SUCCESS;
}
DEFUN (address_family_vpnv6,
DEFUN_NOSH (address_family_vpnv6,
address_family_vpnv6_cmd,
"address-family vpnv6 [unicast]",
"Enter Address Family command mode\n"
@ -5737,7 +5737,7 @@ DEFUN (address_family_vpnv6,
}
#endif
DEFUN (address_family_encap,
DEFUN_NOSH (address_family_encap,
address_family_encap_cmd,
"address-family <encap|encapv4>",
"Enter Address Family command mode\n"
@ -5749,7 +5749,7 @@ DEFUN (address_family_encap,
}
DEFUN (address_family_encapv6,
DEFUN_NOSH (address_family_encapv6,
address_family_encapv6_cmd,
"address-family encapv6",
"Enter Address Family command mode\n"
@ -5759,7 +5759,7 @@ DEFUN (address_family_encapv6,
return CMD_SUCCESS;
}
DEFUN (address_family_evpn,
DEFUN_NOSH (address_family_evpn,
address_family_evpn_cmd,
"address-family <l2vpn evpn>",
"Enter Address Family command mode\n"
@ -5771,7 +5771,7 @@ DEFUN (address_family_evpn,
return CMD_SUCCESS;
}
DEFUN (exit_address_family,
DEFUN_NOSH (exit_address_family,
exit_address_family_cmd,
"exit-address-family",
"Exit from Address Family configuration mode\n")

View File

@ -570,7 +570,7 @@ bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t len
}
}
if_update_vrf (ifp, ifp->name, strlen (ifp->name), new_vrf_id);
if_update (ifp, ifp->name, strlen (ifp->name), new_vrf_id);
bgp = bgp_lookup_by_vrf_id (new_vrf_id);
if (!bgp)
@ -1026,7 +1026,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
{
nexthop->v4 = local->sin.sin_addr;
if (peer->update_if)
ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id);
ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id);
else
ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr, peer->bgp->vrf_id);
}
@ -1035,10 +1035,10 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
{
if (peer->conf_if || peer->ifname)
ifp = if_lookup_by_name_vrf (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id);
ifp = if_lookup_by_name (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id);
}
else if (peer->update_if)
ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id);
ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id);
else
ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr,
local->sin6.sin6_scope_id,
@ -1509,7 +1509,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
if (!ifindex)
{
if (mpinfo->peer->conf_if || mpinfo->peer->ifname)
ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname, bgp->vrf_id);
else if (mpinfo->peer->nexthop.ifp)
ifindex = mpinfo->peer->nexthop.ifp->ifindex;
}

View File

@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nht.h"
#ifdef HAVE_SNMP
#include "bgpd/bgp_snmp.h"
#endif /* HAVE_SNMP */
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_memory.h"
@ -1435,7 +1432,7 @@ bgp_peer_conf_if_to_su_update (struct peer *peer)
return;
prev_family = peer->su.sa.sa_family;
if ((ifp = if_lookup_by_name_vrf (peer->conf_if, peer->bgp->vrf_id)))
if ((ifp = if_lookup_by_name (peer->conf_if, peer->bgp->vrf_id)))
{
peer->ifp = ifp;
/* If BGP unnumbered is not "v6only", we first see if we can derive the
@ -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;
@ -5016,8 +5021,28 @@ int
peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
{
struct peer_group *group;
struct peer *tmp_peer;
struct listnode *node, *nnode;
/* If this is a peer-group we must first clear the flags for all of the
* peer-group members
*/
if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
{
if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) ||
CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
{
tmp_peer->allowas_in[afi][safi] = 0;
peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
peer_on_policy_change (tmp_peer, afi, safi, 0);
}
}
}
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) ||
CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
{
@ -5027,21 +5052,6 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
peer_on_policy_change (peer, afi, safi, 0);
}
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
return 0;
group = peer->group;
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) ||
CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
{
peer->allowas_in[afi][safi] = 0;
peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
peer_on_policy_change (peer, afi, safi, 0);
}
}
return 0;
}
@ -7379,8 +7389,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 +7409,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 +7456,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 +7536,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 +7669,8 @@ bgp_if_finish (struct bgp *bgp)
}
}
extern void bgp_snmp_init (void);
void
bgp_init (void)
{
@ -7695,10 +7719,6 @@ bgp_init (void)
/* Community list initialize. */
bgp_clist = community_list_init ();
#ifdef HAVE_SNMP
bgp_snmp_init ();
#endif /* HAVE_SNMP */
/* BFD init */
bgp_bfd_init();
}

View File

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

View File

@ -323,7 +323,7 @@ DEFUN (vnc_advertise_un_method,
*-----------------------------------------------------------------------*/
DEFUN (vnc_defaults,
DEFUN_NOSH (vnc_defaults,
vnc_defaults_cmd,
"vnc defaults", VNC_CONFIG_STR "Configure default NVE group\n")
{
@ -2419,7 +2419,7 @@ vnc_routemap_event (route_map_event_t type, /* ignored */
*-----------------------------------------------------------------------*/
DEFUN (vnc_nve_group,
DEFUN_NOSH (vnc_nve_group,
vnc_nve_group_cmd,
"vnc nve-group NAME",
VNC_CONFIG_STR "Configure a NVE group\n" "Group name\n")
@ -3223,7 +3223,7 @@ DEFUN (vnc_nve_group_responselifetime,
* with the lack of rigorous level control in the command handler.
* TBD fix command handler.
*/
DEFUN (exit_vnc,
DEFUN_NOSH (exit_vnc,
exit_vnc_cmd,
"exit-vnc",
"Exit VNC configuration mode\n")
@ -3255,7 +3255,7 @@ static struct cmd_node bgp_vnc_nve_group_node = {
* Note there are two types of NVEs, one for VPNs one for RFP NVEs
*-----------------------------------------------------------------------*/
DEFUN (vnc_vrf_policy,
DEFUN_NOSH (vnc_vrf_policy,
vnc_vrf_policy_cmd,
"vrf-policy NAME",
"Configure a VRF policy group\n"
@ -3720,7 +3720,7 @@ DEFUN (vnc_vrf_policy_rd,
return CMD_SUCCESS;
}
DEFUN (exit_vrf_policy,
DEFUN_NOSH (exit_vrf_policy,
exit_vrf_policy_cmd,
"exit-vrf-policy",
"Exit VRF policy configuration mode\n")
@ -3743,7 +3743,7 @@ static struct cmd_node bgp_vrf_policy_node = {
*-----------------------------------------------------------------------*/
DEFUN (vnc_l2_group,
DEFUN_NOSH (vnc_l2_group,
vnc_l2_group_cmd,
"vnc l2-group NAME",
VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n")

View File

@ -1,5 +1,5 @@
##
## Configure template file for FreeRangeRouting.
## Configure template file for FRRouting.
## autoconf will generate configure script.
##
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
@ -7,9 +7,9 @@
##
AC_PREREQ(2.60)
AC_INIT(frr, 2.1-dev, [https://github.com/freerangerouting/frr/issues])
PACKAGE_URL="https://freerangerouting.org/"
PACKAGE_FULLNAME="FreeRangeRouting"
AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
PACKAGE_FULLNAME="FRRouting"
AC_SUBST(PACKAGE_FULLNAME)
CONFIG_ARGS="$ac_configure_args"
@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
AC_SUBST(pkgsrcdir)
AC_SUBST(pkgsrcrcdir)
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
moduledir="$withval"
], [
moduledir="\${libdir}/frr/modules"
])
AC_SUBST([moduledir], [$moduledir])
AC_ARG_ENABLE(tcmalloc,
AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]),
[case "${enableval}" in
@ -66,6 +73,10 @@ LIBS="$LIBS -ltcmalloc_minimal"
esac],[tcmalloc_enabled=false])
dnl Thanks autoconf, but we don't want a default -g -O2. We have our own
dnl flag determination logic.
CFLAGS="${CFLAGS:-}"
dnl --------------------
dnl Check CC and friends
dnl --------------------
@ -78,6 +89,7 @@ AM_PROG_CC_C_O
dnl remove autoconf default "-g -O2"
CFLAGS="$orig_cflags"
AC_PROG_CC_C99
dnl NB: see C11 below
AC_PROG_EGREP
PKG_PROG_PKG_CONFIG
@ -89,7 +101,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
dnl try and enable CFLAGS that are useful for Quagga
dnl - specifically, options to control warnings
AC_USE_SYSTEM_EXTENSIONS()
AC_USE_SYSTEM_EXTENSIONS
AC_DEFUN([AC_C_FLAG], [{
AC_LANG_PUSH(C)
ac_c_flag_save="$CFLAGS"
@ -115,6 +127,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006
dnl need to do this first so we get useful results for the other options
AC_C_FLAG([-diag-error 10006])
dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something
ac_cc="$CC"
CC="${CC% -std=gnu99}"
CC="${CC% -std=c99}"
AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here
if test "z$orig_cflags" = "z"; then
AC_C_FLAG([-g])
@ -170,6 +189,18 @@ AC_LINK_IFELSE(
])
AC_LANG_POP(C)
dnl ----------
dnl Essentials
dnl ----------
AX_PTHREAD([
CC="$PTHREAD_CC"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
], [
AC_MSG_FAILURE([This Quagga version needs pthreads])
])
dnl --------------
dnl Check programs
dnl --------------
@ -354,15 +385,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)
@ -531,6 +565,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
@ -1327,8 +1427,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);
@ -1340,7 +1440,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
@ -1356,6 +1455,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
@ -1656,14 +1802,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
@ -1692,6 +1842,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
@ -1728,7 +1879,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}
@ -1740,6 +1891,7 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
state file directory : ${frr_statedir}
config file directory : `eval echo \`echo ${sysconfdir}\``
example directory : `eval echo \`echo ${exampledir}\``
module directory : ${CFG_MODULE}
user to run as : ${enable_user}
group to run as : ${enable_group}
group for vty sockets : ${enable_vty_group}

View File

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

4
debian/copyright vendored
View File

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

54
defaults.h Normal file
View File

@ -0,0 +1,54 @@
/*
* FRR switchable defaults.
* Copyright (C) 2017 David Lamparter for NetDEF, Inc.
*
* This file is part of FRRouting (FRR).
*
* FRR is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* FRR is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with FRR; see the file COPYING. If not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _FRR_DEFAULTS_H
#define _FRR_DEFAULTS_H
#include "config.h"
#ifdef HAVE_CUMULUS
#define DFLT_BGP_IMPORT_CHECK 1
#define DFLT_BGP_TIMERS_CONNECT 10
#define DFLT_BGP_HOLDTIME 9
#define DFLT_BGP_KEEPALIVE 3
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1
#define DFLT_BGP_SHOW_HOSTNAME 1
#define DFLT_BGP_DETERMINISTIC_MED 1
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1
#else /* !HAVE_CUMULUS */
#define DFLT_BGP_IMPORT_CHECK 0
#define DFLT_BGP_TIMERS_CONNECT 120
#define DFLT_BGP_HOLDTIME 180
#define DFLT_BGP_KEEPALIVE 60
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0
#define DFLT_BGP_SHOW_HOSTNAME 0
#define DFLT_BGP_DETERMINISTIC_MED 0
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0
#endif /* !HAVE_CUMULUS */
#endif /* _FRR_DEFAULTS_H */

View File

@ -18,7 +18,7 @@ Add packages:
sudo yum install git autoconf automake libtool make gawk readline-devel \
texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \
flex pytest
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
@ -48,16 +48,16 @@ Install newer version of autoconf and automake (Package versions are too old)
Install `Python 2.7` in parallel to default 2.6 (needed for `make check` to
run unittests).
Pick correct EPEL based on CentOS version used. Then install current `pytest`
Make sure you've install EPEL (`epel-release` as above). Then install current
`python2.7` and `pytest`
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh https://centos6.iuscommunity.org/ius-release.rpm
yum install python27 python27-pip
yum install python27 python27-devel python27-pip
pip2.7 install pytest
Please note that `CentOS 6` needs to keep python pointing to version 2.6
for `yum` to keep working, so don't create a symlink for python2.7 to python
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -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,9 +78,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--sysconfdir=/etc/frr \

View File

@ -10,12 +10,16 @@ CentOS 7 restrictions:
Install required packages
-------------------------
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
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)
yum install python34-devel
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -28,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
@ -37,9 +41,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--sysconfdir=/etc/frr \

View File

@ -10,12 +10,12 @@ Debian 8 restrictions:
Install required packages
-------------------------
Add packages:
sudo apt-get install git autoconf automake libtool make gawk \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
python-pip
python-pip libc-ares-dev python3-dev
Install newer pytest (>3.0) from pip
@ -32,16 +32,15 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--enable-exampledir=/usr/share/doc/frr/examples/ \

View File

@ -8,7 +8,8 @@ Add packages:
sudo dnf install git autoconf automake libtool make gawk \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel perl-XML-LibXML pytest
json-c-devel pam-devel perl-XML-LibXML c-ares-devel \
python3-devel
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -21,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
@ -30,9 +31,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--sysconfdir=/etc/frr \

View File

@ -16,7 +16,7 @@ Add packages:
install and asked)
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
bison flex py27-pytest
bison flex py27-pytest c-ares python3
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin):
@ -41,9 +41,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
export MAKE=gmake
export LDFLAGS="-L/usr/local/lib"

View File

@ -16,7 +16,7 @@ Add packages:
install and asked)
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
bison flex py27-pytest
bison flex py27-pytest c-ares python3
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin):
@ -41,9 +41,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
export MAKE=gmake
export LDFLAGS="-L/usr/local/lib"

View File

@ -16,7 +16,8 @@ Add packages:
install and asked)
pkg install -y git autoconf automake libtool gmake gawk \
pkgconf texinfo json-c bison flex py27-pytest
pkgconf texinfo json-c bison flex py27-pytest c-ares \
python3
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin):
@ -25,6 +26,13 @@ takes preference in path)
rm -f /usr/bin/flex
For building with clang (instead of gcc), upgrade clang from 3.4 default to 3.6 *This is needed to build FreeBSD packages as well - for packages clang is default* (Clang 3.4 as shipped with FreeBSD 9 crashes during compile)
pkg install clang36
pkg delete clang34
mv /usr/bin/clang /usr/bin/clang34
ln -s /usr/local/bin/clang36 /usr/bin/clang
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -41,9 +49,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
export MAKE=gmake
export LDFLAGS="-L/usr/local/lib"

View File

@ -18,7 +18,7 @@ Configure Package location:
Add packages:
sudo pkg_add git autoconf automake libtool gmake gawk openssl \
pkg-config json-c p5-XML-LibXML python27 py27-test
pkg-config json-c p5-XML-LibXML python27 py27-test python35
Install SSL Root Certificates (for git https access):
@ -45,9 +45,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
MAKE=gmake
export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"

View File

@ -12,7 +12,7 @@ Install required packages
-------------------------
sudo pkgin install git autoconf automake libtool gmake gawk openssl \
pkg-config json-c p5-XML-LibXML python27 py27-test
pkg-config json-c p5-XML-LibXML python27 py27-test python35
Install SSL Root Certificates (for git https access):
@ -39,9 +39,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
MAKE=gmake
export LDFLAGS="-L/usr/pkg/lib -R/usr/pkg/lib"

View File

@ -41,7 +41,7 @@ Add additional Solaris packages:
/opt/csw/bin/pkgutil -y -i texinfo
/opt/csw/bin/pkgutil -y -i perl
/opt/csw/bin/pkgutil -y -i libjson_c_dev
/opt/csw/bin/pkgutil -y -i python27 py_pip
/opt/csw/bin/pkgutil -y -i python27 py_pip python27_dev
Add libjson to Solaris equivalent of ld.so.conf
@ -61,7 +61,7 @@ Select Python 2.7 as default (required for pytest)
rm -f /usr/bin/python
ln -s /opt/csw/bin/python2.7 /usr/bin/python
Fix PATH for all users and non-interactive sessions. Edit `/etc/default/login`
and add the following default PATH:
@ -87,13 +87,13 @@ 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
git checkout stable/2.0
./bootstrap.sh
export MAKE=gmake
export LDFLAGS="-L/opt/csw/lib"
export CPPFLAGS="-I/opt/csw/include"
export PKG_CONFIG_PATH=/opt/csw/lib/pkgconfig
./configure \
--sysconfdir=/etc/frr \
--enable-exampledir=/usr/share/doc/frr/examples/ \

View File

@ -1,12 +1,6 @@
Building FRR on OpenBSD 6 from Git Source
=========================================
OpenBSD restrictions:
---------------------
- MPLS is not tested on `OpenBSD`. It may work as it shares the
sources with the LDPd on OpenBSD. Bug reports and fixes are welcome
Install required packages
-------------------------
@ -40,9 +34,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
export LDFLAGS="-L/usr/local/lib"
export CPPFLAGS="-I/usr/local/include"
@ -61,7 +54,6 @@ an example)
--enable-rtadv \
--enable-tcp-zebra \
--enable-fpm \
--enable-ldpd \
--with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion
gmake
@ -99,6 +91,18 @@ Add the following lines to the end of `/etc/rc.conf`:
**Reboot** to apply the config to the system
### Enable MPLS Forwarding
To enable MPLS forwarding on a given interface, use the following command:
sudo ifconfig em0 mpls
Alternatively, to make MPLS forwarding persistent across reboots, add the "mpls"
keyword in the hostname.* files of the desired interfaces. Example:
cat /etc/hostname.em0
inet 10.0.1.1 255.255.255.0 mpls
### Install rc.d init files
(create them in /etc/rc.d - no example are included at this time with
FRR source)

View File

@ -12,8 +12,8 @@ Install required packages
Add packages:
apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo libpam0g-dev dejagnu libjson0 pkg-config libpam0g-dev \
libjson0-dev flex python-pip
texinfo libpam0g-dev dejagnu libjson0-dev pkg-config libpam0g-dev \
libjson0-dev flex python-pip libc-ares-dev python3-dev
Install newer bison from 14.04 package source (Ubuntu 12.04 package source
is too old)
@ -72,9 +72,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--enable-exampledir=/usr/share/doc/frr/examples/ \
@ -94,7 +93,6 @@ an example.)
--enable-rtadv \
--enable-tcp-zebra \
--enable-fpm \
--enable-ldpd \
--with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion
make
@ -104,20 +102,20 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/etc/ldpd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo touch /etc/frr/ldpd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -8,12 +8,12 @@ Building FRR on Ubuntu 14.04LTS from Git Source
Install required packages
-------------------------
Add packages:
apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
python-pytest
python-pytest libc-ares-dev python3-dev
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -32,9 +32,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--enable-exampledir=/usr/share/doc/frr/examples/ \
@ -63,19 +62,19 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -14,7 +14,7 @@ Add packages:
apt-get install git autoconf automake libtool make gawk libreadline-dev \
texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
python-pytest
python-pytest libc-ares-dev python3-dev
Get FRR, compile it and install it (from Git)
---------------------------------------------
@ -33,9 +33,8 @@ 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
git checkout stable/2.0
./bootstrap.sh
./configure \
--enable-exampledir=/usr/share/doc/frr/examples/ \
@ -55,7 +54,6 @@ an example.)
--enable-rtadv \
--enable-tcp-zebra \
--enable-fpm \
--enable-ldpd \
--with-pkg-git-version \
--with-pkg-extra-version=-MyOwnFRRVersion
make
@ -65,20 +63,20 @@ an example.)
### Create empty FRR configuration files
sudo mkdir /var/log/frr
sudo chown frr:fee /var/log/frr
sudo chown frr:frr /var/log/frr
sudo mkdir /etc/frr
sudo touch /etc/frr/etc/zebra.conf
sudo touch /etc/frr/etc/bgpd.conf
sudo touch /etc/frr/etc/ospfd.conf
sudo touch /etc/frr/etc/ospf6d.conf
sudo touch /etc/frr/etc/isisd.conf
sudo touch /etc/frr/etc/ripd.conf
sudo touch /etc/frr/etc/ripngd.conf
sudo touch /etc/frr/etc/pimd.conf
sudo touch /etc/frr/etc/ldpd.conf
sudo touch /etc/frr/zebra.conf
sudo touch /etc/frr/bgpd.conf
sudo touch /etc/frr/ospfd.conf
sudo touch /etc/frr/ospf6d.conf
sudo touch /etc/frr/isisd.conf
sudo touch /etc/frr/ripd.conf
sudo touch /etc/frr/ripngd.conf
sudo touch /etc/frr/pimd.conf
sudo touch /etc/frr/ldpd.conf
sudo chown frr:frr /etc/frr/
sudo touch /etc/frr/etc/vtysh.conf
sudo chown frr:frrvty /etc/frr/etc/vtysh.conf
sudo touch /etc/frr/vtysh.conf
sudo chown frr:frrvty /etc/frr/vtysh.conf
sudo chmod 640 /etc/frr/*.conf
### Enable IP & IPv6 forwarding

View File

@ -18,6 +18,7 @@ daemons.
* Config Commands:: Commands used in config files
* Terminal Mode Commands:: Common commands used in a VTY
* Common Invocation Options:: Starting the daemons
* Loadable Module Support:: Using extension modules
* Virtual Terminal Interfaces:: Interacting with the daemons
@end menu
@ -372,6 +373,51 @@ Print program version.
@end table
@node Loadable Module Support
@section Loadable Module Support
FRR supports loading extension modules at startup. Loading, reloading or
unloading modules at runtime is not supported (yet). To load a module, use
the following command line option at daemon startup:
@table @samp
@item -M @var{module:options}
@itemx --module @var{module:options}
Load the specified module, optionally passing options to it. If the module
name contains a slash (/), it is assumed to be a full pathname to a file to
be loaded. If it does not contain a slash, the
@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of
the given name; first with the daemon name prepended (e.g. @code{zebra_mod}
for @code{mod}), then without the daemon name prepended.
This option is available on all daemons, though some daemons may not have
any modules available to be loaded.
@end table
@subsection The SNMP Module
If SNMP is enabled during compile-time and installed as part of the package,
the @code{snmp} module can be loaded for the @command{zebra},
@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons.
The module ignores any options passed to it. Refer to @ref{SNMP Support}
for information on its usage.
@subsection The FPM Module
If FPM is enabled during compile-time and installed as part of the package,
the @code{fpm} module can be loaded for the @command{zebra} daemon. This
provides the Forwarding Plane Manager ("FPM") API.
The module expects its argument to be either @code{netlink} or
@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the
default, and @code{protobuf} may not be available if the module was built
without protobuf support. Refer to @ref{zebra FIB push interface} for more
information.
@node Virtual Terminal Interfaces
@section Virtual Terminal Interfaces

View File

@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B bgpd
@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR.
\fB\-S\fR, \fB\-\-skip_runas\fR
Skip setting the process effective user and group.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBbgpd\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -13,6 +13,7 @@
@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
@set INSTALL_PREFIX_SBIN @CFG_SBIN@
@set INSTALL_PREFIX_STATE @CFG_STATE@
@set INSTALL_PREFIX_MODULES @CFG_MODULE@
@set INSTALL_USER @enable_user@
@set INSTALL_GROUP @enable_group@
@set INSTALL_VTY_GROUP @enable_vty_group@

119
doc/dev-modules.md Normal file
View File

@ -0,0 +1,119 @@
# Module and Hook support (developer docs)
## What it does
It uses `dlopen()` to load DSOs at startup.
## Limitations
* can't load, unload, or reload during runtime. This just needs some work
and can probably be done in the future.
* doesn't fix any of the "things need to be changed in the code in the library"
issues. Most prominently, you can't add a CLI node because CLI nodes are
listed in the library...
* if your module crashes, the daemon crashes. Should be obvious.
* **does not provide a stable API or ABI**. Your module must match a version
of FRR and you may have to update it frequently to match changes.
* **does not create a license boundary**. Your module will need to link
libzebra and include header files from the daemons, meaning it will be
GPL-encumbered.
## Installation
Look for `moduledir` in `configure.ac`, default is normally
`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`.
The daemon's name is prepended when looking for a module, e.g. "snmp" tries
to find "zebra_snmp" first when used in zebra. This is just to make it nicer
for the user, with the snmp module having the same name everywhere.
Modules can be packaged separately from FRR. The SNMP and FPM modules are
good candidates for this because they have dependencies (net-snmp / protobuf)
that are not FRR dependencies. However, any distro packages should have an
"exact-match" dependency onto the FRR package. Using a module from a
different FRR version will probably blow up nicely.
For snapcraft (and during development), modules can be loaded with full path
(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output
files in the .libs directory, so during development you have to use
`./zebra -M .libs/zebra_snmp.so`.
## Creating a module
... best to look at the existing SNMP or FPM modules.
Basic boilerplate:
```
#include "hook.h"
#include "module.h"
static int
module_init (void)
{
hook_register(frr_late_init, module_late_init);
return 0;
}
FRR_MODULE_SETUP(
.name = "my module",
.version = "0.0",
.description = "my module",
.init = module_init,
)
```
The `frr_late_init` hook will be called after the daemon has finished its
other startup and is about to enter the main event loop; this is the best
place for most initialisation.
## Compiler & Linker magic
There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility`
attributes to restrict it to the current module. If you get a linker error
with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be
possible, though one way to get it would be to not include libzebra (which
provides a fallback definition for the symbol).
libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable
modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use
the definition in libzebra; same applies if the main executable doesn't use
`FRR_DAEMON_INFO` (e.g. all testcases).
The deciding factor here is "what dynamic linker unit are you using the symbol
from." If you're in a library function and want to know who called you, you
can't use `THIS_MODULE` (because that'll just tell you you're in the library).
Put a macro around your function that adds `THIS_MODULE` in the *caller's
code calling your function*.
The idea is to use this in the future for module unloading. Hooks already
remember which module they were installed by, as groundwork for a function
that removes all of a module's installed hooks.
There's also the `frr_module` symbol in modules, pretty much a standard entry
point for loadable modules.
## Hooks
Hooks are just points in the code where you can register your callback to
be called. The parameter list is specific to the hook point. Since there is
no stable API, the hook code has some extra type safety checks making sure
you get a compiler warning when the hook parameter list doesn't match your
callback. Don't ignore these warnings.
## Relation to MTYPE macros
The MTYPE macros, while primarily designed to decouple MTYPEs from the library
and beautify the code, also work very nicely with loadable modules -- both
constructors and destructors are executed when loading/unloading modules.
This means there is absolutely no change required to MTYPEs, you can just use
them in a module and they will even clean up themselves when we implement
module unloading and an unload happens. In fact, it's impossible to create
a bug where unloading fails to de-register a MTYPE.

View File

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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B isisd
@ -63,6 +66,11 @@ interfaces.
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
Specify the user to run as. Default is \fI@enable_user@\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
There are currently no such modules for
\fBisisd\fR in the base package.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B ldpd
@ -63,6 +66,11 @@ interfaces.
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
Specify the user to run as. Default is \fI@enable_user@\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
There are currently no such modules for
\fBldpd\fR in the base package.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -385,7 +385,8 @@ ip protocol rip route-map RM1
Zebra supports a 'FIB push' interface that allows an external
component to learn the forwarding information computed by the Frr
routing suite.
routing suite. This is a loadable module that needs to be enabled
at startup as described in @ref{Loadable Module Support}.
In Frr, the Routing Information Base (RIB) resides inside
zebra. Routing protocols communicate their best routes to zebra, and
@ -440,9 +441,9 @@ independently.
@end itemize
As mentioned before, zebra encodes routes sent to the FPM in netlink
format by default. The format can be controlled via the
@code{--fpm_format} command-line option to zebra, which currently
takes the values @code{netlink} and @code{protobuf}.
format by default. The format can be controlled via the FPM module's
load-time option to zebra, which currently takes the values @code{netlink}
and @code{protobuf}.
The zebra FPM interface uses replace semantics. That is, if a 'route
add' message for a prefix is followed by another 'route add' message,

View File

@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B nhrpd
@ -63,6 +66,11 @@ interfaces.
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
Specify the user to run as. Default is \fI@enable_user@\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
There are currently no such modules for
\fBnhrpd\fR in the base package.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B ospf6d
@ -64,6 +67,11 @@ interfaces.
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
Specify the user to run as. Default is \fI@enable_user@\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBospf6d\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B ospfd
@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
\fB\-a\fR, \fB\-\-apiserver \fR
Enable OSPF apiserver. Default is disabled.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBospfd\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

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

View File

@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B pimd
@ -70,6 +73,11 @@ interfaces.
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
Specify the user to run as. Default is \fI@enable_user@\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
There are currently no such modules for
\fBpimd\fR in the base package.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.TP

View File

@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B ripd
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
\fB\-r\fR, \fB\-\-retain\fR
When the program terminates, retain routes added by \fBripd\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR module may be available for
\fBripd\fR, if the package was built with SNMP support.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@.
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B ripngd
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
\fB\-r\fR, \fB\-\-retain\fR
When the program terminates, retain routes added by \fBripd\fR.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
There are currently no such modules for
\fBripngd\fR in the base package.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol
(@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the
routing protocol MIBs available through it.
Note that SNMP Support needs to be enabled at compile-time and loaded as
module on daemon startup. Refer to @ref{Loadable Module Support} on
the latter.
@menu
* Getting and installing an SNMP agent::
* AgentX configuration::

View File

@ -108,13 +108,13 @@ Set the logging
(LOG_DEBUG), but higher number can be supplied if extra debugging messages
are required.
.TP
.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number
.BI \-\-min\-restart\-interval " number
Set the minimum
.I number
of seconds to wait between invocations of the daemon restart commands (the
default value is "60").
.TP
.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number
.BI \-\-max\-restart\-interval " number
Set the maximum
.I number
of seconds to wait between invocations of the daemon restart commands (the

View File

@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components
] [
.B \-g
.I group
] [
.B \-M
.I module:options
]
.SH DESCRIPTION
.B zebra
@ -86,6 +89,14 @@ maximum before starting zebra.
Note that this affects Linux only.
.TP
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
Load a module at startup. May be specified more than once.
The \fBsnmp\fR and \fBfpm\fR modules may be
available for \fBzebra\fR, if the package was built with SNMP and FPM support
respectively. The \fBfpm\fR module takes an additional colon-separated
argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR.
It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR.
.TP
\fB\-v\fR, \fB\-\-version\fR
Print the version and exit.
.SH FILES

View File

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

View File

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

View File

@ -1323,7 +1323,7 @@ DEFUN (show_isis_mpls_te_interface,
/* Interface name is specified. */
else
{
if ((ifp = if_lookup_by_name (argv[idx_interface]->arg)) == NULL)
if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL)
vty_out (vty, "No such interface name%s", VTY_NEWLINE);
else
show_mpls_te_sub (vty, ifp);

View File

@ -1576,7 +1576,7 @@ DEFUN (show_database,
/*
* 'router isis' command
*/
DEFUN (router_isis,
DEFUN_NOSH (router_isis,
router_isis_cmd,
"router isis WORD",
ROUTER_STR

View File

@ -24,7 +24,9 @@ noinst_HEADERS = \
control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h
ldp_vty_cmds.c: $(srcdir)/ldp_vty.xml $(srcdir)/../tools/xml2cli.pl
@PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml > $@
@PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml | \
sed -e 's%DEFUN \((ldp_\(interface_\|mpls_ldp\|address_family\|l2vpn_word\|member_pseudo\)\)%DEFUN_NOSH \1%' \
> $@
ldpd_SOURCES = ldpd.c
ldpd_LDADD = libldp.a ../lib/libfrr.la @LIBCAP@

View File

@ -104,6 +104,18 @@ send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list,
}
evbuf_enqueue(&nbr->tcp->wbuf, buf);
/* no errors - update per neighbor message counters */
switch (msg_type) {
case MSG_TYPE_ADDR:
nbr->stats.addr_sent++;
break;
case MSG_TYPE_ADDRWITHDRAW:
nbr->stats.addrwdraw_sent++;
break;
default:
break;
}
}
nbr_fsm(nbr, NBR_EVT_PDU_SENT);

View File

@ -41,6 +41,16 @@ RB_GENERATE(tnbr_head, tnbr, entry, tnbr_compare)
static __inline int
adj_compare(struct adj *a, struct adj *b)
{
if (adj_get_af(a) < adj_get_af(b))
return (-1);
if (adj_get_af(a) > adj_get_af(b))
return (1);
if (ntohl(a->lsr_id.s_addr) < ntohl(b->lsr_id.s_addr))
return (-1);
if (ntohl(a->lsr_id.s_addr) > ntohl(b->lsr_id.s_addr))
return (1);
if (a->source.type < b->source.type)
return (-1);
if (a->source.type > b->source.type)
@ -54,21 +64,13 @@ adj_compare(struct adj *a, struct adj *b)
if (strcmp(a->source.link.ia->iface->name,
b->source.link.ia->iface->name) > 0)
return (1);
if (a->source.link.ia->af < b->source.link.ia->af)
return (-1);
if (a->source.link.ia->af > b->source.link.ia->af)
return (1);
return (ldp_addrcmp(a->source.link.ia->af,
&a->source.link.src_addr, &b->source.link.src_addr));
case HELLO_TARGETED:
if (a->source.target->af < b->source.target->af)
return (-1);
if (a->source.target->af > b->source.target->af)
return (1);
return (ldp_addrcmp(a->source.target->af,
&a->source.target->addr, &b->source.target->addr));
default:
fatalx("adj_get_af: unknown hello type");
fatalx("adj_compare: unknown hello type");
}
return (0);
@ -150,9 +152,10 @@ adj_del(struct adj *adj, uint32_t notif_status)
}
struct adj *
adj_find(struct hello_source *source)
adj_find(struct in_addr lsr_id, struct hello_source *source)
{
struct adj adj;
adj.lsr_id = lsr_id;
adj.source = *source;
return (RB_FIND(global_adj_head, &global.adj_tree, &adj));
}
@ -372,13 +375,17 @@ adj_to_ctl(struct adj *adj)
case HELLO_LINK:
memcpy(actl.ifname, adj->source.link.ia->iface->name,
sizeof(actl.ifname));
actl.src_addr = adj->source.link.src_addr;
break;
case HELLO_TARGETED:
actl.src_addr = adj->source.target->addr;
break;
}
actl.holdtime = adj->holdtime;
actl.holdtime_remaining =
thread_timer_remain_second(adj->inactivity_timer);
actl.trans_addr = adj->trans_addr;
actl.ds_tlv = adj->ds_tlv;
return (&actl);
}

View File

@ -242,6 +242,9 @@ control_dispatch_imsg(struct thread *thread)
case IMSG_CTL_SHOW_DISCOVERY:
ldpe_adj_ctl(c);
break;
case IMSG_CTL_SHOW_DISCOVERY_DTL:
ldpe_adj_detail_ctl(c);
break;
case IMSG_CTL_SHOW_LIB:
case IMSG_CTL_SHOW_L2VPN_PW:
case IMSG_CTL_SHOW_L2VPN_BINDING:

View File

@ -291,7 +291,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
source.link.src_addr = *src;
}
adj = adj_find(&source);
adj = adj_find(lsr_id, &source);
nbr = nbr_find_ldpid(lsr_id.s_addr);
/* check dual-stack tlv */
@ -373,6 +373,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
}
}
adj->ds_tlv = ds_tlv;
/*
* If the hello adjacency's address-family doesn't match the local

View File

@ -261,6 +261,7 @@ send_capability(struct nbr *nbr, uint16_t capability, int enable)
evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
nbr->stats.capability_sent++;
}
int

View File

@ -49,37 +49,48 @@ iface_compare(struct iface *a, struct iface *b)
}
struct iface *
if_new(struct kif *kif)
if_new(const char *name)
{
struct iface *iface;
if ((iface = calloc(1, sizeof(*iface))) == NULL)
fatal("if_new: calloc");
strlcpy(iface->name, kif->ifname, sizeof(iface->name));
LIST_INIT(&iface->addr_list);
if (kif->ifindex)
if_update_info(iface, kif);
strlcpy(iface->name, name, sizeof(iface->name));
/* ipv4 */
iface->ipv4.af = AF_INET;
iface->ipv4.iface = iface;
iface->ipv4.enabled = 0;
iface->ipv4.state = IF_STA_DOWN;
RB_INIT(&iface->ipv4.adj_tree);
/* ipv6 */
iface->ipv6.af = AF_INET6;
iface->ipv6.iface = iface;
iface->ipv6.enabled = 0;
iface->ipv6.state = IF_STA_DOWN;
RB_INIT(&iface->ipv6.adj_tree);
return (iface);
}
void
if_exit(struct iface *iface)
ldpe_if_init(struct iface *iface)
{
log_debug("%s: interface %s", __func__, iface->name);
LIST_INIT(&iface->addr_list);
/* ipv4 */
iface->ipv4.iface = iface;
iface->ipv4.state = IF_STA_DOWN;
RB_INIT(&iface->ipv4.adj_tree);
/* ipv6 */
iface->ipv6.iface = iface;
iface->ipv6.state = IF_STA_DOWN;
RB_INIT(&iface->ipv6.adj_tree);
}
void
ldpe_if_exit(struct iface *iface)
{
struct if_addr *if_addr;
@ -206,7 +217,7 @@ if_addr_add(struct kaddr *ka)
if (if_addr_lookup(&iface->addr_list, ka) == NULL) {
if_addr = if_addr_new(ka);
LIST_INSERT_HEAD(&iface->addr_list, if_addr, entry);
if_update(iface, if_addr->af);
ldp_if_update(iface, if_addr->af);
}
}
}
@ -227,7 +238,7 @@ if_addr_del(struct kaddr *ka)
if_addr = if_addr_lookup(&iface->addr_list, ka);
if (if_addr) {
LIST_REMOVE(if_addr, entry);
if_update(iface, if_addr->af);
ldp_if_update(iface, if_addr->af);
free(if_addr);
}
}
@ -368,7 +379,7 @@ if_update_af(struct iface_af *ia, int link_ok)
}
void
if_update(struct iface *iface, int af)
ldp_if_update(struct iface *iface, int af)
{
int link_ok;
@ -386,7 +397,7 @@ if_update_all(int af)
struct iface *iface;
RB_FOREACH(iface, iface_head, &leconf->iface_tree)
if_update(iface, af);
ldp_if_update(iface, af);
}
uint16_t

View File

@ -40,6 +40,7 @@ send_keepalive(struct nbr *nbr)
debug_kalive_send("keepalive: lsr-id %s", inet_ntoa(nbr->id));
evbuf_enqueue(&nbr->tcp->wbuf, buf);
nbr->stats.kalive_sent++;
}
int

View File

@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
}
struct l2vpn_if *
l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_if *lif;
@ -125,33 +125,27 @@ 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);
}
struct l2vpn_if *
l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
{
struct l2vpn_if *lif;
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
if (lif->ifindex == ifindex)
return (lif);
return (NULL);
}
struct l2vpn_if *
l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname)
l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_if lif;
strlcpy(lif.ifname, ifname, sizeof(lif.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)
{
@ -186,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;
@ -194,29 +188,13 @@ 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);
}
struct l2vpn_pw *
l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex)
{
struct l2vpn_pw *pw;
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
if (pw->ifindex == ifindex)
return (pw);
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
if (pw->ifindex == ifindex)
return (pw);
return (NULL);
}
struct l2vpn_pw *
l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname)
l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_pw *pw;
struct l2vpn_pw s;
@ -228,6 +206,30 @@ l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname)
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
}
struct l2vpn_pw *
l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_pw s;
strlcpy(s.ifname, ifname, sizeof(s.ifname));
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s));
}
struct l2vpn_pw *
l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
{
struct l2vpn_pw s;
strlcpy(s.ifname, ifname, sizeof(s.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)
{
@ -282,9 +284,6 @@ l2vpn_pw_reset(struct l2vpn_pw *pw)
int
l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
{
struct fec fec;
struct fec_node *fn;
/* check for a remote label */
if (fnh->remote_label == NO_LABEL)
return (0);
@ -298,34 +297,6 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh)
pw->remote_status != PW_FORWARDING)
return (0);
/* check for a working lsp to the nexthop */
memset(&fec, 0, sizeof(fec));
switch (pw->af) {
case AF_INET:
fec.type = FEC_TYPE_IPV4;
fec.u.ipv4.prefix = pw->addr.v4;
fec.u.ipv4.prefixlen = 32;
break;
case AF_INET6:
fec.type = FEC_TYPE_IPV6;
fec.u.ipv6.prefix = pw->addr.v6;
fec.u.ipv6.prefixlen = 128;
break;
default:
fatalx("l2vpn_pw_ok: unknown af");
}
fn = (struct fec_node *)fec_find(&ft, &fec);
if (fn == NULL || fn->local_label == NO_LABEL)
return (0);
/*
* Need to ensure that there's a label binding for all nexthops.
* Otherwise, ECMP for this route could render the pseudowire unusable.
*/
LIST_FOREACH(fnh, &fn->nexthops, entry)
if (fnh->remote_label == NO_LABEL)
return (0);
return (1);
}
@ -503,37 +474,6 @@ l2vpn_recv_pw_status_wcard(struct lde_nbr *ln, struct notify_msg *nm)
}
}
void
l2vpn_sync_pws(int af, union ldpd_addr *addr)
{
struct l2vpn *l2vpn;
struct l2vpn_pw *pw;
struct fec fec;
struct fec_node *fn;
struct fec_nh *fnh;
RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
continue;
l2vpn_pw_fec(pw, &fec);
fn = (struct fec_node *)fec_find(&ft, &fec);
if (fn == NULL)
continue;
fnh = fec_nh_find(fn, AF_INET, (union ldpd_addr *)
&pw->lsr_id, 0, 0);
if (fnh == NULL)
continue;
if (l2vpn_pw_ok(pw, fnh))
lde_send_change_klabel(fn, fnh);
else
lde_send_delete_klabel(fn, fnh);
}
}
}
void
l2vpn_pw_ctl(pid_t pid)
{

View File

@ -26,13 +26,13 @@
#include "mpls.h"
static void enqueue_pdu(struct nbr *, struct ibuf *, uint16_t);
static void enqueue_pdu(struct nbr *, uint16_t, struct ibuf *, uint16_t);
static int gen_label_tlv(struct ibuf *, uint32_t);
static int gen_reqid_tlv(struct ibuf *, uint32_t);
static void log_msg_mapping(int, uint16_t, struct nbr *, struct map *);
static void
enqueue_pdu(struct nbr *nbr, struct ibuf *buf, uint16_t size)
enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size)
{
struct ldp_hdr *ldp_hdr;
@ -81,7 +81,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
/* maximum pdu length exceeded, we need a new ldp pdu */
if (size + msg_size > nbr->max_pdu_len) {
enqueue_pdu(nbr, buf, size);
enqueue_pdu(nbr, type, buf, size);
first = 1;
continue;
}
@ -108,11 +108,32 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
log_msg_mapping(1, type, nbr, &me->map);
/* no errors - update per neighbor message counters */
switch (type) {
case MSG_TYPE_LABELMAPPING:
nbr->stats.labelmap_sent++;
break;
case MSG_TYPE_LABELREQUEST:
nbr->stats.labelreq_sent++;
break;
case MSG_TYPE_LABELWITHDRAW:
nbr->stats.labelwdraw_sent++;
break;
case MSG_TYPE_LABELRELEASE:
nbr->stats.labelrel_sent++;
break;
case MSG_TYPE_LABELABORTREQ:
nbr->stats.labelabreq_sent++;
break;
default:
break;
}
TAILQ_REMOVE(mh, me, entry);
free(me);
}
enqueue_pdu(nbr, buf, size);
enqueue_pdu(nbr, type, buf, size);
nbr_fsm(nbr, NBR_EVT_PDU_SENT);
}

View File

@ -33,6 +33,10 @@
#include "privs.h"
#include "sigevent.h"
#include "mpls.h"
#include <lib/linklist.h>
#include "zclient.h"
#include "stream.h"
#include "network.h"
static void lde_shutdown(void);
static int lde_dispatch_imsg(struct thread *);
@ -50,6 +54,11 @@ static void lde_map_free(void *);
static int lde_address_add(struct lde_nbr *, struct lde_addr *);
static int lde_address_del(struct lde_nbr *, struct lde_addr *);
static void lde_address_list_free(struct lde_nbr *);
static void zclient_sync_init (u_short instance);
static void lde_label_list_init(void);
static int lde_get_label_chunk (void);
static void on_get_label_chunk_response(uint32_t start, uint32_t end);
static uint32_t lde_get_next_label(void);
RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare)
@ -83,6 +92,10 @@ static struct zebra_privs_t lde_privs =
.cap_num_i = 0
};
/* List of chunks of labels externally assigned by Zebra */
struct list *label_chunk_list;
struct listnode *current_label_chunk;
/* SIGINT / SIGTERM handler. */
static void
sigint(void)
@ -92,6 +105,10 @@ sigint(void)
static struct quagga_signal_t lde_signals[] =
{
{
.signal = SIGHUP,
/* ignore */
},
{
.signal = SIGINT,
.handler = &sigint,
@ -102,9 +119,38 @@ static struct quagga_signal_t lde_signals[] =
},
};
static void
lde_sleep (void)
{
sleep(1);
if (lde_signals[0].caught || lde_signals[1].caught)
lde_shutdown();
}
struct zclient *zclient_sync = NULL;
static void
zclient_sync_init(u_short instance)
{
/* Initialize special zclient for synchronous message exchanges. */
log_debug("Initializing synchronous zclient for label manager");
zclient_sync = zclient_new(master);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->instance = instance;
while (zclient_socket_connect (zclient_sync) < 0) {
fprintf(stderr, "Error connecting synchronous zclient!\n");
lde_sleep();
}
/* Connect to label manager */
while (lm_label_manager_connect (zclient_sync) != 0) {
fprintf(stderr, "Error connecting to label manager!\n");
lde_sleep();
}
}
/* label decision engine */
void
lde(const char *user, const char *group)
lde(const char *user, const char *group, u_short instance)
{
struct thread thread;
struct timeval now;
@ -124,7 +170,7 @@ lde(const char *user, const char *group)
zprivs_init(&lde_privs);
#ifdef HAVE_PLEDGE
if (pledge("stdio recvfd", NULL) == -1)
if (pledge("stdio recvfd unix", NULL) == -1)
fatal("pledge");
#endif
@ -152,6 +198,10 @@ lde(const char *user, const char *group)
gettimeofday(&now, NULL);
global.uptime = now.tv_sec;
/* Init synchronous zclient and label list */
zclient_sync_init(instance);
lde_label_list_init();
/* Fetch next active thread. */
while (thread_fetch(master, &thread))
thread_call(&thread);
@ -389,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);
@ -418,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 +
@ -490,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:
@ -528,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:
@ -536,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:
@ -544,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:
@ -587,7 +655,6 @@ lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen)
uint32_t
lde_update_label(struct fec_node *fn)
{
static uint32_t label = MPLS_LABEL_RESERVED_MAX;
struct fec_nh *fnh;
int connected = 0;
@ -652,12 +719,7 @@ lde_update_label(struct fec_node *fn)
fn->local_label > MPLS_LABEL_RESERVED_MAX)
return (fn->local_label);
/*
* TODO: request label to zebra or define a range of labels for ldpd.
*/
label++;
return (label);
return lde_get_next_label ();
}
void
@ -681,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));
@ -699,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 ||
@ -748,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));
@ -766,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;
@ -1533,3 +1579,102 @@ lde_address_list_free(struct lde_nbr *ln)
free(lde_addr);
}
}
static void
lde_del_label_chunk(void *val)
{
free(val);
}
static int
lde_get_label_chunk(void)
{
int ret;
uint32_t start, end;
log_debug("Getting label chunk");
ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end);
if (ret < 0)
{
log_warnx("Error getting label chunk!");
close(zclient_sync->sock);
zclient_sync->sock = -1;
return -1;
}
on_get_label_chunk_response(start, end);
return 0;
}
static void
lde_label_list_init(void)
{
label_chunk_list = list_new();
label_chunk_list->del = lde_del_label_chunk;
/* get first chunk */
while (lde_get_label_chunk () != 0) {
fprintf(stderr, "Error getting first label chunk!\n");
lde_sleep();
}
}
static void
on_get_label_chunk_response(uint32_t start, uint32_t end)
{
struct label_chunk *new_label_chunk;
log_debug("Label Chunk assign: %u - %u", start, end);
new_label_chunk = calloc(1, sizeof(struct label_chunk));
if (!new_label_chunk) {
log_warn("Error trying to allocate label chunk %u - %u", start, end);
return;
}
new_label_chunk->start = start;
new_label_chunk->end = end;
new_label_chunk->used_mask = 0;
listnode_add(label_chunk_list, (void *)new_label_chunk);
/* let's update current if needed */
if (!current_label_chunk)
current_label_chunk = listtail(label_chunk_list);
}
static uint32_t
lde_get_next_label(void)
{
struct label_chunk *label_chunk;
uint32_t i, pos, size;
uint32_t label = NO_LABEL;
while (current_label_chunk) {
label_chunk = listgetdata(current_label_chunk);
if (!label_chunk)
goto end;
/* try to get next free label in currently used label chunk */
size = label_chunk->end - label_chunk->start + 1;
for (i = 0, pos = 1; i < size; i++, pos <<= 1) {
if (!(pos & label_chunk->used_mask)) {
label_chunk->used_mask |= pos;
label = label_chunk->start + i;
goto end;
}
}
current_label_chunk = listnextnode(current_label_chunk);
}
end:
/* we moved till the last chunk, or were not able to find a label,
so let's ask for another one */
if (!current_label_chunk || current_label_chunk == listtail(label_chunk_list)
|| label == NO_LABEL) {
if (lde_get_label_chunk() != 0)
log_warn("%s: Error getting label chunk!", __func__);
}
return label;
}

View File

@ -124,6 +124,13 @@ struct fec_node {
void *data; /* fec specific data */
};
#define CHUNK_SIZE 64
struct label_chunk {
uint32_t start;
uint32_t end;
uint64_t used_mask;
};
#define LDE_GC_INTERVAL 300
extern struct ldpd_conf *ldeconf;
@ -132,7 +139,7 @@ extern struct nbr_tree lde_nbrs;
extern struct thread *gc_timer;
/* lde.c */
void lde(const char *, const char *);
void lde(const char *, const char *, u_short instance);
int lde_imsg_compose_parent(int, pid_t, void *, uint16_t);
int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t);
int lde_acl_check(char *, int, union ldpd_addr *, uint8_t);
@ -205,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_find(struct l2vpn *, unsigned int);
struct l2vpn_if *l2vpn_if_find_name(struct l2vpn *, const char *);
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_find(struct l2vpn *, unsigned int);
struct l2vpn_pw *l2vpn_pw_find_name(struct l2vpn *, const char *);
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 *);
@ -224,7 +233,6 @@ void l2vpn_send_pw_status_wcard(struct lde_nbr *, uint32_t,
void l2vpn_recv_pw_status(struct lde_nbr *, struct notify_msg *);
void l2vpn_recv_pw_status_wcard(struct lde_nbr *,
struct notify_msg *);
void l2vpn_sync_pws(int, union ldpd_addr *);
void l2vpn_pw_ctl(pid_t);
void l2vpn_binding_ctl(pid_t);

View File

@ -162,7 +162,7 @@ rt_dump(pid_t pid)
RB_EMPTY(&fn->downstream))
continue;
rtctl.first = 1;
memset(&rtctl, 0, sizeof(rtctl));
switch (fn->fec.type) {
case FEC_TYPE_IPV4:
rtctl.af = AF_INET;
@ -179,23 +179,30 @@ rt_dump(pid_t pid)
}
rtctl.local_label = fn->local_label;
RB_FOREACH(me, lde_map_head, &fn->downstream) {
rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
rtctl.nexthop = me->nexthop->id;
rtctl.remote_label = me->map.label;
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
&rtctl, sizeof(rtctl));
rtctl.first = 0;
}
if (RB_EMPTY(&fn->downstream)) {
rtctl.in_use = 0;
rtctl.nexthop.s_addr = INADDR_ANY;
rtctl.remote_label = NO_LABEL;
rtctl.no_downstream = 1;
}
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN, 0, pid, &rtctl,
sizeof(rtctl));
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
RB_FOREACH(me, lde_map_head, &fn->upstream) {
rtctl.nexthop = me->nexthop->id;
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT, 0, pid,
&rtctl, sizeof(rtctl));
}
RB_FOREACH(me, lde_map_head, &fn->downstream) {
rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
rtctl.nexthop = me->nexthop->id;
rtctl.remote_label = me->map.label;
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD, 0, pid,
&rtctl, sizeof(rtctl));
}
lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END, 0, pid, &rtctl,
sizeof(rtctl));
}
}

View File

@ -71,6 +71,7 @@ int ldp_vty_l2vpn_pw_pwstatus(struct vty *, struct vty_arg *[]);
int ldp_vty_show_binding(struct vty *, struct vty_arg *[]);
int ldp_vty_show_discovery(struct vty *, struct vty_arg *[]);
int ldp_vty_show_interface(struct vty *, struct vty_arg *[]);
int ldp_vty_show_capabilities(struct vty *, struct vty_arg *[]);
int ldp_vty_show_neighbor(struct vty *, struct vty_arg *[]);
int ldp_vty_show_atom_binding(struct vty *, struct vty_arg *[]);
int ldp_vty_show_atom_vc(struct vty *, struct vty_arg *[]);
@ -79,6 +80,5 @@ int ldp_vty_debug(struct vty *, struct vty_arg *[]);
int ldp_vty_show_debugging(struct vty *, struct vty_arg *[]);
void ldp_vty_init(void);
void ldp_vty_if_init(void);
#endif /* _LDP_VTY_H_ */

View File

@ -333,11 +333,17 @@
<!-- exec mode commands -->
<subtree name="ldp_show_af">
<option name="binding" help="Label Information Base (LIB) information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_binding"/>
<option name="binding" help="Label Information Base (LIB) information" function="ldp_vty_show_binding">
<option name="json" arg="json" help="JavaScript Object Notation" function="ldp_vty_show_binding"/>
<option name="detail" arg="detail" help="Show detailed information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_binding"/>
</option>
</option>
<option name="discovery" help="Discovery Hello Information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_discovery"/>
<option name="discovery" help="Discovery Hello Information" function="ldp_vty_show_discovery">
<option name="json" arg="json" help="JavaScript Object Notation" function="ldp_vty_show_discovery"/>
<option name="detail" arg="detail" help="Show detailed information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_discovery"/>
</option>
</option>
<option name="interface" help="interface information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_interface"/>
@ -347,8 +353,17 @@
<option name="show" help="Show running system information">
<option name="mpls" help="MPLS information">
<option name="ldp" help="Label Distribution Protocol">
<option name="neighbor" help="Neighbor information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_neighbor"/>
<option name="capabilities" help="Display LDP Capabilities information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_capabilities"/>
</option>
<option name="neighbor" help="Neighbor information" function="ldp_vty_show_neighbor">
<option name="capabilities" arg="capabilities" help="Display neighbor capability information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_neighbor"/>
</option>
<option name="json" arg="json" help="JavaScript Object Notation" function="ldp_vty_show_neighbor"/>
<option name="detail" arg="detail" help="Show detailed information">
<option name="json" arg="json" optional="true" help="JavaScript Object Notation" function="ldp_vty_show_neighbor"/>
</option>
</option>
<include subtree="ldp_show_af"/>
<select options="address-family" arg="address-family">

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -77,6 +77,7 @@ enum imsg_type {
IMSG_CTL_RELOAD,
IMSG_CTL_SHOW_INTERFACE,
IMSG_CTL_SHOW_DISCOVERY,
IMSG_CTL_SHOW_DISCOVERY_DTL,
IMSG_CTL_SHOW_DISC_IFACE,
IMSG_CTL_SHOW_DISC_TNBR,
IMSG_CTL_SHOW_DISC_ADJ,
@ -84,6 +85,10 @@ enum imsg_type {
IMSG_CTL_SHOW_NBR_DISC,
IMSG_CTL_SHOW_NBR_END,
IMSG_CTL_SHOW_LIB,
IMSG_CTL_SHOW_LIB_BEGIN,
IMSG_CTL_SHOW_LIB_SENT,
IMSG_CTL_SHOW_LIB_RCVD,
IMSG_CTL_SHOW_LIB_END,
IMSG_CTL_SHOW_L2VPN_PW,
IMSG_CTL_SHOW_L2VPN_BINDING,
IMSG_CTL_CLEAR_NBR,
@ -140,7 +145,9 @@ enum imsg_type {
IMSG_RECONF_END,
IMSG_DEBUG_UPDATE,
IMSG_LOG,
IMSG_ACL_CHECK
IMSG_ACL_CHECK,
IMSG_GET_LABEL_CHUNK,
IMSG_RELEASE_LABEL_CHUNK
};
union ldpd_addr {
@ -345,6 +352,29 @@ DECLARE_QOBJ_TYPE(nbr_params)
#define F_NBRP_GTSM 0x02
#define F_NBRP_GTSM_HOPS 0x04
struct ldp_stats {
uint32_t kalive_sent;
uint32_t kalive_rcvd;
uint32_t addr_sent;
uint32_t addr_rcvd;
uint32_t addrwdraw_sent;
uint32_t addrwdraw_rcvd;
uint32_t notif_sent;
uint32_t notif_rcvd;
uint32_t capability_sent;
uint32_t capability_rcvd;
uint32_t labelmap_sent;
uint32_t labelmap_rcvd;
uint32_t labelreq_sent;
uint32_t labelreq_rcvd;
uint32_t labelwdraw_sent;
uint32_t labelwdraw_rcvd;
uint32_t labelrel_sent;
uint32_t labelrel_rcvd;
uint32_t labelabreq_sent;
uint32_t labelabreq_rcvd;
};
struct l2vpn_if {
RB_ENTRY(l2vpn_if) entry;
struct l2vpn *l2vpn;
@ -473,6 +503,7 @@ struct ldpd_af_global {
struct ldpd_global {
int cmd_opts;
int sighup;
time_t uptime;
struct in_addr rtr_id;
struct ldpd_af_global ipv4;
@ -566,7 +597,9 @@ struct ctl_adj {
char ifname[IF_NAMESIZE];
union ldpd_addr src_addr;
uint16_t holdtime;
uint16_t holdtime_remaining;
union ldpd_addr trans_addr;
int ds_tlv;
};
struct ctl_nbr {
@ -576,9 +609,12 @@ struct ctl_nbr {
in_port_t lport;
union ldpd_addr raddr;
in_port_t rport;
enum auth_method auth_method;
uint16_t holdtime;
time_t uptime;
int nbr_state;
struct ldp_stats stats;
int flags;
};
struct ctl_rt {
@ -590,7 +626,7 @@ struct ctl_rt {
uint32_t remote_label;
uint8_t flags;
uint8_t in_use;
int first;
int no_downstream;
};
struct ctl_pw {
@ -610,7 +646,7 @@ struct ctl_pw {
uint32_t status;
};
extern struct ldpd_conf *ldpd_conf;
extern struct ldpd_conf *ldpd_conf, *vty_conf;
extern struct ldpd_global global;
/* parse.y */
@ -670,9 +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 *);
int ldp_reload_ref(struct ldpd_conf *, void **);
struct ldpd_conf *ldp_dup_config_ref(struct ldpd_conf *, void **ref);
struct ldpd_conf *ldp_dup_config(struct ldpd_conf *);
void ldp_clear_config(struct ldpd_conf *);
void merge_config(struct ldpd_conf *, struct ldpd_conf *);
struct ldpd_conf *config_new_empty(void);

View File

@ -87,6 +87,10 @@ sigint(void)
static struct quagga_signal_t ldpe_signals[] =
{
{
.signal = SIGHUP,
/* ignore */
},
{
.signal = SIGINT,
.handler = &sigint,
@ -252,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);
@ -294,19 +298,22 @@ ldpe_dispatch_main(struct thread *thread)
iface = if_lookup_name(leconf, kif->ifname);
if (iface) {
if_update_info(iface, kif);
if_update(iface, AF_UNSPEC);
ldp_if_update(iface, AF_UNSPEC);
break;
}
RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) {
lif = l2vpn_if_find_name(l2vpn, kif->ifname);
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:
@ -354,6 +361,7 @@ ldpe_dispatch_main(struct thread *thread)
#ifdef __OpenBSD__
pfkey_remove(nbr);
#endif
nbr->auth.method = AUTH_NONE;
}
ldpe_close_sockets(af);
if_update_all(af);
@ -409,8 +417,11 @@ ldpe_dispatch_main(struct thread *thread)
af))->trans_addr;
#ifdef __OpenBSD__
nbrp = nbr_params_find(leconf, nbr->id);
if (nbrp && pfkey_establish(nbr, nbrp) == -1)
fatalx("pfkey setup failed");
if (nbrp) {
nbr->auth.method = nbrp->auth.method;
if (pfkey_establish(nbr, nbrp) == -1)
fatalx("pfkey setup failed");
}
#endif
if (nbr_session_active_role(nbr))
nbr_establish_connection(nbr);
@ -441,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:
@ -479,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:
@ -487,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:
@ -495,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;
@ -642,7 +645,10 @@ ldpe_dispatch_lde(struct thread *thread)
send_notification_full(nbr->tcp, nm);
break;
case IMSG_CTL_END:
case IMSG_CTL_SHOW_LIB:
case IMSG_CTL_SHOW_LIB_BEGIN:
case IMSG_CTL_SHOW_LIB_RCVD:
case IMSG_CTL_SHOW_LIB_SENT:
case IMSG_CTL_SHOW_LIB_END:
case IMSG_CTL_SHOW_L2VPN_PW:
case IMSG_CTL_SHOW_L2VPN_BINDING:
control_imsg_relay(&imsg);
@ -819,6 +825,21 @@ ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
void
ldpe_adj_ctl(struct ctl_conn *c)
{
struct adj *adj;
struct ctl_adj *actl;
RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
actl = adj_to_ctl(adj);
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
-1, actl, sizeof(struct ctl_adj));
}
imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
}
void
ldpe_adj_detail_ctl(struct ctl_conn *c)
{
struct iface *iface;
struct tnbr *tnbr;

View File

@ -100,6 +100,7 @@ struct nbr {
int idtimer_cnt;
uint16_t keepalive;
uint16_t max_pdu_len;
struct ldp_stats stats;
struct {
uint8_t established;
@ -207,20 +208,22 @@ void ldpe_stop_init_backoff(int);
struct ctl_conn;
void ldpe_iface_ctl(struct ctl_conn *, unsigned int);
void ldpe_adj_ctl(struct ctl_conn *);
void ldpe_adj_detail_ctl(struct ctl_conn *);
void ldpe_nbr_ctl(struct ctl_conn *);
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 *);
struct iface_af *iface_af_get(struct iface *, int);
void if_addr_add(struct kaddr *);
void if_addr_del(struct kaddr *);
void if_update(struct iface *, int);
void ldp_if_update(struct iface *, int);
void if_update_all(int);
uint16_t if_get_hello_holdtime(struct iface_af *);
uint16_t if_get_hello_interval(struct iface_af *);
@ -231,7 +234,7 @@ in_addr_t if_get_ipv4_addr(struct iface *);
struct adj *adj_new(struct in_addr, struct hello_source *,
union ldpd_addr *);
void adj_del(struct adj *, uint32_t);
struct adj *adj_find(struct hello_source *);
struct adj *adj_find(struct in_addr, struct hello_source *);
int adj_get_af(struct adj *adj);
void adj_start_itimer(struct adj *);
void adj_stop_itimer(struct adj *);

View File

@ -264,6 +264,7 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
nbrp = nbr_params_find(leconf, nbr->id);
if (nbrp) {
nbr->auth.method = nbrp->auth.method;
#ifdef __OpenBSD__
if (pfkey_establish(nbr, nbrp) == -1)
fatalx("pfkey setup failed");
@ -296,6 +297,7 @@ nbr_del(struct nbr *nbr)
(ldp_af_global_get(&global, nbr->af))->ldp_session_socket,
nbr->af, &nbr->raddr, NULL);
#endif
nbr->auth.method = AUTH_NONE;
if (nbr_pending_connect(nbr))
THREAD_WRITE_OFF(nbr->ev_connect);
@ -808,8 +810,11 @@ nbr_to_ctl(struct nbr *nbr)
nctl.lport = nbr->tcp->lport;
nctl.raddr = nbr->raddr;
nctl.rport = nbr->tcp->rport;
nctl.auth_method = nbr->auth.method;
nctl.holdtime = nbr->keepalive;
nctl.nbr_state = nbr->state;
nctl.stats = nbr->stats;
nctl.flags = nbr->flags;
gettimeofday(&now, NULL);
if (nbr->state == NBR_STA_OPER) {

View File

@ -66,6 +66,7 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm)
if (tcp->nbr) {
log_msg_notification(1, tcp->nbr, nm);
nbr_fsm(tcp->nbr, NBR_EVT_PDU_SENT);
tcp->nbr->stats.notif_sent++;
}
evbuf_enqueue(&tcp->wbuf, buf);

View File

@ -572,6 +572,42 @@ session_read(struct thread *thread)
return (0);
}
/* no errors - update per neighbor message counters */
switch (type) {
case MSG_TYPE_NOTIFICATION:
nbr->stats.notif_rcvd++;
break;
case MSG_TYPE_KEEPALIVE:
nbr->stats.kalive_rcvd++;
break;
case MSG_TYPE_CAPABILITY:
nbr->stats.capability_rcvd++;
break;
case MSG_TYPE_ADDR:
nbr->stats.addr_rcvd++;
break;
case MSG_TYPE_ADDRWITHDRAW:
nbr->stats.addrwdraw_rcvd++;
break;
case MSG_TYPE_LABELMAPPING:
nbr->stats.labelmap_rcvd++;
break;
case MSG_TYPE_LABELREQUEST:
nbr->stats.labelreq_rcvd++;
break;
case MSG_TYPE_LABELWITHDRAW:
nbr->stats.labelwdraw_rcvd++;
break;
case MSG_TYPE_LABELRELEASE:
nbr->stats.labelrel_rcvd++;
break;
case MSG_TYPE_LABELABORTREQ:
nbr->stats.labelabreq_rcvd++;
break;
default:
break;
}
/* Analyse the next message */
pdu += msg_size;
len -= msg_size;

View File

@ -418,12 +418,6 @@ pfkey_establish(struct nbr *nbr, struct nbr_params *nbrp)
if (nbrp->auth.method == AUTH_NONE)
return (0);
/*
* make sure we keep copies of everything we need to
* remove SAs and flows later again.
*/
nbr->auth.method = nbrp->auth.method;
switch (nbr->auth.method) {
case AUTH_MD5SIG:
strlcpy(nbr->auth.md5key, nbrp->auth.md5key,

View File

@ -20,7 +20,7 @@ libfrr_la_SOURCES = \
command.c \
sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \
filter.c routemap.c distribute.c stream.c log.c plist.c \
zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
zclient.c sockopt.c md5.c if_rmap.c keychain.c privs.c \
sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
imsg-buffer.c imsg.c skiplist.c \
@ -33,12 +33,29 @@ libfrr_la_SOURCES = \
strlcpy.c \
strlcat.c \
sha256.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 \
@ -55,6 +72,8 @@ pkginclude_HEADERS = \
monotime.h \
spf_backoff.h \
srcdest_table.h \
module.h \
hook.h \
libfrr.h \
sha256.h \
# end

View File

@ -21,7 +21,7 @@
#include <zebra.h>
#if defined HAVE_SNMP && defined SNMP_AGENTX
#ifdef SNMP_AGENTX
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
@ -315,4 +315,4 @@ smux_trap (struct variable *vp, size_t vp_len,
return 1;
}
#endif /* HAVE_SNMP */
#endif /* SNMP_AGENTX */

View File

@ -293,7 +293,7 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp,
/* Lookup index. */
if (ifindex != 0)
{
ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
ifp = if_lookup_by_index (ifindex, vrf_id);
if (ifp == NULL)
{
if (bfd_debug)

View File

@ -41,6 +41,7 @@
#include "vrf.h"
#include "command_match.h"
#include "qobj.h"
#include "defaults.h"
DEFINE_MTYPE( LIB, HOST, "Host config")
DEFINE_MTYPE( LIB, STRVEC, "String vector")
@ -1538,6 +1539,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,
@ -1638,6 +1656,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,
@ -1649,9 +1698,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;
@ -1662,32 +1709,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;
@ -1751,13 +1776,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)
@ -1819,7 +1838,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;
}
/** -- **/
@ -2696,6 +2717,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)
{

View File

@ -524,14 +524,14 @@ distribute_list_init (int node)
disthash = hash_create (distribute_hash_make,
(int (*) (const void *, const void *)) distribute_cmp);
install_element (node, &distribute_list_cmd);
install_element (node, &no_distribute_list_cmd);
/*
install_element (RIP_NODE, &distribute_list_cmd);
install_element (RIP_NODE, &no_distribute_list_cmd);
install_element (RIPNG_NODE, &distribute_list_cmd);
install_element (RIPNG_NODE, &no_distribute_list_cmd);
*/
/* vtysh command-extraction doesn't grok install_element(node, ) */
if (node == RIP_NODE) {
install_element (RIP_NODE, &distribute_list_cmd);
install_element (RIP_NODE, &no_distribute_list_cmd);
} else if (node == RIPNG_NODE) {
install_element (RIPNG_NODE, &distribute_list_cmd);
install_element (RIPNG_NODE, &no_distribute_list_cmd);
}
/* install v6 */
if (node == RIPNG_NODE) {

118
lib/frratomic.h Normal file
View File

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

View File

@ -411,7 +411,7 @@ DEFUN (grammar_findambig,
{
int same = prev && !strcmp (prev->cmd, cur->cmd);
if (printall && !same)
vty_out (vty, "'%s'%s", cur->cmd, VTY_NEWLINE);
vty_out (vty, "'%s' [%x]%s", cur->cmd, cur->el->daemon, VTY_NEWLINE);
if (same)
{
vty_out (vty, "'%s' AMBIGUOUS:%s", cur->cmd, VTY_NEWLINE);

56
lib/hook.c Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "memory.h"
#include "hook.h"
DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry")
void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
struct frrmod_runtime *module, const char *funcname)
{
struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he));
he->hookfn = funcptr;
he->hookarg = arg;
he->has_arg = has_arg;
he->module = module;
he->fnname = funcname;
he->next = hook->entries;
hook->entries = he;
}
void _hook_unregister(struct hook *hook, void *funcptr,
void *arg, bool has_arg)
{
struct hookent *he, **prev;
for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next)
if (he->hookfn == funcptr && he->hookarg == arg
&& he->has_arg == has_arg)
{
*prev = he->next;
XFREE(MTYPE_HOOK_ENTRY, he);
break;
}
}

187
lib/hook.h Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _FRR_HOOK_H
#define _FRR_HOOK_H
#include <stdbool.h>
#include "module.h"
#include "memory.h"
/* type-safe subscribable hook points
*
* where "type-safe" applies to the function pointers used for subscriptions
*
* overall usage:
* - to create a hook:
*
* mydaemon.h:
* #include "hook.h"
* DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info))
*
* mydaemon.c:
* DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info))
* ...
* hook_call (some_update_event, info)
*
* Note: the second and third macro args must be the hook function's
* parameter list, with the same names for each parameter. The second
* macro arg is with types (used for defining things), the third arg is
* just the names (used for passing along parameters).
*
* Do not use parameter names starting with "hook", these can collide with
* names used by the hook code itself.
*
* The return value is always "int" for now; hook_call will sum up the
* return values from each registered user. Default is 0.
*
* There are no pre-defined semantics for the value, in most cases it is
* ignored. For success/failure indication, 0 should be success, and
* handlers should make sure to only return 0 or 1 (not -1 or other values).
*
*
* - to use a hook / create a handler:
*
* #include "mydaemon.h"
* int event_handler (struct eventinfo *info) { ... }
* hook_register (some_update_event, event_handler);
*
* or, if you need an argument to be passed along (addonptr will be added
* as first argument when calling the handler):
*
* #include "mydaemon.h"
* int event_handler (void *addonptr, struct eventinfo *info) { ... }
* hook_register_arg (some_update_event, event_handler, addonptr);
*
* (addonptr isn't typesafe, but that should be manageable.)
*/
/* TODO:
* - hook_unregister_all_module()
* - introspection / CLI / debug
* - testcases ;)
*
* For loadable modules, the idea is that hooks could be automatically
* unregistered when a module is unloaded.
*
* It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK,
* which would make it possible for the CLI to show all hooks and all
* registered handlers.
*/
struct hookent {
struct hookent *next;
void *hookfn; /* actually a function pointer */
void *hookarg;
bool has_arg;
struct frrmod_runtime *module;
const char *fnname;
};
struct hook {
const char *name;
struct hookent *entries;
};
/* subscribe/add callback function to a hook
*
* always use hook_register(), which uses the static inline helper from
* DECLARE_HOOK in order to get type safety
*/
extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
bool has_arg, struct frrmod_runtime *module,
const char *funcname);
#define hook_register(hookname, func) \
_hook_register(&_hook_ ## hookname, \
_hook_typecheck_ ## hookname (func), \
NULL, false, THIS_MODULE, #func)
#define hook_register_arg(hookname, func, arg) \
_hook_register(&_hook_ ## hookname, \
_hook_typecheck_arg_ ## hookname (func), \
arg, true, THIS_MODULE, #func)
extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
bool has_arg);
#define hook_unregister(hookname, func) \
_hook_unregister(&_hook_ ## hookname, \
_hook_typecheck_ ## hookname (func), NULL, false)
#define hook_unregister_arg(hookname, func, arg) \
_hook_unregister(&_hook_ ## hookname, \
_hook_typecheck_arg_ ## hookname (func), arg, true)
/* invoke hooks
* this is private (static) to the file that has the DEFINE_HOOK statement
*/
#define hook_call(hookname, ...) \
hook_call_ ## hookname (__VA_ARGS__)
/* helpers to add the void * arg */
#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__)
#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__)
/* use in header file - declares the hook and its arguments
* usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2))
* as above, "passlist" must use the same order and same names as "arglist"
*
* theoretically passlist is not neccessary, but let's keep things simple and
* use exact same args on DECLARE and DEFINE.
*/
#define DECLARE_HOOK(hookname, arglist, passlist) \
extern struct hook _hook_ ## hookname; \
__attribute__((unused)) \
static void *_hook_typecheck_ ## hookname ( \
int (*funcptr) arglist) { \
return (void *)funcptr; } \
__attribute__((unused)) \
static void *_hook_typecheck_arg_ ## hookname ( \
int (*funcptr) HOOK_ADDDEF arglist) { \
return (void *)funcptr; }
/* use in source file - contains hook-related definitions.
*/
#define DEFINE_HOOK(hookname, arglist, passlist) \
struct hook _hook_ ## hookname = { \
.name = #hookname, \
.entries = NULL, \
}; \
static int hook_call_ ## hookname arglist { \
int hooksum = 0; \
struct hookent *he = _hook_ ## hookname .entries; \
void *hookarg; \
union { \
void *voidptr; \
int (*fptr) arglist; \
int (*farg) HOOK_ADDDEF arglist; \
} hookp; \
for (; he; he = he->next) { \
hookarg = he->hookarg; \
hookp.voidptr = he->hookfn; \
if (!he->has_arg) \
hooksum += hookp.fptr passlist; \
else \
hooksum += hookp.farg HOOK_ADDARG passlist; \
} \
return hooksum; \
}
#endif /* _FRR_HOOK_H */

122
lib/if.c
View File

@ -123,7 +123,7 @@ if_cmp_func (struct interface *ifp1, struct interface *ifp2)
/* Create new interface structure. */
struct interface *
if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
if_create (const char *name, int namelen, vrf_id_t vrf_id)
{
struct interface *ifp;
struct list *intf_list = vrf_iflist_get (vrf_id);
@ -136,7 +136,7 @@ if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
strncpy (ifp->name, name, namelen);
ifp->name[namelen] = '\0';
ifp->vrf_id = vrf_id;
if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
if (if_lookup_by_name (ifp->name, vrf_id) == NULL)
listnode_add_sort (intf_list, ifp);
else
zlog_err("if_create(%s): corruption detected -- interface with this "
@ -158,15 +158,9 @@ if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
return ifp;
}
struct interface *
if_create (const char *name, int namelen)
{
return if_create_vrf (name, namelen, VRF_DEFAULT);
}
/* Create new interface structure. */
void
if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id)
if_update (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id)
{
struct list *intf_list = vrf_iflist_get (vrf_id);
@ -179,7 +173,7 @@ if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vr
strncpy (ifp->name, name, namelen);
ifp->name[namelen] = '\0';
ifp->vrf_id = vrf_id;
if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
if (if_lookup_by_name (ifp->name, vrf_id) == NULL)
listnode_add_sort (intf_list, ifp);
else
zlog_err("if_create(%s): corruption detected -- interface with this "
@ -239,7 +233,7 @@ if_add_hook (int type, int (*func)(struct interface *ifp))
/* Interface existance check by index. */
struct interface *
if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
if_lookup_by_index (ifindex_t ifindex, vrf_id_t vrf_id)
{
struct listnode *node;
struct interface *ifp;
@ -252,45 +246,27 @@ if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
return NULL;
}
struct interface *
if_lookup_by_index (ifindex_t ifindex)
{
return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT);
}
const char *
ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
ifindex2ifname (ifindex_t ifindex, vrf_id_t vrf_id)
{
struct interface *ifp;
return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ?
return ((ifp = if_lookup_by_index (ifindex, vrf_id)) != NULL) ?
ifp->name : "unknown";
}
const char *
ifindex2ifname (ifindex_t ifindex)
{
return ifindex2ifname_vrf (ifindex, VRF_DEFAULT);
}
ifindex_t
ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
ifname2ifindex (const char *name, vrf_id_t vrf_id)
{
struct interface *ifp;
return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp->ifindex
: IFINDEX_INTERNAL;
}
ifindex_t
ifname2ifindex (const char *name)
{
return ifname2ifindex_vrf (name, VRF_DEFAULT);
}
/* Interface existance check by interface name. */
struct interface *
if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
if_lookup_by_name (const char *name, vrf_id_t vrf_id)
{
struct listnode *node;
struct interface *ifp;
@ -312,7 +288,7 @@ if_lookup_by_name_all_vrf (const char *name)
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
{
ifp = if_lookup_by_name_vrf (name, vrf->vrf_id);
ifp = if_lookup_by_name (name, vrf->vrf_id);
if (ifp)
return ifp;
}
@ -321,13 +297,7 @@ if_lookup_by_name_all_vrf (const char *name)
}
struct interface *
if_lookup_by_name (const char *name)
{
return if_lookup_by_name_vrf (name, VRF_DEFAULT);
}
struct interface *
if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
if_lookup_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id)
{
struct listnode *node;
struct interface *ifp;
@ -343,15 +313,9 @@ if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
return NULL;
}
struct interface *
if_lookup_by_name_len(const char *name, size_t namelen)
{
return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
}
/* Lookup interface by IPv4 address. */
struct interface *
if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id)
if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id)
{
struct listnode *node;
struct listnode *cnode;
@ -383,15 +347,9 @@ if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id)
return NULL;
}
struct interface *
if_lookup_exact_address (void *src, int family)
{
return if_lookup_exact_address_vrf (src, family, VRF_DEFAULT);
}
/* Lookup interface by IPv4 address. */
struct connected *
if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id)
{
struct listnode *node;
struct prefix addr;
@ -432,15 +390,9 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
return match;
}
struct connected *
if_lookup_address (void *matchaddr, int family)
{
return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT);
}
/* Lookup interface by prefix */
struct interface *
if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id)
{
struct listnode *node;
struct listnode *cnode;
@ -460,37 +412,25 @@ if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
return NULL;
}
struct interface *
if_lookup_prefix (struct prefix *prefix)
{
return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
}
/* Get interface by name if given name interface doesn't exist create
one. */
struct interface *
if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
if_get_by_name (const char *name, vrf_id_t vrf_id)
{
struct interface *ifp;
return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
if_create_vrf (name, strlen(name), vrf_id);
return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp :
if_create (name, strlen(name), vrf_id);
}
struct interface *
if_get_by_name (const char *name)
{
return if_get_by_name_vrf (name, VRF_DEFAULT);
}
struct interface *
if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int vty)
if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty)
{
struct interface *ifp;
struct vrf *vrf;
struct listnode *node;
ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id);
ifp = if_lookup_by_name_len (name, namelen, vrf_id);
if (ifp)
return ifp;
@ -515,19 +455,13 @@ if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int v
}
else
{
if_update_vrf (ifp, name, namelen, vrf_id);
if_update (ifp, name, namelen, vrf_id);
return ifp;
}
}
}
}
return (if_create_vrf (name, namelen, vrf_id));
}
struct interface *
if_get_by_name_len (const char *name, size_t namelen)
{
return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT, 0);
return (if_create (name, namelen, vrf_id));
}
/* Does interface up ? */
@ -729,7 +663,7 @@ if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
struct interface *ifp;
size_t seppos = 0;
if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
if ( (ifp = if_lookup_by_name_len (name, nlen, vrf_id)) != NULL)
return ifp;
/* hunt the primary interface name... */
@ -738,9 +672,9 @@ if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
/* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
if (seppos < nlen)
return if_get_by_name_len_vrf (name, seppos, vrf_id, 1);
return if_get_by_name_len (name, seppos, vrf_id, 1);
else
return if_get_by_name_len_vrf (name, nlen, vrf_id, 1);
return if_get_by_name_len (name, nlen, vrf_id, 1);
}
#endif /* SUNOS_5 */
@ -776,7 +710,7 @@ DEFUN (interface,
#ifdef SUNOS_5
ifp = if_sunwzebra_get (ifname, sl, vrf_id);
#else
ifp = if_get_by_name_len_vrf (ifname, sl, vrf_id, 1);
ifp = if_get_by_name_len (ifname, sl, vrf_id, 1);
#endif /* SUNOS_5 */
if (!ifp)
@ -807,7 +741,7 @@ DEFUN_NOSH (no_interface,
if (argc > 3)
VRF_GET_ID (vrf_id, vrfname);
ifp = if_lookup_by_name_vrf (ifname, vrf_id);
ifp = if_lookup_by_name (ifname, vrf_id);
if (ifp == NULL)
{
@ -1188,7 +1122,7 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
return ifp;
}
else
return if_lookup_by_index(ifindex);
return if_lookup_by_index(ifindex, VRF_DEFAULT);
}
#endif /* ifaddr_ipv4_table */

View File

@ -229,6 +229,9 @@ struct interface
/* Interface metric */
uint32_t metric;
/* Interface Speed in Mb/s */
uint32_t speed;
/* Interface MTU. */
unsigned int mtu; /* IPv4 MTU */
unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */
@ -389,45 +392,33 @@ struct nbr_connected
/* Prototypes. */
extern int if_cmp_name_func (char *, char *);
extern struct interface *if_create (const char *name, int namelen);
extern struct interface *if_lookup_by_index (ifindex_t);
extern struct interface *if_lookup_exact_address (void *matchaddr, int family);
extern struct connected *if_lookup_address (void *matchaddr, int family);
extern struct interface *if_lookup_prefix (struct prefix *prefix);
extern void if_update_vrf (struct interface *, const char *name, int namelen,
vrf_id_t vrf_id);
extern struct interface *if_create_vrf (const char *name, int namelen,
vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id);
extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct connected *if_lookup_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix,
extern void if_update (struct interface *, const char *name, int namelen,
vrf_id_t vrf_id);
extern struct interface *if_create (const char *name, int namelen,
vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id);
extern struct interface *if_lookup_exact_address (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct connected *if_lookup_address (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct interface *if_lookup_prefix (struct prefix *prefix,
vrf_id_t vrf_id);
/* These 2 functions are to be used when the ifname argument is terminated
/* These 3 functions are to be used when the ifname argument is terminated
by a '\0' character: */
extern struct interface *if_lookup_by_name (const char *ifname);
extern struct interface *if_get_by_name (const char *ifname);
extern struct interface *if_lookup_by_name_all_vrf (const char *ifname);
extern struct interface *if_lookup_by_name_vrf (const char *ifname,
vrf_id_t vrf_id);
extern struct interface *if_get_by_name_vrf (const char *ifname,
extern struct interface *if_lookup_by_name (const char *ifname,
vrf_id_t vrf_id);
extern struct interface *if_get_by_name (const char *ifname,
vrf_id_t vrf_id);
/* For these 2 functions, the namelen argument should be the precise length
of the ifname string (not counting any optional trailing '\0' character).
In most cases, strnlen should be used to calculate the namelen value. */
extern struct interface *if_lookup_by_name_len(const char *ifname,
size_t namelen);
extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen);
extern struct interface *if_lookup_by_name_len_vrf(const char *ifname,
size_t namelen, vrf_id_t vrf_id);
extern struct interface *if_get_by_name_len_vrf(const char *ifname,
size_t namelen, vrf_id_t vrf_id);
extern struct interface *if_get_by_name_len(const char *ifname,
size_t namelen, vrf_id_t vrf_id, int vty);
@ -459,14 +450,12 @@ extern const char *if_link_type_str (enum zebra_link_type);
/* Please use ifindex2ifname instead of if_indextoname where possible;
ifindex2ifname uses internal interface info, whereas if_indextoname must
make a system call. */
extern const char *ifindex2ifname (ifindex_t);
extern const char *ifindex2ifname_vrf (ifindex_t, vrf_id_t vrf_id);
extern const char *ifindex2ifname (ifindex_t, vrf_id_t vrf_id);
/* Please use ifname2ifindex instead of if_nametoindex where possible;
ifname2ifindex uses internal interface info, whereas if_nametoindex must
make a system call. */
extern ifindex_t ifname2ifindex(const char *ifname);
extern ifindex_t ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id);
extern ifindex_t ifname2ifindex(const char *ifname, vrf_id_t vrf_id);
/* Connected address functions. */
extern struct connected *connected_new (void);

View File

@ -240,7 +240,7 @@ key_delete (struct keychain *keychain, struct key *key)
key_free (key);
}
DEFUN (key_chain,
DEFUN_NOSH (key_chain,
key_chain_cmd,
"key chain WORD",
"Authentication key management\n"
@ -280,7 +280,7 @@ DEFUN (no_key_chain,
return CMD_SUCCESS;
}
DEFUN (key,
DEFUN_NOSH (key,
key_cmd,
"key (0-2147483647)",
"Configure a key\n"

View File

@ -28,6 +28,9 @@
#include "memory_vty.h"
#include "zclient.h"
#include "log_int.h"
#include "module.h"
DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
const char frr_sysconfdir[] = SYSCONFDIR;
const char frr_vtydir[] = DAEMON_VTY_DIR;
@ -64,14 +67,16 @@ static const struct option lo_always[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "daemon", no_argument, NULL, 'd' },
{ "module", no_argument, NULL, 'M' },
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
{ NULL }
};
static const struct optspec os_always = {
"hvdi:",
"hvdM:",
" -h, --help Display this help and exit\n"
" -v, --version Print program version\n"
" -d, --daemon Runs in daemon mode\n"
" -M, --module Load specified module\n"
" --vty_socket Override vty socket path\n",
lo_always
};
@ -184,12 +189,18 @@ void frr_help_exit(int status)
exit(status);
}
struct option_chain {
struct option_chain *next;
const char *arg;
};
static struct option_chain *modules = NULL, **modnext = &modules;
static int errors = 0;
static int frr_opt(int opt)
{
static int vty_port_set = 0;
static int vty_addr_set = 0;
struct option_chain *oc;
char *err;
switch (opt) {
@ -203,6 +214,13 @@ static int frr_opt(int opt)
case 'd':
di->daemon_mode = 1;
break;
case 'M':
oc = XMALLOC(MTYPE_TMP, sizeof(*oc));
oc->arg = optarg;
oc->next = NULL;
*modnext = oc;
modnext = &oc->next;
break;
case 'i':
if (di->flags & FRR_NO_CFG_PID_DRY)
return 1;
@ -295,9 +313,12 @@ int frr_getopt(int argc, char * const argv[], int *longindex)
return opt;
}
static struct thread_master *master;
struct thread_master *frr_init(void)
{
struct thread_master *master;
struct option_chain *oc;
struct frrmod_runtime *module;
char moderr[256];
srandom(time(NULL));
@ -307,6 +328,17 @@ struct thread_master *frr_init(void)
zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
#endif
frrmod_init(di->module);
while (modules) {
modules = (oc = modules)->next;
module = frrmod_load(oc->arg, moderr, sizeof(moderr));
if (!module) {
fprintf(stderr, "%s\n", moderr);
exit(1);
}
XFREE(MTYPE_TMP, oc);
}
zprivs_init(di->privs);
master = thread_master_create();
@ -324,6 +356,8 @@ struct thread_master *frr_init(void)
void frr_config_fork(void)
{
hook_call(frr_late_init, master);
if (di->instance) {
snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf",
frr_sysconfdir, di->name, di->instance);

View File

@ -26,6 +26,8 @@
#include "thread.h"
#include "log.h"
#include "getopt.h"
#include "module.h"
#include "hook.h"
#define FRR_NO_PRIVSEP (1 << 0)
#define FRR_NO_TCPVTY (1 << 1)
@ -40,6 +42,7 @@ struct frr_daemon_info {
const char *name;
const char *logname;
unsigned short instance;
struct frrmod_runtime *module;
char *vty_addr;
int vty_port;
@ -67,15 +70,22 @@ struct frr_daemon_info {
* i.e. "ZEBRA" or "BGP"
*
* note that this macro is also a latch-on point for other changes (e.g.
* upcoming plugin support) that need to place some per-daemon things. Each
* upcoming module support) that need to place some per-daemon things. Each
* daemon should have one of these.
*/
#define FRR_DAEMON_INFO(execname, constname, ...) \
static struct frr_daemon_info execname ##_di = { \
.name = # execname, \
.logname = # constname, \
.module = THIS_MODULE, \
__VA_ARGS__ \
};
}; \
FRR_COREMOD_SETUP( \
.name = # execname, \
.description = # execname " daemon", \
.version = FRR_VERSION, \
) \
/* end */
extern void frr_preinit(struct frr_daemon_info *daemon,
int argc, char **argv);
@ -86,6 +96,7 @@ extern void frr_help_exit(int status);
extern struct thread_master *frr_init(void);
DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
extern void frr_config_fork(void);
extern void frr_vty_serv(void);

View File

@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance,
openlog (progname, syslog_flags, zl->facility);
zlog_default = zl;
#ifdef HAVE_GLIBC_BACKTRACE
/* work around backtrace() using lazily resolved dynamically linked
* symbols, which will otherwise cause funny breakage in the SEGV handler.
* (particularly, the dynamic linker can call malloc(), which uses locks
* in programs linked with -pthread, thus can deadlock.) */
void *bt[4];
backtrace (bt, array_size(bt));
free (backtrace_symbols (bt, 0));
backtrace_symbols_fd (bt, 0, 0);
#endif
}
void
@ -964,6 +975,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_ADD),
DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_DELETE),
DESC_ENTRY (ZEBRA_IPMR_ROUTE_STATS),
DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK),
DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK),
};
#undef DESC_ENTRY
@ -1058,7 +1072,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)
@ -1083,7 +1097,7 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_VNC;
else if (strmatch (s, "vnc-direct"))
return ZEBRA_ROUTE_VNC_DIRECT;
else if (strncmp (s, "n", 1) == 0)
else if (strmatch (s, "nhrp"))
return ZEBRA_ROUTE_NHRP;
}
return -1;

View File

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

View File

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

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