Page MenuHomeVyOS Platform

Multi-port USB serial adapters create symlink collisions in console-server
In progress, NormalPublic

Description

Summary

Multi-port USB serial adapters (e.g., MosChip MCS7840, FTDI FT4232H) experience symlink collisions in /dev/serial/by-bus/ because all ports on the same USB device create identical symlink names. This prevents access to ports beyond the last-enumerated port via the console-server.

Current Behavior

When a multi-port USB serial adapter is connected:

  • Device: MosChip MCS7840 (4 ports per chip)
  • USB Path: 1-1.4.1
  • Expected: 4 accessible ports
  • Actual: Only 1 symlink created: usb0b1.4.1p1.0
  • Result: Only the last port (port 3) is accessible; ports 0-2 are unreachable

The issue occurs in /etc/udev/rules.d/90-vyos-serial.rules where both conditions create the same symlink name:

udev
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="",   PROGRAM="/bin/sh -c 'echo $env{ID_PATH} | cut -d- -f3- | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", PROGRAM="/bin/sh -c 'echo $env{ID_PATH} | cut -d- -f3- | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"

The .ID_PORT variable is captured but never used in the symlink name.

Expected Behavior

Each port should have a unique symlink in /dev/serial/by-bus/:

  • usb0b1.4.1p1.0_port0 → ttyUSB7
  • usb0b1.4.1p1.0_port1 → ttyUSB8
  • usb0b1.4.1p1.0_port2 → ttyUSB9
  • usb0b1.4.1p1.0_port3 → ttyUSB10

Proposed Fix

Modify the second rule in 90-vyos-serial.rules to append the port number when .ID_PORT is set:

Current (line 19):

udev
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", PROGRAM="/bin/sh -c 'echo $env{ID_PATH} | cut -d- -f3- | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"

Proposed:

udev
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", PROGRAM="/bin/sh -c 'echo $env{ID_PATH} | cut -d- -f3- | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/ | sed \"s/$/_port$env{.ID_PORT}/\"'", SYMLINK+="serial/by-bus/$result"

This change:

  1. Appends _port and the port number to the symlink name
  2. Only affects multi-port devices (when .ID_PORT is set)
  3. Maintains backward compatibility for single-port devices
  4. Uses underscore _ (not dash -) to match VyOS console-server naming expectations

Testing Results

Tested successfully on VyOS Stream 2025.11 with:

Hardware:

  • MosChip MCS7840 (8-port adapter with 2x 4-port chips)
  • FTDI FT4232H (4-port adapter)
  • Multiple single-port USB serial adapters

Results:

  • All 8 ports from MCS7840 accessible via unique symlinks
  • All 4 ports from FT4232H accessible
  • Single-port adapters unchanged (backward compatible)
  • Console-server can connect to all ports remotely
  • Symlinks persist across reboots and USB re-enumeration

Before fix:

$ ls /dev/serial/by-bus/ | grep 1.4
usb0b1.4.1p1.0  # Only last port accessible
usb0b1.4.2p1.0  # Only last port accessible

After fix:

$ ls /dev/serial/by-bus/ | grep 1.4
usb0b1.4.1p1.0_port0
usb0b1.4.1p1.0_port1
usb0b1.4.1p1.0_port2
usb0b1.4.1p1.0_port3
usb0b1.4.2p1.0_port0
usb0b1.4.2p1.0_port1
usb0b1.4.2p1.0_port2
usb0b1.4.2p1.0_port3

Impact

  • Scope: Affects users with multi-port USB serial adapters using console-server
  • Breaking Change: No - single-port devices behave identically
  • Risk: Low - only modifies symlink creation for multi-port devices

Affected Multi-Port Adapters

Common devices that will benefit:

  • MosChip MCS7820/MCS7840 (2/4 port)
  • FTDI FT2232H, FT4232H (2/4 port)
  • Prolific PL2303 multi-port variants
  • StarTech/IOGear multi-port USB serial hubs
  • Any USB serial adapter with multiple ports on a single USB device

Details

Version
Stream 2025.11
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)

Event Timeline

srnoth triaged this task as Normal priority.
srnoth created this object in space S1 VyOS Public.

Hey @srnoth would you like to create a PR?

Yessir, I am still doing some more testing... this change had negative effects on a FT4232H 4 port USB serial adapter that I need to track down. Will submit a PR once I've figured out a change that doesn't negatively impact the multi-port serial adapters that don't differentiate ports with the ".ID_PORT" field.

Viacheslav changed the task status from Open to In progress.Tue, Jan 27, 7:54 PM
Viacheslav assigned this task to srnoth.

*Edited to remove an "option" I don't have a way to code.

Ok did some more digging, here's my conundrum.

  1. With my initial change, _port[x] gets added to every usb serial device, which means that even for existing devices with only one port, _port0 gets appended to the symlink, e.g.:
usb0b1.3p1.0_port0
usb0b1.3p1.1_port0
usb0b1.3p1.2_port0
usb0b1.3p1.3_port0
usb0b1.4.1p1.0_port0
usb0b1.4.1p1.0_port1
usb0b1.4.1p1.0_port2
usb0b1.4.1p1.0_port3

This creates a consistent looking list, but is a breaking change for existing configs of non-multi-port adapters.

  1. The second option is to only append _port[x] for port1 or greater, which ends up as:
usb0b1.3p1.0
usb0b1.3p1.1
usb0b1.3p1.2
usb0b1.3p1.3
usb0b1.4.1p1.0
usb0b1.4.1p1.0_port1
usb0b1.4.1p1.0_port2
usb0b1.4.1p1.0_port3

This creates no breaking change, but the naming convention is inconsistent between the first port and any subsequent ports on a multi-port adapter.

Any reason not to go with option 2, other than the inconsistent naming convention? Any suggestions of a better way to do this? Per my understanding the limitation here is the udev rule processes each device (port) individually and has no way of knowing if a particular "port0" has additional ports on the same device.