Some misc changes to resolve some c++ compilation errors.
The goal is only to permit an external module - a plugin,
for example - to see frr headers, not to support or encourage
contributions in c++. The changes include: avoiding use
of keywords like 'new', 'delete'; cleaning up implicit
type-casting from 'void *' in several places.
Signed-off-by: Mark Stapp <mjs@voltanet.io>
other daemons need to sync with zebra to get to know which vrf backend
is available. in that time, there may be interface configuration
available. in that specific case, the vrf backend returned is not known.
A specific return value is sent back. This will be useful to know which
specific algorithm to apply.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
If tcp_l3mdev_accept = 0, then creating a socket for a vrf
for communication is allowed. On the other hand if it is =1
then the vrf_socket() code assumes that we have created
a listen socket in the default vrf. This is a bad assumption
in that it is perfectly valid to create a bgp instance like this:
router bgp 99 vrf BLUE
<configuration>
!
But not to create a default bgp instance. As such when BGP
would call the vrf_socket to create the listener for that vrf
the code was dissallowing it.
This code is incorrect behavior. If we are passing in a interface
to bind the socket to, it is not the correct behavior to just not
bind, especially if the interface passed in is not a vrf name.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Now that all daemons receive the VRF backend from zebra, we can get
rid of vrf_is_mapped_on_netns() in favor of using the more convenient
vrf_is_backend_netns() function, which doesn't require any argument.
This commit also fixes the following problem:
debian(config)# ip route 50.0.0.0/8 blackhole vrf FAKE table 2
% table param only available when running on netns-based vrfs
Even when zebra was started with the --vrfwnetns, the error
above would be displayed since the VRF FAKE didn't exist, which
would make vrf_is_mapped_on_netns() return 0 incorrectly. Using
vrf_is_backend_netns() this problem doesn't happen anymore.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Parameters should be const whenever possible to improve code
readability and remove the need to cast away the constness of
const arguments.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
in order to enforce the vrf_id to return, from a vrf name, a check is
done on the vrf_name_to_id callback.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
the netns discovery process executed when vrf backend is netns, allows
the zebra daemon to dynamically change the default vrf name value. This
option is disabled, when the zebra is forced to a default vrf value with
option -o.
PR=61513
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
if zebra is not started, then vrf identifiers are not available. This
prevents import/exportation to be available. This commit permits having
import/export available, even when zebra is not started.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The ->hash_cmp and linked list ->cmp functions were sometimes
being used interchangeably and this really is not a good
thing. So let's modify the hash_cmp function pointer to return
a boolean and convert everything to use the new syntax.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
To correct potential crash with netns implementation of vrf (see next
commit) it is necessary to allow any daemons to know the vrf
implementation whatever the vrf.
With current implementation the daemons do not know the vrf
implementation for the default vrf. For this vrf the returned vrf
implementation is always vrf-lite.
To solve this issue a netns name is set to the default vrf to just test
is presence to know the used implementation.
For zebra a netns name (if needed) is set in the vrf_init function just
before enabling the vrf. So this information is propagated to the other
daemons thanks the zapi message called when the vrf is enable at zebra
layer and override the default configuration (vrf-lite) of the daemon.
Signed-off-by: Thibaut Collet <thibaut.collet@6wind.com>
If default VRF is used, with standard naming convention,
memory allocation can be avoided.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Prevent from creating vrf, if the default vrf name is the same as the
vrf to be created.
Also, prevent at startup from creating default vrf with a name already
used in vrf list.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
For the daemons that do not use vrf_init(), the call to the define
will return a default vrf if no other values has been overriden.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The Vrf aliases can be known with a specific hook. That hook will then,
from zebra propagate the information to the relevant zapi clients.
The registration hook function is the same for all daemons.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The get API is used each time the VRF_DEFAULT_NAME macro is used.
The set API is not yet used.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Memory sizes of the vrf bit-map was insane for a system
with a moderate number of data on it:
Zebra:
VRF bit-map : 601 65536 39391944
Having a full 32bit integer bit space is problematically large,
switch over to a hash to store bit data. We do not need to waste
so much space.
VRF bit-map : 13 8 312
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Add a new error code LIB_ERR_SYSTEM_CALL to the ferr subsystem.
Additionally convert LIB_ERR_VRF_SOCKET to a more generic
LIB_ERR_SOCKET.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Add code to auto-create the ferr infrastructure as well as add
some initial error handling for vrf.c
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
* Only zebra and pimd call vrf_cmd_init(), so these are the only daemons
that should receive VRF commands from vtysh;
* "netns NAME" and "no netns NAME" are available only in zebra, write
custom DEFSHs in vtysh to make it aware of that;
* Remove the "no vrf NAME" definition from vtysh.c and expose the
original command to vtysh by converting the DEFUN_NOSH to a simple
DEFUN. This command doesn't change the vty node so there's no need to
special case it.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Properly notice when we get if up/down and vrf enable/disable
events and attempt to properly install nexthops as they
come in.
Ticket: CM20489
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This list "table" is created in the case the netns backend for VRF is
used. This contains the mapping between the NSID value read from the
'ip netns list' and the ns id external used to create the VRF
value from vrf context. This mapping is
necessary in order to reserve default 0 value for vrf_default.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Because at startup, remote daemons attempt to create default VRF,
the VRF_ID may be set to unknown. In that case, an event will be
triggered later by zebra to inform remote daemon that the vrf id of that
VRF has changed to valid value. In that case, two instances of default
VRF must not be created. By looking first at vrf name, this avoids
having two instances.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Static route commands are now installed inside the VRF nodes. This has
quietly broken top-level static routes in certain scenarios due to
walkup logic resolving a static route configuration command inside
VRF_NODE first if the command is issued while in a CLI node lower than
VRF_NODE. To fix this VRF_NODE needs a special exit command, as has been
done for many other nodes with the same issue, to explicitly change the
vrf context to the default VRF so that when walkup resolves against the
VRF node it will configure against the default VRF as desired.
Of course this is a hack on top of a hack and the CLI walkup
implementation needs to be rewritten.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
The following types are nonstandard:
- u_char
- u_short
- u_int
- u_long
- u_int8_t
- u_int16_t
- u_int32_t
Replace them with the C99 standard types:
- uint8_t
- unsigned short
- unsigned int
- unsigned long
- uint8_t
- uint16_t
- uint32_t
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Vty commands that link netns context to a vrf is requiring some
privileges. The change consists in retrieving the privileges at the
vrf_cmd_init() called by the relevant daemon. Then use it.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Because socket creation is tightly linked with socket binding for vrf
lite, the proposal is made to extend socket creation APIs and to create
a new API called vrf_bind that applies to vrf lite. The passed interface
name is the interface that will be bound to the socket passed.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
That API can be used to wrap the ioctl call with various vrf instances.
This permits transparently doing the ioctl() call without taking into
consideration the vrf backend kind.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This split is introducing logicalrouter.[ch] as the file that contains
the vty commands to configure logical router feature. The split has as
consequence that the backend of logical router is linux_netns.c formerly
called ns.c. The same relationship exists between VRF and its backend
which may be linux_netns.c file.
The split is adapting ns and vrf fiels so as to :
- clarify header
- ensure that the daemon persepctive, the feature VRF or logical router
is called instead of calling directly ns.
- this implies that VRF will call NS apis, as logical router does.
Also, like it is done for default NS and default VRF, the associated VRF
is enabled first, before NETNS is enabled, so that zvrf->zns pointer is
valid when NETNS discovery applies.
Also, other_netns.c file is a stub handler that will be used for non
linux systems. As NETNS feature is only used by Linux, some BSD systems
may want to use the same backend API to benefit from NETNS. This is what
that file has been done.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The vrf_sockunion_socket() wraps sockunion_socket() with vrf_id as
additional parameter. The creation of socket forces the user to
transparently move to new NETNS for doing the operation.
The vrf_getaddr_info() wraps getaddr_info() with vrf_id as additional
parameter. That API relies on the underlying system. Then there may be
need to switch to an other netns in that case too.
Also, the vrf_socket() implementation is simplified.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Two apis are provided so that the switch from one netns to an other one
is taken care.
Also an other API to know if the VRF has a NETNS backend or a VRF Lite
backend.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The addition of the name of the netns in the vrf message introduces also
a limitation when the size of the netns is bigger than 15 bytes. Then
the netns are ignored by the library.
In addition to this, some sanity checks have been introduced. some
functions to create the netns from a call not coming from the vty is
being added with traces.
Also, the ns vty function is reentrant, if the context is already
created.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
In addition to have the possibility to create from vty vrf based on a
netns backend, the API will be made accessible from external, especially
for zebra that will handle the netns discovery part. This commit is
externalising following functions:
- netns_pathname
- ns_handler_create
- vrf_handler_create
Also, the VRF initialisation case when under NETNS backend is changed,
since the NS identifier may not be known at the configuration time,but
may be known later, under discovery process.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Upon following calls: interface poll, address poll, route poll, and
ICMPv6 handling, each new Namespace is being parsed. For that, the
socket operations need to switch from one NS to one other, to get the
necessary information.
As of now, there is a crash when dumping interfaces, through show
running-config.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
a vty command is added:
in addition to this command ( kept for future usage):
- [no] logical-router-id <ID> netns <NETNSNAME>
a new command is being placed under vrf subnode
- vrf <NAME>
[no] netns <NETNSNAME>
exit
This command permits to map a VRF with a Netnamespace.
The commit only handles the relationship between vrf and ns structures.
It adds 2 attributes to vrf structure:
- one defines the kind of vrf ( mapped under netns or vrf from kernel)
- the other is the opaque pointer to ns
The show running-config is handled by zebra daemon.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
The netns backend is chosen by VRF if a runtime flag named vrfwnetns is
selected when running zebra.
In the case the NETNS backend is chosen, in some case the VRFID value is
being assigned the value of the NSID. Within the perimeter of that work,
this is why the vrf_lookup_by_table function is extended with a new
parameter.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Refine the notion of what FRR considers as "configured" VRF. It is no longer
based on user just typing "vrf FOO" but when something is actually configured
against that VRF. Right now, in zebra, the only configuration against a VRF
are static IP routes and EVPN L3 VNI. Whenever a configuration is removed,
check and clear the "configured" flag if there is no other configuration for
this VRF. When user attempts to configure a static route and the VRF doesn't
exist, a VRF is created; the VRF is only active when also defined in the
kernel.
Updates: 8b73ea7bd479030418ca06eef59d0648d913b620
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-10139, CM-18553
Reviewed By: CCR-7019
Testing Done:
1. Manual testing for L3 VNI and static routes - FRR restart, networking
restart etc.
2. 'vrf' smoke
<DETAILED DESCRIPTION (REPLACE)>
When shutting down, ensure that all VRFs including "configured" ones are
cleaned up properly.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-19069
Reviewed By: CCR-7011
Testing Done: Manual verification of failed scenario
A VRF is active only when the corresponding VRF device is present in the
kernel. However, when the kernel VRF device is removed, the VRF container in
FRR should go away only if there is no user configuration for it. Otherwise,
when the VRF device is created again so that the VRF becomes active, FRR
cannot take the correct actions. Example configuration for the VRF includes
static routes and EVPN L3 VNI.
Note that a VRF is currently considered to be "configured" as soon as the
operator has issued the "vrf <name>" command in FRR. Such a configured VRF
is not deleted upon VRF device removal, it is only made inactive. A VRF that
is "configured" can be deleted only upon operator action and only if the VRF
has been deactivated i.e., the VRF device removed from the kernel. This is
an existing restriction.
To implement this change, the VRF disable and delete actions have been modified.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Mitesh Kanjariya <mkanjariya@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-18553, CM-18918, CM-10139
Reviewed By: CCR-7022
Testing Done:
1. vrf and pim-vrf automation tests
2. Multiple VRF delete and readd (ifdown, ifup-with-depends)
3. FRR stop, start, restart
4. Networking restart
5. Configuration delete and readd
Some of the above tests run in different sequences (manually).
The number of vrf bitmap groups is increased so as to avoid consuming
too much memory. This fix is related to a fork memory that occured when
running pimd as daemon.
A check on memory consumed shows that the memory consumed goes from
33480ko to 46888ko with that change. This is less compared to if the
value of the bitmap groups is increased to 16 ( 852776ko).
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This is a preparatory work for configuring vrf/frr over netns
vrf structure is being changed to 32 bit, and the VRF will have the
possibility to have a backend made up of NETNS.
Let's put some history.
Initially the 32 bit was because one wanted to map on vrf_id both the
VRFLITE and the NSID.
Initially, one would have liked to make zebra configure at the same time
both vrf lite and vrf from netns in a flat way. From the show
running perspective, one would have had both kind of vrfs, thatone
would configure on the same way.
however, it leads to inconsistencies in concepts, because it mixes vrf
vrf with vrf, and vrf is not always mapped with netns.
For instance, logical-router could also be used with netns. In that
case, it would not be possible to map vrf with netns.
There was an other reason why 32 bit is proposed. this is because
some systems handle NSID to 32 bits. As vrf lite exists only on
Linux, there are other systems that would like to use an other vrf
backend than vrf lite. The netns backend for vrf will be used for that
too. for instance, for windows or freebsd, some similar
netns concept exists; so it will be easier to reuse netns
backend for vrf, than reusing vrflite backend for vrf.
This commit is here to extend vrf_id to 32 bits. Following commits in a
second step will help in enable a VRF backend.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Performance tests showed that, when running on a system with a large
number of interfaces, some daemons would spend a considerable amount
of time in the if_lookup_by_index() function. Introduce a new rb-tree
to solve this problem.
With this change, we need to use the if_set_index() function whenever
we want to change the ifindex of an interface. This is necessary to
ensure that the 'ifaces_by_index' rb-tree is updated accordingly. The
return value of all insert/remove operations in the interface rb-trees
is checked to ensure that an error is logged if a corruption is
detected.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This is an important optimization for users running FRR on systems with
a large number of interfaces (e.g. thousands of tunnels). Red-black
trees scale much better than sorted linked-lists and also store the
elements in an ordered way (contrary to hash tables).
This is a big patch but the interesting bits are all in lib/if.[ch].
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This fixes the broken indentation of several foreach loops throughout
the code.
From clang's documentation[1]:
ForEachMacros: A vector of macros that should be interpreted as foreach
loops instead of as function calls.
[1] http://clang.llvm.org/docs/ClangFormatStyleOptions.html
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
This allows frr-reload.py (or anything else that scripts via vtysh)
to know if the vtysh command worked or hit an error.
Switch the RB tree implementation completely to the new dlg@'s version
that uses pre-declared functions instead of macros for tree functions.
Original e-mail/diff:
https://marc.info/?l=openbsd-tech&m=147087487111068&w=2
Pros:
* Reduces the amount of code that the usage of those macros generate
* Allows the compiler to do a better compile-time check job
* Might have better i-cache utilization since the tree code is shared
Con:
* dlg@ benchmarks shows it has 'very slightly slower' insertions
* imported RB_* code must adapt the following calls:
RB_INIT(), RB_GENERATE(), RB_ROOT(), RB_EMPTY(), make compare
functions use 'const' (if not already) and maybe others.
We only needed to add/change the vrf callbacks when we initialize
the vrf subsystem. As such it is not necessary to handle the callbacks
in any other way than through the init function.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
vrf_iflist_create -> By the time this is called in enable, the vrf's iflist
is already created. Additionally this code should be a properly of the vrf
to init/destroy not someone else.
vrf_iflist_terminate -> This function should be a property of vrf deletion
and does not need to be exposed.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Segregate the vrf enable/disable functionality from other vrf
code. This is to ensure that people are not actually using
the functions when they should not be. Also document the
why of it properly in the new vrf_int.h header.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
The FSF's address changed, and we had a mixture of comment styles for
the GPL file header. (The style with * at the beginning won out with
580 to 141 in existing files.)
Note: I've intentionally left intact other "variations" of the copyright
header, e.g. whether it says "Zebra", "Quagga", "FRR", or nothing.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
These have copies in vtysh that do the node-switch locally and are
listed in extract.pl's ignore list. The ignore list however is
redundant since DEFUN_NOSH does the same thing...
ldpd is a bit hacky, but Renato is reworking this anyway.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Conflicts (CLI vs. atol()):
- bgpd/bgp_vty.c
- ospfd/ospf_vty.c
- zebra/zebra_vty.c
NB: pull req #65 (LabNConsulting/working/2.0/afi-safi-vty/c) was
excluded from this merge.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
VRF_UNKNOWN = MAX_INT16_T
The vrf macros to determine where in the bitmap something belongs
assume that the valid values of a vrf are 0 - (MAX_INT16 - 1)
so when they attempt to determine where to look in the bitmap
for VRF_DEFAULT, we can get invalid reads of memory.
This happens because bgp can create vrf's with VRF_UNKNOWN
when we get configuration for a vrf before we've been actually
created in zebra.
Ticket: CM-14090
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
There's no need to duplicate the 'vrf_id' and 'name' fields from the 'vrf'
structure into the 'zebra_vrf' structure. Instead of that, add a back
pointer in 'zebra_vrf' that should point to the associated 'vrf' structure.
Additionally, modify the vrf callbacks to pass the whole vrf structure
as a parameter. This allow us to make further simplifications in the code.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Also, for some reason we had two functions to search a VRF by its name:
zebra_vrf_lookup_by_name() and zebra_vrf_list_lookup_by_name(). The first
one would loop through vrf_table and the other one through vrf_list. This
is not necessary anymore, so remove zebra_vrf_lookup_by_name() and rename
zebra_vrf_list_lookup_by_name() to zebra_vrf_lookup_by_name().
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Since we're already using a red-black tree to store VRFs sorted by their
vrf_id's, create a new tree to store VRFs sorted by their names.
The biggest advantage of doing this is that we reduce the time complexity
of vrf_list_lookup_by_name() from O(n) to O(log n).
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Since VRFs can be searched by vrf_id or name, make this explicit in the
helper functions.
s/vrf_lookup/vrf_lookup_by_id/
s/zebra_vrf_lookup/zebra_vrf_lookup_by_id/
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
If we configure a VRF that doesn't match any device in the kernel, we'll
fall in the first case of the vrf_get() function. In this function,
a vrf structure is callocated and it's vrf_id is never set explicitly,
which means it's set to zero (the vrf-id of the default VRF). When this
happens, commands like "router-id A.B.C.D vrf ..." will act on the
default VRF and not on the pre-provisioned VRF. To fix this, always
set the vrf_id of pre-provisioned VRFs to VRF_UNKNOWN.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
* move netlink code from zebra_nc.c to kernel_netlink.c;
* move vrf CLI commands from if.c/interface.c to vrf.c/zebra_vrf.c;
* move declaration of the 'ns' structure to a header file.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This places the appropriate calls so library objects can be used with
qobj "pointers", especially in the CLI.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This is a rather large mechanical commit that splits up the memory types
defined in lib/memtypes.c and distributes them into *_memory.[ch] files
in the individual daemons.
The zebra change is slightly annoying because there is no nice place to
put the #include "zebra_memory.h" statement.
bgpd, ospf6d, isisd and some tests were reusing MTYPEs defined in the
library for its own use. This is bad practice and would break when the
memtype are made static.
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
[CF: rebased for cmaster-next]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Signed-off-by: Christian Franke <chris@opensourcerouting.org>