<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<p class="isSelectedEnd"><span>Hello.</span></p>
<p><span>This is not directly related to BIRD itself. BIRD appears
to work correctly in this case. The question is about how </span><code
dir="ltr"><span>bird_exporter</span></code><span> exposes
metrics for a BIRD 2 BGP protocol with multiple address-family
channels.</span></p>
<p>I am using <code>bird_exporter</code> with BIRD 2 and noticed
confusing behavior when a single BGP protocol has more than one
address-family channel enabled, for example both <code>ipv4</code>
and <code>ipv6</code>.</p>
<p>Versions:</p>
<pre><code class="language-text">bird_exporter: 1.5.0
BIRD: 2.19.0
</code></pre>
<p>Exporter is started like this:</p>
<pre><code class="language-bash">bird_exporter \
-web.listen-address=localhost:9325 \
-bird.v2 \
-bird.socket=/path/to/bird.ctl
</code></pre>
<p>BIRD shows one established BGP session with both IPv4 and IPv6
channels up:</p>
<pre><code class="language-text">Name Proto State Info
example_peer BGP up Established
BGP state: Established
Neighbor address: 2001:db8::1
Source address: 2001:db8::2
Local capabilities:
Multiprotocol
AF announced: ipv4 ipv6
Neighbor capabilities:
Multiprotocol
AF announced: ipv4 ipv6
Channel ipv4
State: UP
Table: master4
Routes: 10 imported, 0 filtered, 6000 exported, 10 preferred
Channel ipv6
State: UP
Table: master6
Routes: 0 imported, 0 filtered, 200 exported, 0 preferred
</code></pre>
<p>Actual <code>bird_exporter</code> output:</p>
<pre><code class="language-text">bird_protocol_up{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="4",name="example_peer",proto="BGP",state="Established"} 1
bird_protocol_up{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="6",name="example_peer",proto="BGP",state=""} 1
bird_protocol_uptime{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="4",name="example_peer",proto="BGP"} 397
bird_protocol_uptime{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="6",name="example_peer",proto="BGP"} 397
bird_protocol_prefix_export_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="4",name="example_peer",proto="BGP"} 6000
bird_protocol_prefix_export_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="6",name="example_peer",proto="BGP"} 200
bird_protocol_prefix_import_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="4",name="example_peer",proto="BGP"} 10
bird_protocol_prefix_import_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="6",name="example_peer",proto="BGP"} 0
bird_protocol_prefix_preferred_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="4",name="example_peer",proto="BGP"} 10
bird_protocol_prefix_preferred_count{export_filter="(unnamed)",import_filter="(unnamed)",ip_version="6",name="example_peer",proto="BGP"} 0
</code></pre>
<p>The important part is that both <code>ip_version="4"</code> and
<code>ip_version="6"</code> are exported for the same BGP
protocol, but only one series has the BGP FSM state:</p>
<pre><code class="language-text">bird_protocol_up{ip_version="4",name="example_peer",proto="BGP",state="Established"} 1
bird_protocol_up{ip_version="6",name="example_peer",proto="BGP",state=""} 1
</code></pre>
<p>The IPv6 series has <code>state=""</code>, although the BGP
protocol is established and the IPv6 channel is UP.</p>
<p>Expected behavior:</p>
<p>Either <code>state="Established"</code> should be present on all
<code>bird_protocol_up</code> series generated from the same
established BGP protocol:</p>
<pre><code class="language-text">bird_protocol_up{ip_version="4",name="example_peer",proto="BGP",state="Established"} 1
bird_protocol_up{ip_version="6",name="example_peer",proto="BGP",state="Established"} 1
</code></pre>
<p>or <code>state</code> should not be attached to per-AF <code>bird_protocol_up</code>
series at all, and a separate protocol-level metric should expose
the BGP FSM state.</p>
<p>The current behavior is confusing for monitoring systems, because
the same BGP protocol appears as partly established and partly
without state, although both address-family channels are UP.</p>
<p>It would also be useful to distinguish clearly between:</p>
<ul>
<li>
<p>protocol/session state, for example <code>BGP state:
Established</code>;</p>
</li>
<li>
<p>channel state, for example <code>Channel ipv4: UP</code>, <code>Channel
ipv6: UP</code>;</p>
</li>
<li>
<p>address-family label, currently exposed as <code>ip_version</code>.</p>
</li>
</ul>
<p>A cleaner model could be something like:</p>
<pre><code class="language-text">bird_protocol_up{name="example_peer",proto="BGP",state="Established"} 1
bird_protocol_channel_up{name="example_peer",proto="BGP",channel="ipv4"} 1
bird_protocol_channel_up{name="example_peer",proto="BGP",channel="ipv6"} 1
</code></pre>
<p>This would avoid ambiguity when one BIRD 2 protocol serves
multiple address families.</p>
<p>Thank you.</p>
<p><br>
</p>
</body>
</html>