Setting Up a Robot LAN with Internet Connection Sharing

Preamble

It can be common to want to run multiple embedded computers on a robotic system. Having multiple systems on a hard LAN makes sense, to enable low latency communication between them. If the robot can connect to a local WiFi source that provides an internet connection then it can be quite easy for each embedded system to connect to the wireless network also, as most will come with a WiFi card. However, if the robot is using a cellular data connection to access the internet, then it might make more sense to have only one embedded system connected to the cellular module and then share the internet connection over the robot LAN to the other devices.

This can be useful for a number of reasons:

  • if you use a VPN for your robot assets (previous post on how to set this up) and only want one IP on your VPN per robot, even though each robot contains multiple embedded systems
  • if you are running ROS, ROS core might be run on the system with the cellular connection and the other embedded systems use the LAN to connect to the ROS core there
  • engineers can also get straight to the system running ROS core if they are remotely connecting over a VPN or similar
  • your cellular data provider may allow for budgeting of data allowance on your connections, which may be easier to manage with just one SIM provisioned for each robot, rather than one for each embedded system

How To

The following post details a setup with one host device, connected to a cellular module, and one client device connected directly with an Ethernet cross-over cable to the host. Both of these devices are using Ubuntu 20.04 LTS and Network Manager but the steps will be applicable on some other platforms also.

Using This Post

For the code chunks used in this blog post, I’ve split them into three groups.

  1. Commands to be run on the embedded system that will host the internet connection
# Host Side
some_command
  1. Commands to be run on the embedded system that will be the client for the internet connection
# Client Side
some_command
  1. Terminal output returned from any commands or the contents of a file being edited
the output of some_command

Planning

It’s worth taking some time to map out the host names and IP addresses we will use in our network. The case detailed here is the most simple but it can quite quickly become more complex and having a good record of the configuration for documentation will only help in future.

Network Name = local_connection

System Host Name IP Address
Embedded System Hosting the Connection embedded-host 10.0.0.1
Embedded System Acting as Client embedded-client 10.0.0.2

Host Side Configuration

I’m going to assume you can establish a ssh connection or you can assume direct terminal control of the embedded computer that will host the internet connection. This will likely be over a VPN connection or local WiFi network.

First off let us use Network Manager to create an Ethernet connection that shares our internet connection and give that connection the name “local_connection”. Then we need to allocate the host device the static IP that we decided upon in the plan above. It’s also worth enabling infinite auto connect retries, to help ensure the connection is always established when it is available.

# Host Side
sudo nmcli connection add type ethernet ifname eth0 ipv4.method shared con-name local_connection
sudo nmcli connection modify local_connection ipv4.addresses 10.0.0.1/24
sudo nmcli c m local_connection connection.autoconnect-retries 0

Next let us set the host name of the internet hosting device.

# Host Side
sudo nano /etc/hostname

Edit the file to just contain the host name we decided upon in the planning stage.

embedded-host

We also need to edit the hosts file so that our host system is aware of the connections we intend to connect to our network.

# Host Side
sudo nano /etc/hosts

This file just needs additions to reflect what is laid out in the plan established at the outset.

127.0.0.1 localhost

# Local Ethernet Link
10.0.0.1 embedded-host
10.0.0.2 embedded-client

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

That’s it for the host side, nice and easy.

Client Side Configuration

Connect the two embedded computers to each other using an Ethernet cross-over cable. A wired connection will establish automatically between the two computers using the “local_connection” network we set up above. However the IP provided to the client is auto assigned from the DHCP pool, so there is no way of ensuring consistency in addressing. For most situations you will want to use static IP addressing to reliably address specific connections on your robot LAN.

Let us get started by trying to connect to the client embedded system from the host over ssh. You can use nmap to find the DHCP IP given to the Nano from the host device.

# Host Side
nmap 10.0.0.*

You should get a return that looks something like this, showing that the other system is available to us on 10.0.0.12.

Nmap scan report for 10.0.0.12
Host is up (0.00017s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE
22/tcp open  ssh

From the host ssh in using the following command, replacing “username” with your login for the client system and “10.0.0.12” with the IP returned by nmap. If your user name for the host and client computer are the same you can drop the “username@” part of the command.

# Host Side
ssh username@10.0.0.12

Once logged in we can see the wired connection that has been established using the Network Manager CLI.

# Client Side
nmcli c s

The return should look something like this.

NAME                UUID                                  TYPE      DEVICE   
Wired connection 1  458c0e33-1b0d-3b3d-8446-f79151e51209  ethernet  eth0

Now we can edit that connection to share the same network name we used previously on the host device, purely for convenience when debugging. I went with “local_connection” again as specified in the plan set out at the top of this post. We can assign a static IP address, I went with 10.0.0.2.. It’s also worth enabling infinite auto connect retries to help ensure the connection is always established when it is available. The three commands below will do all of this, edit as appropriate for your setup.

# Client Side
sudo nmcli c m "Wired connection 1" connection.id local_connection
sudo nmcli c m local_connection ipv4.addresses 10.0.0.2/24
sudo nmcli c m local_connection ipv4.method auto
sudo nmcli c m local_connection connection.autoconnect-retries 0

Now we should edit the host name of the client device to match what we set out in our plan.

# Client Side
sudo nano /etc/hostname

The file contents should just be the host name.

embedded-client

We also need to edit the hosts file to include the known connections on our network.

# Client Side
sudo nano /etc/hosts

This file just needs additions to reflect what is laid out in the plan established at the outset.

127.0.0.1 localhost

# Local Ethernet Link
10.0.0.1 embedded-host
10.0.0.2 embedded-client

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Optional Steps

  1. For those using ROS you may want the client device to use the ROS core of the host device. This can be done by ensuring your client systems ROS_MASTER_URI either uses the known host name or IP address of the host computer. This can be incorporated into any system service calls you have to run your ROS nodes on boot which I may detail further in a separate post in future.
# Client Side
export ROS_MASTER_URI="http://embedded-host:11311"
  1. Another thing you could do is allocate a VPN client connection to the local network client, now that it has an internet connection. But that will depend on your use case and if it is useful for you to establish pseudo-direct connections to each embedded computer.

Resources and Further Reading

Fedora Magazine Article

Hey you!

Found this useful or interesting?

Consider donating to support.

Any question, comments, corrections or suggestions?

Reach out on the social links below through the buttons.