Connect two Ubuntu systems over USB with each other

Is there any way to create a connection between two Ubuntu systems over USB by plugging a USB cable into both of them?

In a simple test environment I'd like to send a couple of characters from one system to another, basically a little chat.

In a little more advanced test I'd like to create a TCP connection and treat the USB connection like any other LAN connection.


The following describes Ethernet over USB

RNDIS

The Remote Network Driver Interface Specification (RNDIS) is a Microsoft proprietary protocol used mostly on top of USB. It provides a virtual Ethernet link to most versions of the Windows, Linux, and FreeBSD operating systems. A partial RNDIS specification is available from Microsoft, but Windows implementations have been observed to issue requests not included in that specification, and to have undocumented constraints.1

The protocol is tightly coupled to Microsoft's programming interfaces and models, most notably the Network Driver Interface Specification (NDIS), which are alien to operating systems other than Windows. This complicates implementing RNDIS on non-Microsoft operating systems, but Linux,2 FreeBSD,3 NetBSD4 and OpenBSD[5] implement RNDIS natively.

The USB Implementers Forum (USB-IF) defines at least three non-proprietary USB communications device class (CDC) protocols with comparable "virtual Ethernet" functionality; one of them (CDC-ECM) predates RNDIS and is widely used for interoperability with non-Microsoft operating systems, but does not work with Windows.

[PATCH] USB: usbnet (8/9) module for RNDIS devices

Ethernet_over_USB Wikipedia

There are numerous protocols for Ethernet-style networking over USB. The main motivation for these protocols is to allow application-independent exchange of data with USB devices, instead of specialized protocols such as video or MTP. Even though USB is not a physical Ethernet, the networking stacks of all major operating systems are set up to transport IEEE 802.3 frames, without caring much what the underlying transport really is.

The main industry protocols are (in chronological order): Remote NDIS (RNDIS, a Microsoft vendor protocol), Ethernet Control Model (ECM), Ethernet Emulation Model (EEM), and Network Control Model (NCM). The latter three are part of the larger Communications Device Class (CDC) group of protocols of the USB Implementers Forum (USB-IF). They are available for download from the USB-IF (see below). The RNDIS specification is available from Microsoft's web site. Regarding de facto standards, some standards, such as ECM, specify use of USB resources that early systems did not have. However, minor modifications of the standard, so-called subsets, make practical implementations possible on such platforms. Remarkably, even some of the most modern platforms need minor accommodations and therefore support for these subsets is still needed.

Of these protocols ECM is by far the simplest—frames are simply sent and received without modification one at a time. This was a good strategy for USB 1.1 systems (current when the protocol was issued) with 64 byte packets but not for USB 2.0 systems which use 512 byte packets.

The problem is that Ethernet frames are about 1500 bytes in size—about 3 USB 2.0 packets, and 23 USB 1.1 packets. According how the USB system works, each packet is sent as a transfer, a series of maximum-length packets terminated by a short packet or a special ZLP (zero-length packet). After this, there is bus latency, where nothing is sent until another transfer can be initiated. This reduces bus occupancy, meaning that nothing is sent for considerable fractions of bus time. A gap every 23 frames is not noticeable, but a gap every three frames can be very costly to throughput.

The following were answered superuser

Ethernet over USB drivers are included into Linux. The relevant host-size drivers are CDC_ETHER and RNDIS. Their slave-size counterparts (that essentially emulate an USB-Ethernet bridge in software) are USB_ETH, USB_ETH_RNDIS. USB_G_ANDROID also supports RNDIS protocol, which is great in my case, since the devices in question use Android kernel, so the driver is enabled by default.

The measured bandwidth of the USB bridge using the USB_G_ANDROID driver is ~130Mbps from host to slave and ~90Mbps the other way round.


You cannot connect two ordinary USB ports (such as those found on most computers) with a cable. The two sides of a USB connection are not symmetrical. Unless you happen to have a machine with a USB-OTG (Google it) interface, and the corresponding drivers, you can't just connect two USB ports.

If one or both computers have a USB-C port then a common USB-C to USB-C, or USB-A to USB-C cable, can be used to connect two computers. The USB 3.x specification defined in 2011 a USB-A to USB-A cable for this purpose, with the Vbus and D+/D- lines unconnected to avoid any issues of shorting out either port. These USB 3.x compliant cables are rare and noncompliant cables are everywhere, for some reason, which makes this potentially dangerous if one is not careful.

This is safe with USB-C because all USB-C ports (at least those that comply with the spec, because apparently this is a problem that has gone beyond just USB-C cables) implement USB-OTG just like the micro style ports. Power is not applied to Vbus on a USB-OTG compliant port unless it sees the ID pin grounded. This means in the default state it is acting as a "B" port, switching to an "A" port if the "A" end of the cable is plugged in.

Connecting a USB-C port on one computer to the USB-C port on another computer is safe as each computer will use the USB-OTG protocol to figure out which computer should be supplying power on the cable. This is what happens every time a smart phone is plugged into a computer by cables with USB-C connectors on each end. This can have undesirable results, such as a laptop drawing power from a phone instead of charging it like most people would want and expect. This is often rectified by just unplugging and plugging back in.

I know that ordinary USB ports on at least some computers allow for communications by USB-A to USB-C ports because I am able to put my MacBook Pro into "Target Disk Mode", then plug it into another MacBook Pro by a USB-A to USB-C cable, and mount the internal drive of my MacBook Pro on the other MacBook Pro.

The hardware is there, but for limited uses on Apple computers as the software is apparently not there for creating a network. Target Disk Mode worked fine but as I recall I could not create a network connection between the computers with this same cable once I left Target Disk Mode. I don't have the hardware with me right now to refresh my memory on what would and would not work.

What confuses some people on this is that some USB-C ports on computers will support the Thunderbolt protocol, and connecting two Thunderbolt ports together will create a network link. That was another thing I did with my MacBook Pro and a different MacBook Pro, I used a Thunderbolt 3 to Thunderbolt 2 adapter to connect these computers together. Two computers with USB-C/Thunderbolt ports can be connected with a common passive USB-C to USB-C cable to make a network. It would come in really handy if this was as simple with USB as it is with Thunderbolt, especially since Thunderbolt has been able to do this for nearly a decade now and the USB 3.x spec defined how to do this for just as long.

I would like to find some kind of USB to USB communications like Thunderbolt offers, not just on Linux but across operating systems so I can network Linux to macOS and Windows by a USB cable. I've been looking for answers but instead I just keep finding more questions.