Clone wiki

roseline / Tutorial 6 - Network booting slave platforms

Overview

The goal of this tutorial is to show how the BeagleBone Black may be configured to boot into a kernel image and device tree that is fetched using TFTP, then mount the kernel modules and shared source code over NFS once booted. The advantage with this approach is that you need not fiddle with the MicroSD card in order to update the kernel or modules, which saves a lot of time during the development cycle.

The first thing that is required is to install the necessary system applications.

sudo apt-get install nfs-kernel-server tftpd-hpa isc-dhcp-server iptables iptables-persistent

STEP 1 : Configure DHCP

The Ubuntu host needs to act as a DHCP server, assigning IPs to slaves as they boot. I personally prefer to define each of my slaves in the configuration file so that they are assigned a constant network address that is preserved across booting.

Firstly, configure your ethernet adapter to take a static IP 10.42.0.1.

netconf.png

Now, configure the DHCP server to listen on the Ethernet adapter you configured with the static IP address. You can find this by typing ifconfig on the command line. Edit the /etc/default/isc-dhcp-server file to add the interface on which you wish to serve DHCP requests (in my case this was eth0).

INTERFACES="eth0"

Now, configure the DHCP server and add an entry for each slave node in /etc/dhcp/dhcpd.conf . The configuration below assigns the IP 10.42.0.100 to the single slave with an Ethernet MAC 6c:ec:eb:ad:a7:3c. To add more slaves, just add additional lines to this file.

subnet 10.42.0.0 netmask 255.255.255.0 {
 range 10.42.0.100 10.42.0.254;
 option domain-name-servers controller.roseline.local;
 option domain-name "roseline.local";
 option routers 10.42.0.1;
 option broadcast-address 10.42.0.255;
 default-lease-time 600;
 max-lease-time 7200;
}

host alpha { hardware ethernet 6c:ec:eb:ad:a7:3c; fixed-address 10.42.0.100; }

Finally, restart the DHCP server:

sudo service isc-dhcp-server restart

STEP 2 : Configure iptables

There are times when you need to access the internet from your slave nodes. This may be to checkout code by git or just perform a system update. The easiest way to allow this is to set up the host PC as a NAT router using iptables.

Firstly, allow ipv4 forwarding:

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

Then, edit /etc/sysctl.conf to make this change permanent:

net.ipv4.ip_forward=1

Then, add some iptables forwarding rules. Note that wlan0 is my internet connection on the host pc, while eth0 is the Ethernet adapter connected through a switch to my slave BeagleBone Black devices.

sudo iptables -A FORWARD -o wlan0 -i eth0 -s 10.42.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -F POSTROUTING
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Log into one of the slave BeagleBone Black devices to check that you can ping a server. If you can, then yo have a working NAT router. The last thing is to save the iptable rules so that they are preserved on reboot.

sudo /etc/init.d/iptables-persistent save 

STEP 2 : Configure TFTP

Then, edit the /etc/default/tftpd-hpa file to the following:

TFTP_USERNAME="tftp" 
TFTP_DIRECTORY="/home/<username>/export/tftp" 
TFTP_ADDRESS="10.42.0.1:69" 
TFTP_OPTIONS="-s -c -l"

Copy over your kernel and device tree binary to the TFTP root, and grant access:

cp <roseline>/kernel/bootloader/* /home/<username>/export/tftp 
sudo chmod -R 777 /home/<username>/export/tftp 
sudo chown -R nobody /home/<username>/export/tftp

Finally, restart the server:

sudo service tftpd-hpa restart

STEP 3 : Configure NFS

Edit the NFS /etc/exports on the host PC to share your root file system over NFS.

/home/<username>/export/rootfs *(rw,sync,no_root_squash,no_subtree_check)

Then, restart the server:

sudo service nfs-kernel-server restart

STEP 4 : Configure the bootloader

Then, update the uEnv.txt file on the first partition of your BeagleBone Black MicroSD card to fetch the kernel and device tree over FTFP and mount the root file system from the second partition:

mmcroot=/dev/mmcblk0p2 ro
mmcrootfstype=ext4 rootwait fixrtc
console=ttyO0,115200n8
fdtfile=am335x-boneblack.dtb
bootfile=zImage
fdt_high=0xffffffff
fdtaddr=0x80F80000
loadaddr=0x80200000
serverip=10.42.0.1
boot_tftp=echo Network configuration via DHCP; dhcp
fdtboot=echo Booting fdt ${fdtfile} from tftp server ...; tftp ${fdtaddr} ${fdtfile}
netargs=setenv bootargs console=${console} root=${mmcroot} rootfstype=${mmcrootfstype} ip=dhcp
uenvcmd=run netargs; run boot_tftp; run fdtboot; bootz ${loadaddr} - ${fdtaddr}

You will also want to change the rootfs /etc/fstab to mount the kernel modules and root shared directory over NFS, which will avoid you having to copy new kernel modules each time they are compiled:

/dev/mmcblk0p1 /boot/uboot auto defaults 0 0
/dev/mmcblk0p2 / auto defaults 0 02
10.42.0.1:/home/<username>/export/rootfs/lib/modules    /lib/modules    nfs     rw,sync,hard,intr  0  0
10.42.0.1:/home/<username>/export/rootfs/root/shared    /root/shared    nfs     rw,sync,hard,intr  0  0

Updated