<!--
.. title: Polycube - Complete Installation on Raspberry Pi CM4
.. slug: polycube-complete-installation-on-raspberry-pi-cm4
.. date: 2023-01-27 10:51:05 UTC-06:00
.. tags:  ebpf, polycube, iptables, firewall, router, networking,compute module
.. category:
.. link:
.. description:  Step by step guide to compiling and installing polycube on Arm-based hardware
.. type: text
-->



<div class="audio-widget">
<div class="audio-widget-header">
<span class="audio-widget-icon">🎧</span>
<span class="audio-widget-label">Listen to this article</span>
</div>
<audio controls preload="metadata">
<source src="/polycube-complete-installation-on-raspberry-pi-cm4_tts.mp3" type="audio/mpeg">
</audio>
<div class="audio-widget-footer">19 min · AI-generated narration</div>
</div>

1. Adding backports and stretch package locations to /etc/apt/source.list
   <pre>deb https://deb.debian.org/debian bullseye-backports main contrib non-free
deb https://deb.debian.org/debian/ stretch-backports main contrib non-free
deb https://deb.debian.org/debian/ stretch main contrib non-free</pre>

2. Update local cache
   <pre><code class="command">sudo apt update</code></pre>
3. Install packages
   <pre><code class="command">sudo apt-get -y install git build-essential cmake bison flex \</code>
       libelf-dev libllvm9 llvm-9-dev libclang-9-dev libpcap-dev \
       libnl-route-3-dev libnl-genl-3-dev uuid-dev pkg-config \
       autoconf libtool m4 automake libssl-dev kmod jq bash-completion  \
       gnupg2 golang-go-1.19 tmux bc libfl-dev libpcre2-dev libpcre3-dev</pre>
4. Add `go` to your `$PATH` in `.bashrc`; this needs to be done for `root` user, as well.  
   <pre>export PATH=/usr/lib/go-1.19/bin:$PATH</pre>
5. Verify `go` is in `$PATH`
   <pre><code class="command">go version</code>
<code>go version go1.19.4 linux/arm64</code></pre>
6. Install `pistache` - needed for the RESTful control daemon, `polycubed`
   <pre><code class="command">git clone https://github.com/oktal/pistache.git</code>
<code class="command">cd pistache</code>
# known working version of pistache
<code class="command">git checkout 117db02eda9d63935193ad98be813987f6c32b33</code>
<code class="command">git submodule update --init</code>
<code class="command">mkdir -p build && cd build</code>
<code class="command">cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DPISTACHE_USE_SSL=ON ..</code>
<code class="command">make -j $(getconf _NPROCESSORS_ONLN)</code>
<code class="command">sudo make install</code></pre>
7. Install `libtins`
   <pre><code class="command">cd
<code class="command">git clone --branch v3.5 https://github.com/mfontanini/libtins.git</code>
<code class="command">cd libtins</code>
<code class="command">mkdir -p build && cd build</code>
<code class="command">cmake -DLIBTINS_ENABLE_CXX11=1 \</code>
 -DLIBTINS_BUILD_EXAMPLES=OFF -DLIBTINS_BUILD_TESTS=OFF \
 -DLIBTINS_ENABLE_DOT11=OFF -DLIBTINS_ENABLE_PCAP=OFF \
 -DLIBTINS_ENABLE_WPA2=OFF -DLIBTINS_ENABLE_WPA2_CALLBACKS=OFF ..
<code class="command">make -j $(getconf _NPROCESSORS_ONLN)</code>
<code class="command">sudo make install</code>
<code class="command">sudo ldconfig</code></pre>
8. Install `libyang`
   <pre><code class="command">cd</code>
<code class="command">git clone https://github.com/CESNET/libyang.git</code>
<code class="command">cd libyang</code>
<code class="command">git checkout libyang1</code>
<code class="command">mkdir build; cd build</code>
<code class="command">cmake ..</code>
<code class="command">make</code>
<code class="command">sudo make install</code></pre>
9. Clone `polycube` repository that contains the necessary changes to `config.cpp`
   <pre><code class="command">cd</code>
<code class="command">git clone https://github.com/ajokela/polycube</code>
<code class="command">cd polycube</code>
<code class="command">git submodule update --init --recursive</code></pre>
10. Build `prometheus-cpp`
    <pre><code class="command">cd src/libs/prometheus-cpp</code>
<code class="command">mkdir build; cd build</code>
<code class="command">cmake .. -DBUILD_SHARED_LIBS=ON</code>
<code class="command">make -j4</code>
<code class="command">sudo make install</code></pre>
11. Configure `polycube`
    <pre><code class="command">cd; cd polycube</code>
<code class="command">mkdir build; cd build</code>
<code class="command">cmake .. -DBUILD_SHARED_LIBS=ON \</code>
           -DENABLE_PCN_IPTABLES=ON     \
           -DENABLE_SERVICE_BRIDGE=ON   \
           -DENABLE_SERVICE_DDOSMITIGATOR=OFF \
           -DENABLE_SERVICE_FIREWALL=ON   \
           -DENABLE_SERVICE_HELLOWORLD=OFF     \
           -DENABLE_SERVICE_IPTABLES=ON     \
           -DENABLE_SERVICE_K8SFILTER=OFF     \
           -DENABLE_SERVICE_K8SWITCH=OFF     \
           -DENABLE_SERVICE_LBDSR=OFF     \
           -DENABLE_SERVICE_LBRP=OFF     \
           -DENABLE_SERVICE_NAT=ON     \
           -DENABLE_SERVICE_PBFORWARDER=OFF     \
           -DENABLE_SERVICE_ROUTER=ON     \
           -DENABLE_SERVICE_SIMPLEBRIDGE=ON     \
           -DENABLE_SERVICE_SIMPLEFORWARDER=ON     \
           -DENABLE_SERVICE_TRANSPARENTHELLOWORLD=OFF \
           -DENABLE_SERVICE_SYNFLOOD=OFF     \
           -DENABLE_SERVICE_PACKETCAPTURE=OFF     \
           -DENABLE_SERVICE_K8SDISPATCHER=OFF
</pre>
12. Build `polycube` (this will take a while; you might want to use `tmux`)
    <pre><code class="command">tmux</code>
<code class="command">make -j4</code></pre>
    To detach from the `tmux` terminal, press `CTL+b, d`<br /><br/>

    To reattached, execute:
    <pre><code class="command">tmux attach -t 0</code></pre><br /><br />

    Grab a coffee and go stare at your phone for a while.

13. If all goes well, you should see the following:
    <pre>[100%] Building CXX object src/polycubed/src/CMakeFiles/polycubed.dir/load_services.cpp.o
[100%] Building CXX object src/polycubed/src/CMakeFiles/polycubed.dir/version.cpp.o
[100%] Linking CXX executable polycubed
[100%] Built target polycubed</pre>
14. Try to execute `polycubed`; we should get some sort of error(s)
    <pre><code class="command">sudo src/polycubed/src/polycubed</code>
[2023-01-27 13:57:22.022] [polycubed] [info] loading configuration from /etc/polycube/polycubed.conf
[2023-01-27 13:57:22.023] [polycubed] [warning] default configfile (/etc/polycube/polycubed.conf) not found, creating a new with default parameters
terminate called after throwing an instance of 'spdlog::spdlog_ex'
  what():  Failed opening file /var/log/polycube/polycubed.log for writing: No such file or directory
Aborted
</pre>
14. This is progress and we can handle this by making a directory.
    <pre><code class="command">sudo mkdir /var/log/polycube</code></pre>
15. Run `polycubed` again, and you should run into kernel header files not being foundation
    <pre><code class="command">sudo src/polycubed/src/polycubed </code>
[2023-01-27 14:01:21.048] [polycubed] [info] loading configuration from /etc/polycube/polycubed.conf
[2023-01-27 14:01:21.051] [polycubed] [info] configuration parameters:
[2023-01-27 14:01:21.051] [polycubed] [info]  loglevel: info
[2023-01-27 14:01:21.051] [polycubed] [info]  daemon: false
[2023-01-27 14:01:21.052] [polycubed] [info]  pidfile: /var/run/polycube.pid
[2023-01-27 14:01:21.052] [polycubed] [info]  port: 9000
[2023-01-27 14:01:21.052] [polycubed] [info]  addr: localhost
[2023-01-27 14:01:21.052] [polycubed] [info]  logfile: /var/log/polycube/polycubed.log
[2023-01-27 14:01:21.052] [polycubed] [info]  cubes-dump-file: /etc/polycube/cubes.yaml
[2023-01-27 14:01:21.052] [polycubed] [info]  cubes-dump-clean-init: false
[2023-01-27 14:01:21.052] [polycubed] [info]  cubes-dump-enable: false
[2023-01-27 14:01:21.052] [polycubed] [info] polycubed starting...
[2023-01-27 14:01:21.052] [polycubed] [info] version v0.9.0+ [git: (branch/commit): master/75da2773]
<b>modprobe: FATAL: Module kheaders not found in directory /lib/modules/5.15.61-v8+
Unable to find kernel headers. Try rebuilding kernel with CONFIG_IKHEADERS=m (module) or installing the kernel development package for your running kernel version.</b>
chdir(/lib/modules/5.15.61-v8+/build): No such file or directory
[2023-01-27 14:01:21.092] [polycubed] [error] error creating patch panel: Unable to initialize BPF program
[2023-01-27 14:01:21.093] [polycubed] [critical] Error starting polycube: Error creating patch panel</pre>
16. We need to get the Raspberry Pi Linux kernel source.
    <pre><code class="command">cd /usr/src</code>
<code class="command">sudo git clone --depth=1 https://github.com/raspberrypi/linux</code></pre>
We need to see what kernel version the Raspberry Pi
    <pre><code class="command">uname -a</code>
Linux polycube-network 5.15.61-v8+ #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux</pre>
    We are using 5.15.61-v8+.  We will need to checkout the correct branch of the kernel.  First move `linux` to `linux-upstream-5.15.61-v8+`
    <pre><code class="command">sudo mv linux linux-upstream-5.15.89-v8+</code>
<code class="command">cd linux-upstream-5.15.89-v8+</code></pre>
    Now, checkout the correct branch.  It takes a format like `rpi-5.15.y` which corresponds to version `5.15.89`
    <pre><code class="command">sudo git checkout rpi-5.15.y</code></pre>
17. Make a symlink from within `/lib/modules` to our source directory
    <pre><code class="command">cd /lib/modules/5.15.61-v8+</code>
<code class="command">sudo ln -s /usr/src/linux-upstream-5.15.89-v8+ build</code>
18. Build a new kernel to auto-generate the necessary header files.
    <pre><code class="command">cd /usr/src/linux-upstream-5.15.89-v8+</code>
<code class="command">sudo make ARCH=arm64 bcm2711_defconfig</code>
<code class="command">sudo make -j4</code></pre>
    Grab another cup of coffee and stare at your phone for a while; this will take some time to complete.  Doing this *in situ* will be slower than cross-compiling on a faster laptop or desktop, but the point of these instructions is not to productionize the process, it is to show how to make `polycube` compile and run on Arm-based systems, specifically, Raspberry Pi 4b or CM4 systems.

    It might be unnecessary to completely build recompile a kernel; maybe experiment a bit with it.
19. Installing and running.  Make sure `go` is available in your `PATH` for `root` user; it is needed to compile `polycubectl`.
    <pre><code class="command">sudo su -</code>
<code class="command">cd ~pi/polycube/build
<code class="command">make install</code></pre>
`make install` should finished a message of `Installation completed successfully`. Now we can run `polycubed` and it will find all the associated shared libraries for the functionality we will be investigating in the next post.
    <pre><code class="command">sudo polycubed</code></pre>
    You should get output that looks like this:
    <pre>[2023-01-27 17:13:46.791] [polycubed] [info] loading configuration from /etc/polycube/polycubed.conf
[2023-01-27 17:13:46.793] [polycubed] [info] configuration parameters:
[2023-01-27 17:13:46.793] [polycubed] [info]  loglevel: info
[2023-01-27 17:13:46.793] [polycubed] [info]  daemon: false
[2023-01-27 17:13:46.793] [polycubed] [info]  pidfile: /var/run/polycube.pid
[2023-01-27 17:13:46.793] [polycubed] [info]  port: 9000
[2023-01-27 17:13:46.793] [polycubed] [info]  addr: localhost
[2023-01-27 17:13:46.793] [polycubed] [info]  logfile: /var/log/polycube/polycubed.log
[2023-01-27 17:13:46.794] [polycubed] [info]  cubes-dump-file: /etc/polycube/cubes.yaml
[2023-01-27 17:13:46.794] [polycubed] [info]  cubes-dump-clean-init: false
[2023-01-27 17:13:46.794] [polycubed] [info]  cubes-dump-enable: false
[2023-01-27 17:13:46.794] [polycubed] [info] polycubed starting...
[2023-01-27 17:13:46.794] [polycubed] [info] version v0.9.0+ [git: (branch/commit): master/75da2773]
prog tag mismatch 3e70ec38a5f6710 1
WARNING: cannot get prog tag, ignore saving source with program tag
prog tag mismatch 1e2ac42799daebd8 1
WARNING: cannot get prog tag, ignore saving source with program tag
[2023-01-27 17:14:03.905] [polycubed] [info] rest server listening on '127.0.0.1:9000'
[2023-01-27 17:14:03.906] [polycubed] [info] rest server starting ...
[2023-01-27 17:14:04.010] [polycubed] [info] service bridge loaded using libpcn-bridge.so
[2023-01-27 17:14:04.050] [polycubed] [info] service firewall loaded using libpcn-firewall.so
[2023-01-27 17:14:04.149] [polycubed] [info] service nat loaded using libpcn-nat.so
[2023-01-27 17:14:04.277] [polycubed] [info] service router loaded using libpcn-router.so
[2023-01-27 17:14:04.340] [polycubed] [info] service simplebridge loaded using libpcn-simplebridge.so
[2023-01-27 17:14:04.370] [polycubed] [info] service simpleforwarder loaded using libpcn-simpleforwarder.so
[2023-01-27 17:14:04.413] [polycubed] [info] service iptables loaded using libpcn-iptables.so
[2023-01-27 17:14:04.553] [polycubed] [info] service dynmon loaded using libpcn-dynmon.so
[2023-01-27 17:14:04.554] [polycubed] [info] loading metrics from yang files
</pre>
<div style="width: 100%; text-align: center; vertical-align: top;">
  <img src="/images/surrealism-painting-raspberry-pi-ethernet-router.png.webp"  loading="lazy" style="zoom: 45%;" />
</div>

<hr />
