Skip to content

Feature: bird vrf support including bgp, ospf and route leaking#3498

Merged
ipspace merged 31 commits into
ipspace:devfrom
jbemmel:feature/bird-vrf-support
Jun 24, 2026
Merged

Feature: bird vrf support including bgp, ospf and route leaking#3498
ipspace merged 31 commits into
ipspace:devfrom
jbemmel:feature/bird-vrf-support

Conversation

@jbemmel

@jbemmel jbemmel commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator
  • Create Linux VRF tables (including any module specific script in initial/bird-clab.j2)
  • Make BGP and OSPF VRF aware
  • Add VRF route leaking (including static routes)
  • Update documentation

Test results:

./device-module-test -d bird -p clab vrf
Pre-test cleanup: 
23:10:18 vrf/01-multi-vrf.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:10:28 vrf/02-multi-vrf-ipv6.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:10:39 vrf/03-multi-vrf-loopback.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:10:43 vrf/04-multi-vrf-loopback-ipv6.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:10:50 vrf/11-multi-vrf-ospf.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:11:12 vrf/12-multi-vrf-bgp.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:12:32 vrf/13-multi-vrf-bgp-loopback.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:12:48 vrf/14-multi-vrf-unnumbered.yml: create(FAIL) 
23:12:49 vrf/15-multi-vrf-mixed.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:13:10 vrf/16-vrf-bgp-community.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:13:20 vrf/21-multi-vrf-ospfv3.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:13:42 vrf/22-multi-vrf-bgp-ipv6.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:13:58 vrf/23-multi-vrf-mixed-ipv6.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:14:21 vrf/31-vrf-common-hosts.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:14:30 vrf/32-vrf-common-hosts-ipv6.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:14:40 vrf/33-vrf-common-ospf.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK
23:15:01 vrf/34-vrf-common-mixed.yml: create(ok) up(ok) config(ok) validate(ok) cleanup(ok) OK

@jbemmel

jbemmel commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

Test vrf/14-multi-vrf-unnumbered.yml can be fixed once #3475 is merged

@ipspace ipspace left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need a significant rework. The hacks like "include everything else in initial.j2" suck.

Also, for all other devices, we configure routing protocol instances within the VRF configuration; here, you do it in the main OSPF/BGP template. While I understand why you went down that route, it will make for an "interesting" experience when someone has to fix this code, and the two similar experiences I already had to go through persuaded me to avoid the third one at all costs 🤷🏻‍♂️

I know you're facing the challenge of doing data-plane configuration and daemon configuration in the same template, and I don't have a good answer for it yet... but it has to be better than this.

@jbemmel

jbemmel commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator Author

I know you're facing the challenge of doing data-plane configuration and daemon configuration in the same template, and I don't have a good answer for it yet... but it has to be better than this.

Currently, the issue is that a vrf key under daemon_config overrides the ansible/templates/vrf/bird-clab.j2 script - hence the initial hack.

Somehow we need to make the daemon_config namespace distinct from regular module scripts, allowing both

@jbemmel jbemmel force-pushed the feature/bird-vrf-support branch from 4088875 to 7160c8b Compare June 20, 2026 15:40
@jbemmel jbemmel marked this pull request as ready for review June 20, 2026 19:52
@jbemmel

jbemmel commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator Author
  • Rebased from dev to get datapath wait functionality
  • Refactor FRR VRF datapath script such that BIRD can import as-is
  • Remove default router role (VRF test cases need fixing: [BUG] VRF integration tests fail to set role 'router' for DUT #3506)
  • Allow daemon config files to include "@conf" such that they can co-exist with a datapath script for the same module
  • Refactor BGP, OSPF and VRF config templates separating out the Jinja2 macro's
  • Align VRF logic with other devices (import BGP/OSPF macros)

@jbemmel jbemmel marked this pull request as draft June 20, 2026 20:02
@jbemmel jbemmel marked this pull request as ready for review June 20, 2026 20:27
@jbemmel jbemmel marked this pull request as draft June 21, 2026 17:18
jbemmel and others added 19 commits June 21, 2026 12:20
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
jbemmel and others added 7 commits June 21, 2026 12:22
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jbemmel jbemmel force-pushed the feature/bird-vrf-support branch from 5dbb382 to 1ce59db Compare June 21, 2026 17:25
jbemmel and others added 2 commits June 21, 2026 12:30
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jbemmel

jbemmel commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator Author
  • Rebased from dev once more to get per-module CP config support for daemons
  • replaced @conf with -daemon in extra_daemon_config

./device-module-test -d bird -p clab vrf still passes (except vrf-unnumbered)

@jbemmel jbemmel marked this pull request as ready for review June 21, 2026 20:57
@ipspace ipspace requested a review from Copilot June 24, 2026 05:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds full VRF support for the BIRD “device” integration, covering per-VRF routing tables, VRF-aware BGP/OSPF instances, and RT-based route leaking (including VRF/inter-VRF static routes), plus documentation and feature-flag updates.

Changes:

  • Implemented VRF-aware BIRD configuration generation (VRF tables, kernel/direct/static, RT-based pipe leaking, VRF BGP/OSPF).
  • Refactored BIRD BGP/OSPF templates into reusable macro libraries and updated feature flags for VRF + static route capabilities.
  • Reused a shared Linux VRF dataplane setup script across FRR/BIRD and updated platform/module docs to reflect new support.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
netsim/daemons/bird/vrf-daemon.j2 New VRF table + protocol definitions, VRF static routes, RT-based leaking, and per-VRF OSPF/BGP rendering.
netsim/daemons/bird/protocols.j2 Excludes VRF interfaces from the global direct protocol.
netsim/daemons/bird/ospf.macros.j2 New OSPF rendering macro with VRF-aware table/import/export handling.
netsim/daemons/bird/ospf.j2 Refactored to use ospf.macros.j2.
netsim/daemons/bird/bgp.macros.j2 New BGP rendering macros, including VRF-aware sessions.
netsim/daemons/bird/bgp.j2 Refactored to use bgp.macros.j2.
netsim/daemons/bird.yml Advertises new BIRD VRF + routing.static (vrf/inter_vrf) feature support.
netsim/ansible/templates/vrf/frr.vrf.j2 New shared script that creates Linux VRFs and assigns interfaces to them.
netsim/ansible/templates/vrf/frr.j2 Refactored to include the shared VRF script.
netsim/ansible/templates/vrf/bird.j2 Uses the shared VRF script for BIRD VRF dataplane setup.
docs/platforms.md Marks BIRD VRF support in platform capability matrix.
docs/module/vrf.md Documents BIRD VRF support and VRF protocol support.
docs/module/routing.md Updates routing module support table to include BIRD static routes.
docs/module/routing-static.txt Adds BIRD to static routing support table.
docs/module/bgp.md Updates BIRD BGP feature support table.
docs/caveats.md Clarifies BIRD router-id behavior for BGP/OSPF instances.

Comment on lines +6 to +8
{% for l in netlab_interfaces if l.vrf is defined %}
interface -"{{ l.ifname }}";
{% endfor %}
Comment thread netsim/ansible/templates/vrf/frr.j2 Outdated
Comment on lines +33 to +38
{% if vrf_name and vrf_data.import|default([]) %}
if netlab_vrf_rt ~ [ {% for rt in vrf_data.import %}{{ rt_value(rt) }}{% if not loop.last %}, {% endif %}{% endfor %} ] then {
ospf_metric2 = 20;
accept;
}
{% endif %}
* Shebang in the top-level file
* No dependence on variables set in included files
* Renamed DP template to reflect what it does
ipspace added a commit that referenced this pull request Jun 24, 2026
The sysctl used in debian/trixie cannot figure out how to handle the
interfaces with dots (for example, ethX.Y). The workaround is to use
slashes in the sysctl parameter. Works on FRR and Bird.
# Move interfaces and loopbacks to vrfs
{% for i in interfaces if i.vrf is defined %}
sysctl -qw net.ipv6.conf.{{ i.ifname }}.keep_addr_on_down=1
sysctl -qw net/ipv6/conf/{{ i.ifname }}/keep_addr_on_down=1

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar issue in

sysctl -w net.ipv6.conf.{{ i.ifname }}.addr_gen_mode=3
?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not a problem (not saying it should not be fixed) because SVI interface names don't have dots in them.

@ipspace

ipspace commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Looks like we're almost there. I ran the whole set of integration tests, and (no surprise there) a few unexpected ones failed. When doing a large change, it's worth testing beyond the immediate feature you think you implemented.

  • bgp.session/04-default-originate is failing the VRF part because the VRF default route is missing.
  • VRF Lite with VLANs test (vlan/52) had a problem with sysctl on ethX.Y interfaces. Fixed.
  • Inter-VRF static routes work (routing/22-static-inter-vrf), but the VRF-to-default ones do not.

I'm perfectly OK disabling BGP default route functionality for the moment (obviously it never worked as it should), documenting a caveat on VRF-to-global static routes and merge this.

Thoughts?

ipspace added a commit that referenced this pull request Jun 24, 2026
@jbemmel

jbemmel commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator Author

Thoughts?

I saw your sysctl patch and found other places in the codebase where this might be a problem. It tends to be in areas of combinations of features that we currently don't test ( e.g. VRFs with VLANs and IPv6 )

I'm ok with documenting the tests that currently fail, and then fixing those in follow-up PRs (instead of trying to fix them all in this one big PR)

@ipspace ipspace merged commit 6f1399a into ipspace:dev Jun 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants