Skip to content

Commit 05fd14a

Browse files
committed
fix(ipam): Correct VLAN ID range calculation logic
Adjust VLAN ID range calculation to use half‑open intervals for consistency. Add a test to validate `_total_vlan_ids`. Fixes #20610
1 parent 4eff4d6 commit 05fd14a

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from django.db import migrations
2+
3+
4+
def populate_vlangroup_total_vlan_ids(apps, schema_editor):
5+
VLANGroup = apps.get_model('ipam', 'VLANGroup')
6+
db_alias = schema_editor.connection.alias
7+
8+
vlan_groups = VLANGroup.objects.using(db_alias).only('id', 'vid_ranges')
9+
for group in vlan_groups:
10+
total_vlan_ids = 0
11+
if group.vid_ranges:
12+
for r in group.vid_ranges:
13+
# Half-open [lo, hi): length is (hi - lo).
14+
if r is not None and r.lower is not None and r.upper is not None:
15+
total_vlan_ids += r.upper - r.lower
16+
group._total_vlan_ids = total_vlan_ids
17+
VLANGroup.objects.using(db_alias).bulk_update(vlan_groups, ['_total_vlan_ids'], batch_size=100)
18+
19+
20+
class Migration(migrations.Migration):
21+
dependencies = [
22+
('ipam', '0082_add_prefix_network_containment_indexes'),
23+
]
24+
25+
operations = [
26+
migrations.RunPython(populate_vlangroup_total_vlan_ids, migrations.RunPython.noop),
27+
]

netbox/ipam/models/vlans.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ def clean(self):
132132
def save(self, *args, **kwargs):
133133
self._total_vlan_ids = 0
134134
for vid_range in self.vid_ranges:
135-
self._total_vlan_ids += vid_range.upper - vid_range.lower + 1
135+
# VID range is inclusive on lower-bound, exclusive on upper-bound
136+
self._total_vlan_ids += vid_range.upper - vid_range.lower
136137

137138
super().save(*args, **kwargs)
138139

netbox/ipam/tests/test_models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ def test_overlapping_vlan(self):
661661
vlangroup.full_clean()
662662
vlangroup.save()
663663

664+
def test_total_vlan_ids(self):
665+
vlangroup = VLANGroup.objects.first()
666+
self.assertEqual(vlangroup._total_vlan_ids, 100)
667+
664668

665669
class TestVLAN(TestCase):
666670

0 commit comments

Comments
 (0)