Page MenuHomeVyOS Platform

Multi-port USB serial adapters create symlink collisions in console-server
Closed, ResolvedPublic

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.Jan 27 2026, 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.

@srnoth why not stick to the existing schema?

usb0b1.4.1p1.0p0
usb0b1.4.1p1.0p1
usb0b1.4.1p1.0p2
usb0b1.4.1p1.0p3

@c-po fair enough. That would end up looking like this though:
usb0b1.4.1p1.0
usb0b1.4.1p1.0p1
usb0b1.4.1p1.0p2
usb0b1.4.1p1.0p3

Since if we make this change for all ttys with a "Port 0" identifier, it would break folks' existing configs for single-port devices (some seem to show no port identifier, others show "Port 0").

If you're good with the above syntax I'll get it tested and the PR submitted.

Went with the pN suffix as suggested by @c-po. Port 0 keeps the base name for backward compatibility, ports 1+ get pN appended.

PR: https://github.com/vyos/vyos-1x/pull/5113

Tested on VyOS 2026.02 with MCS7840 (8-port), FT4232H (4-port), and single-port adapters — all working as expected.

set service console-server device
Possible completions:
 > ttySxxx              Regular serial interface
 > usbxbxpx             USB based serial interface
 > ttyS0
 > ttyS1
 > ttyS2
 > ttyS3
 > usb0b1.3p1.0
 > usb0b1.3p1.1
 > usb0b1.3p1.2
 > usb0b1.3p1.3
 > usb0b1.4.1p1.0
 > usb0b1.4.1p1.0p1
 > usb0b1.4.1p1.0p2
 > usb0b1.4.1p1.0p3
 > usb0b1.4.2p1.0
 > usb0b1.4.2p1.0p1
 > usb0b1.4.2p1.0p2
 > usb0b1.4.2p1.0p3
 > usb0b3p1.0
 > usb0b3p1.2
 > usb0b3p1.3
Viacheslav moved this task from Need Triage to Completed on the VyOS Rolling board.