Hello. This is not directly related to BIRD itself. BIRD appears to work correctly in this case. The question is about how |bird_exporter|exposes metrics for a BIRD 2 BGP protocol with multiple address-family channels. I am using |bird_exporter| with BIRD 2 and noticed confusing behavior when a single BGP protocol has more than one address-family channel enabled, for example both |ipv4| and |ipv6|. Versions: |bird_exporter: 1.5.0 BIRD: 2.19.0 | Exporter is started like this: |bird_exporter \ -web.listen-address=localhost:9325 \ -bird.v2 \ -bird.socket=/path/to/bird.ctl | BIRD shows one established BGP session with both IPv4 and IPv6 channels up: |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 | Actual |bird_exporter| output: |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 | The important part is that both |ip_version="4"| and |ip_version="6"| are exported for the same BGP protocol, but only one series has the BGP FSM state: |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 | The IPv6 series has |state=""|, although the BGP protocol is established and the IPv6 channel is UP. Expected behavior: Either |state="Established"| should be present on all |bird_protocol_up| series generated from the same established BGP protocol: |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 | or |state| should not be attached to per-AF |bird_protocol_up| series at all, and a separate protocol-level metric should expose the BGP FSM state. 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. It would also be useful to distinguish clearly between: * protocol/session state, for example |BGP state: Established|; * channel state, for example |Channel ipv4: UP|, |Channel ipv6: UP|; * address-family label, currently exposed as |ip_version|. A cleaner model could be something like: |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 | This would avoid ambiguity when one BIRD 2 protocol serves multiple address families. Thank you.