Skip to content

Commit

Permalink
[req-changes] Allowed network interface to use software VLAN switch
Browse files Browse the repository at this point in the history
  • Loading branch information
pandafy committed Apr 6, 2023
1 parent cbda77f commit f0d3c13
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 7 deletions.
36 changes: 29 additions & 7 deletions netjsonconfig/backends/openwrt/converters/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Interfaces(OpenWrtConverter):
def __init__(self, backend):
super().__init__(backend)
self._device_config = {}
self._bridge_vlan_config_uci = []

def __set_dsa_interface(self, interface):
"""
Expand All @@ -54,6 +55,8 @@ def __set_dsa_interface(self, interface):
self.dsa
and interface.get('proto', None) not in self._custom_protocols
and interface.get('type', None) in self._interface_dsa_types
and interface.get('ifname', interface.get('device'))
not in self._bridge_vlan_config_uci
)

def to_intermediate_loop(self, block, result, index=None):
Expand Down Expand Up @@ -191,6 +194,18 @@ def __intermediate_interface(self, interface, uci_name):
method = getattr(self, f'_intermediate_{type_}', None)
if method:
interface = method(interface)
self._check_bridge_vlan(interface)
return interface

def _check_bridge_vlan(self, interface):
if self.dsa:
if (
'.' in interface.get('ifname', '')
and interface['ifname'] in self._bridge_vlan_config_uci
):
# Cleans L2 options from the interface
self._add_l2_options({}, interface)
interface['device'] = interface.pop('ifname')
return interface

def _intermediate_modem_manager(self, interface):
Expand Down Expand Up @@ -255,6 +270,7 @@ def __intermediate_vlan(self, uci_name, interface, vlan):
uci_vlan['ports'].append(
'{ifname}{tagging}'.format(ifname=port['ifname'], tagging=tagging)
)
self._bridge_vlan_config_uci.append(uci_vlan_interface['device'])
return uci_vlan, uci_vlan_interface

def __intermediate_device(self, interface):
Expand Down Expand Up @@ -332,6 +348,7 @@ def __intermediate_device(self, interface):
if device['ports'] == []:
device['bridge_empty'] = True
del device['ports']
self._device_config_uci[device['name']] = device
return self.sorted_dict(device)

@staticmethod
Expand Down Expand Up @@ -527,7 +544,6 @@ def __get_device_config_for_interface(self, interface):
if not device_config:
return device_config
if interface.get('type') == 'bridge-vlan':
print('returning bridge-vlan')
return device_config
if interface.get('proto') in self._proto_dsa_conflict:
del device_config['type']
Expand All @@ -541,12 +557,9 @@ def __get_device_config_for_interface(self, interface):
def __update_interface_device_config(self, interface, device_config):
if interface.get('type') == 'bridge-vlan':
return self.__netjson_vlan(interface, device_config)
if '.' in interface.get('ifname', ''):
_, _, vlan_id = interface['ifname'].rpartition('.')
if device_config.get('vlan_filtering', []):
for vlan in device_config['vlan_filtering']:
if vlan['vlan'] == int(vlan_id):
return
interface = self._handle_bridge_vlan(interface, device_config)
if not interface:
return
if (
device_config.pop('bridge_21', None)
or interface.get('proto') in self._proto_dsa_conflict
Expand All @@ -571,6 +584,15 @@ def __update_interface_device_config(self, interface, device_config):
interface['ifname'] = ''.join(interface['ifname'].split('.')[:-1])
return interface

def _handle_bridge_vlan(self, interface, device_config):
if '.' in interface.get('ifname', ''):
_, _, vlan_id = interface['ifname'].rpartition('.')
if device_config.get('vlan_filtering', []):
for vlan in device_config['vlan_filtering']:
if vlan['vlan'] == int(vlan_id):
return
return interface

def __netjson_dsa_interface(self, interface):
if self.__is_device_config(interface) or interface.get('bridge_21', None):
self.__netjson_device(interface)
Expand Down
78 changes: 78 additions & 0 deletions tests/openwrt/test_interfaces_dsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,84 @@ def test_parse_bridge_vlan_filtering(self):
o = OpenWrt(native=self._vlan_filtering_bridge_uci)
self.assertEqual(o.config, self._vlan_filtering_bridge_netjson)

_vlan_filtering_bridge_override_netjson = {
"interfaces": [
{
"type": "bridge",
"bridge_members": ["lan1", "lan2", "lan3"],
"name": "br-lan",
"vlan_filtering": [
{
"vlan": 1,
"ports": [
{"ifname": "lan1"},
{"ifname": "lan2", "tagging": "t"},
{"ifname": "lan3", "tagging": "u"},
],
}
],
},
{
"type": "ethernet",
"name": "br-lan.1",
"mtu": 1500,
"mac": "61:4A:A0:D7:3F:0E",
"addresses": [
{
"proto": "static",
"family": "ipv4",
"address": "192.168.2.1",
"mask": 24,
}
],
},
]
}
_vlan_filtering_bridge_override_uci = """package network
config device 'device_br_lan'
option name 'br-lan'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
option type 'bridge'
option vlan_filtering '1'
config bridge-vlan 'vlan_br_lan_1'
option device 'br-lan'
list ports 'lan1'
list ports 'lan2:t'
list ports 'lan3:u'
option vlan '1'
config interface 'vlan_br_lan_1'
option device 'br-lan.1'
option proto 'none'
config interface 'br_lan'
option device 'br-lan'
option proto 'none'
config interface 'br_lan_1'
option device 'br-lan.1'
option ipaddr '192.168.2.1'
option netmask '255.255.255.0'
option proto 'static'
"""

def test_render_bridge_vlan_filtering_override_interface(self):
o = OpenWrt(self._vlan_filtering_bridge_override_netjson)
self.assertEqual(
self._tabs(self._vlan_filtering_bridge_override_uci), o.render()
)

def test_parse_bridge_vlan_filtering_override_interface(self):
o = OpenWrt(native=self._vlan_filtering_bridge_override_uci)
expected = deepcopy(self._vlan_filtering_bridge_override_netjson)
del expected['interfaces'][1]['mtu']
del expected['interfaces'][1]['mac']
self.assertEqual(o.config, expected)

def test_render_dns(self):
o = OpenWrt(
{
Expand Down

0 comments on commit f0d3c13

Please sign in to comment.