diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 636a4b6be..eaaee97e7 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -1689,6 +1689,10 @@ class MACAddressFilterSet(NetBoxModelFilterSet): class CommonInterfaceFilterSet(django_filters.FilterSet): + mode = django_filters.MultipleChoiceFilter( + choices=InterfaceModeChoices, + label=_('802.1Q Mode') + ) vlan_id = django_filters.CharFilter( method='filter_vlan_id', label=_('Assigned VLAN') diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 4dbceb4f5..8328f502f 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -1332,6 +1332,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): FieldSet('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only', name=_('Attributes')), FieldSet('vrf_id', 'l2vpn_id', 'mac_address', 'wwn', name=_('Addressing')), FieldSet('poe_mode', 'poe_type', name=_('PoE')), + FieldSet('mode', name=_('802.1Q Switching')), FieldSet('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power', name=_('Wireless')), FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')), FieldSet( @@ -1403,6 +1404,11 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): required=False, label=_('PoE type') ) + mode = forms.MultipleChoiceField( + choices=InterfaceModeChoices, + required=False, + label=_('802.1Q mode') + ) rf_role = forms.MultipleChoiceField( choices=WirelessRoleChoices, required=False, diff --git a/netbox/dcim/tests/test_filtersets.py b/netbox/dcim/tests/test_filtersets.py index a938e14c0..727389ef1 100644 --- a/netbox/dcim/tests/test_filtersets.py +++ b/netbox/dcim/tests/test_filtersets.py @@ -4153,7 +4153,7 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) def test_mode(self): - params = {'mode': InterfaceModeChoices.MODE_ACCESS} + params = {'mode': [InterfaceModeChoices.MODE_ACCESS]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_description(self): diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py index 2b2d821fe..87803621a 100644 --- a/netbox/virtualization/forms/filtersets.py +++ b/netbox/virtualization/forms/filtersets.py @@ -1,6 +1,7 @@ from django import forms from django.utils.translation import gettext_lazy as _ +from dcim.choices import * from dcim.models import Device, DeviceRole, Location, Platform, Region, Site, SiteGroup from extras.forms import LocalConfigContextFilterForm from extras.models import ConfigTemplate @@ -200,7 +201,9 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('cluster_id', 'virtual_machine_id', name=_('Virtual Machine')), - FieldSet('enabled', 'mac_address', 'vrf_id', 'l2vpn_id', name=_('Attributes')), + FieldSet('enabled', name=_('Attributes')), + FieldSet('vrf_id', 'l2vpn_id', 'mac_address', name=_('Addressing')), + FieldSet('mode', name=_('802.1Q Switching')), ) selector_fields = ('filter_id', 'q', 'virtual_machine_id') cluster_id = DynamicModelMultipleChoiceField( @@ -237,6 +240,11 @@ class VMInterfaceFilterForm(NetBoxModelFilterSetForm): required=False, label=_('L2VPN') ) + mode = forms.MultipleChoiceField( + choices=InterfaceModeChoices, + required=False, + label=_('802.1Q mode') + ) tag = TagFilterField(model) diff --git a/netbox/virtualization/tests/test_filtersets.py b/netbox/virtualization/tests/test_filtersets.py index eef5d6b52..d53ca78de 100644 --- a/netbox/virtualization/tests/test_filtersets.py +++ b/netbox/virtualization/tests/test_filtersets.py @@ -605,6 +605,7 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): mtu=100, vrf=vrfs[0], description='foobar1', + mode=InterfaceModeChoices.MODE_ACCESS, vlan_translation_policy=vlan_translation_policies[0], ), VMInterface( @@ -614,6 +615,7 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): mtu=200, vrf=vrfs[1], description='foobar2', + mode=InterfaceModeChoices.MODE_TAGGED, vlan_translation_policy=vlan_translation_policies[0], ), VMInterface( @@ -699,6 +701,10 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests): params = {'description': ['foobar1', 'foobar2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_mode(self): + params = {'mode': [InterfaceModeChoices.MODE_ACCESS]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + def test_vlan(self): vlan = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE).first() params = {'vlan_id': vlan.pk}