Commit Graph

35 Commits

Author SHA1 Message Date
Vincent Bernat
abca5e983d chore: modernize some code 2025-11-14 23:22:02 +01:00
Vincent Bernat
b00f74f7e4 demoexporter/bmp: switch to GoBGP v4 2025-11-04 08:05:54 +01:00
Vincent Bernat
ee6e197e8e chore: switch to math/rand/v2 2025-10-26 12:14:20 +01:00
Vincent Bernat
7016d89969 demoexporter/flows: switch to testing/synctest package for clock 2025-08-31 07:56:32 +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
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
6c44019d13 demoexporter/flows: move from net.IP to netip.Addr 2025-08-02 20:01:19 +02:00
Vincent Bernat
bde9cb3b64 chore: Netflow → NetFlow
But like for ClickHouse/clickhouse, we keep using netflow when not
capitalized.
2025-07-31 09:14:02 +02:00
Vincent Bernat
18beb310ee chore: replace interface{} with any 2025-07-29 07:42:49 +02:00
Vincent Bernat
4c0b15e1cd inlet/outlet: rename a few metrics
For example:

```
 17:35 ❱ curl -s 127.0.0.1:8080/api/v0/outlet/metrics | promtool check metrics
akvorado_outlet_core_classifier_exporter_cache_size_items counter metrics should have "_total" suffix
akvorado_outlet_core_classifier_interface_cache_size_items counter metrics should have "_total" suffix
akvorado_outlet_flow_decoder_netflow_flowset_records_sum counter metrics should have "_total" suffix
akvorado_outlet_flow_decoder_netflow_flowset_records_sum non-histogram and non-summary metrics should not have "_sum" suffix
akvorado_outlet_flow_decoder_netflow_flowset_sum counter metrics should have "_total" suffix
akvorado_outlet_flow_decoder_netflow_flowset_sum non-histogram and non-summary metrics should not have "_sum" suffix
akvorado_outlet_kafka_buffered_fetch_records_total non-counter metrics should not have "_total" suffix
akvorado_outlet_kafka_buffered_produce_records_total non-counter metrics should not have "_total" suffix
akvorado_outlet_metadata_cache_refreshs counter metrics should have "_total" suffix
akvorado_outlet_routing_provider_bmp_peers_total non-counter metrics should not have "_total" suffix
akvorado_outlet_routing_provider_bmp_routes_total non-counter metrics should not have "_total" suffix
```

Also ensure metrics using errors as label don't have a too great
cardinality by using constants for error messages used.
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
d7649a36d7 demoexporter/snmp: provide ifName value 2025-02-04 22:25:43 +01: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
de65ee6072 tests: introduce helpers.Pos/helpers.Mark
This helps locating the position of a test.
2024-07-01 07:42:36 +02:00
dependabot[bot]
7d918f8414 build: bump github.com/slayercat/GoSNMPServer from 0.1.2 to 0.5.2
Bumps [github.com/slayercat/GoSNMPServer](https://github.com/slayercat/GoSNMPServer) from 0.1.2 to 0.5.2.
- [Release notes](https://github.com/slayercat/GoSNMPServer/releases)
- [Commits](https://github.com/slayercat/GoSNMPServer/compare/v0.1.2...v0.5.2)

---
updated-dependencies:
- dependency-name: github.com/slayercat/GoSNMPServer
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-31 09:09:33 +02:00
netixx
c2b3cae237 Allow using fields of the netflow packet to set the flow TimeReceived
Today the timestamp can only be from kernel timetstamp put on the UDP packet
by the kernel.

I propose to add 2 alternative methods of getting the timestamp for netflow/IPFix packets:
- TimestampSourceNetflowPacket: use the timestamp field in the netflow packet itself
- TimestampSourceNetflowFirstSwitched: use the FirstSwitched field from each flow
(the field is actually in uptime, so we need to shift it according to sysUptime)

Using those fields requires the router to have accurate time (probably NTP),
but it allows for architectures where a UDP packet is not immediately
received by the collector, eg. if there is a kafka in-between.
That in turns allows to do maintenance on the collector,
without messing up the statistics
2024-03-30 22:01:40 +01:00
Vincent Bernat
71b20f3d26 inlet/flow: update to latest version of GoFlow2
There is no change in performance:

```
goos: linux
goarch: amd64
pkg: akvorado/inlet/flow
cpu: AMD Ryzen 5 5600X 6-Core Processor
BenchmarkDecodeEncodeNetflow/with_encoding-12             155505              8059 ns/op            8178 B/op        130 allocs/op
BenchmarkDecodeEncodeNetflow/without_encoding-12          147974              7554 ns/op            8178 B/op        130 allocs/op
BenchmarkDecodeEncodeSflow/with_encoding-12               126746              9463 ns/op            7200 B/op         90 allocs/op
BenchmarkDecodeEncodeSflow/without_encoding-12            140703              8686 ns/op            7200 B/op         90 allocs/op
```
2023-12-12 23:29:21 +01:00
Vincent Bernat
3b5d1166ab inlet: rename many metrics to match Prometheus best practices
https://prometheus.io/docs/practices/naming/

Notably, unit at the end and use `_total` if the value is accumulating.
2023-11-12 16:32:01 +01:00
Vincent Bernat
1448bb07f8 demoexporter: half-fix for a race condition during shutdown 2023-09-02 08:14:31 +02:00
Vincent Bernat
694a40a5a4 Merge pull request #676 from exaring/feature/netmask-preparation
feat: prepare data structure to fetch prefix len/net mask from BMP
2023-05-27 13:55:37 +02:00
Marvin Gaube
d887f35647 feat: redesign net mask handling, also allow using net masks from BMP 2023-05-08 08:12:48 +02:00
Vincent Bernat
190375d805 config: listen on "*" instead of "0.0.0.0" to help IPv6 users 2023-05-05 08:10:25 +02:00
Vincent Bernat
a912da7fa1 build: use gofumpt
Undecided if we need to use it. I think it's nice.
2023-02-11 10:03:45 +01:00
Vincent Bernat
c6a9319b57 common/schema: turns into a component
This is a first step to make it accept configuration. Most of the
changes are quite trivial, but I also ran into some difficulties with
query columns and filters. They need the schema for parsing, but parsing
happens before dependencies are instantiated (and even if it was not the
case, parsing is stateless). Therefore, I have added a `Validate()`
method that must be called after instantiation. Various bits `panic()`
if not validated to ensure we catch all cases.

The alternative to make the component manages a global state would have
been simpler but it would break once we add the ability to add or
disable columns.
2023-01-18 12:22:10 +01:00
Vincent Bernat
e352202631 inlet: make use of schema for inlet
This is a huge change to make the various subcomponents of the inlet use
the schema to generate the protobuf. For it to make sense, we also
modify the way we parse flows to directly serialize non-essential fields
to Protobuf.

The performance is mostly on par with the previous commit. We are a bit
less efficient because we don't have a fixed structure, but we avoid
loosing too much performance by not relying on reflection and keeping
the production of messages as code. We use less of Goflow2: raw flow
parsing is still done by Goflow2, but we don't use the producer part
anymore. This helps a bit with the performance as we parse less.
Overall, we are 20% than the previous commit and twice faster than the
1.6.4!

```
goos: linux
goarch: amd64
pkg: akvorado/inlet/flow
cpu: AMD Ryzen 5 5600X 6-Core Processor
BenchmarkDecodeEncodeNetflow
BenchmarkDecodeEncodeNetflow/with_encoding
BenchmarkDecodeEncodeNetflow/with_encoding-12             151484              7789 ns/op            8272 B/op        143 allocs/op
BenchmarkDecodeEncodeNetflow/without_encoding
BenchmarkDecodeEncodeNetflow/without_encoding-12          162550              7133 ns/op            8272 B/op        143 allocs/op
BenchmarkDecodeEncodeSflow
BenchmarkDecodeEncodeSflow/with_encoding
BenchmarkDecodeEncodeSflow/with_encoding-12                94844             13193 ns/op            9816 B/op        295 allocs/op
BenchmarkDecodeEncodeSflow/without_encoding
BenchmarkDecodeEncodeSflow/without_encoding-12             92569             12456 ns/op            9816 B/op        295 allocs/op
```

There was a tentative to parse sFlow packets with gopackets, but the
adhoc parser used here is more performant.
2023-01-17 20:53:00 +01:00
Vincent Bernat
0c3a1668d8 inlet/flow: rename SrcNet/DstNet to SrcNetMask/DstNetMask 2022-11-26 14:40:02 +01:00
Vincent Bernat
cfc9a14a50 demoexporter/flows: generate flows with subnets 2022-11-26 14:08:17 +01:00
Vincent Bernat
bf99e2211e common/helpers: correctly validate netip.Addr/netip.Prefix
validate is only able to validate non-struct types (or recurse inside
struct). So, if we want to use "required" on some of them, we need a
custom type.

Fix #263
2022-11-15 18:38:41 +01:00
Vincent Bernat
ebf3645243 demoexporter/bmp: add support for large communities 2022-09-27 17:57:03 +02:00
Vincent Bernat
c769bb5234 inlet/bmp: initial support for BMP protocol
At first, there was a tentative to use BMP collector implementation
from bio-rd. However, this current implementation is using GoBGP
instead:

- BMP is very simple from a protocol point of view. The hard work is
  mostly around decoding. Both bio-rd and GoBGP can decode, but for
  testing, GoBGP is able to generate messages as well (this is its
  primary purpose, I suppose parsing was done for testing purpose).
  Using only one library is always better. An alternative would be
  GoBMP, but it also only do parsing.
- Logging and metrics can be customized easily (but the work was done
  for bio-rd, so not a real argument).
- bio-rd is an application and there is no API stability (and I did
  that too)
- GoBGP supports FlowSpec, which may be useful in the future for the
  DDoS part. Again, one library for everything is better (but
  honestly, GoBGP as a lib is not the best part of it, maybe
  github.com/jwhited/corebgp would be a better fit while keeping GoBGP
  for decoding/encoding).

There was a huge effort around having a RIB which is efficient
memory-wise (data are interned to save memory), performant during
reads, while being decent during insertions. We rely on a patched
version of Kentik's Patricia trees to be able to apply mutations to
the tree.

There was several tentatives to implement some kind of graceful
restart, but ultimetaly, the design is kept simple: when a BMP
connection goes down, routes will be removed after a configurable
time. If the connection comes back up, then it is just considered new.
It would have been ideal to rely on EoR markers, but the RFC is
unclear about them, and they are likely to be per peer, making it
difficult to know what to do if one peer is back, but not the other.

Remaining tasks:

- [ ] Confirm support for LocRIB
- [ ] Import data in ClickHouse
- [ ] Make data available in the frontend

Fix #52
2022-09-27 00:34:41 +02:00
Vincent Bernat
743c98a78f cmd/config: better validation
With maps and slices, we need to explicitely use `dive` to validate
the inner structs.
2022-08-24 00:34:24 +02:00
Vincent Bernat
78fb01c223 chore: fix some small issues detected by golangci-lint
But not using it as some linters are either plain incorrect (the one
suggesting to not use nil for `c.t.Context()`) or just
debatable (checking for err value is a good practice, but there are
good reasons to opt out in some cases).
2022-08-10 17:44:32 +02:00
Vincent Bernat
17eb5529cf inlet/core: correctly close new ticker on stop 2022-08-10 17:21:37 +02:00
Vincent Bernat
2610bd48d1 demo-exporter: also generates reverse flows
This will be useful for some future features.
2022-08-03 16:30:49 +02:00
Vincent Bernat
684a219fac cmd: replace fake-exporter by demo-exporter
Also propagate this rename to configuration and code. It makes easier
to understand the purpose of such a command in the provided
`docker-compose` file.
2022-07-26 17:42:16 +02:00