Skip to content

Commit

Permalink
[feature] Added support for modem manager interfaces #167
Browse files Browse the repository at this point in the history
Closes #167
  • Loading branch information
nemesifier committed Nov 13, 2020
1 parent b81cfd7 commit bf818a5
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Version 0.9.0 [unreleased]
This change is backward incompatible if the same type of configuration
was achieved using a workaround, in these cases the configuration
will have to be upgraded to use the new format.
- [feature] Added support for modem manager interfaces

Version 0.8.2 [2020-08-17]
--------------------------
Expand Down
78 changes: 78 additions & 0 deletions docs/source/backends/openwrt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ There are 4 main types of interfaces:
* **wireless interfaces**: must be of type ``wireless``
* **bridge interfaces**: must be of type ``bridge``
* **dialup interfaces**: must be of type ``dialup``
* **modem manager interfaces**: must be of type ``modem-manager``

Interface object extensions
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -1259,6 +1260,83 @@ Will be rendered as follows::
option password 'jf93nf82o023$'
option mtu '1448'

Modem Manager settings
----------------------

Interfaces of type ``modem-manager`` contain a few options
that are specific to modem-manager interfaces (2G, 3G, 4G, LTE, etc).

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

+--------------+---------+-----------------+--------------------------------------------+
| key name | type | default | allowed values |
+==============+=========+=================+============================================+
| ``proto`` | string | ``modemanager`` | ``modemanager`` |
+--------------+---------+-----------------+--------------------------------------------+
| ``apn`` | string | empty | APN, can be left blank |
+--------------+---------+-----------------+--------------------------------------------+
| ``pin`` | string | empty | PIN code, can be left blank |
+--------------+---------+-----------------+--------------------------------------------+
| ``device`` | string | empty | path to device (see note below) |
+--------------+---------+-----------------+--------------------------------------------+
| ``password`` | string | empty | password, can be left blank |
+--------------+---------+-----------------+--------------------------------------------+
| ``username`` | string | empty | username, can be left blank |
+--------------+---------+-----------------+--------------------------------------------+
| ``metric`` | integer | ``50`` | metric, can be left blank |
+--------------+---------+-----------------+--------------------------------------------+
| ``iptype`` | string | ``ipv4`` | One of ``ipv4``, ``ipv6``, ``ipv4v6`` |
+--------------+---------+-----------------+--------------------------------------------+
| ``lowpower`` | boolean | ``False`` | low power mode |
+--------------+---------+-----------------+--------------------------------------------+

.. note::
``device`` is a required property but can be left empty so that
the default value supplied by the hardware itself and already
present on the device can be left untouched by merging the
configuration generated with netjsonconfig
(instead of fully overwriting it).

Modem Manager interface example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following *configuration dictionary*:

.. code-block:: python
{
"interfaces": [
{
"type": "modem-manager",
"apn": "apn.operator.com",
"pin": "1234",
"device": "/sys/devices/platform/ahb/1b000000.usb/usb1/1-1",
"username": "user123",
"password": "pwd123456",
"metric": 50,
"lowpower": False,
"name": "modem0",
"mtu": 1500
}
]
}
Will be rendered as follows::

package network

config interface 'modem0'
option apn 'apn.operator.com'
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
option ifname 'wwan0'
option lowpower '0'
option metric '50'
option mtu '1500'
option password 'pwd123456'
option pincode '1234'
option proto 'modemmanager'
option username 'user123'

Radio settings
--------------

Expand Down
15 changes: 15 additions & 0 deletions netjsonconfig/backends/openwrt/converters/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from copy import deepcopy
from ipaddress import ip_address, ip_interface

from ..schema import schema
from .base import OpenWrtConverter


Expand Down Expand Up @@ -115,6 +116,10 @@ def __intermediate_interface(self, interface, uci_name):
if method:
interface = method(interface)
return interface

def _intermediate_modem_manager(self, interface):
interface['proto'] = 'modemmanager'
interface['pincode'] = interface.pop('pin', None)
return interface

_address_keys = ['address', 'mask', 'family', 'gateway']
Expand Down Expand Up @@ -291,6 +296,16 @@ def _netjson_dialup(self, interface):
interface['type'] = 'dialup'
return interface

_modem_manager_schema = schema['definitions']['modemmanager_interface']

def _netjson_modem_manager(self, interface):
del interface['proto']
interface['type'] = 'modem-manager'
interface['pin'] = interface.pop('pincode', None)
return self.type_cast(interface, schema=self._modem_manager_schema)

_netjson_modemmanager = _netjson_modem_manager

def __netjson_address(self, address, interface):
ip = ip_interface(address)
family = 'ipv{0}'.format(ip.version)
Expand Down
57 changes: 56 additions & 1 deletion netjsonconfig/backends/openwrt/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from .timezones import timezones

default_radio_driver = "mac80211"
_interface_properties = default_schema["definitions"]["interface_settings"][
"properties"
]


schema = merge_config(
Expand Down Expand Up @@ -158,6 +161,53 @@
{"$ref": "#/definitions/interface_settings"},
],
},
"modemmanager_interface": {
"type": "object",
"title": "Modem manager interface",
"required": ["name", "device"],
"properties": {
"name": _interface_properties["name"],
"mtu": _interface_properties["mtu"],
"autostart": _interface_properties["autostart"],
"disabled": _interface_properties["disabled"],
"type": {
"type": "string",
"enum": ["modem-manager"],
"default": "dialup",
"propertyOrder": 1,
},
"apn": {"type": "string", "title": "APN", "propertyOrder": 1.1},
"pin": {
"type": "string",
"title": "PIN code",
"maxLength": 4,
"propertyOrder": 1.2,
},
"device": {
"type": "string",
"description": "Leave blank to use the hardware default",
"propertyOrder": 1.3,
},
"username": {"type": "string", "propertyOrder": 1.4},
"password": {"type": "string", "propertyOrder": 1.5},
"metric": {"type": "integer", "default": 50, "propertyOrder": 1.6},
"iptype": {
"type": "string",
"title": "IP type",
"default": "ipv4",
"enum": ["ipv4", "ipv6", "ipv4v6"],
"options": {"enum_titles": ["IPv4", "IPv6", "IPv4 and IPv6"]},
"propertyOrder": 1.7,
},
"lowpower": {
"type": "boolean",
"title": "Low power mode",
"format": "checkbox",
"default": False,
"propertyOrder": 1.8,
},
},
},
"base_radio_settings": {
"properties": {
"driver": {
Expand Down Expand Up @@ -212,7 +262,12 @@
}
},
"interfaces": {
"items": {"oneOf": [{"$ref": "#/definitions/dialup_interface"}]}
"items": {
"oneOf": [
{"$ref": "#/definitions/dialup_interface"},
{"$ref": "#/definitions/modemmanager_interface"},
]
}
},
"routes": {
"items": {
Expand Down
52 changes: 52 additions & 0 deletions tests/openwrt/test_modemmanager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import unittest

from netjsonconfig import OpenWrt
from netjsonconfig.utils import _TabsMixin


class TestModemManager(unittest.TestCase, _TabsMixin):
maxDiff = None

_modemmanager_interface_netjson = {
"interfaces": [
{
"name": "wwan0",
"type": "modem-manager",
"apn": "apn.vodafone.com",
"pin": "1234",
"device": "/sys/devices/platform/ahb/1b000000.usb/usb1/1-1",
"username": "user123",
"password": "pwd123456",
"metric": 50,
"iptype": "ipv4v6",
"lowpower": False,
"mtu": 1500,
}
]
}

_modemmanager_interface_uci = """package network
config interface 'wwan0'
option apn 'apn.vodafone.com'
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
option ifname 'wwan0'
option iptype 'ipv4v6'
option lowpower '0'
option metric '50'
option mtu '1500'
option password 'pwd123456'
option pincode '1234'
option proto 'modemmanager'
option username 'user123'
"""

def test_render_modemmanager_interface(self):
result = OpenWrt(self._modemmanager_interface_netjson).render()
expected = self._tabs(self._modemmanager_interface_uci)
self.assertEqual(result, expected)

def test_parse_modemmanager_interface(self):
result = OpenWrt(native=self._modemmanager_interface_uci).config
expected = self._modemmanager_interface_netjson
self.assertDictEqual(result, expected)

0 comments on commit bf818a5

Please sign in to comment.