neutron-understack leaks dynamic VLAN segments on baremetal vif-detach

Open
#2,239 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
networking

Research direction

Start with neutron_understack_mech.UnderstackDriver, tracing _update_port_baremetal into _tenant_network_port_cleanup and comparing the top and bottom bound segments. Run neutron_understack/tests/scenarios/test_baremetal_binding.py::TestBaremetalBinding::test_vif_detach_releases_segment_and_reconciles, then remove its strict xfail when the dynamic VLAN segment is released and the test passes.

Written by the indexing model from the issue text.

Description

Summary

When a baremetal port is unbound via vif-detach (the binding:vif_type OTHER→UNBOUND transition on update_port_postcommit), the dynamically allocated VLAN segment is not released. Its VLAN id is never returned to the pool. The segment is only freed if the port is later deleted.

Component: python/neutron-understackneutron_understack_mech.UnderstackDriver
Severity: Medium — leads to VLAN id exhaustion in a fabric over time

Root cause

_update_port_baremetal_tenant_network_port_cleanup releases context.original_top_bound_segment:

segment_id = context.original_top_bound_segment["id"]
segment = utils.network_segment_by_id(segment_id)
if segment:
    utils.release_segment_if_unused(segment)

In the hierarchical binding, top_bound_segment is binding level 0 — the VXLAN segment, which is not dynamic. release_segment_if_unused only frees a segment when segment.is_dynamic and not ports_bound_to_segment(...), so it no-ops on the VXLAN segment. The dynamic VLAN segment lives at the bottom binding level (original_bottom_bound_segment) and is never targeted here.

This contradicts the comment in _delete_port_baremetal, which states the detach path "normally" releases the dynamic segment.

Impact

Every bind→unbind cycle that does not end in a port delete leaks one dynamic VLAN segment / VLAN id per (network, physnet). Over many provisioning cycles this exhausts the VLAN range for the physnet.

Steps to reproduce

Covered by neutron_understack/tests/scenarios/test_baremetal_binding.py::TestBaremetalBinding::test_vif_detach_releases_segment_and_reconciles (scenario BM-BIND-04), currently @pytest.mark.xfail(strict=True):

  1. Create a VXLAN tenant network + unbound baremetal port.
  2. vif-attach (update with binding:host_id + profile physical_network=physnet1) → binds a dynamic VLAN segment.
  3. vif-detach (clear binding:host_id + profile).
  4. Expected: the dynamic VLAN segment is released. Actual: it persists.

Fix direction

Release the dynamic (bottom) segment on the detach transition — target original_bottom_bound_segment / the dynamic VLAN segment rather than original_top_bound_segment. When fixed, remove the xfail marker on BM-BIND-04 (the strict xfail will otherwise start failing to remind you).

Dominant language
Python
Stars
13
Forks
12
Avg merge
1d 9h
Merged PRs (30d)
73

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rackerlabs/understack

All issues in rackerlabs/understack

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.