diff options
| -rw-r--r-- | bfdd/bfd.c | 6 | ||||
| -rw-r--r-- | bfdd/bfd_packet.c | 3 | ||||
| -rw-r--r-- | bfdd/event.c | 24 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 249 | ||||
| -rw-r--r-- | lib/thread.c | 73 | ||||
| -rw-r--r-- | lib/zebra.h | 6 |
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" |
