summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c6
-rw-r--r--bfdd/bfd_packet.c3
-rw-r--r--bfdd/event.c24
-rw-r--r--doc/user/bgp.rst249
-rw-r--r--lib/thread.c73
-rw-r--r--lib/zebra.h6
6 files changed, 202 insertions, 159 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index cf7c027db5..8d9de857f5 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -157,7 +157,8 @@ void ptm_bfd_echo_stop(struct bfd_session *bfd, int polling)
void ptm_bfd_echo_start(struct bfd_session *bfd)
{
bfd->echo_detect_TO = (bfd->remote_detect_mult * bfd->echo_xmt_TO);
- ptm_bfd_echo_xmt_TO(bfd);
+ if (bfd->echo_detect_TO > 0)
+ ptm_bfd_echo_xmt_TO(bfd);
bfd->polling = 1;
bfd->new_timers.desired_min_tx = bfd->up_min_tx;
@@ -324,7 +325,8 @@ int bfd_echo_xmt_cb(struct thread *t)
{
struct bfd_session *bs = THREAD_ARG(t);
- ptm_bfd_echo_xmt_TO(bs);
+ if (bs->echo_xmt_TO > 0)
+ ptm_bfd_echo_xmt_TO(bs);
return 0;
}
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 8acb9438c5..1ba5ee826f 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -197,7 +197,8 @@ static int ptm_bfd_process_echo_pkt(int s)
bfd->echo_detect_TO = bfd->remote_detect_mult * bfd->echo_xmt_TO;
/* Update echo receive timeout. */
- bfd_echo_recvtimer_update(bfd);
+ if (bfd->echo_detect_TO > 0)
+ bfd_echo_recvtimer_update(bfd);
return 0;
}
diff --git a/bfdd/event.c b/bfdd/event.c
index 63f64077eb..3f48921af9 100644
--- a/bfdd/event.c
+++ b/bfdd/event.c
@@ -39,6 +39,9 @@ void bfd_recvtimer_update(struct bfd_session *bs)
{
struct timeval tv = {.tv_sec = 0, .tv_usec = bs->detect_TO};
+ /* Remove previous schedule if any. */
+ bfd_recvtimer_delete(bs);
+
/* Don't add event if peer is deactivated. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return;
@@ -48,9 +51,6 @@ void bfd_recvtimer_update(struct bfd_session *bs)
log_debug("%s: sec = %ld, usec = %ld", __func__, tv.tv_sec, tv.tv_usec);
#endif /* BFD_EVENT_DEBUG */
- /* Remove previous schedule if any. */
- bfd_recvtimer_delete(bs);
-
thread_add_timer_tv(master, bfd_recvtimer_cb, bs, &tv,
&bs->recvtimer_ev);
}
@@ -59,6 +59,9 @@ void bfd_echo_recvtimer_update(struct bfd_session *bs)
{
struct timeval tv = {.tv_sec = 0, .tv_usec = bs->echo_detect_TO};
+ /* Remove previous schedule if any. */
+ bfd_echo_recvtimer_delete(bs);
+
/* Don't add event if peer is deactivated. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return;
@@ -68,9 +71,6 @@ void bfd_echo_recvtimer_update(struct bfd_session *bs)
log_debug("%s: sec = %ld, usec = %ld", __func__, tv.tv_sec, tv.tv_usec);
#endif /* BFD_EVENT_DEBUG */
- /* Remove previous schedule if any. */
- bfd_echo_recvtimer_delete(bs);
-
thread_add_timer_tv(master, bfd_echo_recvtimer_cb, bs, &tv,
&bs->echo_recvtimer_ev);
}
@@ -79,6 +79,9 @@ void bfd_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
{
struct timeval tv = {.tv_sec = 0, .tv_usec = jitter};
+ /* Remove previous schedule if any. */
+ bfd_xmttimer_delete(bs);
+
/* Don't add event if peer is deactivated. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return;
@@ -88,9 +91,6 @@ void bfd_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
log_debug("%s: sec = %ld, usec = %ld", __func__, tv.tv_sec, tv.tv_usec);
#endif /* BFD_EVENT_DEBUG */
- /* Remove previous schedule if any. */
- bfd_xmttimer_delete(bs);
-
thread_add_timer_tv(master, bfd_xmt_cb, bs, &tv, &bs->xmttimer_ev);
}
@@ -98,6 +98,9 @@ void bfd_echo_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
{
struct timeval tv = {.tv_sec = 0, .tv_usec = jitter};
+ /* Remove previous schedule if any. */
+ bfd_echo_xmttimer_delete(bs);
+
/* Don't add event if peer is deactivated. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN))
return;
@@ -107,9 +110,6 @@ void bfd_echo_xmttimer_update(struct bfd_session *bs, uint64_t jitter)
log_debug("%s: sec = %ld, usec = %ld", __func__, tv.tv_sec, tv.tv_usec);
#endif /* BFD_EVENT_DEBUG */
- /* Remove previous schedule if any. */
- bfd_echo_xmttimer_delete(bs);
-
thread_add_timer_tv(master, bfd_echo_xmt_cb, bs, &tv,
&bs->echo_xmttimer_ev);
}
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index d9d496f7fc..f10883b984 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -181,20 +181,6 @@ will establish the connection with unicast only capability. When there are no
common capabilities, FRR sends Unsupported Capability error and then resets the
connection.
-.. _bgp-concepts-vrfs:
-
-VRFs: Virtual Routing and Forwarding
-------------------------------------
-
-*bgpd* supports :abbr:`L3VPN (Layer 3 Virtual Private Networks)` :abbr:`VRFs
-(Virtual Routing and Forwarding tables)` for IPv4 :rfc:`4364` and IPv6
-:rfc:`4659`. L3VPN routes, and their associated VRF MPLS labels, can be
-distributed to VPN SAFI neighbors in the *default*, i.e., non VRF, BGP
-instance. VRF MPLS labels are reached using *core* MPLS labels which are
-distributed using LDP or BGP labeled unicast. *bgpd* also supports inter-VRF
-route leaking. General information on FRR's VRF support can be found in
-:ref:`zebra-vrf`.
-
.. _bgp-router-configuration:
BGP Router Configuration
@@ -228,6 +214,126 @@ internal or external.
not enabled *bgpd* can't get interface information so `router-id` is set to
0.0.0.0. So please set router-id by hand.
+
+.. _bgp-multiple-autonomous-systems:
+
+Multiple Autonomous Systems
+---------------------------
+
+FRR's BGP implementation is capable of running multiple autonomous systems at
+once. Each configured AS corresponds to a :ref:`zebra-vrf`. In the past, to get
+the same functionality the network administrator had to run a new *bgpd*
+process; using VRFs allows multiple autonomous systems to be handled in a
+single process.
+
+When using multiple autonomous systems, all router config blocks after the
+first one must specify a VRF to be the target of BGP's route selection. This
+VRF must be unique within respect to all other VRFs being used for the same
+purpose, i.e. two different autonomous systems cannot use the same VRF.
+However, the same AS can be used with different VRFs.
+
+.. note::
+
+ The separated nature of VRFs makes it possible to peer a single *bgpd*
+ process to itself, on one machine. Note that this can be done fully within
+ BGP without a corresponding VRF in the kernel or Zebra, which enables some
+ practical use cases such as :ref:`route reflectors <bgp-route-reflector>`
+ and route servers.
+
+Configuration of additional autonomous systems, or of a router that targets a
+specific VRF, is accomplished with the following command:
+
+.. index:: router bgp ASN vrf VRFNAME
+.. clicmd:: router bgp ASN vrf VRFNAME
+
+ ``VRFNAME`` is matched against VRFs configured in the kernel. When ``vrf
+ VRFNAME`` is not specified, the BGP protocol process belongs to the default
+ VRF.
+
+An example configuration with multiple autonomous systems might look like this:
+
+.. code-block:: frr
+
+ router bgp 1
+ neighbor 10.0.0.1 remote-as 20
+ neighbor 10.0.0.2 remote-as 30
+ !
+ router bgp 2 vrf blue
+ neighbor 10.0.0.3 remote-as 40
+ neighbor 10.0.0.4 remote-as 50
+ !
+ router bgp 3 vrf red
+ neighbor 10.0.0.5 remote-as 60
+ neighbor 10.0.0.6 remote-as 70
+ ...
+
+In the past this feature done differently and the following commands were
+required to enable the functionality. They are now deprecated.
+
+.. deprecated:: 5.0
+ This command is deprecated and may be safely removed from the config.
+
+.. index:: bgp multiple-instance
+.. clicmd:: bgp multiple-instance
+
+ Enable BGP multiple instance feature. Because this is now the default
+ configuration this command will not be displayed in the running
+ configuration.
+
+.. deprecated:: 5.0
+ This command is deprecated and may be safely removed from the config.
+
+.. index:: no bgp multiple-instance
+.. clicmd:: no bgp multiple-instance
+
+ In previous versions of FRR, this command disabled the BGP multiple instance
+ feature. This functionality is automatically turned on when BGP multiple
+ instances or views exist so this command no longer does anything.
+
+.. seealso:: :ref:`bgp-vrf-route-leaking`
+.. seealso:: :ref:`zebra-vrf`
+
+
+.. _bgp-views:
+
+Views
+-----
+
+In addition to supporting multiple autonomous systems, FRR's BGP implementation
+also supports *views*.
+
+BGP views are almost the same as normal BGP processes, except that routes
+selected by BGP are not installed into the kernel routing table. Each BGP view
+provides an independent set of routing information which is only distributed
+via BGP. Multiple views can be supported, and BGP view information is always
+independent from other routing protocols and Zebra/kernel routes. BGP views use
+the core instance (i.e., default VRF) for communication with peers.
+
+.. index:: router bgp AS-NUMBER view NAME
+.. clicmd:: router bgp AS-NUMBER view NAME
+
+ Make a new BGP view. You can use an arbitrary word for the ``NAME``. Routes
+ selected by the view are not installed into the kernel routing table.
+
+ With this command, you can setup Route Server like below.
+
+ .. code-block:: frr
+
+ !
+ router bgp 1 view 1
+ neighbor 10.0.0.1 remote-as 2
+ neighbor 10.0.0.2 remote-as 3
+ !
+ router bgp 2 view 2
+ neighbor 10.0.0.3 remote-as 4
+ neighbor 10.0.0.4 remote-as 5
+
+.. index:: show [ip] bgp view NAME
+.. clicmd:: show [ip] bgp view NAME
+
+ Display the routing table of BGP view ``NAME``.
+
+
Route Selection
---------------
@@ -1609,32 +1715,23 @@ Large Communities in Route Map
overwriting other values. Multiple large-community values can be specified.
-.. _bgp-vrfs:
+.. _bgp-l3vpn-vrfs:
-VRFs
-----
+L3VPN VRFs
+----------
-BGP supports multiple VRF instances with the following command:
-
-.. index:: router bgp ASN vrf VRFNAME
-.. clicmd:: router bgp ASN vrf VRFNAME
+*bgpd* supports :abbr:`L3VPN (Layer 3 Virtual Private Networks)` :abbr:`VRFs
+(Virtual Routing and Forwarding)` for IPv4 :rfc:`4364` and IPv6 :rfc:`4659`.
+L3VPN routes, and their associated VRF MPLS labels, can be distributed to VPN
+SAFI neighbors in the *default*, i.e., non VRF, BGP instance. VRF MPLS labels
+are reached using *core* MPLS labels which are distributed using LDP or BGP
+labeled unicast. *bgpd* also supports inter-VRF route leaking.
-``VRFNAME`` is matched against VRFs configured in the kernel. When
-``vrf VRFNAME`` is not specified, the BGP protocol process belongs to the
-default VRF.
-With VRF, you can isolate networking information. Having BGP VRF allows you to
-have several BGP instances on the same system process. This solution solves
-scalabiliy issues where the network administrator had previously to run
-separately several BGP processes on each namespace. Now, not only BGP VRF
-solves this, but also this method applies to both kind of VRFs backend: default
-VRF from Linux kernel or network namespaces. Also, having separate BGP
-instances does not imply that the AS number has to be different. For internal
-purposes, it is possible to do iBGP peering from two differents network
-namespaces.
+.. _bgp-vrf-route-leaking:
VRF Route Leaking
-^^^^^^^^^^^^^^^^^
+-----------------
BGP routes may be leaked (i.e. copied) between a unicast VRF RIB and the VPN
SAFI RIB of the default VRF for use in MPLS-based L3VPNs. Unicast routes may
@@ -1648,7 +1745,7 @@ to a unicast VRF, whereas ``export`` refers to routes leaked from a unicast VRF
to VPN.
Required parameters
-"""""""""""""""""""
+^^^^^^^^^^^^^^^^^^^
Routes exported from a unicast VRF to the VPN RIB must be augmented by two
parameters:
@@ -1682,7 +1779,7 @@ When using the shortcut syntax for vrf-to-vrf leaking, the RD and RT are
auto-derived.
General configuration
-"""""""""""""""""""""
+^^^^^^^^^^^^^^^^^^^^^
Configuration of route leaking between a unicast VRF RIB and the VPN SAFI RIB
of the default VRF is accomplished via commands in the context of a VRF
@@ -1781,86 +1878,6 @@ address-family:
Disables automatic leaking from vrf VRFNAME to the current VRF using
the VPN RIB as intermediary.
-.. _bgp-instances-and-views:
-
-Instances and Views
--------------------
-
-A BGP *instance* is a normal BGP process. Routes selected by BGP are installed
-into the kernel routing table.
-
-.. note::
- In previous versions of FRR, running multiple AS's from the same BGP process
- was not supported; in order to run multiple AS's it was necessary to run
- multiple BGP processes. This had to be explicitly configured with the
- ``bgp multiple-instance`` command. Recent versions of FRR support multiple
- BGP AS's within the same process by simply defining multiple
- ``router bgp X`` blocks, so the ``multiple-instance`` command is now
- unnecessary and deprecated.
-
-.. index:: router bgp AS-NUMBER
-.. clicmd:: router bgp AS-NUMBER
-
- Make a new BGP instance. You can use an arbitrary word for the `name`.
-
- .. code-block:: frr
-
- router bgp 1
- neighbor 10.0.0.1 remote-as 2
- neighbor 10.0.0.2 remote-as 3
- !
- router bgp 2
- neighbor 10.0.0.3 remote-as 4
- neighbor 10.0.0.4 remote-as 5
-
-.. deprecated:: 5.0
- This command does nothing and can be safely removed.
-
-.. index:: bgp multiple-instance
-.. clicmd:: bgp multiple-instance
-
- Enable BGP multiple instance feature. Because this is now the default
- configuration this command will not be displayed in the running
- configuration.
-
-.. deprecated:: 5.0
- This command does nothing and can be safely removed.
-
-.. index:: no bgp multiple-instance
-.. clicmd:: no bgp multiple-instance
-
- In previous versions of FRR, this command disabled the BGP multiple instance
- feature. This functionality is automatically turned on when BGP multiple
- instances or views exist so this command no longer does anything.
-
-BGP views are almost same as normal BGP processes, except that routes selected
-by BGP are not installed into the kernel routing table. The view functionality
-allows the exchange of BGP routing information only without affecting the
-kernel routing tables.
-
-.. index:: router bgp AS-NUMBER view NAME
-.. clicmd:: router bgp AS-NUMBER view NAME
-
- Make a new BGP view. You can use arbitrary word for the ``NAME``. Routes selected by the view are not installed into the kernel routing table.
- view's route selection result does not go to the kernel routing table.
-
- With this command, you can setup Route Server like below.
-
- .. code-block:: frr
-
- !
- router bgp 1 view 1
- neighbor 10.0.0.1 remote-as 2
- neighbor 10.0.0.2 remote-as 3
- !
- router bgp 2 view 2
- neighbor 10.0.0.3 remote-as 4
- neighbor 10.0.0.4 remote-as 5
-
-.. index:: show [ip] bgp view NAME
-.. clicmd:: show [ip] bgp view NAME
-
- Display the routing table of BGP view ``NAME``.
.. _bgp-cisco-compatibility:
diff --git a/lib/thread.c b/lib/thread.c
index a81faae796..267dcd1cfc 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -58,6 +58,7 @@ pthread_key_t thread_current;
pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
static struct list *masters;
+static void thread_free(struct thread_master *master, struct thread *thread);
/* CLI start ---------------------------------------------------------------- */
static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
@@ -538,6 +539,8 @@ static struct thread *thread_trim_head(struct thread_list *list)
/* Move thread to unuse list. */
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
{
+ pthread_mutex_t mtxc = thread->mtx;
+
assert(m != NULL && thread != NULL);
assert(thread->next == NULL);
assert(thread->prev == NULL);
@@ -546,10 +549,15 @@ static void thread_add_unuse(struct thread_master *m, struct thread *thread)
memset(thread, 0, sizeof(struct thread));
thread->type = THREAD_UNUSED;
- if (m->unuse.count < THREAD_UNUSED_DEPTH)
+ /* Restore the thread mutex context. */
+ thread->mtx = mtxc;
+
+ if (m->unuse.count < THREAD_UNUSED_DEPTH) {
thread_list_add(&m->unuse, thread);
- else
- XFREE(MTYPE_THREAD, thread);
+ return;
+ }
+
+ thread_free(m, thread);
}
/* Free all unused thread. */
@@ -560,9 +568,8 @@ static void thread_list_free(struct thread_master *m, struct thread_list *list)
for (t = list->head; t; t = next) {
next = t->next;
- XFREE(MTYPE_THREAD, t);
+ thread_free(m, t);
list->count--;
- m->alloc--;
}
}
@@ -576,8 +583,7 @@ static void thread_array_free(struct thread_master *m,
t = thread_array[index];
if (t) {
thread_array[index] = NULL;
- XFREE(MTYPE_THREAD, t);
- m->alloc--;
+ thread_free(m, t);
}
}
XFREE(MTYPE_THREAD_POLL, thread_array);
@@ -588,9 +594,8 @@ static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
int i;
for (i = 0; i < queue->size; i++)
- XFREE(MTYPE_THREAD, queue->array[i]);
+ thread_free(m, queue->array[i]);
- m->alloc -= queue->size;
pqueue_delete(queue);
}
@@ -608,8 +613,7 @@ void thread_master_free_unused(struct thread_master *m)
{
struct thread *t;
while ((t = thread_trim_head(&m->unuse)) != NULL) {
- pthread_mutex_destroy(&t->mtx);
- XFREE(MTYPE_THREAD, t);
+ thread_free(m, t);
}
}
pthread_mutex_unlock(&m->mtx);
@@ -728,6 +732,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
return thread;
}
+static void thread_free(struct thread_master *master, struct thread *thread)
+{
+ /* Update statistics. */
+ assert(master->alloc > 0);
+ master->alloc--;
+
+ /* Free allocated resources. */
+ pthread_mutex_destroy(&thread->mtx);
+ XFREE(MTYPE_THREAD, thread);
+}
+
static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
nfds_t count, const struct timeval *timer_wait)
{
@@ -1633,25 +1648,27 @@ void funcname_thread_execute(struct thread_master *m,
int (*func)(struct thread *), void *arg, int val,
debugargdef)
{
- struct cpu_thread_history tmp;
- struct thread dummy;
-
- memset(&dummy, 0, sizeof(struct thread));
+ struct thread *thread;
- pthread_mutex_init(&dummy.mtx, NULL);
- dummy.type = THREAD_EVENT;
- dummy.add_type = THREAD_EXECUTE;
- dummy.master = NULL;
- dummy.arg = arg;
- dummy.u.val = val;
+ /* Get or allocate new thread to execute. */
+ pthread_mutex_lock(&m->mtx);
+ {
+ thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
- tmp.func = dummy.func = func;
- tmp.funcname = dummy.funcname = funcname;
- dummy.hist = hash_get(m->cpu_record, &tmp,
- (void *(*)(void *))cpu_record_hash_alloc);
+ /* Set its event value. */
+ pthread_mutex_lock(&thread->mtx);
+ {
+ thread->add_type = THREAD_EXECUTE;
+ thread->u.val = val;
+ thread->ref = &thread;
+ }
+ pthread_mutex_unlock(&thread->mtx);
+ }
+ pthread_mutex_unlock(&m->mtx);
- dummy.schedfrom = schedfrom;
- dummy.schedfrom_line = fromln;
+ /* Execute thread doing all accounting. */
+ thread_call(thread);
- thread_call(&dummy);
+ /* Give back or free thread. */
+ thread_add_unuse(m, thread);
}
diff --git a/lib/zebra.h b/lib/zebra.h
index 4e0e408ea6..46721cc1ab 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -379,6 +379,12 @@ struct in_pktinfo {
*/
#define ZEBRA_HEADER_MARKER 254
+/*
+ * The compiler.h header is used for anyone using the CPP_NOTICE
+ * since this is universally needed, let's add it to zebra.h
+ */
+#include "compiler.h"
+
/* Zebra route's types are defined in route_types.h */
#include "route_types.h"