summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-06-07 14:04:36 +0200
committerChristian Poessinger <christian@poessinger.com>2020-06-07 14:04:36 +0200
commit1c7d7cbd3963428888068af679946e6329567451 (patch)
treeedd24f2122ed0f44a8c9aa1c4814ae76ae524f7a /src
parent1fc4aadb5d87643d6e64805b19a5a9e7671737ba (diff)
downloadvyos-1x-1c7d7cbd3963428888068af679946e6329567451.tar.gz
vyos-1x-1c7d7cbd3963428888068af679946e6329567451.zip
wwan: T2529: migrate device from ttyUSB to usbXbY.YpZ.Z
During testing it was discovered that there is a well known problem (we had for ethernet interfaces) also in the serial port world. They will be enumerated and mapped to /dev/ttyUSBxxx differently from boot to boot. This is especially painful on my development APU4 board which also has a Sierra Wireless MC7710 LTE module installed. The serial port will toggle between ttyUSB2 and ttyUSB5 depending on the amount of serial port extenders attached (FT4232H). The shipped udev rule (/usr/lib/udev/rules.d/60-serial.rules) partly solves this by enumerating the devices into /dev/serial/by-id folder with their name and serial number - it's a very good idea but I've found that not all of the FT4232H dongles have a serial number programmed - this leads to the situation that when you plug in two cables with both having serial number 0 - only one device symlink will appear - the previous one is always overwritten by the latter one. Derive /usr/lib/udev/rules.d/60-serial.rules and create a /dev/serial/by-bus directory and group devices by attached USB root port. vyos@vyos:~$ find /dev/serial/by-bus/ -name usb* -exec basename {} \; | sort usb0b1.3p1.0 usb0b1.3p1.2 usb0b1.3p1.3 usb0b2.4p1.0 usb0b2.4p1.1 usb0b2.4p1.2 usb0b2.4p1.3 So we have USB root 0 with bus 1.3 and port 1.0. The enumeration is constant accross reboots.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/interfaces-wirelessmodem.py32
-rwxr-xr-xsrc/migration-scripts/interfaces/10-to-1155
2 files changed, 81 insertions, 6 deletions
diff --git a/src/conf_mode/interfaces-wirelessmodem.py b/src/conf_mode/interfaces-wirelessmodem.py
index a13c70990..f16457a7f 100755
--- a/src/conf_mode/interfaces-wirelessmodem.py
+++ b/src/conf_mode/interfaces-wirelessmodem.py
@@ -16,9 +16,10 @@
import os
-from sys import exit
from copy import deepcopy
+from fnmatch import fnmatch
from netifaces import interfaces
+from sys import exit
from vyos.config import Config
from vyos.ifconfig import BridgeIf, Section
@@ -36,7 +37,7 @@ default_config_data = {
'chat_script': '',
'deleted': False,
'description': '',
- 'device': 'ttyUSB0',
+ 'device': '',
'disable': False,
'disable_link_detect': 1,
'on_demand': False,
@@ -56,6 +57,16 @@ def check_kmod():
if call(f'modprobe {module}') != 0:
raise ConfigError(f'Loading Kernel module {module} failed')
+def find_device_file(device):
+ """ Recurively search /dev for the given device file and return its full path.
+ If no device file was found 'None' is returned """
+ for root, dirs, files in os.walk('/dev'):
+ for basename in files:
+ if fnmatch(basename, device):
+ return os.path.join(root, basename)
+
+ return None
+
def get_config():
wwan = deepcopy(default_config_data)
conf = Config()
@@ -93,7 +104,13 @@ def get_config():
# System device name
if conf.exists(['device']):
- wwan['device'] = conf.return_value(['device'])
+ tmp = conf.return_value(['device'])
+ wwan['device'] = find_device_file(tmp)
+ # If device file was not found in /dev we will just re-use
+ # the plain device name, thus we can trigger the exception
+ # in verify() as it's a non existent file
+ if wwan['device'] == None:
+ wwan['device'] = tmp
# disable interface
if conf.exists('disable'):
@@ -131,7 +148,10 @@ def verify(wwan):
return None
if not wwan['apn']:
- raise ConfigError(f"APN for {wwan['intf']} not configured")
+ raise ConfigError('No APN configured for "{intf}"'.format(**wwan))
+
+ if not wwan['device']:
+ raise ConfigError('Physical "device" must be configured')
# we can not use isfile() here as Linux device files are no regular files
# thus the check will return False
@@ -169,7 +189,7 @@ def generate(wwan):
script_wwan_ip_up, script_wwan_ip_down]
# Always hang-up WWAN connection prior generating new configuration file
- cmd(f'systemctl stop ppp@{intf}.service')
+ call(f'systemctl stop ppp@{intf}.service')
if wwan['deleted']:
# Delete PPP configuration files
@@ -205,9 +225,9 @@ def apply(wwan):
if not wwan['disable']:
# "dial" WWAN connection
intf = wwan['intf']
- cmd(f'systemctl start ppp@{intf}.service')
# make logfile owned by root / vyattacfg
chown(wwan['logfile'], 'root', 'vyattacfg')
+ call(f'systemctl start ppp@{intf}.service')
# re-add ourselves to any bridge we might have fallen out of
# FIXME: wwan isn't under vyos.ifconfig so we can't call
diff --git a/src/migration-scripts/interfaces/10-to-11 b/src/migration-scripts/interfaces/10-to-11
new file mode 100755
index 000000000..6b8e49ed9
--- /dev/null
+++ b/src/migration-scripts/interfaces/10-to-11
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# rename WWAN (wirelessmodem) serial interface from non persistent ttyUSB2 to
+# a bus like name, e.g. "usb0b1.3p1.3"
+
+import os
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+ base = ['interfaces', 'wirelessmodem']
+ if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+ for wwan in config.list_nodes(base):
+ if config.exists(base + [wwan, 'device']):
+ device = config.return_value(base + [wwan, 'device'])
+
+ for root, dirs, files in os.walk('/dev/serial/by-bus'):
+ for file in files:
+ device_file = os.path.realpath(os.path.join(root, file))
+ if os.path.basename(device_file) == device:
+ config.set(base + [wwan, 'device'], value=file, replace=True)
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)