<!--startmeta
custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/crates/netflow-plugin/integrations/bio-rd_-_ripe_ris.md"
meta_yaml: "https://github.com/netdata/netdata/edit/master/src/crates/netflow-plugin/metadata.yaml"
sidebar_label: "bio-rd / RIPE RIS"
learn_status: "Published"
learn_rel_path: "Network Flows/Enrichment Methods"
keywords: ['bioris', 'bio-rd', 'ripe ris', 'bgp', 'grpc', 'route information service', 'as path', 'bgp communities']
message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE FLOWS' metadata.yaml FILE"
endmeta-->

<!-- markdownlint-disable-file -->

# bio-rd / RIPE RIS


<img src="https://netdata.cloud/img/network-wired.svg" width="150"/>


Plugin: netflow-plugin
Module: bioris

<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" />

## Overview

Enrich network flows with BGP routing context received from a bio-rd-compatible
`RoutingInformationService` gRPC endpoint. [bio-rd](https://github.com/bio-routing/bio-rd)
is a Go-based BGP/BMP daemon that you run yourself. Its `ris` daemon receives BMP
sessions from routers or collectors and exposes the resulting RIB through gRPC.
Netdata is a **client** of that gRPC interface only.

Netdata does **not** connect directly to RIPE NCC RIS Live, RIPEstat, RIS MRT dumps,
or RIPE route collector sessions. RIPE RIS public access is WebSocket JSON, HTTP API,
and MRT dump based. To use a RIPE-derived external view, run a bridge or service that
imports that data into a bio-rd-compatible `RoutingInformationService`, then point
Netdata at that service.

Pick this when bio-rd is already part of your routing toolbox, or when you want Netdata
to consume a routing view that is already exposed through the bio-rd RIS gRPC API. If
your routers can speak BMP straight to Netdata, the `bmp` integration is simpler.

BioRIS populates the same flow-record fields as BMP -- both feed a single shared
in-memory routing trie. See the BMP integration card for the side-by-side comparison
and combined-deployment notes.


The plugin connects as a gRPC client to one or more user-provided bio-rd `ris`
endpoints (`grpc_addr`) and runs three RPCs against each one:

1. `GetRouters` -- discover which routers/VRFs the bio-rd instance is exposing.
2. `DumpRIB` -- pull a baseline RIB for each (router, AFI/SAFI) tuple. This is the
   expensive call -- full IPv4+IPv6 feeds run to millions of prefixes.
3. `ObserveRIB` -- subscribe to incremental updates so the trie tracks live changes.

Per refresh cycle (default 30 minutes), the plugin re-runs `GetRouters` +
`DumpRIB`, then keeps `ObserveRIB` streams open between cycles. Routers that
disappear between refreshes have their routes purged.

Multiple `ris_instances` are **additive**, not failover -- routes from every
configured endpoint merge into the same trie. The trie is also shared with the
`bmp` integration, so if both are enabled their routes coexist and lookups pick
the best match across both sources.

Connection is plain gRPC over HTTP/2 by default; set `grpc_secure: true` to use
TLS with the system CA bundle. There is no client-cert / mTLS and no application
auth -- restrict access at the network layer.

**Fields populated** (same set as BMP):

| Field | Side | Source |
|---|---|---|
| `SRC_AS` / `DST_AS` | both | When the `routing` provider in the `asn_providers` chain matches |
| `SRC_MASK` / `DST_MASK` | both | Prefix length of the longest-match BGP route |
| `NEXT_HOP` | dest only | BGP next-hop attribute from the destination route |
| `DST_AS_PATH` | dest only | Full AS path, CSV of ASNs |
| `DST_COMMUNITIES` | dest only | Standard BGP communities (CSV of u32) |
| `DST_LARGE_COMMUNITIES` | dest only | RFC 8092 large communities |

Source-side AS path and communities are **not** surfaced; BGP path attributes are
most meaningful for the destination of the traffic. AS *names* (`SRC_AS_NAME`,
`DST_AS_NAME`) come from the GeoIP/ASN MMDB, not from BGP -- BioRIS gives you
accurate AS *numbers* and path/community attributes; the names come from the ASN
database integration.

**Storage tier:** `DST_AS_PATH`, `DST_COMMUNITIES`, and `DST_LARGE_COMMUNITIES`
are written only into the raw journal tier. The 1-minute / 5-minute / 1-hour
rollup tiers do not carry them. Queries that need AS path or community data
must run against a window that the raw retention still covers.


This integration is only supported on the following platforms:

- Linux

This integration runs as a single instance per Netdata Agent.


### Default Behavior

#### Auto-Detection

Disabled by default. Set enrichment.routing_dynamic.bioris.enabled to true and provide at least one ris_instances entry.

#### Limits

Memory scales with the number of RIS instances, peers, routing tables, prefixes, AS paths, and communities. Full-table feeds can consume hundreds of MB per peer.

#### Performance Impact

Disabled until BioRIS is configured. Once active, Netdata maintains an
in-memory routing trie for the received RIB and updates. Plan capacity from
the number of peers and tables you import, and watch the agent's RSS.


## Setup


### Prerequisites

#### A running bio-rd 'ris' daemon

bio-rd is a separate project. The plugin only consumes its gRPC interface; it
does not bundle bio-rd. You install and operate it yourself:

```bash
# Install Go (>=1.20), then:
git clone https://github.com/bio-routing/bio-rd.git
cd bio-rd/cmd/ris
go build -o /usr/local/bin/ris .
```

Configure `ris` with one or more BMP sources using bio-rd's `bmp_addr` /
`bmp_servers` configuration. Refer to the bio-rd documentation for the BMP setup
-- this is bio-rd's configuration, not Netdata's.

Do not set Netdata's `grpc_addr` to a RIPE RIS Live URL, RIPEstat API URL, MRT dump
URL, or route collector session address. Those endpoints are not the
`RoutingInformationService` gRPC API that Netdata consumes.

Run the daemon with a gRPC port:
`/usr/local/bin/ris --grpc_port 50051 --config.file /etc/bio-rd.yml`


#### Network reachability + no auth

The gRPC connection is plain HTTP/2 by default, or TLS with the system CA
bundle when `grpc_secure: true`. There is no client-cert / mTLS and no application
authentication -- restrict access at the firewall, or run bio-rd on the same
host as the agent and bind it to localhost.



### Configuration

#### Options

BioRIS options live under `enrichment.routing_dynamic.bioris` in
`netflow.yaml`.


<details open><summary>Config options</summary>



| Option | Description | Default | Required |
|:-----|:------------|:--------|:---------:|
| enabled | Master switch. | false | no |
| timeout | Connect + per-RPC timeout for `GetRouters` and `ObserveRIB` setup. Default is aggressive; raise to 2-5s when reaching a remote bio-rd over the public internet. | 200ms | no |
| refresh | Cadence at which the plugin re-runs `GetRouters` + `DumpRIB` for every router. Floored to 10s. | 30m | no |
| refresh_timeout | Per-DumpRIB request timeout and per-message stream timeout for the baseline RIB pull. | 10s | no |
| ris_instances | List of bio-rd endpoints. Each entry: `grpc_addr` (`host:port` or full `http(s)://` URI), `grpc_secure` (TLS with system CAs when true), `vrf` (string VRF name to filter on), `vrf_id` (numeric VRF ID, alternative to `vrf`). Multiple instances are additive (not failover) -- routes from every instance merge into the same trie. | [] | yes |


</details>



#### via File

The configuration file name for this integration is `netflow.yaml`.


You can edit the configuration file using the [`edit-config`](https://github.com/netdata/netdata/blob/master/docs/netdata-agent/configuration/README.md#edit-configuration-files) script from the
Netdata [config directory](https://github.com/netdata/netdata/blob/master/docs/netdata-agent/configuration/README.md#locate-your-config-directory).

```bash
cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata
sudo ./edit-config netflow.yaml
```

##### Examples

###### Local bio-rd

bio-rd running on the same host, plain gRPC.

```yaml
enrichment:
  routing_dynamic:
    bioris:
      enabled: true
      timeout: 2s
      refresh: 30m
      refresh_timeout: 30s
      ris_instances:
        - grpc_addr: "127.0.0.1:50051"
          grpc_secure: false

```
###### Remote bio-rd over TLS

Across a network, system CA bundle. No client cert / mTLS.

<details open><summary>Config</summary>

```yaml
enrichment:
  routing_dynamic:
    bioris:
      enabled: true
      timeout: 5s
      ris_instances:
        - grpc_addr: "ris.example.internal:50051"
          grpc_secure: true
          vrf: "global"

```
</details>

###### Prefer BGP over the exporter's AS view

With the default provider chain, an exporter-supplied AS number wins over
BGP. If your bio-rd feed is more accurate than what the exporter is
stamping into flow records, reorder the chains so `routing` is consulted
first.


<details open><summary>Config</summary>

```yaml
enrichment:
  asn_providers: [routing, flow, geoip]
  net_providers:  [routing, flow]
  routing_dynamic:
    bioris:
      enabled: true
      ris_instances:
        - grpc_addr: "127.0.0.1:50051"

```
</details>

###### Combined with BMP into a single trie

Run BMP from internal routers and BioRIS from a separate bio-rd-compatible RIS
service, for example one populated from an external routing view. Both populate
the same shared trie -- lookups pick the best-matching route across both sources
at query time.


<details open><summary>Config</summary>

```yaml
enrichment:
  routing_dynamic:
    bmp:
      enabled: true
      listen: "0.0.0.0:10179"
    bioris:
      enabled: true
      ris_instances:
        - grpc_addr: "127.0.0.1:50051"

```
</details>



### Default 200ms timeout too aggressive

`timeout` covers the gRPC connect plus the `GetRouters` and `ObserveRIB`
setup RPCs. Over the public internet to a remote bio-rd, 200ms is often not
enough. If you see "deadline exceeded" errors in the journal, raise to 2-5s.
`refresh_timeout` is separate and bounds the long-running `DumpRIB` and per-
message stream reads (default 10s).


### Initial dump takes minutes for full feeds

A full IPv4+IPv6 RIB from a full-table bio-rd source can contain millions of
prefixes. The first `DumpRIB` after enabling (or after a plugin restart) takes
time -- BGP attribution is incomplete until it finishes. Subsequent
`ObserveRIB` streams are incremental.


### Plugin restart wipes the trie

The trie is in-memory only -- restarting the netflow plugin loses every
learned BGP route. Convergence over BioRIS depends on the upstream feed; a
full DumpRIB from a full-table bio-rd source can take minutes. Schedule
restarts off-peak if BGP attribution matters for your workflow.


### Pointing grpc_addr at RIPE RIS does not work

`grpc_addr` must point to a bio-rd-compatible `RoutingInformationService`
endpoint. RIPE RIS Live, RIPEstat, RIS MRT dumps, and route collector BGP
sessions use different protocols, so they cannot be used directly as
`ris_instances[].grpc_addr`. Put a converter or bio-rd-compatible service in
front of RIPE-derived data if you need that external view.


### Memory growth without bound

The trie has no time-based eviction. Routes are removed only when the
upstream BGP source withdraws them, when a router disappears from
`GetRouters` between refreshes, or on plugin shutdown. A full feed is
several hundred MB of RSS per peer, permanently.


### AS path / communities missing on older queries

`DST_AS_PATH`, `DST_COMMUNITIES`, and `DST_LARGE_COMMUNITIES` only exist in
the raw journal tier. The 1m / 5m / 1h rollup tiers do not carry them. Queries that span beyond the raw
retention horizon will not return BGP path data.


### AS path inconsistent with the exporter's view

Different vantage points see different BGP paths. If your flow exporter and
the BGP source bio-rd is peering with are different boxes with different
routing tables, expect divergence. This is normal in BGP, not a bug.


### Validate BioRIS enrichment after enabling

BioRIS-derived enrichment depends on the bio-rd version, upstream BGP source,
route visibility, and refresh cadence. Validate against your bio-rd setup
before relying on this for capacity or security decisions.



