mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 15:17:15 +00:00
Merge remote-tracking branch 'origin/master' into EIGRP
This commit is contained in:
commit
97133f7915
93
COMMUNITY.md
93
COMMUNITY.md
@ -2,6 +2,16 @@
|
||||
|
||||
[TOC]
|
||||
|
||||
## General note on this document
|
||||
|
||||
This document is "descriptive/post-factual" in that it documents pratices that
|
||||
are in use; it is not "definitive/pre-factual" in prescribing practices.
|
||||
|
||||
This means that when a procedure changes, it is agreed upon, then put into
|
||||
practice, and then documented here. If this document doesn't match reality,
|
||||
it's the document that needs to be updated, not reality.
|
||||
|
||||
|
||||
## Git Structure
|
||||
|
||||
The master Git for PROJECT resides on Github at
|
||||
@ -10,20 +20,21 @@ The master Git for PROJECT resides on Github at
|
||||

|
||||
|
||||
There are 3 main branches for development and a release branch for each
|
||||
There is one main branch for development and a release branch for each
|
||||
major release.
|
||||
|
||||
New contributions are done against the head of the Develop branch. The CI
|
||||
New contributions are done against the head of the master branch. The CI
|
||||
systems will pick up the Github Pull Requests or the new patch from
|
||||
Patchwork, run some basic build and functional tests and will merge them
|
||||
into the branch automatically on success.
|
||||
|
||||
Code on the develop branch will then be further tested and reviewed by the
|
||||
community and merged to master on a regular interval.
|
||||
Patchwork, run some basic build and functional tests.
|
||||
|
||||
For each major release (1.0, 1.1 etc) a new release branch is created based
|
||||
on the master.
|
||||
|
||||
There was an attempt to use a "develop" branch automatically maintained by
|
||||
the CI system. This is not currently in active use, though the system is
|
||||
operational. If the "develop" branch is in active use and this paragraph
|
||||
is still here, this document obviously wasn't updated.
|
||||
|
||||
|
||||
## Programming language, Tools and Libraries
|
||||
|
||||
@ -250,16 +261,72 @@ Portions:
|
||||
|
||||
### Code styling / format
|
||||
|
||||
GNU coding standards apply. Indentation follows the result of invoking GNU
|
||||
indent (as of 2.2.8a) with the `-nut -nfc1` arguments.
|
||||
Coding style standards in FRR vary depending on location. Pre-existing
|
||||
code uses GNU coding standards. New code may use Linux kernel coding style.
|
||||
|
||||
GNU coding style apply to the following parts:
|
||||
|
||||
* lib/
|
||||
* zebra/
|
||||
* bgpd/
|
||||
* ospfd/
|
||||
* ospf6d/
|
||||
* isisd/
|
||||
* ripd/
|
||||
* ripngd/
|
||||
* vtysh/
|
||||
|
||||
Linux kernel coding style applies to:
|
||||
|
||||
* nhrpd/
|
||||
* watchfrr/
|
||||
* pimd/
|
||||
* lib/{checksum,hook,imsg-buffer,imsg,libfrr,md5,module,monotime,queue}.[ch]
|
||||
|
||||
BSD coding style applies to:
|
||||
|
||||
* ldpd/
|
||||
|
||||
**Whitespace changes in untouched parts of the code are not acceptable in
|
||||
patches that change actual code.** To change/fix formatting issues, please
|
||||
create a separate patch that only does formatting changes and nothing else.
|
||||
|
||||
It is acceptable to rewrap entire files to Linux kernel style, but this
|
||||
**MUST** come as a separate patch that does nothing other than this
|
||||
reformatting.
|
||||
|
||||
|
||||
#### GNU style
|
||||
|
||||
For GNU coding style, Indentation follows the result of invoking GNU indent:
|
||||
|
||||
```
|
||||
indent -nut -nfc1 file_for_submission.c
|
||||
```
|
||||
|
||||
Please don’t reformat existing files (or only sections modified by your
|
||||
changes), even if they don’t follow the standard. This makes it very hard to
|
||||
highlight the changes
|
||||
Originally, tabs were used instead of spaces, with tabs are every 8 columns.
|
||||
However, tab interoperability issues mean space characters are now preferred for
|
||||
new changes. We generally only clean up whitespace when code is unmaintainable
|
||||
due to whitespace issues, to minimise merging conflicts.
|
||||
|
||||
|
||||
#### Linux kernel & BSD style
|
||||
|
||||
These styles are documented externally:
|
||||
|
||||
* [https://www.kernel.org/doc/Documentation/CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle).
|
||||
* [http://man.openbsd.org/style](http://man.openbsd.org/style)
|
||||
|
||||
They are relatively similar but differ in details.
|
||||
|
||||
pimd deviates from Linux kernel style in using 2 spaces for indentation, with
|
||||
Tabs replacing 8 spaces, as well as adding a line break between `}` and `else`.
|
||||
It is acceptable to convert indentation in pimd/ to Linux kernel style, but
|
||||
please convert an entire file at a time. (Rationale: apart from 2-space
|
||||
indentation, the styles are sufficiently close to not upset when mixed.)
|
||||
|
||||
Unlike GNU style, these styles use tabs, not spaces.
|
||||
|
||||
|
||||
### Compile-Time conditional code
|
||||
|
||||
@ -307,4 +374,4 @@ of their debugs.
|
||||
CLI's are a complicated ugly beast. Additions or changes to the CLI
|
||||
should use a DEFUN to encapsulate one setting as much as is possible.
|
||||
Additionally as new DEFUN's are added to the system, documentation
|
||||
should be provided for the new commands.
|
||||
should be provided for the new commands.
|
||||
|
@ -1,4 +1,4 @@
|
||||
ChangeLog information for FreeRangeRouting is for now recorded in source-code
|
||||
ChangeLog information for FRRouting is for now recorded in source-code
|
||||
management system. Please see:
|
||||
|
||||
http://www.freerangerouting.org/
|
||||
http://www.frrouting.org/
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
This file describes the procedure for reporting FreeRangeRouting bugs. You are not
|
||||
obliged to follow this format, but it would be great help for FreeRangeRouting developers
|
||||
This file describes the procedure for reporting FRRouting bugs. You are not
|
||||
obliged to follow this format, but it would be great help for FRRouting developers
|
||||
if you report a bug as described below.
|
||||
|
||||
Bugs submitted with woefully incomplete information may be summarily
|
||||
@ -10,10 +10,10 @@ non-response to requests to reconfirm or supply additional
|
||||
information.
|
||||
|
||||
Report bugs on Github Issue Tracker at
|
||||
https://github.com/freerangerouting/frr/issues
|
||||
https://github.com/frrouting/frr/issues
|
||||
|
||||
Please supply the following information:
|
||||
1. Your FreeRangeRouting version or if it is from git then the commit reference.
|
||||
1. Your FRRouting version or if it is from git then the commit reference.
|
||||
Please try to report bugs against git master or the latest release.
|
||||
2. FRR daemons you run e.g. bgpd or ripd and full name of your OS. Any
|
||||
specific options you compiled Quagga with.
|
||||
|
@ -67,6 +67,7 @@ INSTALL_SDATA=@INSTALL@ -m 600
|
||||
AM_CFLAGS = $(WERROR)
|
||||
|
||||
noinst_LIBRARIES = libbgp.a
|
||||
module_LTLIBRARIES =
|
||||
sbin_PROGRAMS = bgpd
|
||||
bin_PROGRAMS = bgp_btoa
|
||||
|
||||
@ -75,7 +76,7 @@ libbgp_a_SOURCES = \
|
||||
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
|
||||
bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
|
||||
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
|
||||
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \
|
||||
bgp_dump.c bgp_ecommunity.c bgp_lcommunity.c \
|
||||
bgp_mplsvpn.c bgp_nexthop.c \
|
||||
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
|
||||
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
|
||||
@ -89,7 +90,7 @@ noinst_HEADERS = \
|
||||
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
|
||||
bgp_ecommunity.h bgp_lcommunity.h \
|
||||
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
|
||||
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
|
||||
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
|
||||
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
|
||||
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h
|
||||
|
||||
@ -101,6 +102,15 @@ bgp_btoa_SOURCES = bgp_btoa.c
|
||||
bgp_btoa_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
bgp_btoa_LDFLAGS = $(BGP_VNC_RFP_LD_FLAGS)
|
||||
|
||||
if SNMP
|
||||
module_LTLIBRARIES += bgpd_snmp.la
|
||||
endif
|
||||
|
||||
bgpd_snmp_la_SOURCES = bgp_snmp.c
|
||||
bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
||||
bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
|
||||
bgpd.conf.vnc.sample
|
||||
|
@ -45,14 +45,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_dump.h"
|
||||
#include "bgpd/bgp_open.h"
|
||||
#include "bgpd/bgp_advertise.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_memory.h"
|
||||
|
||||
DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DEFINE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
/* Definition of display strings corresponding to FSM events. This should be
|
||||
* kept consistent with the events defined in bgpd.h
|
||||
*/
|
||||
@ -1061,9 +1061,7 @@ bgp_stop (struct peer *peer)
|
||||
zlog_debug ("%s remove from all update group", peer->host);
|
||||
update_group_remove_peer_afs(peer);
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapBackwardTransition (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_backward_transition, peer);
|
||||
|
||||
/* Reset peer synctime */
|
||||
peer->synctime = 0;
|
||||
@ -1508,9 +1506,7 @@ bgp_establish (struct peer *peer)
|
||||
zlog_debug ("%s graceful restart timer stopped", peer->host);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
bgpTrapEstablished (peer);
|
||||
#endif /* HAVE_SNMP */
|
||||
hook_call(peer_established, peer);
|
||||
|
||||
/* Reset uptime, send keepalive, send current table. */
|
||||
peer->uptime = bgp_clock ();
|
||||
|
@ -109,4 +109,8 @@ extern void bgp_start_routeadv (struct bgp *);
|
||||
*/
|
||||
extern void bgp_adjust_routeadv (struct peer *);
|
||||
|
||||
#include "hook.h"
|
||||
DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer))
|
||||
DECLARE_HOOK(peer_established, (struct peer *peer), (peer))
|
||||
|
||||
#endif /* _QUAGGA_BGP_FSM_H */
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -20,7 +20,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#ifdef HAVE_SNMP
|
||||
#include <net-snmp/net-snmp-config.h>
|
||||
#include <net-snmp/net-snmp-includes.h>
|
||||
|
||||
@ -31,6 +30,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "thread.h"
|
||||
#include "smux.h"
|
||||
#include "filter.h"
|
||||
#include "hook.h"
|
||||
#include "libfrr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_table.h"
|
||||
@ -38,7 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
|
||||
/* BGP4-MIB described in RFC1657. */
|
||||
#define BGP4MIB 1,3,6,1,2,1,15
|
||||
@ -838,7 +839,7 @@ static struct trap_object bgpTrapList[] =
|
||||
{3, {3, 1, BGPPEERSTATE}}
|
||||
};
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapEstablished (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -847,7 +848,7 @@ bgpTrapEstablished (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -857,9 +858,10 @@ bgpTrapEstablished (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPESTABLISHED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
bgpTrapBackwardTransition (struct peer *peer)
|
||||
{
|
||||
int ret;
|
||||
@ -868,7 +870,7 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
|
||||
ret = inet_aton (peer->host, &addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
oid_copy_addr (index, &addr, IN_ADDR_SIZE);
|
||||
|
||||
@ -878,12 +880,29 @@ bgpTrapBackwardTransition (struct peer *peer)
|
||||
index, IN_ADDR_SIZE,
|
||||
bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
|
||||
BGPBACKWARDTRANSITION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_snmp_init (void)
|
||||
static int
|
||||
bgp_snmp_init (struct thread_master *tm)
|
||||
{
|
||||
smux_init (bm->master);
|
||||
smux_init (tm);
|
||||
REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNMP */
|
||||
|
||||
static int
|
||||
bgp_snmp_module_init (void)
|
||||
{
|
||||
hook_register(peer_established, bgpTrapEstablished);
|
||||
hook_register(peer_backward_transition, bgpTrapBackwardTransition);
|
||||
hook_register(frr_late_init, bgp_snmp_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "bgpd_snmp",
|
||||
.version = FRR_VERSION,
|
||||
.description = "bgpd AgentX SNMP module",
|
||||
.init = bgp_snmp_module_init
|
||||
)
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* BGP4 SNMP support
|
||||
Copyright (C) 1999, 2000 Kunihiro Ishiguro
|
||||
|
||||
This file is part of GNU Zebra.
|
||||
|
||||
GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
GNU Zebra is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#ifndef _QUAGGA_BGP_SNMP_H
|
||||
#define _QUAGGA_BGP_SNMP_H
|
||||
|
||||
extern void bgp_snmp_init (void);
|
||||
extern void bgpTrapEstablished (struct peer *);
|
||||
extern void bgpTrapBackwardTransition (struct peer *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_SNMP_H */
|
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
82
bgpd/bgpd.c
82
bgpd/bgpd.c
@ -72,9 +72,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_vty.h"
|
||||
#include "bgpd/bgp_mpath.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#ifdef HAVE_SNMP
|
||||
#include "bgpd/bgp_snmp.h"
|
||||
#endif /* HAVE_SNMP */
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_memory.h"
|
||||
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
176
configure.ac
176
configure.ac
@ -1,5 +1,5 @@
|
||||
##
|
||||
## Configure template file for FreeRangeRouting.
|
||||
## Configure template file for FRRouting.
|
||||
## autoconf will generate configure script.
|
||||
##
|
||||
## Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
|
||||
@ -7,9 +7,9 @@
|
||||
##
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
AC_INIT(frr, 2.1-dev, [https://github.com/freerangerouting/frr/issues])
|
||||
PACKAGE_URL="https://freerangerouting.org/"
|
||||
PACKAGE_FULLNAME="FreeRangeRouting"
|
||||
AC_INIT(frr, 2.1-dev, [https://github.com/frrouting/frr/issues])
|
||||
PACKAGE_URL="https://frrouting.org/"
|
||||
PACKAGE_FULLNAME="FRRouting"
|
||||
AC_SUBST(PACKAGE_FULLNAME)
|
||||
|
||||
CONFIG_ARGS="$ac_configure_args"
|
||||
@ -55,6 +55,13 @@ dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow
|
||||
AC_SUBST(pkgsrcdir)
|
||||
AC_SUBST(pkgsrcrcdir)
|
||||
|
||||
AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [
|
||||
moduledir="$withval"
|
||||
], [
|
||||
moduledir="\${libdir}/frr/modules"
|
||||
])
|
||||
AC_SUBST([moduledir], [$moduledir])
|
||||
|
||||
AC_ARG_ENABLE(tcmalloc,
|
||||
AS_HELP_STRING([--enable-tcmalloc], [Turn on tcmalloc]),
|
||||
[case "${enableval}" in
|
||||
@ -66,6 +73,10 @@ LIBS="$LIBS -ltcmalloc_minimal"
|
||||
esac],[tcmalloc_enabled=false])
|
||||
|
||||
|
||||
dnl Thanks autoconf, but we don't want a default -g -O2. We have our own
|
||||
dnl flag determination logic.
|
||||
CFLAGS="${CFLAGS:-}"
|
||||
|
||||
dnl --------------------
|
||||
dnl Check CC and friends
|
||||
dnl --------------------
|
||||
@ -78,6 +89,7 @@ AM_PROG_CC_C_O
|
||||
dnl remove autoconf default "-g -O2"
|
||||
CFLAGS="$orig_cflags"
|
||||
AC_PROG_CC_C99
|
||||
dnl NB: see C11 below
|
||||
|
||||
AC_PROG_EGREP
|
||||
PKG_PROG_PKG_CONFIG
|
||||
@ -89,7 +101,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
|
||||
dnl try and enable CFLAGS that are useful for Quagga
|
||||
dnl - specifically, options to control warnings
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS()
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_DEFUN([AC_C_FLAG], [{
|
||||
AC_LANG_PUSH(C)
|
||||
ac_c_flag_save="$CFLAGS"
|
||||
@ -115,6 +127,13 @@ dnl ICC won't bail on unknown options without -diag-error 10006
|
||||
dnl need to do this first so we get useful results for the other options
|
||||
AC_C_FLAG([-diag-error 10006])
|
||||
|
||||
dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something
|
||||
ac_cc="$CC"
|
||||
CC="${CC% -std=gnu99}"
|
||||
CC="${CC% -std=c99}"
|
||||
|
||||
AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
|
||||
|
||||
dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here
|
||||
if test "z$orig_cflags" = "z"; then
|
||||
AC_C_FLAG([-g])
|
||||
@ -170,6 +189,18 @@ AC_LINK_IFELSE(
|
||||
])
|
||||
AC_LANG_POP(C)
|
||||
|
||||
dnl ----------
|
||||
dnl Essentials
|
||||
dnl ----------
|
||||
|
||||
AX_PTHREAD([
|
||||
CC="$PTHREAD_CC"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
], [
|
||||
AC_MSG_FAILURE([This Quagga version needs pthreads])
|
||||
])
|
||||
|
||||
dnl --------------
|
||||
dnl Check programs
|
||||
dnl --------------
|
||||
@ -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}
|
||||
|
2
debian/README.Debian
vendored
2
debian/README.Debian
vendored
@ -14,7 +14,7 @@ available forcing you to explicitly type "apt-get install frr" to upgrade it.
|
||||
* What is frr?
|
||||
=================
|
||||
|
||||
http://www.freerangerouting.org/
|
||||
http://www.frrouting.org/
|
||||
FRR is a routing software suite, providing implementations of OSPFv2,
|
||||
OSPFv3, RIP v1 and v2, RIPng, ISIS, PIM, BGP and LDP for Unix platforms, particularly
|
||||
FreeBSD and Linux and also NetBSD, to mention a few. FRR is a fork of Quagga
|
||||
|
4
debian/copyright
vendored
4
debian/copyright
vendored
@ -1,7 +1,7 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: Frr
|
||||
Upstream-Contact: maintainers@freerangerouting.org, security@freerangerouting.org
|
||||
Source: http://www.freerangerouting.org/
|
||||
Upstream-Contact: maintainers@frrouting.org, security@frrouting.org
|
||||
Source: http://www.frrouting.org/
|
||||
|
||||
Files: *
|
||||
Copyright: 1996-2003 by the original Zebra authors:
|
||||
|
54
defaults.h
Normal file
54
defaults.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* FRR switchable defaults.
|
||||
* Copyright (C) 2017 David Lamparter for NetDEF, Inc.
|
||||
*
|
||||
* This file is part of FRRouting (FRR).
|
||||
*
|
||||
* FRR is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2, or (at your option) any later version.
|
||||
*
|
||||
* FRR is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with FRR; see the file COPYING. If not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_DEFAULTS_H
|
||||
#define _FRR_DEFAULTS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_CUMULUS
|
||||
|
||||
#define DFLT_BGP_IMPORT_CHECK 1
|
||||
#define DFLT_BGP_TIMERS_CONNECT 10
|
||||
#define DFLT_BGP_HOLDTIME 9
|
||||
#define DFLT_BGP_KEEPALIVE 3
|
||||
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 1
|
||||
#define DFLT_BGP_SHOW_HOSTNAME 1
|
||||
#define DFLT_BGP_DETERMINISTIC_MED 1
|
||||
|
||||
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1
|
||||
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1
|
||||
|
||||
#else /* !HAVE_CUMULUS */
|
||||
|
||||
#define DFLT_BGP_IMPORT_CHECK 0
|
||||
#define DFLT_BGP_TIMERS_CONNECT 120
|
||||
#define DFLT_BGP_HOLDTIME 180
|
||||
#define DFLT_BGP_KEEPALIVE 60
|
||||
#define DFLT_BGP_LOG_NEIGHBOR_CHANGES 0
|
||||
#define DFLT_BGP_SHOW_HOSTNAME 0
|
||||
#define DFLT_BGP_DETERMINISTIC_MED 0
|
||||
|
||||
#define DFLT_OSPF_LOG_ADJACENCY_CHANGES 0
|
||||
#define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 0
|
||||
|
||||
#endif /* !HAVE_CUMULUS */
|
||||
|
||||
#endif /* _FRR_DEFAULTS_H */
|
@ -18,7 +18,7 @@ Add packages:
|
||||
|
||||
sudo yum install git autoconf automake libtool make gawk readline-devel \
|
||||
texinfo net-snmp-devel groff pkgconfig json-c-devel pam-devel \
|
||||
flex 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 \
|
||||
|
@ -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 \
|
||||
|
@ -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/ \
|
||||
|
@ -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 \
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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/ \
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -18,6 +18,7 @@ daemons.
|
||||
* Config Commands:: Commands used in config files
|
||||
* Terminal Mode Commands:: Common commands used in a VTY
|
||||
* Common Invocation Options:: Starting the daemons
|
||||
* Loadable Module Support:: Using extension modules
|
||||
* Virtual Terminal Interfaces:: Interacting with the daemons
|
||||
@end menu
|
||||
|
||||
@ -372,6 +373,51 @@ Print program version.
|
||||
@end table
|
||||
|
||||
|
||||
@node Loadable Module Support
|
||||
@section Loadable Module Support
|
||||
|
||||
FRR supports loading extension modules at startup. Loading, reloading or
|
||||
unloading modules at runtime is not supported (yet). To load a module, use
|
||||
the following command line option at daemon startup:
|
||||
|
||||
@table @samp
|
||||
@item -M @var{module:options}
|
||||
@itemx --module @var{module:options}
|
||||
|
||||
Load the specified module, optionally passing options to it. If the module
|
||||
name contains a slash (/), it is assumed to be a full pathname to a file to
|
||||
be loaded. If it does not contain a slash, the
|
||||
@code{@value{INSTALL_PREFIX_MODULES}} directory is searched for a module of
|
||||
the given name; first with the daemon name prepended (e.g. @code{zebra_mod}
|
||||
for @code{mod}), then without the daemon name prepended.
|
||||
|
||||
This option is available on all daemons, though some daemons may not have
|
||||
any modules available to be loaded.
|
||||
@end table
|
||||
|
||||
|
||||
@subsection The SNMP Module
|
||||
|
||||
If SNMP is enabled during compile-time and installed as part of the package,
|
||||
the @code{snmp} module can be loaded for the @command{zebra},
|
||||
@command{bgpd}, @command{ospfd}, @command{ospf6d} and @command{ripd} daemons.
|
||||
|
||||
The module ignores any options passed to it. Refer to @ref{SNMP Support}
|
||||
for information on its usage.
|
||||
|
||||
|
||||
@subsection The FPM Module
|
||||
|
||||
If FPM is enabled during compile-time and installed as part of the package,
|
||||
the @code{fpm} module can be loaded for the @command{zebra} daemon. This
|
||||
provides the Forwarding Plane Manager ("FPM") API.
|
||||
|
||||
The module expects its argument to be either @code{netlink} or
|
||||
@code{protobuf}, specifying the encapsulation to use. @code{netlink} is the
|
||||
default, and @code{protobuf} may not be available if the module was built
|
||||
without protobuf support. Refer to @ref{zebra FIB push interface} for more
|
||||
information.
|
||||
|
||||
|
||||
@node Virtual Terminal Interfaces
|
||||
@section Virtual Terminal Interfaces
|
||||
|
@ -27,6 +27,9 @@ bgpd \- a BGPv4, BGPv4\+, BGPv4\- routing engine for use with @PACKAGE_FULLNAME@
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B bgpd
|
||||
@ -76,6 +79,11 @@ When the program terminates, retain routes added by \fBbgpd\fR.
|
||||
\fB\-S\fR, \fB\-\-skip_runas\fR
|
||||
Skip setting the process effective user and group.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBbgpd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -13,6 +13,7 @@
|
||||
@set INSTALL_PREFIX_ETC @CFG_SYSCONF@
|
||||
@set INSTALL_PREFIX_SBIN @CFG_SBIN@
|
||||
@set INSTALL_PREFIX_STATE @CFG_STATE@
|
||||
@set INSTALL_PREFIX_MODULES @CFG_MODULE@
|
||||
@set INSTALL_USER @enable_user@
|
||||
@set INSTALL_GROUP @enable_group@
|
||||
@set INSTALL_VTY_GROUP @enable_vty_group@
|
||||
|
119
doc/dev-modules.md
Normal file
119
doc/dev-modules.md
Normal file
@ -0,0 +1,119 @@
|
||||
# Module and Hook support (developer docs)
|
||||
|
||||
## What it does
|
||||
|
||||
It uses `dlopen()` to load DSOs at startup.
|
||||
|
||||
|
||||
## Limitations
|
||||
|
||||
* can't load, unload, or reload during runtime. This just needs some work
|
||||
and can probably be done in the future.
|
||||
* doesn't fix any of the "things need to be changed in the code in the library"
|
||||
issues. Most prominently, you can't add a CLI node because CLI nodes are
|
||||
listed in the library...
|
||||
* if your module crashes, the daemon crashes. Should be obvious.
|
||||
* **does not provide a stable API or ABI**. Your module must match a version
|
||||
of FRR and you may have to update it frequently to match changes.
|
||||
* **does not create a license boundary**. Your module will need to link
|
||||
libzebra and include header files from the daemons, meaning it will be
|
||||
GPL-encumbered.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Look for `moduledir` in `configure.ac`, default is normally
|
||||
`/usr/lib64/frr/modules` but depends on `--libdir` / `--prefix`.
|
||||
|
||||
The daemon's name is prepended when looking for a module, e.g. "snmp" tries
|
||||
to find "zebra_snmp" first when used in zebra. This is just to make it nicer
|
||||
for the user, with the snmp module having the same name everywhere.
|
||||
|
||||
Modules can be packaged separately from FRR. The SNMP and FPM modules are
|
||||
good candidates for this because they have dependencies (net-snmp / protobuf)
|
||||
that are not FRR dependencies. However, any distro packages should have an
|
||||
"exact-match" dependency onto the FRR package. Using a module from a
|
||||
different FRR version will probably blow up nicely.
|
||||
|
||||
For snapcraft (and during development), modules can be loaded with full path
|
||||
(e.g. -M `$SNAP/lib/frr/modules/zebra_snmp.so`). Note that libtool puts output
|
||||
files in the .libs directory, so during development you have to use
|
||||
`./zebra -M .libs/zebra_snmp.so`.
|
||||
|
||||
|
||||
## Creating a module
|
||||
|
||||
... best to look at the existing SNMP or FPM modules.
|
||||
|
||||
Basic boilerplate:
|
||||
|
||||
```
|
||||
#include "hook.h"
|
||||
#include "module.h"
|
||||
|
||||
static int
|
||||
module_init (void)
|
||||
{
|
||||
hook_register(frr_late_init, module_late_init);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FRR_MODULE_SETUP(
|
||||
.name = "my module",
|
||||
.version = "0.0",
|
||||
.description = "my module",
|
||||
.init = module_init,
|
||||
)
|
||||
```
|
||||
|
||||
The `frr_late_init` hook will be called after the daemon has finished its
|
||||
other startup and is about to enter the main event loop; this is the best
|
||||
place for most initialisation.
|
||||
|
||||
|
||||
## Compiler & Linker magic
|
||||
|
||||
There's a `THIS_MODULE` (like in the Linux kernel), which uses `visibility`
|
||||
attributes to restrict it to the current module. If you get a linker error
|
||||
with `_frrmod_this_module`, there is some linker SNAFU. This shouldn't be
|
||||
possible, though one way to get it would be to not include libzebra (which
|
||||
provides a fallback definition for the symbol).
|
||||
|
||||
libzebra and the daemons each have their own `THIS_MODULE`, as do all loadable
|
||||
modules. In any other libraries (e.g. `libfrrsnmp`), `THIS_MODULE` will use
|
||||
the definition in libzebra; same applies if the main executable doesn't use
|
||||
`FRR_DAEMON_INFO` (e.g. all testcases).
|
||||
|
||||
The deciding factor here is "what dynamic linker unit are you using the symbol
|
||||
from." If you're in a library function and want to know who called you, you
|
||||
can't use `THIS_MODULE` (because that'll just tell you you're in the library).
|
||||
Put a macro around your function that adds `THIS_MODULE` in the *caller's
|
||||
code calling your function*.
|
||||
|
||||
The idea is to use this in the future for module unloading. Hooks already
|
||||
remember which module they were installed by, as groundwork for a function
|
||||
that removes all of a module's installed hooks.
|
||||
|
||||
There's also the `frr_module` symbol in modules, pretty much a standard entry
|
||||
point for loadable modules.
|
||||
|
||||
|
||||
## Hooks
|
||||
|
||||
Hooks are just points in the code where you can register your callback to
|
||||
be called. The parameter list is specific to the hook point. Since there is
|
||||
no stable API, the hook code has some extra type safety checks making sure
|
||||
you get a compiler warning when the hook parameter list doesn't match your
|
||||
callback. Don't ignore these warnings.
|
||||
|
||||
|
||||
## Relation to MTYPE macros
|
||||
|
||||
The MTYPE macros, while primarily designed to decouple MTYPEs from the library
|
||||
and beautify the code, also work very nicely with loadable modules -- both
|
||||
constructors and destructors are executed when loading/unloading modules.
|
||||
|
||||
This means there is absolutely no change required to MTYPEs, you can just use
|
||||
them in a module and they will even clean up themselves when we implement
|
||||
module unloading and an unload happens. In fact, it's impossible to create
|
||||
a bug where unloading fails to de-register a MTYPE.
|
12
doc/frr.texi
12
doc/frr.texi
@ -7,7 +7,7 @@
|
||||
@setfilename frr.info
|
||||
@c Set variables - sourced from defines.texi
|
||||
@include defines.texi
|
||||
@settitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}}
|
||||
@settitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}}
|
||||
@c %**end of header
|
||||
|
||||
@c automake will automatically generate version.texi
|
||||
@ -48,16 +48,16 @@ This file documents the Frr Software Routing Suite which manages common
|
||||
TCP/IP routing protocols.
|
||||
|
||||
This is Edition @value{EDITION}, last updated @value{UPDATED} of
|
||||
@cite{The Frr Manual}, for @uref{http://www.freerangerouting.org/,,@value{PACKAGE_NAME}}
|
||||
@cite{The Frr Manual}, for @uref{http://www.frrouting.org/,,@value{PACKAGE_NAME}}
|
||||
Version @value{VERSION}.
|
||||
|
||||
@insertcopying
|
||||
@end ifinfo
|
||||
|
||||
@titlepage
|
||||
@title @uref{http://www.freerangerouting.org,,Frr}
|
||||
@title @uref{http://www.frrouting.org,,Frr}
|
||||
@subtitle A routing software package for TCP/IP networks
|
||||
@subtitle @uref{http://www.freerangerouting.org,,@value{PACKAGE_NAME}} @value{VERSION}
|
||||
@subtitle @uref{http://www.frrouting.org,,@value{PACKAGE_NAME}} @value{VERSION}
|
||||
@subtitle @value{UPDATED-MONTH}
|
||||
@author @value{AUTHORS}
|
||||
|
||||
@ -72,9 +72,9 @@ Version @value{VERSION}.
|
||||
@node Top
|
||||
@top Frr -- With Virtual Network Control
|
||||
|
||||
@uref{http://www.freerangerouting.org,,Frr} is an advanced routing software package
|
||||
@uref{http://www.frrouting.org,,Frr} is an advanced routing software package
|
||||
that provides a suite of TCP/IP based routing protocols. This is the Manual
|
||||
for @value{PACKAGE_STRING}. @uref{http://www.freerangerouting.org,,Frr} is a fork of
|
||||
for @value{PACKAGE_STRING}. @uref{http://www.frrouting.org,,Frr} is a fork of
|
||||
@uref{http://www.quagga.net,,Quagga}.
|
||||
|
||||
@insertcopying
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 22 KiB |
@ -23,6 +23,9 @@ isisd \- an IS-IS routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B isisd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBisisd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ldpd \- an LDP engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ldpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBldpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -385,7 +385,8 @@ ip protocol rip route-map RM1
|
||||
|
||||
Zebra supports a 'FIB push' interface that allows an external
|
||||
component to learn the forwarding information computed by the Frr
|
||||
routing suite.
|
||||
routing suite. This is a loadable module that needs to be enabled
|
||||
at startup as described in @ref{Loadable Module Support}.
|
||||
|
||||
In Frr, the Routing Information Base (RIB) resides inside
|
||||
zebra. Routing protocols communicate their best routes to zebra, and
|
||||
@ -440,9 +441,9 @@ independently.
|
||||
@end itemize
|
||||
|
||||
As mentioned before, zebra encodes routes sent to the FPM in netlink
|
||||
format by default. The format can be controlled via the
|
||||
@code{--fpm_format} command-line option to zebra, which currently
|
||||
takes the values @code{netlink} and @code{protobuf}.
|
||||
format by default. The format can be controlled via the FPM module's
|
||||
load-time option to zebra, which currently takes the values @code{netlink}
|
||||
and @code{protobuf}.
|
||||
|
||||
The zebra FPM interface uses replace semantics. That is, if a 'route
|
||||
add' message for a prefix is followed by another 'route add' message,
|
||||
|
@ -23,6 +23,9 @@ nhrpd \- a Next Hop Routing Protocol routing engine for use with @PACKAGE_FULLNA
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B nhrpd
|
||||
@ -63,6 +66,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBnhrpd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospf6d \- an OSPFv3 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospf6d
|
||||
@ -64,6 +67,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospf6d\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ospfd \- an OSPFv2 routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ospfd
|
||||
@ -66,6 +69,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-a\fR, \fB\-\-apiserver \fR
|
||||
Enable OSPF apiserver. Default is disabled.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBospfd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -2,7 +2,7 @@
|
||||
@chapter Overview
|
||||
@cindex Overview
|
||||
|
||||
@uref{http://www.freerangerouting.org,,Frr} is a routing software package that
|
||||
@uref{http://www.frrouting.org,,Frr} is a routing software package that
|
||||
provides TCP/IP based routing services with routing protocols support such
|
||||
as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+ (@pxref{Supported
|
||||
RFCs}). Frr also supports special BGP Route Reflector and Route Server
|
||||
@ -275,12 +275,12 @@ November 1995.}
|
||||
|
||||
The official Frr web-site is located at:
|
||||
|
||||
@uref{http://www.freerangerouting.org/}
|
||||
@uref{http://www.frrouting.org/}
|
||||
|
||||
and contains further information, as well as links to additional
|
||||
resources.
|
||||
|
||||
@uref{http://www.freerangerouting.org/,Frr} is a fork of Quagga, whose
|
||||
@uref{http://www.frrouting.org/,Frr} is a fork of Quagga, whose
|
||||
web-site is located at:
|
||||
|
||||
@uref{http://www.quagga.net/}.
|
||||
@ -298,7 +298,7 @@ comments or suggestions to Frr, please subscribe to:
|
||||
|
||||
@uref{http://lists.nox.tf/listinfo/frr-users}.
|
||||
|
||||
The @uref{http://www.freerangerouting.org/,,Frr} site has further information on
|
||||
The @uref{http://www.frrouting.org/,,Frr} site has further information on
|
||||
the available mailing lists, see:
|
||||
|
||||
@uref{http://lists.nox.tf/lists.php}
|
||||
@ -315,7 +315,7 @@ the available mailing lists, see:
|
||||
|
||||
If you think you have found a bug, please send a bug report to:
|
||||
|
||||
@uref{http://github.com/freerangerouting/frr/issues}
|
||||
@uref{http://github.com/frrouting/frr/issues}
|
||||
|
||||
When you send a bug report, please be careful about the points below.
|
||||
|
||||
@ -334,4 +334,4 @@ arguments to the configure script please note that too.
|
||||
|
||||
Bug reports are very important for us to improve the quality of Frr.
|
||||
Frr is still in the development stage, but please don't hesitate to
|
||||
send a bug report to @uref{http://github.com/freerangerouting/frr/issues}.
|
||||
send a bug report to @uref{http://github.com/frrouting/frr/issues}.
|
||||
|
@ -26,6 +26,9 @@ pimd \- a PIM routing for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B pimd
|
||||
@ -70,6 +73,11 @@ interfaces.
|
||||
\fB\-u\fR, \fB\-\-user \fR\fIuser\fR
|
||||
Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBpimd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.TP
|
||||
|
@ -23,6 +23,9 @@ ripd \- a RIP routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR module may be available for
|
||||
\fBripd\fR, if the package was built with SNMP support.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -23,6 +23,9 @@ ripngd \- a RIPNG routing engine for use with @PACKAGE_FULLNAME@.
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ripngd
|
||||
@ -67,6 +70,11 @@ Specify the user to run as. Default is \fI@enable_user@\fR.
|
||||
\fB\-r\fR, \fB\-\-retain\fR
|
||||
When the program terminates, retain routes added by \fBripd\fR.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
There are currently no such modules for
|
||||
\fBripngd\fR in the base package.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -8,6 +8,10 @@ but is able to connect to a SNMP agent using the SMUX protocol
|
||||
(@cite{RFC1227}) or the AgentX protocol (@cite{RFC2741}) and make the
|
||||
routing protocol MIBs available through it.
|
||||
|
||||
Note that SNMP Support needs to be enabled at compile-time and loaded as
|
||||
module on daemon startup. Refer to @ref{Loadable Module Support} on
|
||||
the latter.
|
||||
|
||||
@menu
|
||||
* Getting and installing an SNMP agent::
|
||||
* AgentX configuration::
|
||||
|
@ -108,13 +108,13 @@ Set the logging
|
||||
(LOG_DEBUG), but higher number can be supplied if extra debugging messages
|
||||
are required.
|
||||
.TP
|
||||
.BI \-m " number" "\fR, \fB\-\-min\-restart\-interval " number
|
||||
.BI \-\-min\-restart\-interval " number
|
||||
Set the minimum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
default value is "60").
|
||||
.TP
|
||||
.BI \-M " number" "\fR, \fB\-\-max\-restart\-interval " number
|
||||
.BI \-\-max\-restart\-interval " number
|
||||
Set the maximum
|
||||
.I number
|
||||
of seconds to wait between invocations of the daemon restart commands (the
|
||||
|
@ -23,6 +23,9 @@ zebra \- a routing manager for use with associated @PACKAGE_FULLNAME@ components
|
||||
] [
|
||||
.B \-g
|
||||
.I group
|
||||
] [
|
||||
.B \-M
|
||||
.I module:options
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B zebra
|
||||
@ -86,6 +89,14 @@ maximum before starting zebra.
|
||||
|
||||
Note that this affects Linux only.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module \fR\fImodule:options\fR
|
||||
Load a module at startup. May be specified more than once.
|
||||
The \fBsnmp\fR and \fBfpm\fR modules may be
|
||||
available for \fBzebra\fR, if the package was built with SNMP and FPM support
|
||||
respectively. The \fBfpm\fR module takes an additional colon-separated
|
||||
argument specifying the encapsulation, either \fBnetlink\fR or \fBprotobuf\fR.
|
||||
It should thus be loaded with \fB-M fpm:netlink\fR or \fB-M fpm:protobuf\fR.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print the version and exit.
|
||||
.SH FILES
|
||||
|
@ -279,6 +279,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff),
|
||||
MSG_DONTWAIT, (struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
|
||||
if (bytesread < 0)
|
||||
zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed");
|
||||
|
||||
return ISIS_WARNING;
|
||||
}
|
||||
/*
|
||||
@ -322,10 +326,10 @@ isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
|
||||
addr_len = sizeof (s_addr);
|
||||
|
||||
/* we can read directly to the stream */
|
||||
bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
|
||||
circuit->interface->mtu, 0,
|
||||
(struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
stream_recvfrom (circuit->rcv_stream, circuit->fd,
|
||||
circuit->interface->mtu, 0,
|
||||
(struct sockaddr *) &s_addr,
|
||||
(socklen_t *) &addr_len);
|
||||
|
||||
if (s_addr.sll_pkttype == PACKET_OUTGOING)
|
||||
{
|
||||
|
@ -68,7 +68,6 @@ remove_excess_adjs (struct list *adjs)
|
||||
if (candidate->sys_type < adj->sys_type)
|
||||
{
|
||||
excess = node;
|
||||
candidate = adj;
|
||||
continue;
|
||||
}
|
||||
if (candidate->sys_type > adj->sys_type)
|
||||
@ -78,7 +77,6 @@ remove_excess_adjs (struct list *adjs)
|
||||
if (comp > 0)
|
||||
{
|
||||
excess = node;
|
||||
candidate = adj;
|
||||
continue;
|
||||
}
|
||||
if (comp < 0)
|
||||
@ -87,7 +85,6 @@ remove_excess_adjs (struct list *adjs)
|
||||
if (candidate->circuit->circuit_id > adj->circuit->circuit_id)
|
||||
{
|
||||
excess = node;
|
||||
candidate = adj;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -98,7 +95,6 @@ remove_excess_adjs (struct list *adjs)
|
||||
if (comp > 0)
|
||||
{
|
||||
excess = node;
|
||||
candidate = adj;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
136
ldpd/l2vpn.c
136
ldpd/l2vpn.c
@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
|
||||
}
|
||||
|
||||
struct l2vpn_if *
|
||||
l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
|
||||
l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname)
|
||||
{
|
||||
struct l2vpn_if *lif;
|
||||
|
||||
@ -125,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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
221
ldpd/lde.c
221
ldpd/lde.c
@ -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;
|
||||
}
|
||||
|
24
ldpd/lde.h
24
ldpd/lde.h
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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
@ -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) {
|
||||
|
579
ldpd/ldpd.c
579
ldpd/ldpd.c
File diff suppressed because it is too large
Load Diff
45
ldpd/ldpd.h
45
ldpd/ldpd.h
@ -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);
|
||||
|
59
ldpd/ldpe.c
59
ldpd/ldpe.c
@ -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;
|
||||
|
11
ldpd/ldpe.h
11
ldpd/ldpe.h
@ -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 *);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
118
lib/frratomic.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRRATOMIC_H
|
||||
#define _FRRATOMIC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef FRR_AUTOCONF_ATOMIC
|
||||
#error autoconf checks for atomic functions were not properly run
|
||||
#endif
|
||||
|
||||
/* ISO C11 */
|
||||
#ifdef HAVE_STDATOMIC_H
|
||||
#include <stdatomic.h>
|
||||
|
||||
/* gcc 4.7 and newer */
|
||||
#elif defined(HAVE___ATOMIC)
|
||||
|
||||
#define _Atomic volatile
|
||||
|
||||
#define memory_order_relaxed __ATOMIC_RELAXED
|
||||
#define memory_order_consume __ATOMIC_CONSUME
|
||||
#define memory_order_acquire __ATOMIC_ACQUIRE
|
||||
#define memory_order_release __ATOMIC_RELEASE
|
||||
#define memory_order_acq_rel __ATOMIC_ACQ_REL
|
||||
#define memory_order_seq_cst __ATOMIC_SEQ_CST
|
||||
|
||||
#define atomic_load_explicit __atomic_load_n
|
||||
#define atomic_store_explicit __atomic_store_n
|
||||
#define atomic_exchange_explicit __atomic_exchange_n
|
||||
#define atomic_fetch_add_explicit __atomic_fetch_add
|
||||
#define atomic_fetch_sub_explicit __atomic_fetch_sub
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
|
||||
__atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2)
|
||||
|
||||
/* gcc 4.1 and newer,
|
||||
* clang 3.3 (possibly older)
|
||||
*
|
||||
* __sync_swap isn't in gcc's documentation, but clang has it
|
||||
*
|
||||
* note __sync_synchronize()
|
||||
*/
|
||||
#elif defined(HAVE___SYNC)
|
||||
|
||||
#define _Atomic volatile
|
||||
|
||||
#define memory_order_relaxed 0
|
||||
#define memory_order_consume 0
|
||||
#define memory_order_acquire 0
|
||||
#define memory_order_release 0
|
||||
#define memory_order_acq_rel 0
|
||||
#define memory_order_seq_cst 0
|
||||
|
||||
#define atomic_load_explicit(ptr, mem) \
|
||||
({ __sync_synchronize(); \
|
||||
typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \
|
||||
__sync_synchronize(); rval; })
|
||||
#define atomic_store_explicit(ptr, val, mem) \
|
||||
({ __sync_synchronize(); \
|
||||
*(ptr) = (val); \
|
||||
__sync_synchronize(); (void)0; })
|
||||
#ifdef HAVE___SYNC_SWAP
|
||||
#define atomic_exchange_explicit(ptr, val, mem) \
|
||||
({ __sync_synchronize(); \
|
||||
typeof(*ptr) rval = __sync_swap((ptr, val), 0); \
|
||||
__sync_synchronize(); rval; })
|
||||
#else /* !HAVE___SYNC_SWAP */
|
||||
#define atomic_exchange_explicit(ptr, val, mem) \
|
||||
({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \
|
||||
__sync_synchronize(); \
|
||||
typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \
|
||||
do { \
|
||||
old1 = old2; \
|
||||
old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \
|
||||
} while (old1 != old2); \
|
||||
__sync_synchronize(); \
|
||||
old2; \
|
||||
})
|
||||
#endif /* !HAVE___SYNC_SWAP */
|
||||
#define atomic_fetch_add_explicit(ptr, val, mem) \
|
||||
({ __sync_synchronize(); \
|
||||
typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \
|
||||
__sync_synchronize(); rval; })
|
||||
#define atomic_fetch_sub_explicit(ptr, val, mem) \
|
||||
({ __sync_synchronize(); \
|
||||
typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \
|
||||
__sync_synchronize(); rval; })
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
|
||||
({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \
|
||||
typeof(desire) _desire = (desire); \
|
||||
__sync_synchronize(); \
|
||||
typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \
|
||||
__sync_synchronize(); \
|
||||
bool ret = (rval == *_expect); *_expect = rval; ret; })
|
||||
|
||||
#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */
|
||||
#error no atomic functions...
|
||||
#endif
|
||||
|
||||
#endif /* _FRRATOMIC_H */
|
@ -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
56
lib/hook.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
#include "hook.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry")
|
||||
|
||||
void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg,
|
||||
struct frrmod_runtime *module, const char *funcname)
|
||||
{
|
||||
struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he));
|
||||
he->hookfn = funcptr;
|
||||
he->hookarg = arg;
|
||||
he->has_arg = has_arg;
|
||||
he->module = module;
|
||||
he->fnname = funcname;
|
||||
|
||||
he->next = hook->entries;
|
||||
hook->entries = he;
|
||||
}
|
||||
|
||||
void _hook_unregister(struct hook *hook, void *funcptr,
|
||||
void *arg, bool has_arg)
|
||||
{
|
||||
struct hookent *he, **prev;
|
||||
|
||||
for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next)
|
||||
if (he->hookfn == funcptr && he->hookarg == arg
|
||||
&& he->has_arg == has_arg)
|
||||
{
|
||||
*prev = he->next;
|
||||
XFREE(MTYPE_HOOK_ENTRY, he);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
187
lib/hook.h
Normal file
187
lib/hook.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2016 David Lamparter, for NetDEF, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_HOOK_H
|
||||
#define _FRR_HOOK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* type-safe subscribable hook points
|
||||
*
|
||||
* where "type-safe" applies to the function pointers used for subscriptions
|
||||
*
|
||||
* overall usage:
|
||||
* - to create a hook:
|
||||
*
|
||||
* mydaemon.h:
|
||||
* #include "hook.h"
|
||||
* DECLARE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
*
|
||||
* mydaemon.c:
|
||||
* DEFINE_HOOK (some_update_event, (struct eventinfo *info), (info))
|
||||
* ...
|
||||
* hook_call (some_update_event, info)
|
||||
*
|
||||
* Note: the second and third macro args must be the hook function's
|
||||
* parameter list, with the same names for each parameter. The second
|
||||
* macro arg is with types (used for defining things), the third arg is
|
||||
* just the names (used for passing along parameters).
|
||||
*
|
||||
* Do not use parameter names starting with "hook", these can collide with
|
||||
* names used by the hook code itself.
|
||||
*
|
||||
* The return value is always "int" for now; hook_call will sum up the
|
||||
* return values from each registered user. Default is 0.
|
||||
*
|
||||
* There are no pre-defined semantics for the value, in most cases it is
|
||||
* ignored. For success/failure indication, 0 should be success, and
|
||||
* handlers should make sure to only return 0 or 1 (not -1 or other values).
|
||||
*
|
||||
*
|
||||
* - to use a hook / create a handler:
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (struct eventinfo *info) { ... }
|
||||
* hook_register (some_update_event, event_handler);
|
||||
*
|
||||
* or, if you need an argument to be passed along (addonptr will be added
|
||||
* as first argument when calling the handler):
|
||||
*
|
||||
* #include "mydaemon.h"
|
||||
* int event_handler (void *addonptr, struct eventinfo *info) { ... }
|
||||
* hook_register_arg (some_update_event, event_handler, addonptr);
|
||||
*
|
||||
* (addonptr isn't typesafe, but that should be manageable.)
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - hook_unregister_all_module()
|
||||
* - introspection / CLI / debug
|
||||
* - testcases ;)
|
||||
*
|
||||
* For loadable modules, the idea is that hooks could be automatically
|
||||
* unregistered when a module is unloaded.
|
||||
*
|
||||
* It's also possible to add a constructor (MTYPE style) to DEFINE_HOOK,
|
||||
* which would make it possible for the CLI to show all hooks and all
|
||||
* registered handlers.
|
||||
*/
|
||||
|
||||
struct hookent {
|
||||
struct hookent *next;
|
||||
void *hookfn; /* actually a function pointer */
|
||||
void *hookarg;
|
||||
bool has_arg;
|
||||
struct frrmod_runtime *module;
|
||||
const char *fnname;
|
||||
};
|
||||
|
||||
struct hook {
|
||||
const char *name;
|
||||
struct hookent *entries;
|
||||
};
|
||||
|
||||
/* subscribe/add callback function to a hook
|
||||
*
|
||||
* always use hook_register(), which uses the static inline helper from
|
||||
* DECLARE_HOOK in order to get type safety
|
||||
*/
|
||||
extern void _hook_register(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg, struct frrmod_runtime *module,
|
||||
const char *funcname);
|
||||
#define hook_register(hookname, func) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), \
|
||||
NULL, false, THIS_MODULE, #func)
|
||||
#define hook_register_arg(hookname, func, arg) \
|
||||
_hook_register(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), \
|
||||
arg, true, THIS_MODULE, #func)
|
||||
|
||||
extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg,
|
||||
bool has_arg);
|
||||
#define hook_unregister(hookname, func) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_ ## hookname (func), NULL, false)
|
||||
#define hook_unregister_arg(hookname, func, arg) \
|
||||
_hook_unregister(&_hook_ ## hookname, \
|
||||
_hook_typecheck_arg_ ## hookname (func), arg, true)
|
||||
|
||||
/* invoke hooks
|
||||
* this is private (static) to the file that has the DEFINE_HOOK statement
|
||||
*/
|
||||
#define hook_call(hookname, ...) \
|
||||
hook_call_ ## hookname (__VA_ARGS__)
|
||||
|
||||
/* helpers to add the void * arg */
|
||||
#define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__)
|
||||
#define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__)
|
||||
|
||||
/* use in header file - declares the hook and its arguments
|
||||
* usage: DECLARE_HOOK(my_hook, (int arg1, struct foo *arg2), (arg1, arg2))
|
||||
* as above, "passlist" must use the same order and same names as "arglist"
|
||||
*
|
||||
* theoretically passlist is not neccessary, but let's keep things simple and
|
||||
* use exact same args on DECLARE and DEFINE.
|
||||
*/
|
||||
#define DECLARE_HOOK(hookname, arglist, passlist) \
|
||||
extern struct hook _hook_ ## hookname; \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_ ## hookname ( \
|
||||
int (*funcptr) arglist) { \
|
||||
return (void *)funcptr; } \
|
||||
__attribute__((unused)) \
|
||||
static void *_hook_typecheck_arg_ ## hookname ( \
|
||||
int (*funcptr) HOOK_ADDDEF arglist) { \
|
||||
return (void *)funcptr; }
|
||||
|
||||
/* use in source file - contains hook-related definitions.
|
||||
*/
|
||||
#define DEFINE_HOOK(hookname, arglist, passlist) \
|
||||
struct hook _hook_ ## hookname = { \
|
||||
.name = #hookname, \
|
||||
.entries = NULL, \
|
||||
}; \
|
||||
static int hook_call_ ## hookname arglist { \
|
||||
int hooksum = 0; \
|
||||
struct hookent *he = _hook_ ## hookname .entries; \
|
||||
void *hookarg; \
|
||||
union { \
|
||||
void *voidptr; \
|
||||
int (*fptr) arglist; \
|
||||
int (*farg) HOOK_ADDDEF arglist; \
|
||||
} hookp; \
|
||||
for (; he; he = he->next) { \
|
||||
hookarg = he->hookarg; \
|
||||
hookp.voidptr = he->hookfn; \
|
||||
if (!he->has_arg) \
|
||||
hooksum += hookp.fptr passlist; \
|
||||
else \
|
||||
hooksum += hookp.farg HOOK_ADDARG passlist; \
|
||||
} \
|
||||
return hooksum; \
|
||||
}
|
||||
|
||||
#endif /* _FRR_HOOK_H */
|
122
lib/if.c
122
lib/if.c
@ -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 */
|
||||
|
||||
|
53
lib/if.h
53
lib/if.h
@ -229,6 +229,9 @@ struct interface
|
||||
/* Interface metric */
|
||||
uint32_t metric;
|
||||
|
||||
/* Interface Speed in Mb/s */
|
||||
uint32_t speed;
|
||||
|
||||
/* Interface MTU. */
|
||||
unsigned int mtu; /* IPv4 MTU */
|
||||
unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */
|
||||
@ -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);
|
||||
|
@ -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"
|
||||
|
38
lib/libfrr.c
38
lib/libfrr.c
@ -28,6 +28,9 @@
|
||||
#include "memory_vty.h"
|
||||
#include "zclient.h"
|
||||
#include "log_int.h"
|
||||
#include "module.h"
|
||||
|
||||
DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
|
||||
const char frr_sysconfdir[] = SYSCONFDIR;
|
||||
const char frr_vtydir[] = DAEMON_VTY_DIR;
|
||||
@ -64,14 +67,16 @@ static const struct option lo_always[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "daemon", no_argument, NULL, 'd' },
|
||||
{ "module", no_argument, NULL, 'M' },
|
||||
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
|
||||
{ NULL }
|
||||
};
|
||||
static const struct optspec os_always = {
|
||||
"hvdi:",
|
||||
"hvdM:",
|
||||
" -h, --help Display this help and exit\n"
|
||||
" -v, --version Print program version\n"
|
||||
" -d, --daemon Runs in daemon mode\n"
|
||||
" -M, --module Load specified module\n"
|
||||
" --vty_socket Override vty socket path\n",
|
||||
lo_always
|
||||
};
|
||||
@ -184,12 +189,18 @@ void frr_help_exit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
struct option_chain {
|
||||
struct option_chain *next;
|
||||
const char *arg;
|
||||
};
|
||||
static struct option_chain *modules = NULL, **modnext = &modules;
|
||||
static int errors = 0;
|
||||
|
||||
static int frr_opt(int opt)
|
||||
{
|
||||
static int vty_port_set = 0;
|
||||
static int vty_addr_set = 0;
|
||||
struct option_chain *oc;
|
||||
char *err;
|
||||
|
||||
switch (opt) {
|
||||
@ -203,6 +214,13 @@ static int frr_opt(int opt)
|
||||
case 'd':
|
||||
di->daemon_mode = 1;
|
||||
break;
|
||||
case 'M':
|
||||
oc = XMALLOC(MTYPE_TMP, sizeof(*oc));
|
||||
oc->arg = optarg;
|
||||
oc->next = NULL;
|
||||
*modnext = oc;
|
||||
modnext = &oc->next;
|
||||
break;
|
||||
case 'i':
|
||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||
return 1;
|
||||
@ -295,9 +313,12 @@ int frr_getopt(int argc, char * const argv[], int *longindex)
|
||||
return opt;
|
||||
}
|
||||
|
||||
static struct thread_master *master;
|
||||
struct thread_master *frr_init(void)
|
||||
{
|
||||
struct thread_master *master;
|
||||
struct option_chain *oc;
|
||||
struct frrmod_runtime *module;
|
||||
char moderr[256];
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
@ -307,6 +328,17 @@ struct thread_master *frr_init(void)
|
||||
zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
|
||||
#endif
|
||||
|
||||
frrmod_init(di->module);
|
||||
while (modules) {
|
||||
modules = (oc = modules)->next;
|
||||
module = frrmod_load(oc->arg, moderr, sizeof(moderr));
|
||||
if (!module) {
|
||||
fprintf(stderr, "%s\n", moderr);
|
||||
exit(1);
|
||||
}
|
||||
XFREE(MTYPE_TMP, oc);
|
||||
}
|
||||
|
||||
zprivs_init(di->privs);
|
||||
|
||||
master = thread_master_create();
|
||||
@ -324,6 +356,8 @@ struct thread_master *frr_init(void)
|
||||
|
||||
void frr_config_fork(void)
|
||||
{
|
||||
hook_call(frr_late_init, master);
|
||||
|
||||
if (di->instance) {
|
||||
snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf",
|
||||
frr_sysconfdir, di->name, di->instance);
|
||||
|
15
lib/libfrr.h
15
lib/libfrr.h
@ -26,6 +26,8 @@
|
||||
#include "thread.h"
|
||||
#include "log.h"
|
||||
#include "getopt.h"
|
||||
#include "module.h"
|
||||
#include "hook.h"
|
||||
|
||||
#define FRR_NO_PRIVSEP (1 << 0)
|
||||
#define FRR_NO_TCPVTY (1 << 1)
|
||||
@ -40,6 +42,7 @@ struct frr_daemon_info {
|
||||
const char *name;
|
||||
const char *logname;
|
||||
unsigned short instance;
|
||||
struct frrmod_runtime *module;
|
||||
|
||||
char *vty_addr;
|
||||
int vty_port;
|
||||
@ -67,15 +70,22 @@ struct frr_daemon_info {
|
||||
* i.e. "ZEBRA" or "BGP"
|
||||
*
|
||||
* note that this macro is also a latch-on point for other changes (e.g.
|
||||
* upcoming plugin support) that need to place some per-daemon things. Each
|
||||
* upcoming module support) that need to place some per-daemon things. Each
|
||||
* daemon should have one of these.
|
||||
*/
|
||||
#define FRR_DAEMON_INFO(execname, constname, ...) \
|
||||
static struct frr_daemon_info execname ##_di = { \
|
||||
.name = # execname, \
|
||||
.logname = # constname, \
|
||||
.module = THIS_MODULE, \
|
||||
__VA_ARGS__ \
|
||||
};
|
||||
}; \
|
||||
FRR_COREMOD_SETUP( \
|
||||
.name = # execname, \
|
||||
.description = # execname " daemon", \
|
||||
.version = FRR_VERSION, \
|
||||
) \
|
||||
/* end */
|
||||
|
||||
extern void frr_preinit(struct frr_daemon_info *daemon,
|
||||
int argc, char **argv);
|
||||
@ -86,6 +96,7 @@ extern void frr_help_exit(int status);
|
||||
|
||||
extern struct thread_master *frr_init(void);
|
||||
|
||||
DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm))
|
||||
extern void frr_config_fork(void);
|
||||
|
||||
extern void frr_vty_serv(void);
|
||||
|
18
lib/log.c
18
lib/log.c
@ -734,6 +734,17 @@ openzlog (const char *progname, const char *protoname, u_short instance,
|
||||
|
||||
openlog (progname, syslog_flags, zl->facility);
|
||||
zlog_default = zl;
|
||||
|
||||
#ifdef HAVE_GLIBC_BACKTRACE
|
||||
/* work around backtrace() using lazily resolved dynamically linked
|
||||
* symbols, which will otherwise cause funny breakage in the SEGV handler.
|
||||
* (particularly, the dynamic linker can call malloc(), which uses locks
|
||||
* in programs linked with -pthread, thus can deadlock.) */
|
||||
void *bt[4];
|
||||
backtrace (bt, array_size(bt));
|
||||
free (backtrace_symbols (bt, 0));
|
||||
backtrace_symbols_fd (bt, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -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;
|
||||
|
146
lib/memory.c
146
lib/memory.c
@ -27,119 +27,107 @@ struct memgroup **mg_insert = &mg_first;
|
||||
DEFINE_MGROUP(LIB, "libfrr")
|
||||
DEFINE_MTYPE(LIB, TMP, "Temporary memory")
|
||||
|
||||
static inline void
|
||||
mt_count_alloc (struct memtype *mt, size_t size)
|
||||
static inline void mt_count_alloc(struct memtype *mt, size_t size)
|
||||
{
|
||||
mt->n_alloc++;
|
||||
size_t oldsize;
|
||||
|
||||
if (mt->size == 0)
|
||||
mt->size = size;
|
||||
else if (mt->size != size)
|
||||
mt->size = SIZE_VAR;
|
||||
atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed);
|
||||
|
||||
oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed);
|
||||
if (oldsize == 0)
|
||||
oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed);
|
||||
if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR)
|
||||
atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mt_count_free (struct memtype *mt)
|
||||
static inline void mt_count_free(struct memtype *mt)
|
||||
{
|
||||
assert(mt->n_alloc);
|
||||
mt->n_alloc--;
|
||||
assert(mt->n_alloc);
|
||||
atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
mt_checkalloc (struct memtype *mt, void *ptr, size_t size)
|
||||
static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
|
||||
{
|
||||
if (__builtin_expect(ptr == NULL, 0))
|
||||
{
|
||||
memory_oom (size, mt->name);
|
||||
return NULL;
|
||||
}
|
||||
mt_count_alloc (mt, size);
|
||||
return ptr;
|
||||
if (__builtin_expect(ptr == NULL, 0)) {
|
||||
memory_oom(size, mt->name);
|
||||
return NULL;
|
||||
}
|
||||
mt_count_alloc(mt, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
qmalloc (struct memtype *mt, size_t size)
|
||||
void *qmalloc(struct memtype *mt, size_t size)
|
||||
{
|
||||
return mt_checkalloc (mt, malloc (size), size);
|
||||
return mt_checkalloc(mt, malloc(size), size);
|
||||
}
|
||||
|
||||
void *
|
||||
qcalloc (struct memtype *mt, size_t size)
|
||||
void *qcalloc(struct memtype *mt, size_t size)
|
||||
{
|
||||
return mt_checkalloc (mt, calloc (size, 1), size);
|
||||
return mt_checkalloc(mt, calloc(size, 1), size);
|
||||
}
|
||||
|
||||
void *
|
||||
qrealloc (struct memtype *mt, void *ptr, size_t size)
|
||||
void *qrealloc(struct memtype *mt, void *ptr, size_t size)
|
||||
{
|
||||
if (ptr)
|
||||
mt_count_free (mt);
|
||||
return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size);
|
||||
if (ptr)
|
||||
mt_count_free(mt);
|
||||
return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size);
|
||||
}
|
||||
|
||||
void *
|
||||
qstrdup (struct memtype *mt, const char *str)
|
||||
void *qstrdup(struct memtype *mt, const char *str)
|
||||
{
|
||||
return mt_checkalloc (mt, strdup (str), strlen (str) + 1);
|
||||
return mt_checkalloc(mt, strdup(str), strlen(str) + 1);
|
||||
}
|
||||
|
||||
void
|
||||
qfree (struct memtype *mt, void *ptr)
|
||||
void qfree(struct memtype *mt, void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
mt_count_free (mt);
|
||||
free (ptr);
|
||||
if (ptr)
|
||||
mt_count_free(mt);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
qmem_walk (qmem_walk_fn *func, void *arg)
|
||||
int qmem_walk(qmem_walk_fn *func, void *arg)
|
||||
{
|
||||
struct memgroup *mg;
|
||||
struct memtype *mt;
|
||||
int rv;
|
||||
struct memgroup *mg;
|
||||
struct memtype *mt;
|
||||
int rv;
|
||||
|
||||
for (mg = mg_first; mg; mg = mg->next)
|
||||
{
|
||||
if ((rv = func (arg, mg, NULL)))
|
||||
return rv;
|
||||
for (mt = mg->types; mt; mt = mt->next)
|
||||
if ((rv = func (arg, mg, mt)))
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
for (mg = mg_first; mg; mg = mg->next) {
|
||||
if ((rv = func(arg, mg, NULL)))
|
||||
return rv;
|
||||
for (mt = mg->types; mt; mt = mt->next)
|
||||
if ((rv = func(arg, mg, mt)))
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct exit_dump_args
|
||||
{
|
||||
const char *prefix;
|
||||
int error;
|
||||
struct exit_dump_args {
|
||||
const char *prefix;
|
||||
int error;
|
||||
};
|
||||
|
||||
static int
|
||||
qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt)
|
||||
static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
|
||||
{
|
||||
struct exit_dump_args *eda = arg;
|
||||
struct exit_dump_args *eda = arg;
|
||||
|
||||
if (!mt)
|
||||
{
|
||||
fprintf (stderr, "%s: showing active allocations in memory group %s\n",
|
||||
eda->prefix, mg->name);
|
||||
}
|
||||
else if (mt->n_alloc)
|
||||
{
|
||||
char size[32];
|
||||
eda->error++;
|
||||
snprintf (size, sizeof (size), "%10zu", mt->size);
|
||||
fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n",
|
||||
eda->prefix, mt->name, mt->n_alloc,
|
||||
mt->size == SIZE_VAR ? "(variably sized)" : size);
|
||||
}
|
||||
return 0;
|
||||
if (!mt) {
|
||||
fprintf(stderr, "%s: showing active allocations in "
|
||||
"memory group %s\n",
|
||||
eda->prefix, mg->name);
|
||||
|
||||
} else if (mt->n_alloc) {
|
||||
char size[32];
|
||||
eda->error++;
|
||||
snprintf(size, sizeof(size), "%10zu", mt->size);
|
||||
fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n",
|
||||
eda->prefix, mt->name, mt->n_alloc,
|
||||
mt->size == SIZE_VAR ? "(variably sized)" : size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
log_memstats_stderr (const char *prefix)
|
||||
void log_memstats_stderr(const char *prefix)
|
||||
{
|
||||
struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
|
||||
qmem_walk (qmem_exit_walker, &eda);
|
||||
struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
|
||||
qmem_walk(qmem_exit_walker, &eda);
|
||||
}
|
||||
|
43
lib/memory.h
43
lib/memory.h
@ -18,23 +18,22 @@
|
||||
#define _QUAGGA_MEMORY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <frratomic.h>
|
||||
|
||||
#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
|
||||
|
||||
#define SIZE_VAR ~0UL
|
||||
struct memtype
|
||||
{
|
||||
struct memtype *next, **ref;
|
||||
const char *name;
|
||||
size_t n_alloc;
|
||||
size_t size;
|
||||
struct memtype {
|
||||
struct memtype *next, **ref;
|
||||
const char *name;
|
||||
_Atomic size_t n_alloc;
|
||||
_Atomic size_t size;
|
||||
};
|
||||
|
||||
struct memgroup
|
||||
{
|
||||
struct memgroup *next, **ref;
|
||||
struct memtype *types, **insert;
|
||||
const char *name;
|
||||
struct memgroup {
|
||||
struct memgroup *next, **ref;
|
||||
struct memtype *types, **insert;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
@ -82,14 +81,14 @@ struct memgroup
|
||||
* DEFINE_MGROUP(MYDAEMON, "my daemon memory")
|
||||
* DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
|
||||
* "this mtype is used in multiple files in mydaemon")
|
||||
* foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo))
|
||||
* foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
|
||||
*
|
||||
* mydaemon_io.c
|
||||
* bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar))
|
||||
* bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
|
||||
*
|
||||
* DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
|
||||
* "this mtype is used only in this file")
|
||||
* baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz))
|
||||
* baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
|
||||
*
|
||||
* Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
|
||||
* by not having these as part of the macro arguments)
|
||||
@ -155,15 +154,15 @@ DECLARE_MGROUP(LIB)
|
||||
DECLARE_MTYPE(TMP)
|
||||
|
||||
|
||||
extern void *qmalloc (struct memtype *mt, size_t size)
|
||||
extern void *qmalloc(struct memtype *mt, size_t size)
|
||||
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
|
||||
extern void *qcalloc (struct memtype *mt, size_t size)
|
||||
extern void *qcalloc(struct memtype *mt, size_t size)
|
||||
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
|
||||
extern void *qrealloc (struct memtype *mt, void *ptr, size_t size)
|
||||
extern void *qrealloc(struct memtype *mt, void *ptr, size_t size)
|
||||
__attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL));
|
||||
extern void *qstrdup (struct memtype *mt, const char *str)
|
||||
__attribute__ ((malloc, nonnull (1) _RET_NONNULL));
|
||||
extern void qfree (struct memtype *mt, void *ptr)
|
||||
extern void qfree(struct memtype *mt, void *ptr)
|
||||
__attribute__ ((nonnull (1)));
|
||||
|
||||
#define XMALLOC(mtype, size) qmalloc(mtype, size)
|
||||
@ -183,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
|
||||
*
|
||||
* return value: 0: continue, !0: abort walk. qmem_walk will return the
|
||||
* last value from qmem_walk_fn. */
|
||||
typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt);
|
||||
extern int qmem_walk (qmem_walk_fn *func, void *arg);
|
||||
extern void log_memstats_stderr (const char *);
|
||||
typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
|
||||
extern int qmem_walk(qmem_walk_fn *func, void *arg);
|
||||
extern void log_memstats_stderr(const char *);
|
||||
|
||||
extern void memory_oom (size_t size, const char *name);
|
||||
extern void memory_oom(size_t size, const char *name);
|
||||
|
||||
#endif /* _QUAGGA_MEMORY_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user