Skip to content

Commit 858aa19

Browse files
pandafynemesifier
andauthored
[fix] Fixed modem-manager configuration for OpenWrt 21 #228
- Fixed modem-manager configuration for OpenWrt 21 - Added missing signalrate option for modemmanager interface Closes #228 Co-authored-by: Federico Capoano <f.capoano@openwisp.io>
1 parent 81887fd commit 858aa19

5 files changed

Lines changed: 126 additions & 40 deletions

File tree

docs/source/backends/openwrt.rst

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,27 +1713,29 @@ that are specific to modem-manager interfaces (2G, 3G, 4G, LTE, etc).
17131713

17141714
These are the ``OpenWrt`` backend NetJSON extensions for Modem Manager interfaces:
17151715

1716-
+--------------+---------+-----------------+--------------------------------------------+
1717-
| key name | type | default | allowed values |
1718-
+==============+=========+=================+============================================+
1719-
| ``proto`` | string | ``modemanager`` | ``modemanager`` |
1720-
+--------------+---------+-----------------+--------------------------------------------+
1721-
| ``apn`` | string | empty | APN, can be left blank |
1722-
+--------------+---------+-----------------+--------------------------------------------+
1723-
| ``pin`` | string | empty | PIN code, can be left blank |
1724-
+--------------+---------+-----------------+--------------------------------------------+
1725-
| ``device`` | string | empty | path to device (see note below) |
1726-
+--------------+---------+-----------------+--------------------------------------------+
1727-
| ``password`` | string | empty | password, can be left blank |
1728-
+--------------+---------+-----------------+--------------------------------------------+
1729-
| ``username`` | string | empty | username, can be left blank |
1730-
+--------------+---------+-----------------+--------------------------------------------+
1731-
| ``metric`` | integer | ``50`` | metric, can be left blank |
1732-
+--------------+---------+-----------------+--------------------------------------------+
1733-
| ``iptype`` | string | ``ipv4`` | One of ``ipv4``, ``ipv6``, ``ipv4v6`` |
1734-
+--------------+---------+-----------------+--------------------------------------------+
1735-
| ``lowpower`` | boolean | ``False`` | low power mode |
1736-
+--------------+---------+-----------------+--------------------------------------------+
1716+
+----------------+---------+-----------------+--------------------------------------------+
1717+
| key name | type | default | allowed values |
1718+
+================+=========+=================+============================================+
1719+
| ``proto`` | string | ``modemanager`` | ``modemanager`` |
1720+
+----------------+---------+-----------------+--------------------------------------------+
1721+
| ``apn`` | string | empty | APN, can be left blank |
1722+
+----------------+---------+-----------------+--------------------------------------------+
1723+
| ``pin`` | string | empty | PIN code, can be left blank |
1724+
+----------------+---------+-----------------+--------------------------------------------+
1725+
| ``device`` | string | empty | path to device (see note below) |
1726+
+----------------+---------+-----------------+--------------------------------------------+
1727+
| ``password`` | string | empty | password, can be left blank |
1728+
+----------------+---------+-----------------+--------------------------------------------+
1729+
| ``username`` | string | empty | username, can be left blank |
1730+
+----------------+---------+-----------------+--------------------------------------------+
1731+
| ``metric`` | integer | ``50`` | metric, can be left blank |
1732+
+----------------+---------+-----------------+--------------------------------------------+
1733+
| ``iptype`` | string | ``ipv4`` | One of ``ipv4``, ``ipv6``, ``ipv4v6`` |
1734+
+----------------+---------+-----------------+--------------------------------------------+
1735+
| ``lowpower`` | boolean | ``False`` | low power mode |
1736+
+----------------+---------+-----------------+--------------------------------------------+
1737+
| ``signalrate`` | integer | | singal refresh rate in seconds |
1738+
+----------------+---------+-----------------+--------------------------------------------+
17371739

17381740
.. note::
17391741
``device`` is a required property but can be left empty so that
@@ -1761,7 +1763,8 @@ The following *configuration dictionary*:
17611763
"metric": 50,
17621764
"lowpower": False,
17631765
"name": "modem0",
1764-
"mtu": 1500
1766+
"mtu": 1500,
1767+
"signalrate": 5,
17651768
}
17661769
]
17671770
}
@@ -1770,16 +1773,19 @@ Will be rendered as follows::
17701773

17711774
package network
17721775

1776+
config device 'device_modem0'
1777+
option mtu '1500'
1778+
option name 'modem0'
1779+
17731780
config interface 'modem0'
17741781
option apn 'apn.operator.com'
17751782
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
1776-
option ifname 'wwan0'
17771783
option lowpower '0'
17781784
option metric '50'
1779-
option mtu '1500'
17801785
option password 'pwd123456'
17811786
option pincode '1234'
17821787
option proto 'modemmanager'
1788+
option signalrate '5'
17831789
option username 'user123'
17841790

17851791
Radio settings

netjsonconfig/backends/openwrt/converters/interfaces.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class Interfaces(OpenWrtConverter):
3232
}
3333
_device_config = {}
3434
_custom_protocols = ['ppp']
35-
_interface_dsa_types = ['loopback', 'ethernet', 'bridge']
35+
_proto_dsa_conflict = ['modemmanager', 'modem-manager']
36+
_interface_dsa_types = ['loopback', 'ethernet', 'bridge'] + _proto_dsa_conflict
3637

3738
def __set_dsa_interface(self, interface):
3839
"""
@@ -216,7 +217,8 @@ def __intermediate_device(self, interface):
216217
}
217218
)
218219
# Add 'device' option in related interface configuration
219-
interface['device'] = device['name']
220+
if not interface.get('device', None):
221+
interface['device'] = device['name']
220222

221223
if interface['type'] != 'bridge':
222224
# A non-bridge interface that contains L2 options.
@@ -420,20 +422,33 @@ def __netjson_interface(self, interface):
420422
interface = method(interface)
421423
return interface
422424

425+
def __get_device_config_for_interface(self, interface):
426+
device = interface.get('device')
427+
name = interface.get('name')
428+
if not name and interface.get('proto') in self._proto_dsa_conflict:
429+
name = interface.get('.name')
430+
device_config = self._device_config.get(device, self._device_config.get(name))
431+
if not device_config:
432+
return device_config
433+
if interface.get('proto') in self._proto_dsa_conflict:
434+
del device_config['type']
435+
# ifname has been renamed to device in OpenWrt 21.02
436+
if device_config.get('type') == 'bridge':
437+
interface['ifname'] = 'br-{}'.format(interface.pop('device'))
438+
elif interface.get('proto') not in self._proto_dsa_conflict:
439+
interface['ifname'] = interface.pop('device')
440+
return device_config
441+
423442
def __netjson_dsa_interface(self, interface):
424443
if self.__is_device_config(interface) or interface.get('bridge_21', None):
425444
self.__netjson_device(interface)
426445
else:
427-
device = interface.get('device')
428-
# adding device property to interface
429-
if self._device_config.get(device, None):
430-
device_config = self._device_config[device]
431-
# ifname has been renamed to device in OpenWrt 21.02
432-
if device_config.get('type') == 'bridge':
433-
interface['ifname'] = 'br-{}'.format(interface.pop('device'))
434-
else:
435-
interface['ifname'] = interface.pop('device')
436-
if device_config.pop('bridge_21', None):
446+
device_config = self.__get_device_config_for_interface(interface)
447+
if device_config:
448+
if (
449+
device_config.pop('bridge_21', None)
450+
or interface.get('proto') in self._proto_dsa_conflict
451+
):
437452
for option in device_config:
438453
if 'name' in option:
439454
continue
@@ -483,7 +498,8 @@ def __netjson_device(self, interface):
483498
interface[option] = value == '1'
484499
except KeyError:
485500
continue
486-
self._device_config[interface['name']] = interface
501+
name = interface.get('name')
502+
self._device_config[name] = interface
487503

488504
def __netjson_type(self, interface):
489505
if 'type' in interface and interface['type'] == 'bridge':

netjsonconfig/backends/openwrt/schema.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,12 @@
367367
"default": False,
368368
"propertyOrder": 1.8,
369369
},
370+
"signalrate": {
371+
"type": "integer",
372+
"title": "Signal refresh rate",
373+
"propertyOrder": 1.9,
374+
"description": "singal refresh rate in seconds",
375+
},
370376
}
371377
},
372378
{"$ref": "#/definitions/base_interface_settings"},
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,27 @@ class TestModemManager(unittest.TestCase, _TabsMixin):
2121
"iptype": "ipv4v6",
2222
"lowpower": False,
2323
"mtu": 1500,
24+
"signalrate": 5,
2425
}
2526
]
2627
}
2728

2829
_modemmanager_interface_uci = """package network
2930
31+
config device 'device_wwan0'
32+
option mtu '1500'
33+
option name 'wwan0'
34+
3035
config interface 'wwan0'
3136
option apn 'apn.vodafone.com'
3237
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
33-
option ifname 'wwan0'
3438
option iptype 'ipv4v6'
3539
option lowpower '0'
3640
option metric '50'
37-
option mtu '1500'
3841
option password 'pwd123456'
3942
option pincode '1234'
4043
option proto 'modemmanager'
44+
option signalrate '5'
4145
option username 'user123'
4246
"""
4347

@@ -49,4 +53,4 @@ def test_render_modemmanager_interface(self):
4953
def test_parse_modemmanager_interface(self):
5054
result = OpenWrt(native=self._modemmanager_interface_uci).config
5155
expected = self._modemmanager_interface_netjson
52-
self.assertDictEqual(result, expected)
56+
self.assertEqual(result, expected)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import unittest
2+
3+
from netjsonconfig import OpenWrt
4+
from netjsonconfig.utils import _TabsMixin
5+
6+
7+
class TestModemManager(unittest.TestCase, _TabsMixin):
8+
maxDiff = None
9+
10+
_modemmanager_interface_netjson = {
11+
"interfaces": [
12+
{
13+
"name": "wwan0",
14+
"type": "modem-manager",
15+
"apn": "apn.vodafone.com",
16+
"pin": "1234",
17+
"device": "/sys/devices/platform/ahb/1b000000.usb/usb1/1-1",
18+
"username": "user123",
19+
"password": "pwd123456",
20+
"metric": 50,
21+
"iptype": "ipv4v6",
22+
"lowpower": False,
23+
"mtu": 1500,
24+
"signalrate": 5,
25+
}
26+
]
27+
}
28+
29+
_modemmanager_interface_uci = """package network
30+
31+
config interface 'wwan0'
32+
option apn 'apn.vodafone.com'
33+
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
34+
option ifname 'wwan0'
35+
option iptype 'ipv4v6'
36+
option lowpower '0'
37+
option metric '50'
38+
option mtu '1500'
39+
option password 'pwd123456'
40+
option pincode '1234'
41+
option proto 'modemmanager'
42+
option signalrate '5'
43+
option username 'user123'
44+
"""
45+
46+
def test_render_modemmanager_interface(self):
47+
result = OpenWrt(self._modemmanager_interface_netjson, dsa=False).render()
48+
expected = self._tabs(self._modemmanager_interface_uci)
49+
self.assertEqual(result, expected)
50+
51+
def test_parse_modemmanager_interface(self):
52+
result = OpenWrt(native=self._modemmanager_interface_uci, dsa=False).config
53+
expected = self._modemmanager_interface_netjson
54+
self.assertDictEqual(result, expected)

0 commit comments

Comments
 (0)