137 Commits

Author SHA1 Message Date
Vincent Bernat
cb92fc7199 outlet/flow: persist decoders' state
Currently, for NetFlow, persist data/options templates and options. This
should allow the outlet to restart without loosing any message.

Fix #2100
2025-11-18 21:13:51 +01:00
Vincent Bernat
61eb082db5 common/helpers: replace custom code for atomic file writing
Use github.com/google/renameio/v2 instead.
2025-11-18 08:44:51 +01:00
Vincent Bernat
0a18f447b9 common/helpers: remove deprecated reflect.PtrTo
Some checks failed
CI / 🤖 Check dependabot status (push) Has been cancelled
CI / 🐧 Test on Linux (${{ github.ref_type == 'tag' }}, misc) (push) Has been cancelled
CI / 🐧 Test on Linux (coverage) (push) Has been cancelled
CI / 🐧 Test on Linux (regular) (push) Has been cancelled
CI / ❄️ Build on Nix (push) Has been cancelled
CI / 🍏 Build and test on macOS (push) Has been cancelled
CI / 🧪 End-to-end testing (push) Has been cancelled
CI / 🔍 Upload code coverage (push) Has been cancelled
CI / 🔬 Test only Go (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 20) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 22) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 24) (push) Has been cancelled
CI / ⚖️ Check licenses (push) Has been cancelled
CI / 🐋 Build Docker images (push) Has been cancelled
CI / 🐋 Tag Docker images (push) Has been cancelled
CI / 🚀 Publish release (push) Has been cancelled
2025-11-14 23:30:01 +01:00
Vincent Bernat
abca5e983d chore: modernize some code 2025-11-14 23:22:02 +01:00
Vincent Bernat
beb9a3f0ba build: add even more linting rules
Notably, shorten function signatures by not repeating types.
2025-11-12 22:43:12 +01:00
Vincent Bernat
7f5950f89c build: add more linting rules with revive 2025-11-12 22:37:44 +01:00
Vincent Bernat
217c484061 common/helpers: rename PrefixTo16 to PrefixTo6
Move it to common/helpers/ipv6.go and use it where needed.
2025-11-04 08:05:30 +01:00
Vincent Bernat
ffe696e0e1 common/helpers: rename NetIPTo6 to AddrTo6 2025-11-04 07:43:19 +01:00
Vincent Bernat
23518c3e2e common/helpers: add a NetIPTo6() function
Some checks failed
CI / 🤖 Check dependabot status (push) Has been cancelled
CI / 🐧 Test on Linux (${{ github.ref_type == 'tag' }}, misc) (push) Has been cancelled
CI / 🐧 Test on Linux (coverage) (push) Has been cancelled
CI / 🐧 Test on Linux (regular) (push) Has been cancelled
CI / ❄️ Build on Nix (push) Has been cancelled
CI / 🍏 Build and test on macOS (push) Has been cancelled
CI / 🧪 End-to-end testing (push) Has been cancelled
CI / 🔍 Upload code coverage (push) Has been cancelled
CI / 🔬 Test only Go (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 20) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 22) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 24) (push) Has been cancelled
CI / ⚖️ Check licenses (push) Has been cancelled
CI / 🐋 Build Docker images (push) Has been cancelled
CI / 🐋 Tag Docker images (push) Has been cancelled
CI / 🚀 Publish release (push) Has been cancelled
Update Nix dependency hashes / Update dependency hashes (push) Has been cancelled
This should be netip.To6() but it does not exist and it was rejected.
There is a benchmark showing the improvment of such optimisation:

BenchmarkNetIPTo6/safe_v4-12            170152954                7.054 ns/op
BenchmarkNetIPTo6/unsafe_v4-12          764772190                1.553 ns/op

See https://github.com/golang/go/issues/54365.
2025-11-03 21:36:33 +01:00
Vincent Bernat
e68b2de72c common/helpers: migrate from verify to skip-verify in TLS config
Some checks failed
CI / 🤖 Check dependabot status (push) Has been cancelled
CI / 🐧 Test on Linux (${{ github.ref_type == 'tag' }}, misc) (push) Has been cancelled
CI / 🐧 Test on Linux (coverage) (push) Has been cancelled
CI / 🐧 Test on Linux (regular) (push) Has been cancelled
CI / ❄️ Build on Nix (push) Has been cancelled
CI / 🍏 Build and test on macOS (push) Has been cancelled
CI / 🧪 End-to-end testing (push) Has been cancelled
CI / 🔍 Upload code coverage (push) Has been cancelled
CI / 🔬 Test only Go (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 20) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 22) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 24) (push) Has been cancelled
CI / ⚖️ Check licenses (push) Has been cancelled
CI / 🐋 Build Docker images (push) Has been cancelled
CI / 🐋 Tag Docker images (push) Has been cancelled
CI / 🚀 Publish release (push) Has been cancelled
Otherwise, the default is "false" for verify. This is a breaking change.

Fix #2055.
2025-10-30 08:31:27 +01:00
Vincent Bernat
a2339312ac common/remotedatasource: accept specific TLS configuration
Some checks failed
CI / 🤖 Check dependabot status (push) Has been cancelled
CI / 🐧 Test on Linux (${{ github.ref_type == 'tag' }}, misc) (push) Has been cancelled
CI / 🐧 Test on Linux (coverage) (push) Has been cancelled
CI / 🐧 Test on Linux (regular) (push) Has been cancelled
CI / ❄️ Build on Nix (push) Has been cancelled
CI / 🍏 Build and test on macOS (push) Has been cancelled
CI / 🧪 End-to-end testing (push) Has been cancelled
CI / 🔍 Upload code coverage (push) Has been cancelled
CI / 🔬 Test only Go (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 20) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 22) (push) Has been cancelled
CI / 🔬 Test only JS (${{ needs.dependabot.outputs.package-ecosystem }}, 24) (push) Has been cancelled
CI / ⚖️ Check licenses (push) Has been cancelled
CI / 🐋 Build Docker images (push) Has been cancelled
CI / 🐋 Tag Docker images (push) Has been cancelled
CI / 🚀 Publish release (push) Has been cancelled
Update Nix dependency hashes / Update dependency hashes (push) Has been cancelled
2025-10-29 22:34:38 +01:00
Vincent Bernat
9f34f9caf9 common/helpers: return files parsed by yaml.UnmarshalWithInclude 2025-09-19 21:53:01 +02:00
Vincent Bernat
31b6591e0e build: update revive
And remove some unused variables.
2025-09-09 07:39:00 +02:00
Vincent Bernat
8a38e2a912 common/helpers: switch to go.yaml.in/yaml/v3
gopkg.in/yaml.v3 is now unmaintained.
2025-09-09 07:24:42 +02:00
Vincent Bernat
93ae69ad9e inlet/flow: switch to binary.NativeEndian to get native endianness
This is available since Go 1.21 and it is better than enumerating
architectures. We were not up-to-date. See for example:

https://cs.opensource.google/go/go/+/refs/tags/go1.25.1:src/encoding/binary/native_endian_big.go
2025-09-07 10:18:26 +02:00
Vincent Bernat
e21e612259 common/helpers: use Modify() for subnet maps as well
Replace `table.Update()` with `table.Modify()`.
2025-09-06 20:01:19 +02:00
Vincent Bernat
fdb65c93a5 outlet/routing: store v4 routes into a v4 tree
This is improves performance significantly:

```
goos: linux
goarch: amd64
pkg: akvorado/outlet/routing/provider/bmp
cpu: AMD Ryzen 5 5600X 6-Core Processor
                                       │      1       │                  2                   │
                                       │  sec/route   │  sec/route    vs base                │
RIBInsertion/1000_routes,_1_peers-12     466.6n ± ∞ ¹   413.6n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/1000_routes,_2_peers-12     468.5n ± ∞ ¹   424.6n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/1000_routes,_5_peers-12     475.0n ± ∞ ¹   419.6n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/10000_routes,_1_peers-12    485.3n ± ∞ ¹   434.1n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/10000_routes,_2_peers-12    532.6n ± ∞ ¹   477.0n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/10000_routes,_5_peers-12    585.6n ± ∞ ¹   551.9n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/100000_routes,_1_peers-12   623.8n ± ∞ ¹   587.7n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/100000_routes,_2_peers-12   682.1n ± ∞ ¹   637.8n ± ∞ ¹       ~ (p=1.000 n=1) ²
RIBInsertion/100000_routes,_5_peers-12   804.9n ± ∞ ¹   740.8n ± ∞ ¹       ~ (p=1.000 n=1) ²
geomean                                  559.6n         510.1n        -8.85%
¹ need >= 6 samples for confidence interval at level 0.95
² need >= 4 samples to detect a difference at alpha level 0.05

                                    │       1       │                   2                   │
                                    │    sec/op     │    sec/op     vs base                 │
RIBLookup/1000_routes,_1_peers-12      82.87n ± ∞ ¹   14.59n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/1000_routes,_2_peers-12      82.86n ± ∞ ¹   14.68n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/1000_routes,_5_peers-12      83.24n ± ∞ ¹   14.56n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/10000_routes,_1_peers-12     87.27n ± ∞ ¹   14.69n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/10000_routes,_2_peers-12     89.92n ± ∞ ¹   14.62n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/10000_routes,_5_peers-12     99.67n ± ∞ ¹   14.74n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/100000_routes,_1_peers-12   129.60n ± ∞ ¹   14.68n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/100000_routes,_2_peers-12   121.50n ± ∞ ¹   14.71n ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBLookup/100000_routes,_5_peers-12   122.90n ± ∞ ¹   14.69n ± ∞ ¹        ~ (p=1.000 n=1) ²
geomean                                98.40n         14.66n        -85.10%
¹ need >= 6 samples for confidence interval at level 0.95
² need >= 4 samples to detect a difference at alpha level 0.05

                                   │      1       │                   2                   │
                                   │    ms/op     │    ms/op      vs base                 │
RIBFlush/1000_routes,_1_peers-12     268.9m ± ∞ ¹   214.4m ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/1000_routes,_2_peers-12     457.2m ± ∞ ¹   357.8m ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/1000_routes,_5_peers-12     954.7m ± ∞ ¹   697.6m ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/10000_routes,_1_peers-12     2.832 ± ∞ ¹    2.157 ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/10000_routes,_2_peers-12     5.660 ± ∞ ¹    4.247 ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/10000_routes,_5_peers-12     14.00 ± ∞ ¹    10.48 ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/100000_routes,_1_peers-12    48.33 ± ∞ ¹    41.31 ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/100000_routes,_2_peers-12    86.33 ± ∞ ¹    75.51 ± ∞ ¹        ~ (p=1.000 n=1) ²
RIBFlush/100000_routes,_5_peers-12    197.5 ± ∞ ¹    155.7 ± ∞ ¹        ~ (p=1.000 n=1) ²
geomean                               6.534          5.138        -21.36%
¹ need >= 6 samples for confidence interval at level 0.95
² need >= 4 samples to detect a difference at alpha level 0.05
```

Suggested in https://github.com/gaissmai/bart/issues/247#issuecomment-3257156436.
2025-09-05 20:49:16 +02:00
Vincent Bernat
e2f1df9add tests: replace godebug by go-cmp for structure diffs
go-cmp is stricter and allow to catch more problems. Moreover, the
output is a bit nicer.
2025-08-23 16:03:09 +02:00
Vincent Bernat
6b2af58a64 orchestrator/geoip: add a benchmark for Iterate*Databases()
Now:

```
goos: linux
goarch: amd64
pkg: akvorado/orchestrator/geoip
cpu: AMD Ryzen 7 PRO 6850U with Radeon Graphics
BenchmarkIterDatabase/ASN-16                3376               457.0 ns/entry
BenchmarkIterDatabase/GeoIP-16              2410               754.5 ns/entry
```

Before 0a10764cc9:

```
goos: linux
goarch: amd64
pkg: akvorado/orchestrator/geoip
cpu: AMD Ryzen 7 PRO 6850U with Radeon Graphics
BenchmarkIterDatabase/ASN-16                2863               609.3 ns/entry
BenchmarkIterDatabase/GeoIP-16              3286               719.3 ns/entry
```

I was hoping for a bit more!
2025-08-17 08:48:25 +02:00
Vincent Bernat
6118bb7aac common/helpers: convert SubnetMap to github.com/gaissmai/bart
I did not benchmark it myself, but it was benchmarked here:
 https://github.com/osrg/gobgp/issues/1414#issuecomment-3067255941

Of course, no guarantee that this benchmark matches our use cases.
Moreover, SubnetMap have been optimized to avoid parsing keys all
the time.

Also, the interface is a bit nicer and it uses netip.Prefix directly.

The next step is to convert outlet/routing/provider/bmp.
2025-08-16 09:38:44 +02:00
Vincent Bernat
03b947e3c5 chore: fix many staticcheck warnings
The most important ones were fixed in the two previous commit.
2025-08-02 20:54:49 +02:00
Vincent Bernat
3d01a68bcb common/helpers: cache skip decision when requiring external services 2025-07-30 08:19:00 +02:00
Vincent Bernat
18beb310ee chore: replace interface{} with any 2025-07-29 07:42:49 +02:00
Vincent Bernat
76151bea66 common/helpers: make some mapstructure hooks work with embedded structs
When using `mapstructure:",squash"`, most structure-specific hook don't
dive into the structure as they are provided with the parent structure.
Add an helper to make them work on the embedded structure as well and
use it for the generic "deprecated fields" hook, but also for the hook
for the common Kafka configuration.

This is a bit brittle. There are other use cases, but they may not need
this change.
2025-07-27 21:44:28 +02:00
Vincent Bernat
756e4a8fbd */kafka: switch to franz-go
The concurrency of this library is easier to handle than Sarama.
Notably, it is more compatible with the new model of "almost share
nothing" we use for the inlet and the outlet. The lock for workers in
outlet is removed. We can now use sync.Pool to allocate slice of bytes
in inlet.

It may also be more performant.

In the future, we may want to commit only when pushing data to
ClickHouse. However, this does not seem easy when there is a rebalance.
In case of rebalance, we need to do something when a partition is
revoked to avoid duplicating data. For example, we could flush the
current batch to ClickHouse. Have a look at the
`example/mark_offsets/main.go` file in franz-go repository for a
possible approach. In the meantime, we rely on autocommit.

Another contender could be https://github.com/segmentio/kafka-go. Also
see https://github.com/twmb/franz-go/pull/1064.
2025-07-27 21:44:28 +02:00
Vincent Bernat
ac68c5970e inlet: split inlet into new inlet and outlet
This change split the inlet component into a simpler inlet and a new
outlet component. The new inlet component receive flows and put them in
Kafka, unparsed. The outlet component takes them from Kafka and resume
the processing from here (flow parsing, enrichment) and puts them in
ClickHouse.

The main goal is to ensure the inlet does a minimal work to not be late
when processing packets (and restart faster). It also brings some
simplification as the number of knobs to tune everything is reduced: for
inlet, we only need to tune the queue size for UDP, the number of
workers and a few Kafka parameters; for outlet, we need to tune a few
Kafka parameters, the number of workers and a few ClickHouse parameters.

The outlet component features a simple Kafka input component. The core
component becomes just a callback function. There is also a new
ClickHouse component to push data to ClickHouse using the low-level
ch-go library with batch inserts.

This processing has an impact on the internal representation of a
FlowMessage. Previously, it was tailored to dynamically build the
protobuf message to be put in Kafka. Now, it builds the batch request to
be sent to ClickHouse. This makes the FlowMessage structure hides the
content of the next batch request and therefore, it should be reused.
This also changes the way we decode flows as they don't output
FlowMessage anymore, they reuse one that is provided to each worker.

The ClickHouse tables are slightly updated. Instead of using Kafka
engine, the Null engine is used instead.

Fix #1122
2025-07-27 21:44:28 +02:00
Vincent Bernat
5a9a6e6f0a common/helpers: add a hook to deprecate some fields
And apply it to SystemLogTTL and PrometheusEndpoint. It would be nice to
log a warning, but we don't have access to a logger here.
2025-07-27 21:44:28 +02:00
Vincent Bernat
1c42211219 common/helpers: fix mapstructure tests 2025-06-19 06:57:37 +02:00
Vincent Bernat
322ddbe2ab common/helpers: add a useless test for how Diff() works with []byte 2025-06-11 22:47:27 +02:00
Vincent Bernat
edf37390d4 common/helpers: remove nonexistent fields from TLS validation 2025-05-01 19:37:06 +02:00
Vincent Bernat
e1672c7f32 common/helpers: fix decoding of strings as slice
We use the previous version of the function from upstream.
2025-02-15 14:51:17 +01:00
Vincent Bernat
e08331a286 common/helpers: switch to a blessed fork of mapstructure 2025-02-15 14:51:17 +01:00
Vincent Bernat
4a9430e74b inlet/metadata: merge SNMP communities and USM into credentials
This unifies both structure and allows a user to define exception for
some specific subnets. See #1606.
2025-01-18 17:05:43 +01:00
Vincent Bernat
faf58ba5bb common/helpers: be stricter when trying to look for subnets
Otherwise, if the map contains "cafe", we may think this is a subnet
while it is obviously not. But we want to catch user errors like
"2o01:db8::/64" to provide a better error message.
2025-01-18 13:50:35 +01:00
Vincent Bernat
c948b9779e common/helper: add a helper to rename a configuration setting 2024-08-21 19:19:38 +02:00
Vincent Bernat
a449736a62 build: use Go 1.22 range over ints
Done with:

```
git grep -l 'for.*:= 0.*++' \
  | xargs sed -i -E 's/for (.*) := 0; \1 < (.*); \1\+\+/for \1 := range \2/'
```

And a few manual fixes due to unused variables. There is something fishy
in BMP rib test. Add a comment about that. This is not equivalent (as
with range, random is evaluated once, while in the original loop, it is
evaluated at each iteration). I believe the intent was to behave like
with range.
2024-08-14 10:11:35 +02:00
Vincent Bernat
51cae28c23 common/helpers: make readPcap a test helper 2024-07-21 16:22:18 +02:00
Vincent Bernat
0239cd0a9f common: remove MarshalJSON helpers for mapstructure
They are not needed anymore since we don't exchange configuration files
using JSON, since baac495b9c.
2024-07-20 14:51:40 +02:00
Vincent Bernat
3812ca7882 tests: more helpers.Pos/helpers.Mark
This is related to de65ee6072.
2024-07-20 12:00:14 +02:00
Vincent Bernat
de65ee6072 tests: introduce helpers.Pos/helpers.Mark
This helps locating the position of a test.
2024-07-01 07:42:36 +02:00
Vincent Bernat
3af8b942d2 build: move version to a single place
Instead of trying to copy Akvorado version around, move it to a single
place, which can be imported by everything else.
2024-06-02 14:04:54 +02:00
Vincent Bernat
c6bff791a0 inlet/routing: do not rely on custom RWMutex
It was done to add the ability to downgrade the lock. However, the
number of times the RW lock is taken has been greatly reduced and it
does not make sense to maintain another implementation just for that.
2024-05-25 18:35:36 +02:00
guangwu
98a9303ff9 fix: close cache file 2024-05-23 05:51:21 +02:00
Vincent Bernat
2467a3c136 inlet/metadata: fix versioning of metadata cache
Gob decoding is quite liberal and accepts anything that is not
conflicting as long as there is at least one field matching. That's not
what we want. To check we are decoding the right things, use a string
representation of zero values.
2024-04-12 22:44:50 +02:00
Francois Espinet
87a57bf82e Do geoip enrich in clickhouse instead of inlet
One solution to https://github.com/akvorado/akvorado/issues/62
2024-03-11 15:29:09 +01:00
Vincent Bernat
b3a9f6ab2e chore: remove unused parameters
They were not detected by revive in function literals.
2024-02-08 08:30:33 +01:00
Vincent Bernat
8ad3492579 commmon/helpers: fix decoding of SubnetMap that are already SubnetMap
Fix #1067
2024-02-01 23:22:14 +01:00
Vincent Bernat
194019535c chore: add missing SPDX header to some source files 2024-02-01 00:17:32 +01:00
Vincent Bernat
55f685fbf8 common/helpers: remove unused function semacquire 2024-02-01 00:14:18 +01:00
Vincent Bernat
f321e8fa64 common/helpers: add a way to test Marshal/Unmarshal for bimaps 2024-01-22 21:53:26 +01:00