feat: Implement vrf router with auto-allocating evpn_vni attribute#2109
feat: Implement vrf router with auto-allocating evpn_vni attribute#2109stevekeay wants to merge 2 commits into
Conversation
This was added because a test case was registering multiple conflicting options. I am removing because it is no longer required.
| "allow_post": True, | ||
| "allow_put": False, | ||
| "convert_to": converters.convert_to_int_if_not_none, | ||
| "default": 0, |
There was a problem hiding this comment.
should that be 0 or ATTR_NOT_SPECIFIED ? I am concerned if having it as 0 will not prevent non-admin users from creating routers
There was a problem hiding this comment.
I am a bit hazy on the logic for collections, but I think we want non-admin users to create routers, we just don't want them to be able to choose a VNI.
A value of zero is explicitly interpreted as "please auto-assign" in the assignment hook, so the value that actually gets persisted should be non-zero.
Technically it may be more correct to use the sentinel value but I thought this was going to the DB layer, I'm not sure what the best answer is.
There was a problem hiding this comment.
The python/neutron-understack/neutron_understack/conf/policies/evpn.py has:
policy.DocumentedRuleDefault(
name="create_router:evpn_vni",
check_str=base.ADMIN,
scope_types=["project"],
description="Specify ``evpn_vni`` attribute when creating a router",
operations=ACTION_POST,
...
which will translate to "create_router:evpn_vni": "rule:admin_only" inside a default policy (similarly to stock one and if the user provides any value of the attribute in the request, it will match the rule, effectively requiring admin privileges, so we may need to adjust base.ADMIN to sth else.
There was a problem hiding this comment.
These are the results of my manual testing:
If a non-admin user provides a valid VNI, it fails:
ubuntu@devstack-ovn:~$ OS_CLOUD=devstack-alt-member openstack router create --flavor understack-vrf-demo --extra-property type=int,name=evpn_vni,value=10099 steve-test-b
ForbiddenException: 403: Client Error for url: http://192.168.99.10/networking/v2.0/routers, ((rule:create_router and rule:create_router:flavor_id) and rule:create_router:evpn_vni) is disallowed by policy
(The above succeeds when performed as an admin user.)
If a non-admin user provides a VNI of zero, it still fails:
ubuntu@devstack-ovn:~$ OS_CLOUD=devstack-alt-member openstack router create --flavor understack-vrf-demo --extra-property type=int,name=evpn_vni,value=0 steve-test-b
ForbiddenException: 403: Client Error for url: http://192.168.99.10/networking/v2.0/routers, ((rule:create_router and rule:create_router:flavor_id) and rule:create_router:evpn_vni) is disallowed by policy
(The above succeeds when performed as an admin user.)
If any user created a router but does not include a VNI, the call succeeds and a VNI is allocated from the configured range:
ubuntu@devstack-ovn:~$ OS_CLOUD=devstack-alt-member openstack router create --flavor understack-vrf-demo steve-test-c
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
| admin_state_up | UP |
| availability_zone_hints | |
| availability_zones | |
| created_at | 2026-07-08T13:22:11Z |
| description | |
| enable_default_route_bfd | False |
| enable_default_route_ecmp | False |
| enable_ndp_proxy | None |
| enable_snat | True |
| evpn_vni | 10007 |
| external_gateway_info | null |
| external_gateways | [] |
| flavor_id | 00035dcb-968b-4be6-9057-026f4069ee1a |
| id | 92df1c90-78c4-4412-8eb4-e1c94288a4ef |
| name | steve-test-c |
| project_id | fa2408453dfa4a658fca0aff301b94ba |
| revision_number | 1 |
| routes | |
| status | ACTIVE |
| tags | |
| updated_at | 2026-07-08T13:22:11Z |
+---------------------------+--------------------------------------+
There was a problem hiding this comment.
So I had to walk the code and I still was confused. So I had to have Claude walk it with me to understand and run it in a little repl to test. It's the way for the non-default value (which the default value is 0). So the behavior is actually correct as Steve coded it. But holy cow that feels like a foot gun.
There was a problem hiding this comment.
Cool cool - I misunderstood the requirements and thought we want to allow users to select the VNI, but after thinking about it, it would be bad idea. Thanks for testing
cardoe
left a comment
There was a problem hiding this comment.
I think it would be good to get some operator docs.
This creates a standalone plugin for 2026.1 to provide the vrf router behaviour we need, including auto-assignment of VNIs from a configured range.
Some of this overlaps work in progress upstream. I have intentionally mirrored the --evpn-vni API surface of the evpn plugin. We are not using any of the actual evpn plugin code but (in theory) once it gains feature parity, we should be able to switch over to it without affecting our users.
This got fairly big. I was thinking it might be cleaner to break it out into a separate package (that we would install separately via pip install in the container) but I wanted to solicit opinions from the team.
To use this:
service_pluginsremovingevpnand addingunderstack_vni[understack_vni]section likevni_ranges = 10000:19999