Skip to content
Josh Blum edited this page Sep 22, 2015 · 47 revisions

Remote support for Soapy SDR

https://raw.githubusercontent.com/wiki/pothosware/SoapyRemote/images/soapy_sdr_remote_logo.png

Use any SoapySDR supported device transparently over a local network link. The remote support feature can turn any SDR into a network peripheral.

Potential use-cases for Soapy Remote:

  • share the SDR device over a network
  • use the device in multiple processes
  • or use the device on multiple hosts
  • a multi-threaded abstraction layer
  • aid in embedded-device development
  • or a work-around for software issues
  • adapt an IPv4 SDR for an IPv6 network

Soon SoapyRemote is fairly new, its not yet versioned off and packaged into the PPA and Pothos SDR windows installer. In the meantime, installing from source is about as simple as any source build can be.

Pre-built installers for various systems are available through the Pothos SDR environment.

The remote device support has no additional dependencies other than SoapySDR itself:

The CMake build system will locate SoapySDR development files on your system. The plugin module and SoapySDRServer application will be built and installed into the SoapySDR modules directory and bin/ directory (respectively). The SoapyRemote project must be installed on both the remote and local system.

git clone https://github.com/pothosware/SoapyRemote.git
cd SoapyRemote
mkdir build
cd build
cmake ..
make
sudo make install

Run the server on the remote machine (the machine with the SDR hardware):

SoapySDRServer --bind

Or specify a custom bind address and port:

SoapySDRServer --bind="0.0.0.0:1234"

IPv6 address URLs are also supported:

SoapySDRServer --bind="[::]:1234"

The device should be supported transparently over the network using the standard SoapySDR API, SoapySDRUtil, and any applications built on top of the SoapySDR API. However, users will need to specify an additional device argument to engage the remote support module:

Specify the "remote" key to engage the support module. The value of the "remote" key should be the remote server's hostname or IP address. If a custom port was selected, the value should be specified as "myServer:portNum":

SoapySDRUtil --find="remote=myServer"

Filter out local devices with the "driver" key set to "remote". When the "driver" key specifies the "remote" plugin module, all other plugin modules will be ignored by the device enumeration routine:

SoapySDRUtil --find="remote=myServer, driver=remote"

Specify the "remote:driver" key to filter plugins on the remote system. The args will be rewritten to strip out the "remote:" key prefix. Use the "remote:" prefix to apply keys to the remote device only that would otherwise conflict with local keys:

SoapySDRUtil --find="remote=myServer, remote:driver=bladerf"

Use UHD with a remote device when SoapyUHD is installed. The same instructions for "driver" and "remote" keys apply. We can even use SoapyRemote to share the device locally to several processes:

uhd_find_devices --args="driver=remote,remote=myServer"

#use only SoapyRemote when UHD devices are available locally
uhd_find_devices --args="driver=remote,remote=myServer,type=soapy"

#example use of explicit type filter on remote server
uhd_find_devices --args="driver=remote,remote=myServer,remote:type=b200"

There are several optional stream arguments for setupStream() that can be used to tweak the performance of the remote stream forwarding. Regardless, we recommend that linux users follow the instructions for sysctrl and limits.conf, as SoapyRemote can automatically take advantage of these reconfigured settings.

The remote format key specifies the stream format that should be used on the remote device. By default the remote and local endpoints use the same data format. However users may want to conserve bandwidth by using complex shorts over the link, and using floats locally. Specify {"remote:format":"CS16"} to use complex shorts over the link, and the remote stream driver will perform the conversion to/from floating point.

The remote scalar specifies the floating point scale factor used when the user specifies floats locally and integers over the link. By default the scale factor is 32768 to convert between 1.0 full-scale floats and 16 bit shorts. For the Blade RF, which uses the lower 12 bits, specify {"remote:format":"CS16", "remote:scalar":2048}.

The remote MTU specifies the maximum datagram transfer size in bytes. By default the MTU is just under 1500 bytes (the default ethernet MTU). Users may increase the MTU to improve throughput. Not all hardware supports jumbo-frames. Check your ethernet configuration and hardware support before using this option.

On linux, use ifconfig to set the ethernet MTU:

sudo ifconfig eth0 mtu 4096

The remote window specifies the size of the kernel socket buffer in bytes. For applications that can tolerate large queues of samples, a large socket buffer (10s of megabytes) is recommended. The operating system may limit the upper bounds of the socket buffer size. The driver will print a warning if the buffer limit is exceeded.

On linux, use sysctrl to set the maximum socket buffer size:

#I like big buffers and I can not lie
#You other developers can't deny
#That when a socket walks in with an itty bitty SO_RCVBUF
#And a sysctl limit in your face
#You must run,
sudo sysctl -w net.core.rmem_max=104857600
sudo sysctl -w net.core.wmem_max=104857600

The remote priority specifies the scheduling priority of the server forwarding threads. Its recommended to use an elevated priority for the forwarding threads to reduce latency and to avoid potential hiccups like overflows and underflows. The priority is a floating point value between -1.0 (low), 0.0 (normal), and 1.0 (high). By default, the server will try to elevate the priority for the forwarder threads. Users may need to tweak their system configuration to allow elevated thread priority. The driver will print a warning if the thread priority setting is not possible.

To allow elevated priority on linux, edit /etc/security/limits.conf and add the following line for your username:

<username> hard rtprio 99

SoapyRemote is composed of two major pieces: The server, which is an executable that runs on the remote machine. And the client, which is just a regular SoapySDR plugin module that knows how to communicate with the server.

The server operates a simple RPC protocol over the reliable TCP socket layer. The client connects to the server to perform device discovery, creation, and configuration settings. Stream configuration and controls are also implemented through the RPC, however the streams themselves use a separate protocol for high bandwidth.

Streaming operates through a windowed-datagram protcol over the unreliable UDP socket layer. A stream receiver endpoint socket is responsible for buffering the incoming stream data, and sending out flow control messages to the sender endpoint. The sender endpoint waits on flow control messages and forwards the stream data to the receiver. The goal of the flow control is to never send more data into the link, than there is space within the socket buffers.