Maria Matejka [Fri, 13 Oct 2023 08:22:09 +0000 (10:22 +0200)]
Protocol: better granularity of pool management
There are now 3 different pools with specific lifetime. All of these are
available since protocol start, anyway they get freed in different
moments.
First, pool_up gets freed immediately after announcing PS_STOP, to e.g.
stop all timers and events regularly updating the routing table when the
imports are already flushing.
Then, pool_inloop gets freed just before the protocol loop is finally
stopped, after all channels, imports and exports and other hooks are
cleaned up.
And finally, the pool itself is freed the last. Unless you explicitly
need the early free, use this pool.
Ondrej Zajicek [Thu, 27 Apr 2023 16:20:49 +0000 (18:20 +0200)]
Conf: Improve handling of keywords
For whatever reason, parser allocated a symbol for every parsed keyword
in each scope. That wasted time and memory. The effect is worsened with
recent changes allowing local scopes, so keywords often promote soft
scopes (with no symbols) to real scopes.
Do not allocate a symbol for a keyword. Take care of keywords that could
be promoted to symbols (kw_sym) and do it explicitly.
Maria Matejka [Fri, 29 Sep 2023 14:24:50 +0000 (16:24 +0200)]
Channel: Refeeding by an auxiliary request if needed.
If the protocol supports route refresh on export, we keep the stop-start
method of route refeed. This applies for BGP with ERR or with export
table on, for OSPF, Babel, RIP or Pipe.
For BGP without ERR or for future selective ROA reloads, we're adding an
auxiliary export request, doing the refeed while the main export request
is running, somehow resembling the original method of BIRD 2 refeed.
There is also a refeed request queue to keep track of different refeed
requests.
Maria Matejka [Sun, 24 Sep 2023 21:22:43 +0000 (23:22 +0200)]
Protocols have now assigned startup phases
For now, there are 4 phases: Necessary (device), Connector (kernel, pipe), Generator (static, rpki) and Regular.
Started and reconfigured are from Necessary to Regular, shutdown backwards.
This way, kernel can flush routes before actually being shutdown.
Maria Matejka [Sun, 24 Sep 2023 09:47:24 +0000 (11:47 +0200)]
Table: Fixed feed race condition
The problem happened like this:
1. Single route for the given net in table
2. A feed is started
3. The route is deleted (from another thread)
4. The feed finds an empty net, exports nothing, ignores journal (here is bug)
5. The route is added
6. The export transitions from FEEDING to READY
7. While processing the journal, the route deletion and addition combines into noop.
This way routes mysteriously disappeared in specific cases of link instability.
Problem fixed by explicitly marking the empty-net journal entries as processed in step 4.
Maria Matejka [Thu, 24 Aug 2023 15:00:54 +0000 (17:00 +0200)]
Logging: fixed size logfiles behaving as mmapped ringbuffers
This variant of logging avoids calling write() for every log line,
allowing for waitless logging. This makes heavy logging less heavy
and more useful for race condition debugging.
Maria Matejka [Mon, 21 Aug 2023 16:44:10 +0000 (18:44 +0200)]
Logging now doesn't lock with each message
The original logging routines were locking a common mutex. This led to
massive underperformance and unwanted serialization when heavily logging
due to lock contention. Now the logging is lockless, though still
serializing on write() syscalls to the same filedescriptor.
This change also brings in a persistent logging channel structures and
thus avoids writing into active configuration data structures during
regular run.
Maria Matejka [Mon, 28 Aug 2023 13:36:40 +0000 (15:36 +0200)]
Hostentry application locking
Due to a race condition between rta_apply_hostentry() and rt_update_hostentry(),
happening when a new route is inserted to a table, this commit makes it mandatory
to lock the next hop resolution table while resolving the next hop.
This may be slow, we'll fix it better in some future release
Ondrej Zajicek [Wed, 23 Aug 2023 13:55:31 +0000 (15:55 +0200)]
Nest: Treat VRF interfaces as inside respective VRFs
Despite not having defined 'master interface', VRF interfaces should be
treated as being inside respective VRFs. They behave as a loopback for
respective VRFs. Treating the VRF interface as inside the VRF allows
e.g. OSPF to pick up IP addresses defined on the VRF interface.
For this, we also need to tell apart VRF interfaces and regular interfaces.
Extend Netlink code to parse interface type and mark VRF interfaces with
IF_VRF flag.
Ondrej Zajicek [Mon, 21 Aug 2023 23:24:21 +0000 (01:24 +0200)]
BMP: Improve peer_down handling
Move all bmp_peer_down() calls to one place and make it synchronous with
BGP session down, ensuring that BMP receives peer_down before route
withdraws from flushing.
Also refactor bmp_peer_down_() message generating code.
Ondrej Zajicek [Fri, 18 Aug 2023 01:53:58 +0000 (03:53 +0200)]
BMP: Refactor route monitoring
- Manage BMP state through bmp_peer, bmp_stream, bmp_table structures
- Use channels and rt_notify() hook for route announcements
- Add support for post-policy monitoring
- Send End-of-RIB even when there is no routes
- Remove rte_update_in_notify() hook from import tables
- Update import tables to support channels
- Add bmp_hack (no feed / no flush) flag to channels
Alexander Zubkov [Fri, 23 Jun 2023 15:21:05 +0000 (17:21 +0200)]
RAdv: Add custom options
Currently one can use only a predefined set of advertised options in RAdv
protocol, which are supported by BIRD configuration. It would be convenient
to be able to specify other possible options at least manually as a blob
so one should not wait until it is supported in the code, released, etc.
This idea is inspired by presentation by Ondřej Caletka at CSNOG, in which
he noticed the lack of either PREF64 option or possibility to add custom
options in various software.
The patch makes it possible to define such options with the syntax:
Ondrej Zajicek [Thu, 18 May 2023 23:02:57 +0000 (01:02 +0200)]
BGP: Fix role check when no capability option is present
When an OPEN message without capability options was parsed, the remote
role field was not initialized with the proper (non-zero) default value,
so it was interpreted as if 'provider' was announced.
Ondrej Zajicek [Thu, 8 Jun 2023 02:56:41 +0000 (04:56 +0200)]
BMP: Support multiple instances of BMP protocol
Add internal BMP functions with plicit bmp_proto *p as first argument,
which allows using TRACE() macro. Keep list of BMP instances and call
internal functions. Old BMP functions are wrappers that call internal
functions for all enabled BMP instances.
Extract End-of-RIB mark into separate function.
Based on patch from Michal Zagorski <mzagorsk@akamai.com>. Thanks!
This adds support to the Babel protocol for the RTT extension specified
in draft-ietf-babel-rtt-extension. While this extension is not yet at the
RFC stage, it is one of the more useful extensions to Babel[0], so it
seems worth having in Bird as well.
The extension adds timestamps to Hello and IHU TLVs and uses these to
compute an RTT to each neighbour. An extra per-neighbour cost is then
computed from the RTT based on a minimum and maximum interval and cost
value specified in the configuration. The primary use case for this is
improving routing in a geographically distributed tunnel-based overlay
network.
The implementation follows the babeld implementation when picking
constants and default configuration values. It also uses the same RTT
smoothing algorithm as babeld, and follows it in adding a new 'tunnel'
interface type which enables RTT by default.
IO: Add current_time_now() function for immediate timestamp
Add a current_time_now() function which gets an immediate monotonic
timestamp instead of using the cached value from the event loop. This is
useful for callers that need precise times, such as the Babel RTT
measurement code.
Maria Matejka [Mon, 29 May 2023 17:32:26 +0000 (19:32 +0200)]
BFD: Fixed reconfiguration issues
After converting BFD to the new IO loop system, reconfiguration never
really worked. Sadly, we missed this case in our testing suite so it
passed under the radar for quite a while.
Thanks to Andrei Dinu <andrei.dinu@digitalit.ro> for reporting and
isolating this issue.
Ondrej Zajicek [Thu, 18 May 2023 23:02:57 +0000 (01:02 +0200)]
BGP: Fix role check when no capability option is present
When an OPEN message without capability options was parsed, the remote
role field was not initialized with the proper (non-zero) default value,
so it was interpreted as if 'provider' was announced.
Ondrej Zajicek [Thu, 18 May 2023 13:55:45 +0000 (15:55 +0200)]
Lib: Improve IP/net hashing
Backport some changes from branch oz-parametric-hashes. Replace naive
hash function for IPv6 addresses, fix hashing of VPNx (where upper half
of RD was ignored), fix hashing of MPLS labels (where identity was used).
Ondrej Zajicek [Tue, 16 May 2023 11:25:48 +0000 (13:25 +0200)]
Nest: Add tests and benchmark for FIB
Basic fib_get() / fib_find() test for random prefixes, FIB_WALK() test,
and benchmark for fib_find(). Also generalize and reuse some code from
trie tests.
Maria Matejka [Sat, 13 May 2023 18:33:35 +0000 (20:33 +0200)]
Fixed abort when running in foreground but stdin is closed
A forgotten else-clause caused BIRD to treat some pseudo-random place in
memory as fd-pair. This was happening only on startup of the first
thread in group and the value there in memory was typically zero ... and
writing to stdin succeeded.
When running BIRD with stdin not present (like systemd does), it died on
this spurious write. Now it seems to work correctly.
Thanks to Daniel Suchy <danny@danysek.cz> for reporting.
Maria Matejka [Mon, 8 May 2023 11:09:02 +0000 (13:09 +0200)]
Properly protecting the route src global index by RCU read lock and atomic operations
There was a bug occuring when one thread sought for a src by its global id
and another one was allocating another src with such an ID that it caused
route src global index reallocation. This brief moment of inconsistency
led to a rare use-after-free of the old global index block.
Maria Matejka [Fri, 5 May 2023 07:39:13 +0000 (09:39 +0200)]
Fixed a bug in hot page global storage
The original algorithm was suffering from an ABA race condition:
A: fp = page_stack
B: completely allocates the same page and writes into it some data
A: unsuspecting, loads (invalid) next = fp->next
B: finishes working with the page and returns it back to page_stack
A: compare-exchange page_stack: fp => next succeeds and writes garbage
to page_stack
Fixed this by using an implicit spinlock in hot page allocator.