<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Bits of networks</title>
    <subtitle>Networking, system, research</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.bitsofnetworks.org/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-17T00:00:00+00:00</updated>
    <id>https://blog.bitsofnetworks.org/atom.xml</id>
    <entry xml:lang="en">
        <title>Patching OpenSSH in Debian</title>
        <published>2026-08-17T00:00:00+00:00</published>
        <updated>2026-08-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/patching-openssh-debian/"/>
        <id>https://blog.bitsofnetworks.org/patching-openssh-debian/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/patching-openssh-debian/">&lt;p&gt;&lt;em&gt;This article was written entirely without the help of any generative AI tool.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I needed to test an OpenSSH patch. I thought that rebuilding the Debian package would be easy, but it wasn&#x27;t.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;my-case-for-rebuilding-the-openssh-debian-package&quot;&gt;My case for rebuilding the OpenSSH Debian package&lt;&#x2F;h1&gt;
&lt;p&gt;My main use-case when building or rebuild packages is to use patched or backported versions locally or for internal server use, not to push them in the Debian archive.
It means I don&#x27;t need the same kind of quality process, but I would still like the resulting packages to be as close to Debian as possible, hoping it helps my system to remain stable.&lt;&#x2F;p&gt;
&lt;p&gt;I love Debian for its stability and community, but there&#x27;s one thing that has always irritated me: there are so many available tools to build Debian packages,
and there is no particular recommendation to use any of them. Besides, the whole building process feels quite obscure and magical.&lt;&#x2F;p&gt;
&lt;p&gt;In that particular case, I wanted to test a patch to the OpenSSH client.  Since I use SSH daily, I definitely don&#x27;t want to run a weird build that could break any of my workflows.
I thought I was starting to master the art of building Debian packages, but there were new interesting surprises!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rebuilding-debian-packages-is-easier-than-before&quot;&gt;Rebuilding Debian packages is easier than before&lt;&#x2F;h1&gt;
&lt;p&gt;In recent years, the ease of building Debian packages has improved, notably because many packages are now maintained as a git repository.&lt;&#x2F;p&gt;
&lt;p&gt;Obtaining and modifying the source Debian package is easier for me thanks to git:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I go to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;trixie&#x2F;openssh-client&quot;&gt;package details&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I jump to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;source&#x2F;trixie&#x2F;openssh&quot;&gt;source package details&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I follow the link &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;salsa.debian.org&#x2F;ssh-team&#x2F;openssh&quot;&gt;Debian Source Repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I clone the git repository&lt;&#x2F;li&gt;
&lt;li&gt;I checkout the correct git branch for the target version of Debian&lt;&#x2F;li&gt;
&lt;li&gt;I add my own commits to the git repository if needed&lt;&#x2F;li&gt;
&lt;li&gt;I can now build the package!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That last step can still be difficult, but at least it&#x27;s nice to be able to work with a familiar git environment with branches, stashes, cherry-picks, etc.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, there is (yet another) wrapper to facilitate working with Debian packages that are maintained in git repositories: &lt;code&gt;git-buildpackage&lt;&#x2F;code&gt;.
It can integrate with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pbuilder-team.pages.debian.net&#x2F;pbuilder&#x2F;&quot;&gt;pbuilder&lt;&#x2F;a&gt; to build package in a chroot.&lt;&#x2F;p&gt;
&lt;p&gt;I found this particular guide to be quite useful: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.debian.org&#x2F;~debalance&#x2F;packaging-with-git.html&quot;&gt;https:&#x2F;&#x2F;people.debian.org&#x2F;~debalance&#x2F;packaging-with-git.html&lt;&#x2F;a&gt;.
The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.debian.org&#x2F;doc&#x2F;manuals&#x2F;maint-guide&#x2F;build.en.html&quot;&gt;Debian maintainer guide&lt;&#x2F;a&gt; is a good resource too.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;hitting-a-wall-at-first&quot;&gt;Hitting a wall at first&lt;&#x2F;h1&gt;
&lt;p&gt;Armed with that knowledge, I quickly tried to build my patched OpenSSH package.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s clone the repository and apply our patch:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git clone https:&#x2F;&#x2F;salsa.debian.org&#x2F;ssh-team&#x2F;openssh.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git checkout trixie&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git apply my-openssh-patch.patch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git commit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -am&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;Apply local patch to fix race condition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we need to initialize a fresh pbuilder chroot (see the guides above):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; DIST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;trixie&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; git-pbuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; create&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now let&#x27;s try to build in the chroot:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; DIST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;trixie&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; gbp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; buildpackage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --git-ignore-branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: info: building openssh using existing .&#x2F;openssh_10.0p1.orig.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: info: using patch list from debian&#x2F;patches&#x2F;series&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: info: local changes detected, the modified files are:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;clientloop.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;mux.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;ssh.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: error: aborting due to unexpected upstream changes, see &#x2F;tmp&#x2F;openssh_10.0p1-4.diff.R0ebST&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: hint: make sure the version in debian&#x2F;changelog matches the unpacked source tree&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: hint: you can integrate the local changes with dpkg-source --commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gbp:error: &amp;#39;git-pbuilder&amp;#39; failed: it exited with 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;OK, it seems that we need to maintain the patch with quilt instead of committing the code change directly to the git repository.
This is annoying but doable.  I must admit I did it by hand by simply copying the patch and editing &lt;code&gt;debian&#x2F;patches&#x2F;series&lt;&#x2F;code&gt;,
and committing the patch (replacing the previous commit).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; DIST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;trixie&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; gbp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; buildpackage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --git-ignore-branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: info: local changes detected, the modified files are:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;clientloop.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;mux.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; openssh&#x2F;ssh.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dpkg-source: error: aborting due to unexpected upstream changes, see &#x2F;tmp&#x2F;openssh_10.0p1-4.diff.R0ebST&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In short, we get the same error, even though this time I didn&#x27;t touch the actual openssh code in the git repository.
I verified several times that I didn&#x27;t make a mistake somewhere, but no, the only commit I added is touching &lt;code&gt;debian&#x2F;patches&lt;&#x2F;code&gt;,
not the upstream code directly.&lt;&#x2F;p&gt;
&lt;p&gt;At the point, I&#x27;m in WTF mode, and I leave this rest for a while.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;hunting-for-the-culprit&quot;&gt;Hunting for the culprit&lt;&#x2F;h1&gt;
&lt;p&gt;Several days later, looking at the problem again, I found a blog post from Colin Watson, OpenSSH&#x27;s Debian maintainer, precisely about converting
the OpenSSH package to the &quot;new&quot; (that is, new as in 2010) quilt format: https:&#x2F;&#x2F;www.chiark.greenend.org.uk&#x2F;~cjwatson&#x2F;blog&#x2F;thoughts-on-3.0-quilt-format.html&lt;&#x2F;p&gt;
&lt;p&gt;According to his article, Colin takes the unusual (but well-motivated) approach of having an already-patched tree in the main git branch,
while other maintainers prefer having their git repository reflect the upstream code: they manage patches either with quilt
or in a separate branch.  Due to this choice, Colin says &lt;em&gt;&quot;it’s a bit awkward to set things up when checking out from revision control&quot;&lt;&#x2F;em&gt;,
because quilt doesn&#x27;t understand that the patches are already applied.
&lt;strong&gt;AH AH!&lt;&#x2F;strong&gt; It seems we got our culprit!&lt;&#x2F;p&gt;
&lt;p&gt;The article mentions an helpful script that sets things up properly, let&#x27;s use it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; debian&#x2F;rules quilt-setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dh&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; quilt-setup&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --with=runit&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dh:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; error: Unknown sequence quilt-setup&lt;&#x2F;span&gt;&lt;span&gt; (choose&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; from: binary binary-arch binary-indep build build-arch build-indep clean install install-arch install-indep&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;make:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;font-style: italic;&quot;&gt; ***&lt;&#x2F;span&gt;&lt;span&gt; [debian&#x2F;rules:122:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; quilt-setup] Error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 255&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Err, so the helpful script doesn&#x27;t exist!&lt;&#x2F;p&gt;
&lt;p&gt;Looking around some more, I found out that the script was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;salsa.debian.org&#x2F;ssh-team&#x2F;openssh&#x2F;-&#x2F;commit&#x2F;d26565af8589d88f824b26f31da493f1056efcf4&quot;&gt;removed in 2014&lt;&#x2F;a&gt;
with a commit message &quot;Initialize git-dpm&quot;.  We are on a good follow-up trail here.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;trying-out-git-dpm&quot;&gt;Trying out git-dpm&lt;&#x2F;h1&gt;
&lt;p&gt;So, let&#x27;s learn to use (yet another) tool to manage Debian packages in a git repository!&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;manpages.debian.org&#x2F;trixie&#x2F;git-dpm&#x2F;git-dpm.1.en.html&quot;&gt;manpage for git-dpm&lt;&#x2F;a&gt; is actually rather helpful.
The only confusing aspect is that Colin is again storing the applied state of patches in the git tree, while git-dpm defaults to store the unapplied state (i.e. upstream state).
It means the branches explanations from the manpage don&#x27;t actually apply to the Debian openssh repository.
It&#x27;s a choice to make when initializing a new repository, see the &lt;code&gt;--patches-applied&lt;&#x2F;code&gt; option).&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, with the right tool, it&#x27;s now straightforward to patch and build the package:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellsession&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ git-dpm checkout-patched&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ git cherry-pick XXX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;  # or git am, git apply + commit, etc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ git-dpm dch -- -i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; DIST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;trixie&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; gbp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; buildpackage&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --git-ignore-branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And I got my patched package &lt;code&gt;openssh-client_10.0p1-7+deb13u4.2_amd64.deb&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;Building Debian package still feels obscure, but at least I learned new tools to manage packages in git.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a bit annoying that different Debian maintainers have different habits, but I feel the ecosystem is already
more homogenenous than it was a few years ago. Besides, once you understand the maintainer&#x27;s logic (especially through
their useful blog posts!), things become easier.&lt;&#x2F;p&gt;
&lt;p&gt;About git-dpm, there is a small downside for me: most commits are merges, which makes it difficult to review historical diff.
My first reflex to understand the packaging of openssh was to look at the commit history:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; debian&#x2F;rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;but this was mostly useless: I could see the introduction of &lt;code&gt;quilt-setup&lt;&#x2F;code&gt; in 2010 but not its removal afterwards, WTF.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out that git doesn&#x27;t display diff for merges by default, but you can ask for them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; git log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -p --first-parent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; debian&#x2F;rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s already more useful, and one more thing I learnt during this small experience!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>BananaPi BPI-F3: bootstraping upstream Debian</title>
        <published>2024-09-30T00:00:00+00:00</published>
        <updated>2024-09-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part2-debian/"/>
        <id>https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part2-debian/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part2-debian/">&lt;p&gt;This post is part of the &lt;strong&gt;Upstream RISC-V&lt;&#x2F;strong&gt; serie:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part0&#x2F;&quot;&gt;The upstream RISC-V experience: running RISC-V hardware with upstream distros&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;Benchmarking RISC-V: VisionFive 2 vs the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;&quot;&gt;VisionFive 2: the hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BananaPi BPI-F3&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;BananaPi BPI-F3: hardware and software overview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;BananaPi BPI-F3: bootstraping upstream Debian&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;debian-bootstrap-method&quot;&gt;Debian bootstrap method&lt;&#x2F;h2&gt;
&lt;p&gt;Since July 2023, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lists.debian.org&#x2F;debian-riscv&#x2F;2023&#x2F;07&#x2F;msg00053.html&quot;&gt;riscv64 is an official Debian architecture&lt;&#x2F;a&gt;.
It means that generating a RISC-V Debian rootfs is really straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;However, &lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;without kernel support&lt;&#x2F;a&gt;, it is not that straightforward to actually install
Debian on RISC-V hardware.&lt;&#x2F;p&gt;
&lt;p&gt;Here, we will run the Bianbu Linux system from a SD card and use it to bootstrap Debian on the internal eMMC storage,
using debootstrap.  For the kernel, we will simply re-use the Bianbu kernel.  This is clearly not ideal but it is the
only way currently (all distributions with early support for this hardware are doing the same).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisite&quot;&gt;Prerequisite&lt;&#x2F;h2&gt;
&lt;p&gt;To follow this tutorial, you will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;a BananaPi BPI-F3&lt;&#x2F;strong&gt;, of course :)  I tried two versions of the hardware: one with 4 GB RAM + 16 GB eMMC, and one with 16 GB RAM + 128 GB eMMC&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;a UART serial-to-USB converter&lt;&#x2F;strong&gt;, necessary to debug things and connect through the serial console&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;a good-quality USB-C power supply&lt;&#x2F;strong&gt;.  Don&#x27;t underestimate this requirement: I spent too much time debugging weird issues on various boards,
and 90% of the time it was caused by the power supply.  I am now using a 45 W laptop power supply that is capable of delivering 12 V
and everything works fine.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;a good-quality micro-SD card&lt;&#x2F;strong&gt; to be able to boot Bianbu Linux.  Again, I spent hours failing to boot any image on this board, even though I
was trying two different SD cards.  It turns out that both were old and not booting correctly for some reason.  A third recent SD card,
a SanDisk Ultra Plus, worked fine.&lt;&#x2F;li&gt;
&lt;li&gt;optionally, a NVMe drive.  Typically you can setup &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; on the NVMe (this is quite standard Linux sysadmin and not explained here)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;debian-installation&quot;&gt;Debian installation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;step-1-boot-bianbu-linux&quot;&gt;Step 1: boot Bianbu Linux&lt;&#x2F;h3&gt;
&lt;p&gt;Get the most recent version of Bianbu from &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;archive.spacemit.com&#x2F;image&#x2F;k1&#x2F;version&#x2F;bianbu&#x2F;&quot;&gt;http:&#x2F;&#x2F;archive.spacemit.com&#x2F;image&#x2F;k1&#x2F;version&#x2F;bianbu&#x2F;&lt;&#x2F;a&gt;.  In particular, version 2 images have a newer kernel.
Use the minimal image for SD card, for instance &lt;code&gt;bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808.img.zip&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On your laptop, unzip the image and flash it to a SD card, for instance using a standard &lt;code&gt;dd&lt;&#x2F;code&gt; copy.&lt;&#x2F;p&gt;
&lt;p&gt;After inserting the SD card on the BPI-F3, it should boot without problem and you will see the login prompt on the serial console.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;step-2-prepare-the-internal-emmc-with-partitions-and-bootloader&quot;&gt;Step 2: prepare the internal eMMC with partitions and bootloader&lt;&#x2F;h3&gt;
&lt;p&gt;Login with user &lt;code&gt;root&lt;&#x2F;code&gt; and password &lt;code&gt;bianbu&lt;&#x2F;code&gt; on the serial console.  Then either continue through the serial console,
or setup networking and SSH to login through SSH.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s partition the internal eMMC storage &lt;code&gt;mmcblk2&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; LANG&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;UTF-8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;EOF&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; sfdisk&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;mmcblk2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;label: gpt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;first-lba: 256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;1 : start=256, size=512, name=unused&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;2 : start=768, size=128, name=env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;3 : start=2048, size=2048, name=opensbi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;4 : start=4096, size=4096, name=uboot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;5 : start=8192, size=400M, name=bootfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;6 : name=rootfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For simplicity, this partition scheme is very similar to the vendor scheme, with a larger boot filesystem.
The first partition is not actually useful on the eMMC, but we need it, otherwise u-boot gets really confused when
it tries to compute which partition is the root partition to pass to the kernel.&lt;&#x2F;p&gt;
&lt;p&gt;Next, you need to obtain the magic bootinfo specific for the eMMC.  Without it, booting will fail.
It can be found in the other zip file (e.g. &lt;code&gt;bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808.zip&lt;&#x2F;code&gt;).
This bootinfo magic and the FSBL (copied from the SD card) will need to be flashed to a special portion of the eMMC.&lt;&#x2F;p&gt;
&lt;p&gt;You can get it directly from the board:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;wget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; http:&#x2F;&#x2F;archive.spacemit.com&#x2F;image&#x2F;k1&#x2F;version&#x2F;bianbu&#x2F;v2.0rc1&#x2F;bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;unzip&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; ..&#x2F;bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; ..&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then flash bootinfo and FSBL (thanks &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stijn.tintel.eu&#x2F;blog&#x2F;2024&#x2F;05&#x2F;19&#x2F;compiling-uboot-bpi-f3&#x2F;&quot;&gt;stintel&lt;&#x2F;a&gt; for the trick to make this part of the eMMC writable):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;sys&#x2F;block&#x2F;mmcblk2boot0&#x2F;force_ro&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; if=bianbu-24.04-minimal-k1-v2.0rc1-release-20240909131808&#x2F;factory&#x2F;bootinfo_emmc.bin of=&#x2F;dev&#x2F;mmcblk2boot0 bs=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;512&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; count=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; if=&#x2F;dev&#x2F;mmcblk0p1 of=&#x2F;dev&#x2F;mmcblk2boot0 bs=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;512&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; seek=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then copy all other bootloader stages from the SD card:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# u-boot env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; if=&#x2F;dev&#x2F;mmcblk0p2 of=&#x2F;dev&#x2F;mmcblk2p2 bs=64K status=progress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# opensbi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; if=&#x2F;dev&#x2F;mmcblk0p3 of=&#x2F;dev&#x2F;mmcblk2p3 bs=64K status=progress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# u-boot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;dd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; if=&#x2F;dev&#x2F;mmcblk0p4 of=&#x2F;dev&#x2F;mmcblk2p4 bs=64K status=progress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;step-3-debootstrap-debian&quot;&gt;Step 3: debootstrap Debian&lt;&#x2F;h3&gt;
&lt;p&gt;Prepare the filesystems for the future &lt;code&gt;&#x2F;boot&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; and mount them:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Create boot and root filesystems&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkfs.ext4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -m 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;mmcblk2p5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkfs.ext4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -m 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;mmcblk2p6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Mount everything&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;mmcblk2p6 &#x2F;mnt&#x2F;target&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;boot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;mmcblk2p5 &#x2F;mnt&#x2F;target&#x2F;boot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then run debootstrap.  Here we include some base packages, feel free to modify the list.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Debootstrap with some base packages&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;PACKAGES&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;openssh-server,systemd-timesyncd,bash-completion,vim,htop,wget,xz-utils,zstd,file,locales,dbus,openssl,ca-certificates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;debootstrap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --arch=riscv64 --include=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;$PACKAGES&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; unstable &#x2F;mnt&#x2F;target http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;step-4-finishing-touches-before-first-boot&quot;&gt;Step 4: finishing touches before first boot&lt;&#x2F;h3&gt;
&lt;p&gt;Copy the kernel, kernel modules, and necessary firmware:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;boot&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;font-style: italic;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;boot&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;usr&#x2F;lib&#x2F;modules &#x2F;mnt&#x2F;target&#x2F;usr&#x2F;lib&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;usr&#x2F;lib&#x2F;firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;usr&#x2F;lib&#x2F;firmware&#x2F;esos.elf &#x2F;mnt&#x2F;target&#x2F;usr&#x2F;lib&#x2F;firmware&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make sure you will be able to login to the system:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Setup a root password for the console&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;root:CHANGEME&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; chpasswd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Setup a SSH key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;.ssh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;YOUR_SSH_KEY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;.ssh&#x2F;authorized_keys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Setup target fstab, using &lt;code&gt;blkid&lt;&#x2F;code&gt; to get the UUID of the new boot and root partitions,
and then editing fstab manually:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;blkid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;etc&#x2F;fstab &#x2F;mnt&#x2F;target&#x2F;etc&#x2F;fstab&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;nano&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;etc&#x2F;fstab&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your fstab file should look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# &amp;lt;file system&amp;gt;     &amp;lt;dir&amp;gt;    &amp;lt;type&amp;gt;  &amp;lt;options&amp;gt;                          &amp;lt;dump&amp;gt; &amp;lt;pass&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX   &#x2F;        ext4    defaults,noatime,errors=remount-ro 0      1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;UUID=YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY   &#x2F;boot    ext4    defaults                           0      2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, setup basic DHCP network, adapt to your need:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;EOF&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;auto end0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;iface end0 inet dhcp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You are now done with the setup, you can umount and shutdown the board:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;umount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&#x2F;boot&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;umount&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;mnt&#x2F;target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;sync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;poweroff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;step-5-first-boot-on-debian&quot;&gt;Step 5: first boot on Debian&lt;&#x2F;h3&gt;
&lt;p&gt;Boot without the SD card: Debian should come up on the serial console!&lt;&#x2F;p&gt;
&lt;p&gt;Login on the serial console and&#x2F;or SSH, and finish the setup according
to your needs,  e.g. set a locale:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;localectl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; set-locale C.UTF-8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;step-6-optional-fix-initramfs-generation&quot;&gt;Step 6 (optional): fix initramfs generation&lt;&#x2F;h3&gt;
&lt;p&gt;If you are playing with kernels, you will quickly discover that an initramfs
built from Debian will hang during boot.  The initramfs provided by Bianbu,
&lt;code&gt;&#x2F;boot&#x2F;initrd.img-6.6.36&lt;&#x2F;code&gt;, works fine though.&lt;&#x2F;p&gt;
&lt;p&gt;This is because a firmware needs to be added to the initramfs (thanks aurel32 for the tip
and hook script below).&lt;&#x2F;p&gt;
&lt;p&gt;First, backup the vendor initramfs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;cp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;boot&#x2F;initrd.img-6.6.36 &#x2F;boot&#x2F;backup-initrd.img-6.6.36&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Install initramfs-tools if needed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; install initramfs-tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then add a hook &lt;code&gt;&#x2F;etc&#x2F;initramfs-tools&#x2F;hooks&#x2F;bianbu-firmware&lt;&#x2F;code&gt; that copies the required firmware into the initramfs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#!&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# List the soft prerequisites here.  This is a space separated list of&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# names, of scripts that are in the same directory as this one, that&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# must be run before this one can be.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PREREQ=&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prereqs()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        echo &amp;quot;$PREREQ&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;case $1 in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# get pre-requisites&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prereqs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prereqs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        exit 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;esac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. &#x2F;usr&#x2F;share&#x2F;initramfs-tools&#x2F;hook-functions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Ensure the esos.elf firmware is included&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;copy_file firmware &amp;quot;&#x2F;usr&#x2F;lib&#x2F;firmware&#x2F;esos.elf&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don&#x27;t forget to make the hook executable, and rebuild the initramfs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; +x &#x2F;etc&#x2F;initramfs-tools&#x2F;hooks&#x2F;bianbu-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;update-initramfs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -u&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reboot to check if everything works fine.  Otherwise, you can also boot back on Bianbu
using the SD card to fix your system.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>BananaPi BPI-F3: hardware and software overview</title>
        <published>2024-09-29T00:00:00+00:00</published>
        <updated>2024-09-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part1-hardware/"/>
        <id>https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part1-hardware/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/riscv-upstream-bpi-f3-part1-hardware/">&lt;p&gt;This post is part of the &lt;strong&gt;Upstream RISC-V&lt;&#x2F;strong&gt; serie:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part0&#x2F;&quot;&gt;The upstream RISC-V experience: running RISC-V hardware with upstream distros&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;Benchmarking RISC-V: VisionFive 2 vs the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;&quot;&gt;VisionFive 2: the hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BananaPi BPI-F3&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;BananaPi BPI-F3: hardware and software overview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;BananaPi BPI-F3: bootstraping upstream Debian&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-bananapi-bpi-f3-hardware&quot;&gt;The BananaPi BPI-F3 hardware&lt;&#x2F;h2&gt;
&lt;p&gt;I recently received several BananaPi BPI-F3 boards from RISC-V International, thanks to them for their support.
After some software experimentation, the boards will be made available to all users of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&#x2F;&quot;&gt;cfarm.net&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This hardware is interesting for a couple of reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;it is the first widely available hardware with &lt;strong&gt;RISC-V Vector Extensions (RVV 1.0)&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;it comes with 8 CPU cores and up to 16 GB of RAM, which is double that of the VisionFive 2&lt;&#x2F;li&gt;
&lt;li&gt;it comes with complete storage connectivity (NVMe, internal eMMC, SD card) and even has a mini-PCIe slot for e.g. a Wi-Fi card&lt;&#x2F;li&gt;
&lt;li&gt;this is a completely different SoC compared to the VisionFive 2: it uses the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.banana-pi.org&#x2F;en&#x2F;BPI-F3&#x2F;SpacemiT_K1_datasheet&quot;&gt;SpacemiT K1 SoC&lt;&#x2F;a&gt; with SpacemiT X60 cores at 1.60 GHz&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;power-consumption-and-performance&quot;&gt;Power consumption and performance&lt;&#x2F;h2&gt;
&lt;p&gt;Initial power measurements and performance benchmarks look quite good.
Overall, it is very similar to the &lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;VisionFive 2 as measured in a previous article&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;single-threaded performance is roughly the same as the VisionFive 2 (but the BPI-F3 has twice as many cores)&lt;&#x2F;li&gt;
&lt;li&gt;power consumption is also similar to the VisionFive 2: around 5 to 8 W when idle, around 13 to 15 W when fully loaded.
These power figures are measured on the 230 V AC side, which means that they are very dependent on the power
adapater: take them with a grain of salt.&lt;&#x2F;li&gt;
&lt;li&gt;CPU frequency scaling works, with 5 steps: 614 MHz, 819 MHz, 1000 MHz, 1.23 GHz, 1.60 GHz.
Idling at 614 MHz saves around 1 W of power compared to idling at 1.60 GHz.  Again, this is very similar to the VisionFive 2.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These measurements were done on Bianbu Linux 2.0rc6, with their vendor kernel based on Linux 6.6.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;EDIT 2024-10-03:&lt;&#x2F;strong&gt; actually, CPU frequency scaling has unfortunate side-effects with the vendor kernel.
When using a dynamic cpupower governor such as &lt;code&gt;powersave&lt;&#x2F;code&gt; or &lt;code&gt;schedutil&lt;&#x2F;code&gt;, a kernel thread starts spinning
at 100% CPU on one core: this is unexpected.  When using a fixed frequency with &lt;code&gt;performance&lt;&#x2F;code&gt; or &lt;code&gt;powersave&lt;&#x2F;code&gt;,
everything is working fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;operating-system-support&quot;&gt;Operating system support&lt;&#x2F;h2&gt;
&lt;p&gt;As usual, the operating system offer from the vendor is clearly unsatisfying.  They provide
a weird &quot;Bianbu Linux&quot; distribution, which seems to be a heavily customised version of Ubuntu.
When trying it, I managed to crash their version of openssl.  They also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.banana-pi.org&#x2F;en&#x2F;BPI-F3&#x2F;BananaPi_BPI-F3#_all_image_download&quot;&gt;provide modified versions
of OpenWrt, Fedora, Armbian&lt;&#x2F;a&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;Overall, I have zero confidence in their software, so I would like to run a standard Debian OS on the board.
The &lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt; will focus on how to install an upstream Debian on the board.&lt;&#x2F;p&gt;
&lt;p&gt;It should be noted that third-party distributions started supporting this board: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.armbian.com&#x2F;bananapi-f3&#x2F;&quot;&gt;Armbian&lt;&#x2F;a&gt;
(official support), &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forum.banana-pi.org&#x2F;t&#x2F;gentoo-on-bpi-f3&#x2F;18389&quot;&gt;Gentoo&lt;&#x2F;a&gt; (unofficial),
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forum.banana-pi.org&#x2F;t&#x2F;irradium-based-on-crux-linux-spacemit-banana-pi-bpi-f3-k1-riscv64&#x2F;17989&quot;&gt;Irradium&lt;&#x2F;a&gt; (never heard of it before).
They all use the vendor u-boot and Linux kernel, for very good (or rather very bad) reasons, see below.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linux-kernel-support&quot;&gt;Linux kernel support&lt;&#x2F;h2&gt;
&lt;p&gt;Unfortunately, we are very far from upstream support in the Linux kernel.&lt;&#x2F;p&gt;
&lt;p&gt;The vendor maintains a custom Linux kernel, with two base kernel versions: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitee.com&#x2F;bianbu-linux&#x2F;linux-6.1&quot;&gt;bianbu 1.0 based on linux 6.1&lt;&#x2F;a&gt;,
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitee.com&#x2F;bianbu-linux&#x2F;linux-6.6&quot;&gt;bianbu 2.0 based on linux 6.6&lt;&#x2F;a&gt;.
These kernels are themselves based on a kernel from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BPI-SINOVOIP&#x2F;pi-linux&#x2F;tree&#x2F;linux-6.6.36-k&quot;&gt;SINOVOIP&lt;&#x2F;a&gt;, with small changes to DTS and cpufreq code.&lt;&#x2F;p&gt;
&lt;p&gt;All the sources are available, which is good, but they are not based on the upstream kernel git tree,
so it&#x27;s hard to figure out what they changed.
I experimented a bit with the bianbu 2.0 kernel, and the code seems to be low-quality.  For instance,
many of their drivers completely fail to build when built as module, so it&#x27;s likely that they were
never tested this way.&lt;&#x2F;p&gt;
&lt;p&gt;On the upstream side, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lore.kernel.org&#x2F;all&#x2F;?q=spacemit&quot;&gt;some initial patches have been posted by the community&lt;&#x2F;a&gt;,
independently from the vendor.
As of now, no code has been merged in the upstream kernel.  Let&#x27;s hope that progress will be made on this front.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rebuilding-a-kernel-for-cfarm95&quot;&gt;Rebuilding a kernel for cfarm95&lt;&#x2F;h2&gt;
&lt;p&gt;Somebody reported an issue when using vector instructions and signals on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&#x2F;machines&#x2F;list&#x2F;&quot;&gt;cfarm95&lt;&#x2F;a&gt;
with the vendor kernel.
It turns out to be a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.kernel.org&#x2F;pub&#x2F;scm&#x2F;linux&#x2F;kernel&#x2F;git&#x2F;stable&#x2F;linux.git&#x2F;commit&#x2F;?id=c27fa53b858b4ee6552a719aa599c250cf98a586&quot;&gt;kernel bug that was fixed recently upstream&lt;&#x2F;a&gt;,
but the vendor kernel does not include this fix.&lt;&#x2F;p&gt;
&lt;p&gt;So, we are now building our own kernel for cfarm95, based on the vendor source + assorted patches.
The build happens here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;framagit.org&#x2F;compile-farm&#x2F;riscv64-kernel-build-bananapi-f3&quot;&gt;https:&#x2F;&#x2F;framagit.org&#x2F;compile-farm&#x2F;riscv64-kernel-build-bananapi-f3&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>VisionFive 2: the hardware</title>
        <published>2024-05-06T00:00:00+00:00</published>
        <updated>2024-05-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/riscv-upstream-part1-vf2-hardware/"/>
        <id>https://blog.bitsofnetworks.org/riscv-upstream-part1-vf2-hardware/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/riscv-upstream-part1-vf2-hardware/">&lt;p&gt;This post is part of the &lt;strong&gt;Upstream RISC-V&lt;&#x2F;strong&gt; serie:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part0&#x2F;&quot;&gt;The upstream RISC-V experience: running RISC-V hardware with upstream distros&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;Benchmarking RISC-V: VisionFive 2 vs the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;&quot;&gt;VisionFive 2: the hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BananaPi BPI-F3&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;BananaPi BPI-F3: hardware and software overview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;BananaPi BPI-F3: bootstraping upstream Debian&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-visionfive-2-hardware-tl-dr&quot;&gt;The VisionFive 2 hardware: TL;DR&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The board comes with a cute transparent case&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The hardware is relatively fast and stable&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;You absolutely need a good power supply, especially if you want to use a NVMe SSD&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hardware-assembly&quot;&gt;Hardware assembly&lt;&#x2F;h2&gt;
&lt;p&gt;The kit came with a cute transparent case that you have to assemble.
Peeling off the protective adhesive can be a bit challenging at first, but
it&#x27;s otherwise straightforward to assemble.
On the board itself, you have to apply the thermal pad on the CPU,
then attach the fan on top of it (again, it can a bit challenging the first time).&lt;&#x2F;p&gt;
&lt;p&gt;The kit also came with a 16 GB eMMC module that you can use as a replacement
for a SD card, and an adapter to be able to plug your eMMC module on a standard
micro-SD slot.  I guess you could technically use both a SD card and the eMMC
module simultaneously on the board, but it has limited usefulness (has anyone tried RAID?)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;riscv-vf2-case.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-vf2-case.334797a40ba497b3.jpg&quot; alt=&quot;VisionFive 2 in its case&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Regarding the NVMe, I found it difficult to attach a SSD firmly in the M.2 slot, but
this is a general woe I have with all M.2 slots on all motherboards.  Most SSD vendors don&#x27;t give you
a screw to attach it, and even if they do, it&#x27;s often not working terribly well.
Here, I ended up bending the NVMe so that it stays in place even with no screw.
It doesn&#x27;t feel right, but maybe this is how it&#x27;s designed to be attached?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;riscv-vf2-nvme.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-vf2-nvme.5f137629ab8b2612.jpg&quot; alt=&quot;NVMe SSD on VisionFive 2&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The DIP switch to select the boot mode is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc-en.rvspace.org&#x2F;VisionFive2&#x2F;Boot_UG&#x2F;VisionFive2_SDK_QSG&#x2F;boot_mode_settings.html&quot;&gt;well-documented&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc-en.rvspace.org&#x2F;VisionFive2&#x2F;Datasheet&#x2F;VisionFive_2&#x2F;boot_mode_pins.html&quot;&gt;elsewhere&lt;&#x2F;a&gt;,
but let&#x27;s include it for completeness.  Interestingly, I couldn&#x27;t manage to load u-boot directly from the eMMC
while it works from the SD card, but that will be a topic for the next article.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;riscv-vf2-bootmode.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-vf2-bootmode.8b224498b9f252ba.jpg&quot; alt=&quot;VisionFive 2 boot modes (from rvspace doc)&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Finally, you will certainly need a serial console, and again the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc-en.rvspace.org&#x2F;VisionFive2&#x2F;Datasheet&#x2F;VisionFive_2&#x2F;gpio_pin_assig.html&quot;&gt;UART pins are well-documented&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware-performance&quot;&gt;Hardware performance&lt;&#x2F;h2&gt;
&lt;p&gt;The VisionFive 2 has a StarFive JH7110 SoC, with 4 SiFive U74 cores at 1.5 GHz.&lt;&#x2F;p&gt;
&lt;p&gt;More than one year ago, I had run &lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;benchmarks of the VisionFive 2&lt;&#x2F;a&gt; (version 1.2A).
The numbers are very encouraging: the board is about as fast and power-efficient as a Raspberry Pi 3B&#x2F;3B+.
Crucially, it is also 50% to 75% faster per-core than previous RISC-V boards.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, it feels quite responsive in interactive usage over SSH, where the VisionFive 1 or the HiFive Unmatched
always felt a bit slow.  I suspect this is combination of reasonable CPU performance and good NVMe performance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-tale-of-weird-kernel-woes-with-a-nvme-drive&quot;&gt;A tale of weird kernel woes with a NVMe drive&lt;&#x2F;h2&gt;
&lt;p&gt;When trying out the board initially, I simply used a SD card and left the NVMe slot empty.
It was working completely fine.&lt;&#x2F;p&gt;
&lt;p&gt;However, as soon as I tried a NVMe SSD (with a patched kernel because there is still no upstream support), I had weird issues:
while a Crucial P3 drive worked correctly, a Samsung 970 EVO Plus drive would fail spectacularly.
The system completely locked up shortly after boot, with RCU stalls and hard lockup printed to the serial console:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.799589] rcu: INFO: rcu_sched detected stalls on CPUs&#x2F;tasks:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.805520] rcu:     3-...0: (10 ticks this GP) idle=d754&#x2F;1&#x2F;0x4000000000000000 softirq=2411&#x2F;2411 fqs=1053&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.814830] rcu:     (detected by 2, t=5256 jiffies, g=1493, q=1059 ncpus=4)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.821618] Task dump for CPU 3:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.824849] task:(udev-worker)   state:R  running task     stack:0     pid:274   ppid:261    flags:0x0000000a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.834769] Call Trace:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   34.837220] [&amp;lt;ffffffff80944056&amp;gt;] __schedule+0x346&#x2F;0xb0e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[   48.279586] watchdog: Watchdog detected hard LOCKUP on cpu 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I initially thought it could be a software issue in the kernel, since the patch series is not yet merged in the upstream kernel.
But at this point the patch series was in its 9th iteration and other people seemed fine.&lt;&#x2F;p&gt;
&lt;p&gt;The next logical culprit is the hardware. I had a second Samsung 970 EVO Plus drive and two other VisionFive 2 boards,
so I tried all combinations: I got mostly the same lockups in all cases, while all boards were still working fine with
the Crucial P3 drive.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, it started to smell like a &lt;strong&gt;power supply&lt;&#x2F;strong&gt; issue: maybe the Samsung SSD was simply consuming more power
than the Crucial SSD?
So I tested several power supplies and got interesting results:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Akashi smart charger 5V&#x2F;2.4A using 230V, model ALT2USBACCH: kernel stalls
as soon as the NVMe drive is present, even if not using it at all&lt;&#x2F;li&gt;
&lt;li&gt;ALLNET USB charger 5V&#x2F;3A using 230V, model KA1803A-EU: works fine when the
NVMe drive is present and unused, but produces kernel stalls when trying
to actually read&#x2F;write data from the NVMe&lt;&#x2F;li&gt;
&lt;li&gt;my phone&#x27;s power supply at 5V&#x2F;2A (but 5V&#x2F;6A in &quot;WarpCharge mode&quot;, whatever it is),
using 230V, model WC0506A3HK: works correctly in all cases, even when actively
using the NVMe&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Clearly, the rating of the power supply had a big impact, and the board seems to be
able to make use of voltage above 5V.&lt;&#x2F;p&gt;
&lt;p&gt;I ended up buying a laptop-class USB-C power supply, a 45 W &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ldlc.com&#x2F;fiche&#x2F;PB00278735.html&quot;&gt;Bluestork NB-PW-45-C&lt;&#x2F;a&gt;,
and I had absolutely no NVMe issue since then.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;While we are still very far from mainstream RISC-V adoption outside of the embedded space,
this is a good board to start tinkering with Linux on RISC-V.  In particular, this is the
first RISC-V board with both reasonably good performance and reasonably good upstream software
support.  The rest of the serie will be dedicated to software support.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The upstream RISC-V experience: running RISC-V hardware with upstream distros</title>
        <published>2024-05-01T00:00:00+00:00</published>
        <updated>2024-05-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/riscv-upstream-part0/"/>
        <id>https://blog.bitsofnetworks.org/riscv-upstream-part0/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/riscv-upstream-part0/">&lt;p&gt;This post is part of the &lt;strong&gt;Upstream RISC-V&lt;&#x2F;strong&gt; serie:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part0&#x2F;&quot;&gt;The upstream RISC-V experience: running RISC-V hardware with upstream distros&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;Benchmarking RISC-V: VisionFive 2 vs the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;&quot;&gt;VisionFive 2: the hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BananaPi BPI-F3&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;BananaPi BPI-F3: hardware and software overview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;BananaPi BPI-F3: bootstraping upstream Debian&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;a-foreword-on-cfarm-net&quot;&gt;A foreword on cfarm.net&lt;&#x2F;h2&gt;
&lt;p&gt;In case you don&#x27;t know about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&#x2F;&quot;&gt;cfarm.net&lt;&#x2F;a&gt; (formerly the GCC Compile Farm), it is
the longest-running and most comprehensive compile farm for free software developers.  We provide SSH access
to machines with many different operating systems and many different CPU architectures.
Currently, we have 6 Linux distributions, 5 other OS, and 7 architecture families (with several variants such as big-endian and little-endian ppc64).
The goal is to help developers to port, build and debug their projets on less common or hard-to-get hardware.&lt;&#x2F;p&gt;
&lt;p&gt;So, of course, we have been very interested in RISC-V: it&#x27;s not every day that a whole new CPU architecture gets
its place in the landscape, and this specific architecture holds very interesting promises of openness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-many-challenges-of-a-new-architecture&quot;&gt;The many challenges of a new architecture&lt;&#x2F;h2&gt;
&lt;p&gt;Adding RISC-V machines to cfarm.net turned out to be a big challenge: for many years, there was no hardware
that was both capable of running Linux and stable enough to provide a compilation service to many concurrent users.
Like many projects, we resorted to QEMU emulation.  It was working mostly fine (especially because user-mode emulation
is reasonably fast on server-class x86 hardware), but it did not provide everything needed: debugging with
&lt;code&gt;gdb&lt;&#x2F;code&gt; was a challenge, and microarchitectural details are obviously different in QEMU compared to real hardware.&lt;&#x2F;p&gt;
&lt;p&gt;When capable RISC-V hardware eventually became available, it came with very custom software,
because the software ecosystem needed time and hardware to support this new architecture properly.  In practice,
it meant custom bootloader, custom kernel, and hacked-up Linux distros.&lt;&#x2F;p&gt;
&lt;p&gt;Now, the lowest-levels of software support (libc, compiler, bootloader, kernel) are definitely ready for RISC-V.
But support for specific hardware is another story.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;making-the-case-for-upstream-software-and-distros&quot;&gt;Making the case for upstream software and distros&lt;&#x2F;h2&gt;
&lt;p&gt;To properly integrate new RISC-V hardware in cfarm.net, we set ourselves a challenge: try to run them with
upstream software and distros as much as possible.  On our side, this makes the machines easier to manage and is more future-proof.
In addition, this offers a more consistent environment to developers using the farm: if their code works on
the farm, there is a good chance it will work on different RISC-V hardware and in a different software environment.&lt;&#x2F;p&gt;
&lt;p&gt;This may feel a bit theoretical, but if you have ever worked with vendor SDKs in the embedded world, you know
the nightmare it quickly becomes: ancient kernels with very questionable hacks, old compilation toolchains,
low-level code that is highly specific to a particular hardware, poor security support, custom and hacky implementations of features that
have since been upstreamed in a different way...  Unfortunately, the RISC-V ecosystem tends to go a bit into
this direction, although it is very far from the worst and we see RISC-V vendors making real efforts to upstream their code.&lt;&#x2F;p&gt;
&lt;p&gt;To give more substance to the argument, here is a list of issues we have encountered so far because of non-upstream code:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Starfive only provides &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rvspace.org&#x2F;en&#x2F;project&#x2F;VisionFive2_Debian_User_Guide&quot;&gt;custom Debian images with a full graphical environment&lt;&#x2F;a&gt;.
This is something we can&#x27;t use in the farm because it&#x27;s a headless environment.  In addition, they seem to be
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rvspace.org&#x2F;en&#x2F;project&#x2F;Building_StarFive_Debian_Image&quot;&gt;based on a Debian snapshot from 2022&lt;&#x2F;a&gt;, and many packages
are customized by Starfive.  This is not a good base to build and debug free software projects on top of it,
because there is no guarantee that another RISC-V system would work the same way.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;the u-boot shipped with the VisionFive boards is old and highly misconfigured, needing workarounds in the operating system.
I reported the issues for the VisionFive v1 and even proposed fixes (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;u-boot&#x2F;pull&#x2F;31&quot;&gt;one&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;u-boot&#x2F;pull&#x2F;32&quot;&gt;two&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;u-boot&#x2F;pull&#x2F;33&quot;&gt;three&lt;&#x2F;a&gt;).  They were eventually merged after one year, but by this time the VisionFive v1 was already more or less abandoned.  The u-boot shipped with VisionFive v2
is better configured, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forum.rvspace.org&#x2F;t&#x2F;nvme-boot-using-visionfive2-software-v2-11-5&#x2F;2464&quot;&gt;doesn&#x27;t provide an easy way to boot an upstream distro from NVMe&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;the non-upstream kernel on the VisionFive v1 caused confusion when &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;open-mpi&#x2F;hwloc&#x2F;issues&#x2F;536&quot;&gt;reporting an issue in a userspace software&lt;&#x2F;a&gt;.
I used the kernel of the VisionFive v1 as an example of correct behaviour, but that was actually due to a downstream change in Starfive&#x27;s patched kernel: the upstream kernel code was still buggy.
This wrong assumption caused &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lkml.org&#x2F;lkml&#x2F;2022&#x2F;7&#x2F;5&#x2F;1568&quot;&gt;much head-scratching to the third-party kernel developer working on a fix&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Of course, I understand that upstream code does not appear magically, and there is always a fuzzy phase during which code is only available in downstream vendor forks.
The point I want to make is the following: &lt;strong&gt;we should not be satisfied until the code is available upstream, as it is the only way to ensure its quality and longevity&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;targeted-hardware-and-current-plans&quot;&gt;Targeted hardware and current plans&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to the awesome support from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;riscv.org&#x2F;&quot;&gt;RISC-V International&lt;&#x2F;a&gt;, we already have received several boards to work on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;VisionFive v2&lt;&#x2F;li&gt;
&lt;li&gt;Milk-V Pioneer&lt;&#x2F;li&gt;
&lt;li&gt;Lichee Pi 4A&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We plan to experiment with upstream distros on these boards, document the installation process, submit fixes upstream if required, and generally smooth out the path to get upstream software up and running on this hardware.
Then, of course, we will make these boards and upstream software freely available to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&#x2F;users&#x2F;new&#x2F;&quot;&gt;all cfarm.net developers&lt;&#x2F;a&gt;
for the foreseeable future.&lt;&#x2F;p&gt;
&lt;p&gt;Expect more blog articles and news as we progress through this plan.&lt;&#x2F;p&gt;
&lt;p&gt;So far, we mostly target &lt;strong&gt;Debian&lt;&#x2F;strong&gt;, &lt;strong&gt;Alpine Linux&lt;&#x2F;strong&gt; and &lt;strong&gt;Arch Linux&lt;&#x2F;strong&gt;, but we are also exploring other OSes such as &lt;strong&gt;OpenBSD&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It should be noted that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ubuntu.com&#x2F;download&#x2F;risc-v&quot;&gt;Ubuntu generally has first-class upstream support for RISC-V boards&lt;&#x2F;a&gt;.
Of course they still need to patch the Linux kernel to support the hardware, but this is currently unavoidable.
In any case, it&#x27;s very nice that a distro is able to offer official images with this level of quality.
Given this, I believe that we have very little to contribute to Ubuntu to make it better.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;long-term-plans&quot;&gt;Long-term plans&lt;&#x2F;h2&gt;
&lt;p&gt;In the long term, we would like to work on vector instructions and virtualisation instructions support,
but this is still a long way to go given the lack of hardware supporting these instructions.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Moving from Pelican to Zola</title>
        <published>2024-01-19T00:00:00+00:00</published>
        <updated>2024-01-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/from-pelican-to-zola/"/>
        <id>https://blog.bitsofnetworks.org/from-pelican-to-zola/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/from-pelican-to-zola/">&lt;p&gt;I have been using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;getpelican.com&#x2F;&quot;&gt;Pelican&lt;&#x2F;a&gt; for almost 10 years for this blog.  It&#x27;s very good and does the job,
but I do find it a bit complex to use, and I wanted to switch to a new theme, so I looked at
alternatives.  Among the current alternatives, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; clearly emerged
as the simplest and most efficient solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-pelican&quot;&gt;From Pelican ...&lt;&#x2F;h2&gt;
&lt;p&gt;I must admit that Pelican is still working fine after 10 years, which is quite a feat for a Python project.&lt;&#x2F;p&gt;
&lt;p&gt;However, over time, I found it was not that intuitive to use, mostly because I write blog articles very infrequently.
Each time, I had to remember how it works: do I have to use the Makefile or the &lt;code&gt;develop_server.sh&lt;&#x2F;code&gt; script?
Did I have a virtualenv somewhere or is it a global install? Why is there a specific config file for publishing?
I had to reinstall Pelican, and now it is complaining that some of my configuration is deprecated (but amazingly,
my old Pelican configuration from 2014 still works without any change)&lt;&#x2F;p&gt;
&lt;p&gt;But the real reason to switch is the theme. I don&#x27;t like HTML&#x2F;CSS, so I was quite happy with a very basic Pelican theme at the time,
but it is showing its age now.  While looking for a newer Pelican theme, I found nothing that I liked much.  So, time to switch!
Since &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deuxfleurs.fr&#x2F;&quot;&gt;Deuxfleurs&lt;&#x2F;a&gt; is using Zola a lot and it seems really simple to use, I went this route.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-zola&quot;&gt;... to Zola&lt;&#x2F;h2&gt;
&lt;p&gt;Most tools advertise themselves as &quot;easy to use&quot;, but that often means &quot;easy to use for the authors&quot;.  But in the case of Zola, it is actually impressively easy to use.
Having a single binary instead of having to play with virtualenvs: a big win.  Having just two main commands &lt;code&gt;zola serve&lt;&#x2F;code&gt; and &lt;code&gt;zola build&lt;&#x2F;code&gt;: a big win.
There are many great themes to use as a base, and extending themes is simple and really well documented.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keeping-compatibility-with-old-urls&quot;&gt;Keeping compatibility with old URLs&lt;&#x2F;h2&gt;
&lt;p&gt;While migrating my content, I encountered a difficulty to maintain compatibility with the old URLs.
I would like to avoid breaking URLs to old articles.&lt;&#x2F;p&gt;
&lt;p&gt;Pelican generates URLs such as &lt;code&gt;&#x2F;blog&#x2F;my-article-slug.html&lt;&#x2F;code&gt;. But Zola would generate &lt;code&gt;&#x2F;blog&#x2F;my-article-slug&#x2F;&lt;&#x2F;code&gt; instead, by putting the content in a &lt;code&gt;index.html&lt;&#x2F;code&gt; file within that directory.
This behaviour is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;issues&#x2F;840&quot;&gt;currently not configurable&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Given this, keeping compatibile URLs seemed like an impossible task, but there is actually a way if you are a bit creative with aliases.
You just have to add an alias with the old name in the front matter of your article:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;title = &amp;quot;My page title&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;aliases = [&amp;quot;posts&#x2F;old-page-name.html&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will still generate the file as usual for Zola (let&#x27;s say &lt;code&gt;blog&#x2F;my-page&#x2F;index.html&lt;&#x2F;code&gt;, exposed as &lt;code&gt;&#x2F;blog&#x2F;my-page&#x2F;&lt;&#x2F;code&gt;),
BUT it will also generate a redirect page at &lt;code&gt;&#x2F;posts&#x2F;old-page-name.html&lt;&#x2F;code&gt;.  This way, old URLs still work and they redirect to the new URL.&lt;&#x2F;p&gt;
&lt;p&gt;Check &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;issues&#x2F;840#issuecomment-1813284418&quot;&gt;issue #840&lt;&#x2F;a&gt; for more details.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;theme-fork&quot;&gt;Theme fork&lt;&#x2F;h2&gt;
&lt;p&gt;I chose the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jimmyff&#x2F;zola-inky&quot;&gt;jimmyff&#x2F;zola-inky&lt;&#x2F;a&gt; theme because it fits my requirements: it&#x27;s very simple but elegant.
In addition, I really like the way it lists articles by year, and the fact that you can show a small excerpt of each article in this list.&lt;&#x2F;p&gt;
&lt;p&gt;However, it was missing a few things for my use-case, so I forked it to add the following features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;styling for tables&lt;&#x2F;li&gt;
&lt;li&gt;allow to override the content of footers easily&lt;&#x2F;li&gt;
&lt;li&gt;use a different set of icons (I needed the Mastodon logo)&lt;&#x2F;li&gt;
&lt;li&gt;stop loading external fonts from Google and scripts from CDN&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.deuxfleurs.fr&#x2F;baptiste&#x2F;zola-inky-fork&quot;&gt;fork is available here&lt;&#x2F;a&gt;. I should find time to try to upstream some of these changes.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, I &lt;a href=&quot;&#x2F;tags&#x2F;&quot;&gt;changed the style of tags&lt;&#x2F;a&gt;, but this is a local change for my blog, not part of the theme (it feels too specific).&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introduction to DevOps for experimental research</title>
        <published>2023-09-18T00:00:00+00:00</published>
        <updated>2023-09-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/devops-tutorial/"/>
        <id>https://blog.bitsofnetworks.org/devops-tutorial/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/devops-tutorial/">&lt;p&gt;I recently gave a full-day training session called &lt;strong&gt;Introduction to DevOps for experimental research&lt;&#x2F;strong&gt;
with several colleagues.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-devops-in-research&quot;&gt;Why DevOps in research?&lt;&#x2F;h2&gt;
&lt;p&gt;At first glance, DevOps and experimental research in computer science have widely different goals:
most of the time, researchers perform experiments using software but they don&#x27;t have to maintain
production systems in the long run!&lt;&#x2F;p&gt;
&lt;p&gt;However, we do have to build, deploy and configure complex software ecosystems to be able to do
experimental research.  In this process, we often need very fine control over the deployment
process, and we need to be extra sure about our results.  Imagine: you measure the impact of
a specific parameter of a PostgreSQL database on the performance of various applications,
and you happily write and publish a paper about it.  Two years later, somebody writes you an email
stating that they obtain completely different performance results with this parameter.  What happened?
Are you sure that you didn&#x27;t mess up your deployment or forgot to restart the database after changing
its configuration?  Do you still have your deployment scripts around, and can you still get them to run
in the same conditions?  Maybe a newer version of PostgreSQL changes the performance results completely?&lt;&#x2F;p&gt;
&lt;p&gt;I believe that these kind of problems in research can (partially) be solved by adapting ideas and tools
from the DevOps ecosystem.  In particular, &lt;strong&gt;automation&lt;&#x2F;strong&gt; is a core concept in DevOps and is definitely
100% necessary in research: this is the first step to improve the quality of research works
that are based on deploying complex software.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;devops-tools-in-research&quot;&gt;DevOps tools in research&lt;&#x2F;h2&gt;
&lt;p&gt;Researchers are more and more using classical DevOps tools: Git, Docker, Terraform, Kubernetes, Ansible...
For general automation, Gitlab CI is particularly appreciated in research because it can be run on independant on-premise infrastucture,
which is often a requirement for publicly-funded research (see this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.inria.fr&#x2F;gitlabci_gallery&quot;&gt;Gitlab CI gallery&lt;&#x2F;a&gt;
for many examples)&lt;&#x2F;p&gt;
&lt;p&gt;But researchers also develop tools that are specific to research problems.  To give just a few examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;kameleon.imag.fr&#x2F;&quot;&gt;Kameleon&lt;&#x2F;a&gt;: a very flexible tool to build customized software appliance (VM images, Docker images, bare-metal images...).  Similar to Packer but much more flexible.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discovery.gitlabpages.inria.fr&#x2F;enoslib&#x2F;&quot;&gt;EnOSlib&lt;&#x2F;a&gt;: a Python library allowing to easily provision hardware resources on research platforms, and then configure them through Ansible&lt;&#x2F;li&gt;
&lt;li&gt;scientific workflow engines such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nextflow.io&#x2F;&quot;&gt;Nextflow&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nipype&#x2F;pydra&quot;&gt;Pydra&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;snakemake.github.io&#x2F;&quot;&gt;SnakeMake&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Scientific_workflow_system&quot;&gt;many others&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;focus-on-reproducibility&quot;&gt;Focus on reproducibility&lt;&#x2F;h2&gt;
&lt;p&gt;A specific concept we need in research is &lt;strong&gt;reproducibility&lt;&#x2F;strong&gt;.  Reproducibility means that somebody else should be
able to take your code and your data and use it to reproduce your research results.  It looks simple, but this is very
hard to achieve in practice: your results also depend on the software environment (OS, libraries, compiler, interpreter...)
and the hardware you run it on.  In addition, this environment evolves very rapidly: if you write moderately complex Python code today,
there is a good chance that you won&#x27;t be able to run it again five years from now.  The language itself and its interpreter will have changed, your
OS will have new versions of everything, your Python dependencies will no longer exist or will have broken compatibility, etc.&lt;&#x2F;p&gt;
&lt;p&gt;DevOps tools are not specifically designed for reproducibility: sure, you can build a Docker image with your code,
its dependencies, and the right version of the Python interpreter.
This image will probably still run fine in five years.  But what if you or somebody else wants to extend this work, for instance
changing a small parameter or updating a single dependency?  In a production system, how would you update dependencies
to fix known security issues that were uncovered in the last five years?
For both problems, you would need to rebuild the Docker image: hopefully, you still have
a Dockerfile around, but it will most likely fail to build (see the examples in the training material below).&lt;&#x2F;p&gt;
&lt;p&gt;If you think about it, DevOps is all about deploying and iterating as fast as possible, and this
does not particularly encourage reproduciblity.  In a modern production systems where a new version is deployed
every day, why would you even try to rebuild your software stack from two years ago?&lt;&#x2F;p&gt;
&lt;p&gt;However, the DevOps tooling situation is improving: tools that focus on full reproducibility such as Nix and Guix are getting mainstream,
and initiatives around the &quot;Software Supply Chain&quot; such as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openssf.org&#x2F;&quot;&gt;OpenSSF&lt;&#x2F;a&gt; are targeting the provenance
of software dependencies, which helps improve reproducibility.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;training-material&quot;&gt;Training material&lt;&#x2F;h2&gt;
&lt;p&gt;This blog article is purposefully short: you can find &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.inria.fr&#x2F;sed-rennes&#x2F;formations&#x2F;devops-tutorial&quot;&gt;all material used for the training here&lt;&#x2F;a&gt;.
This includes slides but also example code for several of the tools that were demonstrated: Docker, Packer, Nix, Guix, Ansible, Terraform and EnOSlib.
Many thanks to the colleagues that contributed to the training and the associated material.&lt;&#x2F;p&gt;
&lt;p&gt;The training does not go a lot in-depth into each tool: the goal is to give an overview of the ecosystem and understand
what each DevOps tool can and cannot do.  It is then up to you to choose the right tool for your specific research problem,
and then learn to use this tool.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Benchmarking RISC-V: VisionFive 2 vs the world</title>
        <published>2023-01-21T00:00:00+00:00</published>
        <updated>2023-01-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/riscv-performance-power-usage/"/>
        <id>https://blog.bitsofnetworks.org/riscv-performance-power-usage/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/riscv-performance-power-usage/">&lt;p&gt;This post is part of the &lt;strong&gt;Upstream RISC-V&lt;&#x2F;strong&gt; serie:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part0&#x2F;&quot;&gt;The upstream RISC-V experience: running RISC-V hardware with upstream distros&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;&quot;&gt;Benchmarking RISC-V: VisionFive 2 vs the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-part1-vf2-hardware&#x2F;&quot;&gt;VisionFive 2: the hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;BananaPi BPI-F3&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part1-hardware&#x2F;&quot;&gt;BananaPi BPI-F3: hardware and software overview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-upstream-bpi-f3-part2-debian&#x2F;&quot;&gt;BananaPi BPI-F3: bootstraping upstream Debian&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;I recently got my &quot;super early bird&quot; version of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.starfivetech.com&#x2F;en&#x2F;site&#x2F;boards&quot;&gt;VisionFive 2 RISC-V board&lt;&#x2F;a&gt;.
As the documentation says, it is supposed to be &lt;em&gt;&quot;the world’s first high-performance RISC-V single board computer (SBC) with an integrated GPU&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since I have access to several kind of RISC-V, ARM and x86 boards, let&#x27;s
see if the claim about performance is true!  We will look both at
processing performance and energy efficiency.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated 2023-01-22:&lt;&#x2F;strong&gt; added Kobol Helios64 performance results from Max&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated 2023-01-23:&lt;&#x2F;strong&gt; added results (performance and power) for Raspberry Pi 3B+&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated 2023-01-24:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;re-done all SBC power measurements, significant changes for VisionFive 2&lt;&#x2F;li&gt;
&lt;li&gt;fixed completely incorrect performance measurements for Raspberry Pi 3B+
caused by a faulty USB cable (causing a huge 2.5x drop in performance!)&lt;&#x2F;li&gt;
&lt;li&gt;re-done measurements for Raspberry Pi 1 with Debian 11 and without the
faulty USB cable&lt;&#x2F;li&gt;
&lt;li&gt;added results for Raspberry Pi 3B, it was not fried after all, it was
also the faulty USB cable&lt;&#x2F;li&gt;
&lt;li&gt;re-done Raspberry Pi 4 power measurements to be more comparable (avoid
POE)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Updated 2024-05-15:&lt;&#x2F;strong&gt; added Raspberry Pi 5 performance results from Denis&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-setup.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-setup.3dd118d6dfce83c6.jpg&quot; alt=&quot;Picture of my setup&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Power measurement setup. The VisionFive 2 is visible at the bottom with
its serial cable, the wattmeter is on the left. The other visible boards
are Raspberry Pis.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-disclaimer-on-methodology&quot;&gt;A disclaimer on methodology&lt;&#x2F;h2&gt;
&lt;p&gt;Benchmarking CPU performance correctly requires a huge software and
hardware expertise, and I can certainly not claim to have such an
expertise.  I have chosen two basic computing primitives, hoping that they
are representative enough: crypto (sha1 and chacha20-poly1305 using
openssl) and decompression (&lt;code&gt;xz&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;All numbers shown in this article are very &quot;unscientific&quot;: I made no
formal repetition to account for variability, and there are many factors
that I purposefully ignore (kernel version, software version,
compiler...).  That being said, I tried to document these parameters as
much as possible to help further analysis.&lt;&#x2F;p&gt;
&lt;p&gt;Overall, the goal is to give a rough idea of the CPU performance and power
efficiency you can expect from RISC-V hardware.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware-and-software-environment&quot;&gt;Hardware and software environment&lt;&#x2F;h2&gt;
&lt;p&gt;The VisionFive 2 has a StarFive JH7110 SoC, with 4 SiFive U74 cores at 1.5 GHz.&lt;&#x2F;p&gt;
&lt;p&gt;The original VisionFive had a StarFive JH7100 SoC with 2 SiFive U74 cores at 1.2 GHz.
It had known hardware design issues: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;linux&#x2F;issues&#x2F;1&quot;&gt;frequent L2 cache flushing needed because of a non-coherent bus&lt;&#x2F;a&gt;
and a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;linux&#x2F;issues&#x2F;27#issuecomment-1371275755&quot;&gt;slow RAM controller&lt;&#x2F;a&gt;.
So, the new SoC should be significantly faster.&lt;&#x2F;p&gt;
&lt;p&gt;Software-wise, I built a Linux kernel using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;starfive-tech&#x2F;linux&quot;&gt;non-upstream repository&lt;&#x2F;a&gt;
(5.18-based for VisionFive 1, and 5.15-based for VisionFive 2).
I built a Debian rootfs using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.debian.org&#x2F;InstallingDebianOn&#x2F;StarFive&#x2F;VisionFiveV1&quot;&gt;Debian guide for VisionFive&lt;&#x2F;a&gt;.
That guide works almost the same way for VisionFive 2, but that (as well as the upstream status for kernel support) will be for another article.&lt;&#x2F;p&gt;
&lt;p&gt;For other systems used in the comparison, they mostly run Debian or
Ubuntu, with a few exceptions (NixOS, Armbian).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cpu-performance&quot;&gt;CPU performance&lt;&#x2F;h2&gt;
&lt;p&gt;Here are the three benchmarks I will use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;openssl speed -evp sha1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;openssl speed -evp chacha20-poly1305&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# https:&#x2F;&#x2F;cdn.kernel.org&#x2F;pub&#x2F;linux&#x2F;kernel&#x2F;v5.x&#x2F;linux-5.10.tar.xz (116606704 bytes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time xz -d &amp;lt; &#x2F;dev&#x2F;shm&#x2F;linux-5.10.tar.xz &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;xz&lt;&#x2F;code&gt; benchmark uses decompression of a known file to ease
reproducibility, and this file is stored in memory (&lt;code&gt;&#x2F;dev&#x2F;shm&lt;&#x2F;code&gt;) to make
sure we have no disk I&#x2F;O.&lt;&#x2F;p&gt;
&lt;p&gt;All benchmarks are using a single CPU core.&lt;&#x2F;p&gt;
&lt;p&gt;I converted all results into MB&#x2F;s for easier comparison, taking the
largest block size for the openssl results (16 KiB).  As a reminder, one
MB equals 1000000 bytes.  For the &lt;code&gt;xz&lt;&#x2F;code&gt; benchmark, the real elapsed time is
used.&lt;&#x2F;p&gt;
&lt;p&gt;To ease comparisons with other hardware, I computed a &quot;speedup&quot; of each
board compared to the VisionFive 2: &lt;code&gt;1x&lt;&#x2F;code&gt; means the same performance, &lt;code&gt;2x&lt;&#x2F;code&gt;
means twice as fast, &lt;code&gt;0.33x&lt;&#x2F;code&gt; means three times as slow, etc.&lt;&#x2F;p&gt;
&lt;p&gt;You can find the full output of the benchmarks for each machine
&lt;a href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-performance-power-usage-data.txt&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Most hardware is either running locally, from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&quot;&gt;Compile
Farm&lt;&#x2F;a&gt;, or from
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.grid5000.fr&#x2F;w&#x2F;Grid5000:Home&quot;&gt;Grid&#x27;5000&lt;&#x2F;a&gt;.  The Celeron G1840T
system belongs to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deuxfleurs.fr&#x2F;&quot;&gt;Deuxfleurs&lt;&#x2F;a&gt;.  The Kobol
Helios64 result is from Max.  Raspberry Pi 3B+ and 4 are courtesy
of $DAYJOB.  Raspberry Pi 5 result is from Denis.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hardware&lt;&#x2F;th&gt;&lt;th&gt;sha1&lt;&#x2F;th&gt;&lt;th&gt;chacha20&lt;&#x2F;th&gt;&lt;th&gt;&lt;code&gt;xz&lt;&#x2F;code&gt; decompr.&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;RISC-V&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;&lt;br&gt;Debian unstable&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;97.5&lt;&#x2F;strong&gt; MB&#x2F;s&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;50.8&lt;&#x2F;strong&gt; MB&#x2F;s&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;4.66&lt;&#x2F;strong&gt; MB&#x2F;s&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;VisionFive 1 (gcc91)&lt;br&gt;Debian unstable&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;64.1&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.66x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;33.0&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.65x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2.68&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.58x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HiFive Unmatched&lt;br&gt;gcc92, Ubuntu 22.04&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;34.7&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.36x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;40.6&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.80x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;3.12&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.67x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;ARM &#x2F; ARM64&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 1&lt;br&gt;Debian 11, armv6l&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;27.3&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.28x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;22.9&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.45x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.928&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.20x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B&lt;br&gt;Debian 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;149&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.53x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;188&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;3.70x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;4.35&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;0.93x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B+&lt;br&gt;Debian 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;174&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.79x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;225&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;4.44x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;5.02&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.08x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 4B&lt;br&gt;Debian 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;192&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.97x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;266&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;5.24x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;6.82&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.46x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 5&lt;br&gt;RaspiOS, Debian 12&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1437&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;14.7x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;703&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;13.9x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;14.4&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;3.09x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kobol Helios64&lt;br&gt;Armbian 22.02.1&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;979&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;10x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;323&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;6.36x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;7.64&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;1.64x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Ampere eMAG&lt;br&gt;gcc185, CentOS 8&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;903&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;9.26x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;296&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;5.83x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;12.3&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;2.64x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Mac M1&lt;br&gt;gcc103, Debian 12&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2244&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;23x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1710&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;33.7x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;21.0&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;4.51x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;x86_64&lt;&#x2F;em&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Celeron G1840T&lt;br&gt;NixOS 22.11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;599&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;6.14x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;678&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;13.3x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;11.2&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;2.40x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Xeon Gold 6130&lt;br&gt;dahu.g5k, Deb. 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1045&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;10.7x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2611&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;51.4x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;17.1&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;3.67x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;i7-8086K&lt;br&gt;Ubuntu 20.04&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1414&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;14.5x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2971&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;58.5x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;22.6&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;4.85x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AMD EPYC 7642&lt;br&gt;neowise.g5k, Deb. 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1706&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;17.5x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1796&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;35.4x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;17.0&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;3.65x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AMD EPYC 7513&lt;br&gt;grat.g5k, Deb. 11&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1875&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;19.2x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2460&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;48.4x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;21.3&lt;&#x2F;strong&gt; MB&#x2F;s&lt;br&gt;(&lt;strong&gt;4.57x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;SHA1 and Chacha20-poly1305 results are very variable, which may be due to
optimizations in certain versions of OpenSSL (vectorisation, assembly
implementation) or even hardware acceleration for SHA1.  They also seem to
be sensitive to memory bandwidth: the Raspberry Pis have much better
memory bandwidth than the RISC-V boards.  In contrast, &lt;code&gt;xz&lt;&#x2F;code&gt; results seem
much more representative of raw CPU performance (clock frequency, CPU
cache, out-of-order execution, memory access patterns...)&lt;&#x2F;p&gt;
&lt;p&gt;To get clock frequency out of the equation, I am now showing &lt;code&gt;xz&lt;&#x2F;code&gt; results
normalized by the clock frequency, measured in &quot;CPU cycles per processed byte&quot;
(basically dividing clock frequency by &lt;code&gt;xz&lt;&#x2F;code&gt; performance).  It should give an
idea of the overall performance of the CPU architecture for this specific
decompression task.  Beware, lower values are now better!&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hardware&lt;&#x2F;th&gt;&lt;th&gt;Max clock frequency&lt;&#x2F;th&gt;&lt;th&gt;&lt;code&gt;xz -d&lt;&#x2F;code&gt; cycles&#x2F;byte&lt;br&gt;(lower is better)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;1.50 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;322&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;VisionFive 1&lt;&#x2F;td&gt;&lt;td&gt;1.20 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;448&lt;&#x2F;strong&gt; (&lt;strong&gt;0.72x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HiFive Unmatched&lt;&#x2F;td&gt;&lt;td&gt;1.20 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;385&lt;&#x2F;strong&gt; (&lt;strong&gt;0.84x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 1&lt;&#x2F;td&gt;&lt;td&gt;0.70 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;754&lt;&#x2F;strong&gt; (&lt;strong&gt;0.43x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B&lt;&#x2F;td&gt;&lt;td&gt;1.20 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;276&lt;&#x2F;strong&gt; (&lt;strong&gt;1.17x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B+&lt;&#x2F;td&gt;&lt;td&gt;1.40 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;279&lt;&#x2F;strong&gt; (&lt;strong&gt;1.15x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 4B&lt;&#x2F;td&gt;&lt;td&gt;1.50 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;220&lt;&#x2F;strong&gt; (&lt;strong&gt;1.46x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 5&lt;&#x2F;td&gt;&lt;td&gt;2.40 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;167&lt;&#x2F;strong&gt; (&lt;strong&gt;1.93x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kobol Helios64&lt;&#x2F;td&gt;&lt;td&gt;1.80 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;236&lt;&#x2F;strong&gt; (&lt;strong&gt;1.37x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Ampere eMAG&lt;&#x2F;td&gt;&lt;td&gt;3.00 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;244&lt;&#x2F;strong&gt; (&lt;strong&gt;1.32x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Mac M1&lt;&#x2F;td&gt;&lt;td&gt;3.00 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;143&lt;&#x2F;strong&gt; (&lt;strong&gt;2.25x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Celeron G1840T&lt;&#x2F;td&gt;&lt;td&gt;2.50 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;223&lt;&#x2F;strong&gt; (&lt;strong&gt;1.44x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Xeon Gold 6130&lt;&#x2F;td&gt;&lt;td&gt;3.70 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;216&lt;&#x2F;strong&gt; (&lt;strong&gt;1.49x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;i7-8086K&lt;&#x2F;td&gt;&lt;td&gt;5.00 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;221&lt;&#x2F;strong&gt; (&lt;strong&gt;1.45x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AMD EPYC 7642&lt;&#x2F;td&gt;&lt;td&gt;3.30 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;194&lt;&#x2F;strong&gt; (&lt;strong&gt;1.66x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AMD EPYC 7513&lt;&#x2F;td&gt;&lt;td&gt;3.65 GHz&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;171&lt;&#x2F;strong&gt; (&lt;strong&gt;1.88x&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Here are some of the main highlights of these results:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2 single-core performance is 52% to 74% higher than
VisionFive 1&lt;&#x2F;strong&gt;.  This is very good compared to the 25% clock frequency
improvement.  When normalizing by the clock frequency, the VisionFive 2
is &lt;strong&gt;39% faster per MHz&lt;&#x2F;strong&gt; compared to the VisionFive 1&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2 is also 25% to 50% faster than the HiFive Unmatched&lt;&#x2F;strong&gt;.
When normalizing by the clock frequency, the VisionFive 2 is &lt;strong&gt;20%
faster per MHz&lt;&#x2F;strong&gt; compared to the Unmatched.  The Unmatched was itself
slightly faster than the VisionFive 1 on a single-core basis.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2 is roughly as fast as a Raspberry Pi 3B&#x2F;3B+&lt;&#x2F;strong&gt; on the &lt;code&gt;xz&lt;&#x2F;code&gt;
benchmark, but much slower for SHA1 and Chacha20.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2 is still around 1.5 slower than a Raspberry Pi 4&lt;&#x2F;strong&gt; (and 5
times slower on Chacha20)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here are other interesting insights:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Raspberry Pi 1 always felt really slow.  Well, now I know it&#x27;s
&lt;em&gt;objectively&lt;&#x2F;em&gt; really slow.  Even when taking into account its low
clock frequency of 700 MHz, performance per MHz is still really poor.&lt;&#x2F;li&gt;
&lt;li&gt;The Intel CPUs (from 2014, 2017 and 2018 respectively) have very similar
performance per MHz for this task, despite being very different in terms
of frequency, number of cores and price.  This indicate that they
basically share the same kind of architectural design.&lt;&#x2F;li&gt;
&lt;li&gt;The Raspberry Pi 4 and the Helios64 have good performance per MHz for a
SoC, even comparable to an $1900 Intel CPU from 2017!  Of course, the
Intel CPU has much more cores, and there may be other workloads where
Intel CPUs are much better.&lt;&#x2F;li&gt;
&lt;li&gt;The AMD EPYC CPUs (Zen 2 and Zen 3) have very good performance per MHz
for this workload, and there is a clear improvement from Zen 2 to Zen 3.&lt;&#x2F;li&gt;
&lt;li&gt;The Raspberry Pi 5 has roughly the same performance per MHz as a Zen 3 CPU,
which is really impressive.&lt;&#x2F;li&gt;
&lt;li&gt;As always, despite being already a few years old, the Mac M1 is even more
impressive and easily smashes all other processors I could test on a per-MHz
basis.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As a final note: remember that this is a single benchmark and is not
representative of all kind of computing workloads.  I suspect &lt;code&gt;xz&lt;&#x2F;code&gt; to be
quite sensitive to the amount of CPU cache and to memory latency.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;energy-consumption&quot;&gt;Energy consumption&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have an idea of CPU performance, the other important criteria
is energy consumption.  Here, I am interested in whole-system energy
consumption.  I could only measure it for systems I have locally, so only
a subset of the previous machines are tested here.  Technically, I could
have used wattmeters available on Grid&#x27;5000, but it makes little sense to
compare the power consumption of a big server with that of a small
embedded board.&lt;&#x2F;p&gt;
&lt;p&gt;All figures below are taken using a basic Perel plug-in wattmeter on
230V.  The wattmeter gives the &quot;active&quot; (or real) power in Watts, as well
as the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Power_factor&quot;&gt;power factor&lt;&#x2F;a&gt;.  All
figures include the power transformer, which is either: an Akashi
ALT2USBACCH USB transformer designed for up to 2.4A (VisionFive 1 &amp;amp; 2,
Raspberry Pis) ; the stock Lenovo power transformer (Celeron G1840T) ; or an
ATX power supply (HiFive Unmatched, i7-8086K).&lt;&#x2F;p&gt;
&lt;p&gt;For each system, I measure power consumption in the following situations:
idle ; 1 CPU core at 100% ; half of CPU cores at 100% ; all CPU cores at 100%
(ignoring hyper-threads).  Each measurement is run for only a few seconds
(still waiting for a steady-state) to avoid thermal throttling.&lt;&#x2F;p&gt;
&lt;p&gt;The workload is a simple infinite loop in bash: &lt;code&gt;while :; do :; done&lt;&#x2F;code&gt;.
All systems run Linux (various versions and distributions), have one NIC
up, and no screen or other peripheral attached.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; I am not very confident in the absolute power values shown below
(because I don&#x27;t really trust the wattmeter &lt;strong&gt;or&lt;&#x2F;strong&gt; the USB transformer).
However, since I did all measurements in the same conditions, the values
are comparable with each other.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hardware&lt;&#x2F;th&gt;&lt;th&gt;Idle&lt;&#x2F;th&gt;&lt;th&gt;1 core&lt;&#x2F;th&gt;&lt;th&gt;Half cores&lt;&#x2F;th&gt;&lt;th&gt;All cores&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;&lt;br&gt;4 cores, 8 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;7.4 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;10.4 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;11.2 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;13.1 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;VisionFive 1&lt;br&gt;2 cores, 8 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;10.6 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;11.1 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;-&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;11.6 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HiFive Unmatched&lt;br&gt;4 cores, 16 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;56.8 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;57.7 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;58.6 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;60.7 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 1&lt;br&gt;1 core, 512 MB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;5.9 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;6.2 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;-&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;-&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B&lt;br&gt;rev 1.2&lt;br&gt;4 cores, 1 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;4.5 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;6.5 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;8.7 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;13.8 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B+&lt;br&gt;4 cores, 1 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;7.0 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;9.7 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;12.2 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;18.0 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 4B&lt;br&gt;rev 1.5&lt;br&gt;4 cores, 2 GB RAM&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;4.6 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;6.8 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;8.3 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;11.1 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Celeron G1840T&lt;br&gt;2 cores&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;12 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;18 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;-&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;23.5 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;i7-8086K&lt;br&gt;6 c. &#x2F; 12 threads&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;23.4 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;61.5 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;79.5 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;112.7 W&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Clearly, the VisionFive 2 is quite power-efficient compared to the older
RISC-V boards.  According to its documentation, it can run without any
headsink or fan for bursty loads (e.g. web browsing), but a fan is
recommended for long computations.  This is consistent with my power
consumption measurements.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, the Raspberry Pi 3B+ has a similar power profile as the
VisionFive 2.  This makes sense because they are in the same class of
devices: same amount of cores, similar maximum clock frequency, similar
performance.  But it&#x27;s still noteworthy that the relatively young SoC
found on the VisionFive 2 has a power consumption that is so similar to
that of the more mature SoC found on the Raspberry Pi 3B+.&lt;&#x2F;p&gt;
&lt;p&gt;We can also observe that Intel is much better at dynamic frequency
scaling, which helps to achieve low power usage when the CPU is idle.  As
far as I know, the SoC in the VisionFive 1 and the HiFive Unmatched have
no frequency scaling, which explains their near-constant power usage.  The
VisionFive 2 does have frequency scaling, so it&#x27;s already much better
(-45% power usage when idle compared to fully loaded).&lt;&#x2F;p&gt;
&lt;p&gt;Here are some details about the hardware to put these numbers into context:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 1&lt;&#x2F;strong&gt;: no fan, kernel 5.18 (Debian).  Power consumption
changes significantly with die temperature (9 W idle at 36 °C, 10.4 W idle at 50 °C)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;: no fan, kernel 5.15 (Debian), no NVMe, 100M NIC.
Using the gigabit NIC would add 0.5 W of power usage.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi 3B&lt;&#x2F;strong&gt;: rev 1.2, 1 GB RAM, no fan, kernel 5.10 (Debian 10).  600 MHz idle frequency, 1.20 GHz max frequency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi 3B+&lt;&#x2F;strong&gt;: 1 GB RAM, no fan, kernel 5.10 (Debian 10).  600 MHz idle frequency, 1.40 GHz max frequency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi 4B&lt;&#x2F;strong&gt;: rev 1.5, 2 GB RAM, no fan, kernel 5.10 (Debian 10).  600 MHz idle frequency, 1.50 GHz max frequency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Celeron G1840T&lt;&#x2F;strong&gt;: 800 MHz idle frequency, 2.5 GHz max frequency.
Lenovo ThinkCentre M73, 4 GB DDR3, ST500LM021-1KJ15 disk.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;i7-8086K&lt;&#x2F;strong&gt;: 800 MHz idle frequency, 4 GHz max frequency, 5 GHz turbo
frequency.  ASRock H310CM-HDV&#x2F;M.2 motherboard, 16 GB + 8 GB DDR4,
Samsung 980 500GB NVMe, ATX power supply, 2 case fans&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;Note: earlier versions of this article used some POE power measurements
from a switch (for the Raspberry Pis, with the POE hat).  After re-doing
the measurements with the USB power supply and plug-in wattmeter, it turns
out that power measurements given by the POE switch were substantially
lower than the wattmeter (probably because the POE switch measurements do
not include the AC-to-DC power converter).  Moreover, POE values were not
stable.  In the end, I decided to remove these POE values and only use the
USB power supply to enable a fair comparison.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cpu-performance-vs-energy&quot;&gt;CPU performance vs. energy&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have both CPU performance and energy consumption, we can mix
the two results to look at energy efficiency.  The most reliable figure in
the table below is &lt;strong&gt;single-core efficiency&lt;&#x2F;strong&gt;: it is obtained by simply
dividing the result of the single-core performance benchmark for &lt;code&gt;xz&lt;&#x2F;code&gt; by
the single-core power consumption.  I also extrapolate some figures for
&lt;strong&gt;all-cores efficiency&lt;&#x2F;strong&gt;, but this value should be taken with a grain of
salt: it is obtained by multiplying single-core performance by the number
of cores (excluding hyper-threads) and dividing the total by the measured
all-cores power consumption.  Many effects such as thermal throttling,
frequency boost for single-core load, and shared cache between cores may
decrease the actual all-cores performance and thus decrease the actual
all-cores efficiency compared to the figures below.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hardware&lt;&#x2F;th&gt;&lt;th&gt;Single-core efficiency&lt;&#x2F;th&gt;&lt;th&gt;All-cores efficiency&lt;br&gt;(extrapolated)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VisionFive 2&lt;&#x2F;strong&gt;&lt;br&gt;(4 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.448&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1.42&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;VisionFive 1&lt;br&gt;(2 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.241&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.462&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HiFive Unmatched&lt;br&gt;(4 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.0541&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.206&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 1&lt;br&gt;(1 core)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.150&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B&lt;br&gt;(4 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.670&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1.26&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 3B+&lt;br&gt;(4 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.517&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1.12&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Raspberry Pi 4B&lt;br&gt;(4 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1.00&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;w&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;2.46&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Celeron G1840T&lt;br&gt;(2 cores)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.622&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.953&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;i7-8086K&lt;br&gt;(6 c. &#x2F; 12 threads)&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;0.367&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1.20&lt;&#x2F;strong&gt; MB&#x2F;s&#x2F;W&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Overall, the VisionFive 2 is much more energy-efficient than existing
RISC-V boards: it is &lt;strong&gt;2 to 3 times more energy-efficient than the
VisionFive 1&lt;&#x2F;strong&gt;, and &lt;strong&gt;7 to 8 times more energy-efficient than the
Unmatched&lt;&#x2F;strong&gt;.  It may seem counter-intuitive that the Unmatched is so
inefficient, but that&#x27;s probably because of its larger form factor,
power-hungry PCIe and DDR4, and the need for an ATX power supply that may
not be super efficient at low power load.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, even though x86_64 hardware is much faster than the
VisionFive 2 (2.4 times to 4.8 times faster), it has roughly the same
energy efficiency!  If you have moderate computing needs, the VisionFive 2
is an efficient alternative to bigger systems.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to the Raspberry Pi 3B and 3B+, the VisionFive 2 again has
&lt;strong&gt;similar energy-efficiency&lt;&#x2F;strong&gt;.  This makes sense because it has roughly
the same performance and the same power consumption.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the Raspberry Pi 4 is the real winner on the efficiency metric:
&lt;strong&gt;the VisionFive 2 is half as energy-efficiency as a Raspberry Pi 4&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;When looking at single-core CPU performance, the VisionFive 2 is roughly
&lt;strong&gt;75% faster than the original VisionFive&lt;&#x2F;strong&gt;.  Since it has twice the core
count, that means a &lt;strong&gt;+150% total performance increase&lt;&#x2F;strong&gt;.  And since it
has a similar power consumption, it is also &lt;strong&gt;2 to 3 times more
energy-efficient&lt;&#x2F;strong&gt;.  So that&#x27;s definitely a very big improvement.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to the HiFive Unmatched (which is not even technically a SBC),
the VisionFive 2 still outperforms it by &lt;strong&gt;50%&lt;&#x2F;strong&gt;, and is &lt;strong&gt;7 to 8 times
more energy-efficient&lt;&#x2F;strong&gt;.  So, as far as I can tell, the claim about
it being a &lt;em&gt;&quot;high-performance RISC-V SBC&quot;&lt;&#x2F;em&gt; is true.&lt;&#x2F;p&gt;
&lt;p&gt;When comparing with Raspberry Pis, the VisionFive 2 is about &lt;strong&gt;as fast as
a Raspberry Pi 3B+&lt;&#x2F;strong&gt;, although much slower on memory-heavy benchmarks, and
also &lt;strong&gt;as energy-efficient&lt;&#x2F;strong&gt;.  However, it is still &lt;strong&gt;46% slower than a
Raspberry Pi 4&lt;&#x2F;strong&gt;, and &lt;strong&gt;two times less energy-efficient&lt;&#x2F;strong&gt;.  As far as I
can tell, both SoC are 28 nm, so we would ideally expect the same
energy-efficiency.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to low-power x86_64 systems, the VisionFive 2 is of course slower
when looking at raw performance, but at the same time it is &lt;strong&gt;as
energy-efficient&lt;&#x2F;strong&gt;.  This is a general advantage that SBCs have over more
complete systems: they have much less peripherals, are less extensible and
have generally lower performance, but they are much more energy-efficient.&lt;&#x2F;p&gt;
&lt;p&gt;Again, remember that all figures discussed here are approximate, and
specific benchmark results cannot be extrapolated to generic performance
results for all applications.&lt;&#x2F;p&gt;
&lt;p&gt;Overall, the VisionFive 2 is a big step in the right direction, and this
kind of RISC-V hardware can definitely compete with recent ARM boards
since they have very similar performance-energy tradeoffs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-pictures&quot;&gt;More pictures&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-box.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-box.9593cdfa2acc87f8.jpg&quot; alt=&quot;VisionFive 2 in its box&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;VisionFive 2 in its box (I removed the antistatic wrapping)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-front.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-front.5f664e4dbd75a163.jpg&quot; alt=&quot;VisionFive 2 front&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Front with audio, 4xUSB, HDMI, 2xNIC (with one being a 100M NIC, specific to the super early bird version)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-rear.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-rear.bab840716641d46c.jpg&quot; alt=&quot;VisionFive 2 rear&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Rear with USB-C power input, reset button, GPIOs&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;riscv-performance-power-usage&#x2F;riscv-back.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;riscv-back.0f1ff4d70a674be2.jpg&quot; alt=&quot;VisionFive 2 back&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Back with NVMe M.2 slot, micro-SD card slot&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debugging eBPF-enabled programs in Docker</title>
        <published>2022-08-13T00:00:00+00:00</published>
        <updated>2022-08-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/debug-bpf-docker-l2tpns/"/>
        <id>https://blog.bitsofnetworks.org/debug-bpf-docker-l2tpns/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/debug-bpf-docker-l2tpns/">&lt;p&gt;These days, I&#x27;m adding XDP offloading to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code.ffdn.org&#x2F;l2tpns&#x2F;l2tpns&#x2F;&quot;&gt;l2tpns&lt;&#x2F;a&gt;,
a L2TP server used in production by several non-profit ISPs in France.&lt;&#x2F;p&gt;
&lt;p&gt;While doing that, I need to test if l2tpns can successfully load
XDP programs into the kernel.  But I don&#x27;t want to run that directly
on my Debian host: it might break network connectivity, and in addition
l2tpns is updating the routing table of the kernel.  So, let&#x27;s just run
l2tpns in Docker and allow it to break things!  It turns out to be not so easy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ebpf-and-xdp&quot;&gt;eBPF and XDP&lt;&#x2F;h3&gt;
&lt;p&gt;As a reminder, XDP is a kernel mechanism that allows you to load custom eBPF programs
that will execute right in the network device driver.  You write your eBPF
program in C, load it in the kernel from userspace with a simple system call,
and from that point on, your program can process network packets in the kernel,
before the rest of the kernel has even started parsing the packets!
For a project like l2tpns, this is extremely powerful, fast and flexible,
because we should be able to offload the bulk of encapsulation&#x2F;desencapsulation
work to the kernel while keeping a lot of flexibility.&lt;&#x2F;p&gt;
&lt;p&gt;That being said, the eBPF ecosystem is still young and is moving fast,
and the whole software architecture to make this work is actually very complex.
In the end, you always end up with weird errors that can be hard to track down,
and especially when trying to run XDP in Docker!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-i-want-to-debug&quot;&gt;What I want to debug&lt;&#x2F;h3&gt;
&lt;p&gt;In this case, I&#x27;m extending l2tpns so that it loads XDP programs on network
interfaces when it starts.  The basic process looks like this with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libbpf&#x2F;libbpf&quot;&gt;libbpf&lt;&#x2F;a&gt;
(error handling omitted):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;char[]&lt;&#x2F;span&gt;&lt;span&gt; xdp_filename &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;&#x2F;path&#x2F;to&#x2F;xdp_prog.o&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;char[]&lt;&#x2F;span&gt;&lt;span&gt; if_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;__u32 ifindex;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; prog_fd &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;= -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; bpf_object &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;obj;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;__u32 xdp_flags &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;&#x2F;&#x2F; Load XDP program into the kernel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;bpf_prog_load&lt;&#x2F;span&gt;&lt;span&gt;(xdp_filename, BPF_PROG_TYPE_XDP,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFB86C;font-style: italic;&quot;&gt;obj&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFB86C;font-style: italic;&quot;&gt;prog_fd&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;&#x2F;&#x2F; Find network interface by name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ifindex &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; if_nametoindex&lt;&#x2F;span&gt;&lt;span&gt;(if_name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;&#x2F;&#x2F; Attach XDP program to network interface&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;bpf_set_link_xdp_fd&lt;&#x2F;span&gt;&lt;span&gt;(ifindex, prog_fd, xdp_flags);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;See the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;xdp-project&#x2F;xdp-tutorial&quot;&gt;xdp-tutorial repository&lt;&#x2F;a&gt;
for more complete examples, but as a starting point this is the basic
functionality I want to debug in Docker.&lt;&#x2F;p&gt;
&lt;p&gt;Most programs manipulating eBPF are leveraging &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libbpf&#x2F;libbpf&quot;&gt;libbpf&lt;&#x2F;a&gt; to do the hard work.
As such, the debugging steps below can be generalized to any eBPF-enabled
userspace program.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;basic-docker-setup&quot;&gt;Basic Docker setup&lt;&#x2F;h3&gt;
&lt;p&gt;To keep things simple, I only want to &lt;strong&gt;run&lt;&#x2F;strong&gt; l2tpns in a container.  I will
keep developing and building on my Debian host.  So, let&#x27;s get started with
a simple Dockerfile that installs the required libraries and creates a minimum
config to make l2tpns happy:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Dockerfile used to test l2tpns during development.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Do not use in production!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; debian:bullseye&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; mkdir -p &#x2F;etc&#x2F;l2tpns; echo &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;&amp;quot;10.10.10.0&#x2F;24&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt; &#x2F;etc&#x2F;l2tpns&#x2F;ip_pool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt update &amp;amp;&amp;amp; apt install -y libbpf0 libcli1.10 iproute2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;VOLUME&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;ENTRYPOINT&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;&amp;quot;&#x2F;src&#x2F;l2tpns&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My Debian host is running Bullseye, so I use the same distro in the container
to make sure I have the same libraries.&lt;&#x2F;p&gt;
&lt;p&gt;Build the image from the Dockerfile:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker build -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; l2tpns:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; Dockerfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then give it a try (from the host, in the l2tpns git repository):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; make&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -j4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# To send all logs to stderr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sed&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -i -e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;s&#x2F;set log_file&#x2F;#set log_file&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Run docker image with parameters&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm -v $PWD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;:&#x2F;src l2tpns:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This yields an error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Can&amp;#39;t open &#x2F;dev&#x2F;net&#x2F;tun: No such file or directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, this first error is unrelated to XDP: l2tpns needs to create a &lt;code&gt;tun&lt;&#x2F;code&gt; interface
and it cannot.  Let&#x27;s fix this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm -v $PWD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;:&#x2F;src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --cap-add=NET_ADMIN --device=&#x2F;dev&#x2F;net&#x2F;tun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; l2tpns:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we start seeing the interesting stuff:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libbpf: Error in bpf_object__probe_loading():Operation not permitted(1).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Couldn&amp;#39;t load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;and&#x2F;or that RLIMIT_MEMLOCK is set to big enough value.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From this point on, I will omit the tun-related options from the examples, but for the specific
case of l2tpns they are still needed&lt;&#x2F;p&gt;
&lt;h3 id=&quot;allowing-the-bpf-syscall&quot;&gt;Allowing the BPF syscall&lt;&#x2F;h3&gt;
&lt;p&gt;Obviously, to load a eBPF program into the kernel, you need to do a syscall at some point.
This is role of the BPF syscall, that is also used for other eBPF-related functionalities.&lt;&#x2F;p&gt;
&lt;p&gt;There is a new &lt;code&gt;CAP_BPF&lt;&#x2F;code&gt; capability that enables the BPF syscal for unprivileged users.
This was introduced in Linux 5.8 according to &lt;code&gt;capabilities(7)&lt;&#x2F;code&gt;, which is good because
Debian bullseye runs a 5.10 kernel.  Let&#x27;s try:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm -v $PWD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;:&#x2F;src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --cap-add=BPF&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; l2tpns:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;docker: Error response from daemon: invalid CapAdd: unknown capability: &amp;quot;CAP_BPF&amp;quot;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Crap.  Maybe my Docker version is too old to know about this capability.  Let&#x27;s just use
a bigger hammer and settle for &lt;code&gt;CAP_SYS_ADMIN&lt;&#x2F;code&gt;, which gives a lot of priviledges, including BPF:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ docker run -it --rm -v $PWD:&#x2F;src --cap-add=SYS_ADMIN l2tpns:latest -c etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libbpf: Error in bpf_object__probe_loading():Operation not permitted(1).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Couldn&amp;#39;t load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;and&#x2F;or that RLIMIT_MEMLOCK is set to big enough value.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well, this is the exact same error as before!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configuring-limits-in-the-container&quot;&gt;Configuring limits in the container&lt;&#x2F;h3&gt;
&lt;p&gt;Helpfully, the error message mentions something about the &quot;memlock&quot; limit.
Let&#x27;s have a look at the limits in a simple Debian bullseye container:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; debian:bullseye &#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;ulimit -a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since &lt;code&gt;ulimit&lt;&#x2F;code&gt; is a shell builtin, we cannot run it directly as the command from Docker.&lt;&#x2F;p&gt;
&lt;p&gt;Result:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time(seconds)        unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file(blocks)         unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data(kbytes)         unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stack(kbytes)        8192&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;coredump(blocks)     unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;memory(kbytes)       unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;locked memory(kbytes) 64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;process              unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nofiles              1048576&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vmemory(kbytes)      unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;locks                unlimited&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rtprio               0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are interested in the &quot;locked memory&quot; limit.  64 KB is indeed on the low side
(try comparing this value with your host system).&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;engine&#x2F;reference&#x2F;commandline&#x2F;run&#x2F;#set-ulimits-in-container---ulimit&quot;&gt;relevant Docker documentation&lt;&#x2F;a&gt;,
we find there&#x27;s an option we can pass to Docker to raise this limit:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm --ulimit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; memlock=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1073741824&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; debian:bullseye &#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;ulimit -l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;1048576&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That looks much better!  Now on the real container:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -it --rm -v $PWD&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;:&#x2F;src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; --ulimit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; memlock=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1073741824 --cap-add=SYS_ADMIN&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; l2tpns:latest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; etc&#x2F;startup-config.default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;libbpf:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;sessions_table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;: failed to create: Invalid argument&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;-22&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, we still have an error, but it looks application-specific (libbpf fails to create
a map that is defined in the l2tpns code).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;EDIT 2022-08-15:&lt;&#x2F;strong&gt; &lt;em&gt;it turned out to be indeed a programming error:
BPF array maps MUST have a 32-bits key size and I was trying to create a map with
a 16-bits key size.  It&#x27;s hard to debug because there is no detailed error reporting,
the syscall simply fails with EINVAL.  Here is what &lt;code&gt;strace&lt;&#x2F;code&gt; is seeing, not really
helpful:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=2, value_size=20,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     max_entries=60000, map_flags=0, inner_map_fd=0,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     map_name=&amp;quot;sessions_table&amp;quot;, map_ifindex=0, btf_fd=0,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     btf_key_type_id=0, btf_value_type_id=0,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     btf_vmlinux_value_type_id=0},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    72)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  = -1 EINVAL (Invalid argument)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;After fixing this bug, libbpf happily creates the map in the kernel:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libbpf: map &amp;#39;sessions_table&amp;#39;: created successfully, fd=8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;So far, after a bit of efforts, I could get basic BPF functionalities to work
in a Docker container for debugging purposes!  Of course, for further debugging,
you would need tools such as &lt;code&gt;bpftools&lt;&#x2F;code&gt; to dump the XDP programs, observe
the behaviour of the program by sending packets to the interface, and so on.
But this part of the work should be quite similar whether using Docker or not.
If this turns out to be more difficult than expected, I will update the article!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Teaching routing and network security — Daily log</title>
        <published>2019-02-13T00:00:00+00:00</published>
        <updated>2019-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/daily-log-teaching-routing-and-network-security/"/>
        <id>https://blog.bitsofnetworks.org/daily-log-teaching-routing-and-network-security/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/daily-log-teaching-routing-and-network-security/">&lt;p&gt;Today I have been mostly teaching or preparing upcoming courses.  I also
had a nice lunch discussion with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;drakkar.imag.fr&#x2F;spip.php?rubrique18&quot;&gt;colleagues&lt;&#x2F;a&gt; on DNS and the
role of transaction IDs, but that story will have to wait until tomorrow!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;teaching-routing&quot;&gt;Teaching routing&lt;&#x2F;h3&gt;
&lt;p&gt;I gave another networking course for first year&#x27;s students today.  This
was the first practical session where they actually had to plug some
cables around: you can imagine the excitement but also the mess!  To make
things even easier, the course was in a new networking lab I had never
been before, so I had to improvise with the hardware lying around.&lt;&#x2F;p&gt;
&lt;p&gt;The students learnt how to configure network interfaces (&lt;code&gt;ifconfig&lt;&#x2F;code&gt;,
&lt;code&gt;route&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;netstat&lt;&#x2F;code&gt; on FreeBSD), and they had to use their prior knowledge
of packet capture and &lt;code&gt;ping&lt;&#x2F;code&gt; to troubleshoot when things didn&#x27;t work as
expected.  They had to form a simple &quot;chain&quot; topology (shown below) with
two subnets, and the computer in the middle needed to be configured as a
router.  They needed to figure out that static routes were required on
both edge computers, so that they knew how to reach the remote subnet
through the router.  Finally, they looked in details at the behaviour of
ARP and the scope of MAC addresses.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;20190213&#x2F;20190213-tproutage.png&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;20190213-tproutage.ffb387a066cf8ed3.png&quot; alt=&quot;Target network topology for the lab&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network-security-course&quot;&gt;Network security course&lt;&#x2F;h3&gt;
&lt;p&gt;I then prepared an upcoming practical session on network security with a
colleague working for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.quarkslab.com&#x2F;&quot;&gt;Quarkslab&lt;&#x2F;a&gt;.  I already
have a good part of the course ready from last year on firewalling and
advanced uses of &lt;code&gt;iptables&lt;&#x2F;code&gt; (including compiling custom BPF programs!).
My colleague wants to add a part where students will practice ARP
spoofing, so we looked at how to integrate that with the existing content.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, he showed me how to automate virtual machine generation
using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.packer.io&#x2F;&quot;&gt;Packer&lt;&#x2F;a&gt;.  This should be really helpful for
future teachers in this course: they will be able to easily customize and
rebuild the virtual machine images used by the students!  Last year, I
installed and configured the virtual machine manually, which makes it hard
to update it or apply the same modifications to a new VM image.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Multipath scheduling simulation — Daily log</title>
        <published>2019-02-12T00:00:00+00:00</published>
        <updated>2019-02-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/daily-log-multipath-scheduling-simulation/"/>
        <id>https://blog.bitsofnetworks.org/daily-log-multipath-scheduling-simulation/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/daily-log-multipath-scheduling-simulation/">&lt;h3 id=&quot;multipath-scheduling&quot;&gt;Multipath scheduling&lt;&#x2F;h3&gt;
&lt;p&gt;Today I mostly worked on my current research project, a &lt;strong&gt;simulator of
multipath multistream scheduling algorithms&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Multipath scheduling is needed when you want to transmit data over several
concurrent paths: which piece of data should be sent on which path?  This
problem has been made visible by &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;multipath-tcp.org&#x2F;&quot;&gt;Multipath
TCP&lt;&#x2F;a&gt;, since the Linux implementation includes
several
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;multipath-tcp.org&#x2F;pmwiki.php&#x2F;Users&#x2F;ConfigureMPTCP&quot;&gt;schedulers&lt;&#x2F;a&gt;
that can be changed at runtime.  Several new schedulers for MPTCP are
being proposed in the academic literature every year: the original
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;conference&#x2F;nsdi12&#x2F;nsdi12-final125.pdf&quot;&gt;LowRTT&lt;&#x2F;a&gt;
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;inl.info.ucl.ac.be&#x2F;system&#x2F;files&#x2F;paper_7.pdf&quot;&gt;its evaluation&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;olivier.mehani.name&#x2F;publications&#x2F;2014kuhn_daps.pdf&quot;&gt;Delay-Aware Packet
Scheduling&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;olivier.mehani.name&#x2F;publications&#x2F;2016ferlin_blest_blocking_estimation_mptcp_scheduler.pdf&quot;&gt;BLocking
ESTimation&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.repository.cam.ac.uk&#x2F;bitstream&#x2F;handle&#x2F;1810&#x2F;279113&#x2F;ecf_extended_abstract_rev1.pdf?sequence=1&quot;&gt;Earliest Completion
First&lt;&#x2F;a&gt;,
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;citation.cfm?id=3197922&quot;&gt;many&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;citation.cfm?id=2910594&quot;&gt;others&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All these algorithms mostly differ in the objective function they try to
optimize or in assumptions that can be made for specific data flows
(&lt;em&gt;e.g.&lt;&#x2F;em&gt; video streaming traffic).  However, they all adopt the semantic of
TCP, which transports a &lt;strong&gt;single flow&lt;&#x2F;strong&gt; of data.  I am interested in
extending the problem for &lt;strong&gt;several streams&lt;&#x2F;strong&gt; (have you heard of QUIC?)
that need to be scheduled on multiple paths.  Instead of a single
optimisation problem, you now end up with several concurrent streams,
where each stream wants to complete as soon as possible!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;writing-a-simulator&quot;&gt;Writing a simulator&lt;&#x2F;h3&gt;
&lt;p&gt;The goal of my simulator is to quickly obtain an intuition on the
behaviour of scheduling algorithms: it provides a graphical and animated
visualisation of what&#x27;s going on over time.  The simulator also allows for
more in-depth exploration, for instance comparing the completion times of
streams for different scheduling algorithms.&lt;&#x2F;p&gt;
&lt;p&gt;Below is a screenshot of the current simulator: it is not very pretty
because that&#x27;s not its goal!  The streams are represented by vertical bars
whose size equals the amount of data remaining to be transmitted, and the
darker parts represent in-flight data.  Below are two paths, each modelled
as a packet queue with a constant-rate service (link capacity) and a fixed
propagation time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;20190212&#x2F;20190212-multipathsim.png&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;blog.bitsofnetworks.org&#x2F;processed_images&#x2F;20190212-multipathsim.83238b54d5e7d51b.png&quot; alt=&quot;Screenshot of the current simulator&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I am writing this simulator in Python thanks to
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.salabim.org&#x2F;&quot;&gt;salabim&lt;&#x2F;a&gt;: this is a really well designed,
easy-to-use and well-documented simulation framework.  I had an initial
simulation prototype working in less than one day, and it took only an
additional day to add graphical visualisation.  One of the reasons it&#x27;s so
easy to use is thanks to Python: I didn&#x27;t want to spend days implementing
complex algorithms in NS-3, even though it would be much more realistic.
At the same time, salabim is reasonably fast once you disable logging and
visualisation.&lt;&#x2F;p&gt;
&lt;p&gt;After working with salabim some more, I did find some limitations: the
programming style around salabim is fine for small simulations, but
quickly becomes a mess for larger projects.  All examples use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;salabim&#x2F;salabim&#x2F;issues&#x2F;13&quot;&gt;lots of
global variables&lt;&#x2F;a&gt;, which
encourages you to write all your code in one file (after all, this is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;salabim&#x2F;salabim&#x2F;blob&#x2F;master&#x2F;salabim.py#L15442&quot;&gt;how
salabim itself is
developed&lt;&#x2F;a&gt;
with its 15k lines in a single file...)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introducing daily logs</title>
        <published>2019-02-12T00:00:00+00:00</published>
        <updated>2019-02-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/daily-logs/"/>
        <id>https://blog.bitsofnetworks.org/daily-logs/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/daily-logs/">&lt;p&gt;As you may have seen, I am not very good at writing regular articles here!
I often get ideas for an article; sometimes I am motivated enough to actually
start writing it; but then, most of the time, I never finish the article.&lt;&#x2F;p&gt;
&lt;p&gt;With my third and (hopefully) last year of PhD going full steam, and still
lots of involvement in community networks, I decided to change my writing
approach and start publishing a daily log of what I do.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-should-you-expect&quot;&gt;What should you expect?&lt;&#x2F;h3&gt;
&lt;p&gt;Content-wise, I will mostly talk about networking, of course!&lt;&#x2F;p&gt;
&lt;p&gt;More precisely, I will cover the following activities:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;my research activities: what I&#x27;m currently working on, interesting
discussions with colleagues, conferences I attend, etc;&lt;&#x2F;li&gt;
&lt;li&gt;my teaching activities, also mostly related to networking;&lt;&#x2F;li&gt;
&lt;li&gt;my non-profit activities in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.grenode.net&quot;&gt;Grenode&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rezine.org&quot;&gt;Rézine&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ffdn.org&quot;&gt;Fédération FDN&lt;&#x2F;a&gt;
and other organisations related to community networks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I may also cover other activities that are not directly related to
networking, for instance
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.openstreetmap.org&#x2F;about&quot;&gt;Openstreetmap&lt;&#x2F;a&gt;, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;portal.cfarm.net&#x2F;&quot;&gt;GCC compile
farm&lt;&#x2F;a&gt;, contribution to various free
software, and so on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;feedback&quot;&gt;Feedback&lt;&#x2F;h3&gt;
&lt;p&gt;Since this is a new exercise for me, I welcome all kind of feedback!  You
can reach me on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;social.atypique.net&#x2F;@zorun&quot;&gt;Mastodon&lt;&#x2F;a&gt; or by email
(&lt;code&gt;root at &amp;lt;the current domain name minus blog&amp;gt;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Etat des points d&#x27;échange Internet en France</title>
        <published>2018-02-11T00:00:00+00:00</published>
        <updated>2018-02-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/ixp-france/"/>
        <id>https://blog.bitsofnetworks.org/ixp-france/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/ixp-france/">&lt;h3 id=&quot;qu-est-ce-qu-un-point-d-echange-internet&quot;&gt;Qu&#x27;est-ce qu&#x27;un point d&#x27;échange Internet ?&lt;&#x2F;h3&gt;
&lt;p&gt;Un &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fr.wikipedia.org&#x2F;wiki&#x2F;Internet_Exchange_Point&quot;&gt;point d&#x27;échange Internet&lt;&#x2F;a&gt;,
ou IXP (Internet eXchange Point), c&#x27;est un endroit où plusieurs opérateurs réseau
s&#x27;interconnectent pour échanger du trafic.&lt;&#x2F;p&gt;
&lt;p&gt;De façon simplifiée, il faut voir ça comme un gros switch Ethernet sur lequel
chaque opérateur réseau va se brancher, à l&#x27;aide d&#x27;un câble RJ45 ou une fibre optique.
Oui oui, on parle bien du même genre de switch Ethernet que vous avez sûrement chez
vous pour brancher vos ordinateurs, juste un peu plus rapide et fiable (et donc plus cher).&lt;&#x2F;p&gt;
&lt;p&gt;Dans la réalité, la plupart des IXP ont une architecture plus complexe, avec plusieurs switches
dans différentes baies d&#x27;un datacenter, et des points de présence (&quot;PoP&quot; pour &quot;Point of Presence&quot;)
dans plusieurs datacenters, reliés entre eux avec des fibres optiques.  Mais le principe reste le même.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;analyse-des-points-d-echange-internet&quot;&gt;Analyse des points d&#x27;échange Internet&lt;&#x2F;h3&gt;
&lt;p&gt;Récemment, le centre de recherche &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.caida.org&#x2F;home&#x2F;&quot;&gt;CAIDA&lt;&#x2F;a&gt; a publié
un &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.caida.org&#x2F;data&#x2F;ixps&#x2F;&quot;&gt;jeu de données sur les IXP&lt;&#x2F;a&gt;.  Du coup je me
suis dit que j&#x27;allais regarder ce qu&#x27;il y a dedans !&lt;&#x2F;p&gt;
&lt;p&gt;C&#x27;est intéressant d&#x27;avoir une vision globale du paysage des IXPs, parce qu&#x27;ils dessinent
une grande partie de l&#x27;architecture physique d&#x27;Internet (qui est, je le rappelle, justement
une interconnexion de réseaux).&lt;&#x2F;p&gt;
&lt;p&gt;Regardons d&#x27;abord quelles informations sont disponibles :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; tail&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; +2 ixs_201712.jsonl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;select(.name == &amp;quot;France-IX&amp;quot;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ce qui donne :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;France-IX&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;city&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;Paris&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;country&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;FR&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;sources&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;pdb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;wiki&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;pch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;looking&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;alternatenames&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;Mix Internet Exchange and Transit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;FNIX6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;France Internet Exchange &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;geo_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 2988507&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;region&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;Paris&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;pch_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 74&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;http:&#x2F;&#x2F;www.mixt.net&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;http:&#x2F;&#x2F;www.fnix6.net&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;pdb_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 68&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;pdb_org_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 147&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;alternativenames&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;French National Internet Exchange IPv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;ix_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 377&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FD;&quot;&gt;org_id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BE9FE;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 23&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On peut déjà remarquer plusieurs choses :&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;les données viennent de différentes sources, comme &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.caida.org&#x2F;data&#x2F;ixps&#x2F;&quot;&gt;indiqué ici&lt;&#x2F;a&gt; :
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;peeringdb.com&#x2F;&quot;&gt;PeeringDB&lt;&#x2F;a&gt;, la &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_Internet_exchange_points&quot;&gt;page Wikipédia sur les points d&#x27;échanges&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prefix.pch.net&#x2F;applications&#x2F;ixpdir&#x2F;menu_download.php&quot;&gt;PCH&lt;&#x2F;a&gt;, et &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.bgplookingglass.com&#x2F;ixp-database&quot;&gt;bgplookingglass.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;c&#x27;est un peu le bazar...  En recoupant les différentes sources, CAIDA a associé
des points d&#x27;échange qui n&#x27;ont rien à voir les uns avec les autres (FranceIX, MIXT, FNIX6) !
Là encore, la méthode utilisée est décrite sur &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.caida.org&#x2F;data&#x2F;ixps&#x2F;&quot;&gt;la page du jeu de données&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Ensuite, on voit qu&#x27;on peut facilement filtrer par pays :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; tail&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; +2 ixs_201712.jsonl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; jq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;select(.country == &amp;quot;FR&amp;quot;) | .name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; wc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;42&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Il semble donc y avoir 42 IXPs en France (modulo les doublons et erreurs), ça ne s&#x27;invente pas :)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;les-points-d-echange-en-france&quot;&gt;Les points d&#x27;échange en France&lt;&#x2F;h3&gt;
&lt;p&gt;Après nettoyage manuel des doublons et des vieux IXPs qui ont disparus, il reste environ 21 points d&#x27;échange
en France, ce qui reste un nombre conséquent !&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.auvernix.org&#x2F;&quot;&gt;Auvernix&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1019&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1670&quot;&gt;Breizhix&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.de-cix.net&#x2F;en&#x2F;locations&#x2F;france&#x2F;marseille&quot;&gt;DE-CIX Marseille&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1149&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.equinix-ix.fr&#x2F;&quot;&gt;Equinix Paris&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;255&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.eurogix.net&quot;&gt;EuroGIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;148&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.fnix6.net&#x2F;&quot;&gt;FNIX6&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;68&quot;&gt;PeeringDB&lt;&#x2F;a&gt;) : n&#x27;a plus l&#x27;air très actif, mais le site web marche toujours et il y a quelques membres connectés d&#x27;après PeeringDB&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.franceix.net&quot;&gt;FranceIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;359&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.franceix.net&#x2F;fr&#x2F;france-ix-marseille&#x2F;&quot;&gt;FranceIX Marseille&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;880&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.fr-ix.fr&#x2F;&quot;&gt;FR-IX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;410&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.grenoblix.net&#x2F;&quot;&gt;GrenoblIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1428&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lyonix.net&#x2F;&quot;&gt;LyonIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;69&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.renater.fr&#x2F;guyanix?lang=fr&quot;&gt;Guyanix&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1134&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;hopus.net&#x2F;&quot;&gt;Hopus&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1320&quot;&gt;PeeringDB&lt;&#x2F;a&gt;) : pas vraiment un IXP, mais présent dans les données CAIDA et PeeringDB&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lillix.fr&#x2F;&quot;&gt;Lillix&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;881&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.netix.net&#x2F;&quot;&gt;NetIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;699&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1040&quot;&gt;NormandIX&lt;&#x2F;a&gt; : encore en projet ?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.ouestix.fr&#x2F;&quot;&gt;OuestIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;1312&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;40&quot;&gt;PARIX&lt;&#x2F;a&gt; : n&#x27;a plus l&#x27;air très actif, le site web est down, mais il y encore des membres connectés d&#x27;après PeeringDB&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.renater.fr&#x2F;reunix&quot;&gt;REUNIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;381&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.sfinx.fr&#x2F;&quot;&gt;SFINX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;34&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.touix.net&#x2F;&quot;&gt;TouIX&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;ix&#x2F;336&quot;&gt;PeeringDB&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Contrairement à ce qu&#x27;on pourrait penser, il n&#x27;y a que 4 points d&#x27;échanges actifs à Paris :
FranceIX, FR-IX, Equinix et SFINX (ainsi que Hopus, qui n&#x27;est pas vraiment un IXP).
Tous les autres (environ 13 actifs) sont donc soit en région, soit en outre-mer.&lt;&#x2F;p&gt;
&lt;p&gt;C&#x27;est étonnant quand on sait que l&#x27;Internet français est ultra-centralisé sur Paris
(heureusement, ça s&#x27;améliore depuis quelques années, grâce notamment à &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rezopole.net&#x2F;fr&#x2F;&quot;&gt;Rézopole&lt;&#x2F;a&gt;).
D&#x27;ailleurs, il y a historiquement eu beaucoup de points d&#x27;échange à Paris, mais la plupart sont morts
ou ont été absorbés.&lt;&#x2F;p&gt;
&lt;p&gt;On peut analyser cette rareté relative des points d&#x27;échanges à Paris, ainsi que leur prolifération
en région et en outre-mer, de plusieurs manières :&lt;&#x2F;p&gt;
&lt;h4 id=&quot;les-ixp-permettent-de-developper-le-territoire-local&quot;&gt;Les IXP permettent de développer le territoire local&lt;&#x2F;h4&gt;
&lt;p&gt;Les points d&#x27;échange sont importants pour développer le réseau sur le territoire local, puisqu&#x27;ils
permettent aux opérateurs locaux de s&#x27;échanger du trafic directement, sans passer par les gros noeuds
d&#x27;interconnexion comme Paris, Londres ou Amsterdam.  Ça permet de réduire la latence et le coût,
et de moins dépendre d&#x27;infrastructures qui deviennent critiques de par leur concentration
(par exemple &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.peeringdb.com&#x2F;fac&#x2F;53&quot;&gt;TH2&lt;&#x2F;a&gt; à Paris concentre une grosse partie des interconnexions de l&#x27;Internet français...).
En somme, décentraliser et relocaliser le réseau, ce qui a des vertus non seulement techniques et économiques,
mais également humaines : cela permet aussi de relocaliser les compétences techniques.&lt;&#x2F;p&gt;
&lt;p&gt;C&#x27;est d&#x27;autant plus important en outre-mer !  Imaginons un abonné à La Réunion qui veut accéder à un serveur
hébergé également à La Réunion.  Sans point d&#x27;échange local, sa requête passera par une fibre sous-marine,
parcourera probablement quelques centaines ou milliers de kilomètres, et reviendra par le même chemin...&lt;&#x2F;p&gt;
&lt;p&gt;Du coup, il paraît logique que de plus en plus de régions développent des points d&#x27;échanges Internet en local.
Par exemple, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rezopole.net&#x2F;fr&#x2F;&quot;&gt;Rézopole&lt;&#x2F;a&gt; est financé en partie par la Région Rhône-Alpes pour s&#x27;occuper
de &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lyonix.net&#x2F;fr&#x2F;&quot;&gt;LyonIX&lt;&#x2F;a&gt; et &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.grenoblix.net&#x2F;fr&#x2F;&quot;&gt;GrenoblIX&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;deux-ixp-sur-un-meme-territoire-se-font-concurrence&quot;&gt;Deux IXP sur un même territoire se font concurrence&lt;&#x2F;h4&gt;
&lt;p&gt;Une autre explication, c&#x27;est qu&#x27;il y a peu de place pour plusieurs points d&#x27;échanges sur
un même territoire.  En effet :&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;pour un opérateur, se connecter à un point d&#x27;échange représente &lt;strong&gt;un coût majoritairement fixe&lt;&#x2F;strong&gt;,
qui ne dépend que très peu de la quantité de trafic échangée (contrairement à du transit).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Il faut payer le cablage dans le datacenter, puis le port sur le switch du point d&#x27;échange :
ce dernier coût est souvent lié à la capacité du port (1 Gbit&#x2F;s, 10 Gbit&#x2F;s, etc) et non à
son utilisation réelle.&lt;&#x2F;p&gt;
&lt;p&gt;Du coup, si un opérateur a le choix entre 5 petits points d&#x27;échanges qui permettront au total
d&#x27;échanger 400 Mbit&#x2F;s, et un seul point d&#x27;échange plus gros sur lequel il pourra écouler ses
400 Mbit&#x2F;s, il aura tendance à privilégier le plus gros.&lt;&#x2F;p&gt;
&lt;p&gt;Bien sûr, il y a d&#x27;autres critères de choix (redondance, présence dans plusieurs datacenters,
tarifs, qualité du service) qui font que quelques points d&#x27;échange peuvent cohabiter sur le même territoire,
mais ça limite quand même fortement le potentiel d&#x27;avoir des dizaines d&#x27;IXP au même endroit.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;l&#x27;effet de réseau&lt;&#x2F;strong&gt; joue : comme pour beaucoup de systèmes en réseau, plus un point d&#x27;échange possède
de membres, plus il devient intéressant de s&#x27;y connecter.  En effet, plus de membres présents
signifie d&#x27;avantage de trafic échangé potentiel, pour le même coût fixe.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Cet effet a naturellement tendance à faire grossir les gros IXP et à faire disparaître les petits,
et finit généralement par converger vers un unique IXP sur un territoire donné (sauf à Paris, où la demande
est suffisamment forte et les datacenters suffisamment nombreux pour permettre à quelques IXP
de co-exister ; on peut également voir des IXP avec des politiques très différentes co-exister,
par exemple un IXP académique et un IXP commercial)&lt;&#x2F;p&gt;
&lt;p&gt;Notons qu&#x27;il est quand même possible d&#x27;aller à contre-courant de cet effet de réseau.  Par exemple,
le point d&#x27;échange &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.seattleix.net&#x2F;&quot;&gt;SIX à Seattle&lt;&#x2F;a&gt; a un modèle financier particulier :
les opérateurs payent uniquement des frais d&#x27;accès au service, et ensuite ils peuvent échanger du trafic
sur le point d&#x27;échange sans frais récurrents !   Le &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.minap.it&#x2F;&quot;&gt;MINAP à Milan&lt;&#x2F;a&gt; a un modèle similaire,
à une plus petite échelle, où même les frais d&#x27;accès sont offerts (mais pas les frais de raccordement).&lt;&#x2F;p&gt;
&lt;p&gt;Plus généralement, pas mal de points d&#x27;échange (notamment les petits) sont sponsorisés par des acteurs du marché
télécom local, qui se rendent bien compte des intérêts techniques et politiques de l&#x27;interconnexion locale :
faible latence, contrôle de l&#x27;infrastructure, indépendance.  En outre, les membres du point d&#x27;échange représentent
des clients potentiels, à qui les sponsors du point d&#x27;échange pourront ensuite vendre de l&#x27;hébergement ou du transit !&lt;&#x2F;p&gt;
&lt;h4 id=&quot;la-qualite-de-service-d-un-ixp-doit-etre-irreprochable&quot;&gt;La qualité de service d&#x27;un IXP doit être irréprochable&lt;&#x2F;h4&gt;
&lt;p&gt;Lorsqu&#x27;un point d&#x27;échange commence à grossir, il se pose forcément la question de la qualité du service.&lt;&#x2F;p&gt;
&lt;p&gt;Tant que le point d&#x27;échange connecte le FAI associatif de la ville d&#x27;à côté et les 2 petites boîtes du coin,
les coupures n&#x27;ont pas un impact énorme.  Mais lorsque des centaines de membres sont connectés, certains de grosse taille,
la moindre panne peut impacter des millions d&#x27;utilisateurs finals.&lt;&#x2F;p&gt;
&lt;p&gt;Par ailleurs, pour les opérateurs, cela représente du travail de maintenance et de suivi, qui peut s&#x27;avérer plus lourd
et coûteux que le bénéfice d&#x27;être connecté au point d&#x27;échange.&lt;&#x2F;p&gt;
&lt;p&gt;Les opérateurs ont donc naturellement tendance à privilégier les points d&#x27;échange bien gérés et fiables.
En réponse, les points d&#x27;échanges qui veulent subsister et grossir se donnent les moyens d&#x27;assurer un service fiable :
astreinte 24&#x2F;24, architecture technique redondée, matériel de pointe, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Soyons clair : gérer un point d&#x27;échange de taille raisonnable n&#x27;est pas facile, puisque cela demande à la fois une
forte expertise technique (matériel spécialisé, architecture distribuée sur plusieurs sites) mais il y a aussi une forte
composante relationnelle : la structure opérant le point d&#x27;échange doit interagir avec des centaines de structures hétérogènes,
qui souhaitent toutes avoir un service fonctionnel sans que ça ne leur demande trop de temps de gestion et d&#x27;entretien.&lt;&#x2F;p&gt;
&lt;p&gt;On assiste donc à la fois à un regroupement des compétences, via des structures comme &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rezopole.net&#x2F;fr&#x2F;&quot;&gt;Rézopole&lt;&#x2F;a&gt;
pour éviter de tout réinventer de zéro à chaque IXP, mais aussi à un fort partage de connaissance
et d&#x27;expérience à plus large échelle, avec le &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ripe.net&#x2F;participate&#x2F;ripe&#x2F;wg&#x2F;connect&quot;&gt;RIPE&lt;&#x2F;a&gt; et &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.euro-ix.net&#x2F;&quot;&gt;EuroIX&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;L&#x27;ecosystème des points d&#x27;échange n&#x27;est pas un sujet nouveau, mais il reste fascinant
parce qu&#x27;il entrelace des problématiques techniques et des relations entre structures
parfois très différentes.  Il illustre bien le modèle distribué et pair-à-pair
qui a fait d&#x27;Internet un succès.  On peut par ailleurs constater que certains points
d&#x27;échange sont gérés comme un bien commun !&lt;&#x2F;p&gt;
&lt;p&gt;Si le sujet vous intéresse, le RIPE NCC maintient un &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;labs.ripe.net&quot;&gt;blog collaboratif&lt;&#x2F;a&gt; très actif sur
des sujets liés à Internet en Europe, notamment les &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;labs.ripe.net&#x2F;@@search?Subject%3Alist=ixp&amp;amp;path=&#x2F;labs&quot;&gt;IXP&lt;&#x2F;a&gt;
et le &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;labs.ripe.net&#x2F;@@search?Subject%3Alist=peering&amp;amp;path=&#x2F;labs&quot;&gt;peering&lt;&#x2F;a&gt;.  Toujours sur RIPE labs, Uta Meier-Hahn
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;labs.ripe.net&#x2F;Members&#x2F;uta_meier_hahn&quot;&gt;écrit régulièrement des articles passionnants&lt;&#x2F;a&gt; sur les enjeux des interconnexions
entre opérateurs.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>OVH&#x27;s OverTheBox: Internet access link aggregation using Multipath TCP</title>
        <published>2015-09-24T00:00:00+00:00</published>
        <updated>2015-09-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/ovh-overthebox-mptcp/"/>
        <id>https://blog.bitsofnetworks.org/ovh-overthebox-mptcp/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/ovh-overthebox-mptcp/">&lt;p&gt;OVH announced today its
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ovhtelecom.fr&#x2F;overthebox&#x2F;&quot;&gt;OverTheBox&lt;&#x2F;a&gt; project, which is
basically a link-aggregation solution for Internet access links.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;analysis-of-the-technology&quot;&gt;Analysis of the technology&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;foreword-on-link-aggregation&quot;&gt;Foreword on link aggregation&lt;&#x2F;h4&gt;
&lt;p&gt;First of all, aggregating Internet access links has nothing to do with
classical
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Link_aggregation&quot;&gt;link aggregation&lt;&#x2F;a&gt; (also
called bonding or trunking).  This is a much harder problem, because the
access links typically have very diverse characteristics, in terms of
latency, capacity, and packet loss.&lt;&#x2F;p&gt;
&lt;p&gt;Think of aggregating a DSL line, a FTTH line and a satellite connection.
If you simply send packets in a round-robin fashion, you will basically
get the worst out of each link: packets will be heavily reordered, causing
TCP to fall apart.  The latency of a flow will basically be the latency of
the worst link.  Additionally, packet loss on any of the links will
heavily impact the whole flow.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;technology-used-in-overthebox&quot;&gt;Technology used in OverTheBox&lt;&#x2F;h4&gt;
&lt;p&gt;For OverTheBox, the main technology used by OVH is
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;multipath-tcp.org&#x2F;&quot;&gt;Multipath TCP&lt;&#x2F;a&gt;, often abbreviated as MPTCP.
Multipath TCP basically allows to split a TCP flow across multiple paths,
providing redundancy and increased throughput.  It does so in a clever
way: each subflow runs TCP independently, providing congestion control and
packet loss recovery independently for each path.  A scheduler decides on
which path to send data, based first on the RTT of each path (lower RTT is
preferred) and moving to the next path when the congestion window is
filled.&lt;&#x2F;p&gt;
&lt;p&gt;While Multipath TCP was not initially designed for link aggregation, it
implements all necessary ingredients to do this efficiently.  However, it
only works for TCP traffic, and requires that both ends of a TCP
connection know how to speak Multipath TCP.  This is actually by design:
end hosts are in the best position to discover paths and their associated
characteristics (the typical use-case being a
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;blog.multipath-tcp.org&#x2F;blog&#x2F;html&#x2F;2015&#x2F;07&#x2F;24&#x2F;korea.html&quot;&gt;smartphone with both 4G and Wi-Fi&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;OVH used the Linux implementation of Multipath TCP, and
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ovh&#x2F;overthebox-openwrt&quot;&gt;based its distribution on OpenWRT&lt;&#x2F;a&gt;,
using an existing patch.&lt;&#x2F;p&gt;
&lt;p&gt;Since Multipath TCP is not yet widely deployed in end-hosts, a
link-aggregation solution based on Multipath TCP must be transparent for
the devices behind the aggregation point.  To do this, OVH used a
classical solution based on a VPN.  The idea is to run a VPN protocol able
to tunnel data over TCP, such as OpenVPN.  This way, provided both the VPN
client and servers and MPTCP-compatible, the VPN will automatically use
all available paths, with associated load-balancing and failover benefits.&lt;&#x2F;p&gt;
&lt;p&gt;OVH
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ovh&#x2F;overthebox-feeds&#x2F;tree&#x2F;master&#x2F;vtund&quot;&gt;apparently decided&lt;&#x2F;a&gt;
to use &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;vtun.sourceforge.net&#x2F;&quot;&gt;vtun&lt;&#x2F;a&gt;, which I had never heard of
before.  That being said, there are also
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ovh&#x2F;overthebox-feeds&#x2F;blob&#x2F;master&#x2F;overthebox&#x2F;defaults&#x2F;network.defaults#L53&quot;&gt;references to OpenVPN&lt;&#x2F;a&gt;
in the code, so I am not sure which one they use.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to that, OVH seems to use a transparent SOCKS proxy,
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;shadowsocks.org&#x2F;en&#x2F;index.html&quot;&gt;shadowsocks&lt;&#x2F;a&gt;.  The goal is to avoid
TCP over TCP encapsulation, which is
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;sites.inka.de&#x2F;bigred&#x2F;devel&#x2F;tcp-tcp.html&quot;&gt;notoriously a bad idea&lt;&#x2F;a&gt;.
Thanks to the SOCKS proxy, TCP connections from local clients are
terminated locally, and new TCP connections are established from the other
end of the tunnel towards the destination.  This way, any packet loss on
the path towards the destination does not trigger retransmissions inside
the VPN.&lt;&#x2F;p&gt;
&lt;p&gt;For UDP traffic, I am not sure whether it also goes through the SOCKS
proxy (this is possible with SOCKS5, but would be somewhat useless in this
case) or travels directly on the VPN.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, as a last note, OVH decided to shoot IPv6 in the head by
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ovh&#x2F;overthebox-openwrt&#x2F;commit&#x2F;2c46395abf00fd47c14909d5ac844c2e571dcc7a&quot;&gt;completely ignoring AAAA DNS requests&lt;&#x2F;a&gt;
in their local DNS resolver.  This is a ugly hack, and sounds like a quick
and dirty fix for an issue discovered just before the initial release.  My
guess is that either shadowsocks does not support IPv6, or the IPv6
connectivity provided by some of the access links interferes with the
operation of the OverTheBox box.  I do hope that this is a temporary fix,
because crippling IPv6 like this will certainly not help its deployment.
By the way, Multipath TCP of course fully supports IPv6.&lt;&#x2F;p&gt;
&lt;p&gt;By the way, this analysis is based on a rather quick look at the source
code, and my own experience.  If you think I made a mistake, feel free to
send me an email (contact &lt;em&gt;at&lt;&#x2F;em&gt; the domain name of this blog).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;impact-of-overthebox&quot;&gt;Impact of OverThebox&lt;&#x2F;h3&gt;
&lt;p&gt;As such, this project from OVH merely assembles existing components.  It
introduces nothing new, except maybe a nice web interface (which is
actually non-negligible in terms of user impact).&lt;&#x2F;p&gt;
&lt;p&gt;And indeed, technically speaking, people have already been doing the exact
same thing for a while: Multipath TCP for link aggregation, a VPN such as
OpenVPN for encapsulation, and a transparent SOCKS proxy to terminate
client TCP connections before entering the tunnel.  See for instance
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;listes-2.sipr.ucl.ac.be&#x2F;sympa&#x2F;arc&#x2F;mptcp-dev&#x2F;2014-09&#x2F;msg00098.html&quot;&gt;this mail on the mptcp-dev mailing list&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But this is, to my knowledge, the first open off-the-shelf solution
providing an easy-to-use interface.  What&#x27;s more, OVH
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ovh&#x2F;&quot;&gt;released the code&lt;&#x2F;a&gt;, and the solution should work
just fine with your own VPN server: it does not force you to use OVH
services, which is extremely nice.&lt;&#x2F;p&gt;
&lt;p&gt;This is in huge contrast with existing proprietary solutions for the same
problem, such as the products sold by
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.peplinkworks.com&#x2F;Tech-Load-Balancing.asp&quot;&gt;Peplink&lt;&#x2F;a&gt;.  Their
business model is to sell you the hardware &lt;em&gt;and&lt;&#x2F;em&gt; the service, with
associated licensing fees.  Since the protocol is proprietary, you are
forced to use the Peplink VPN servers (even though they seem to offer to
deploy VPN servers in the cloud, that you can manage through their
provided interface).  OverTheBox is likely to have an effect on this kind
of proprietary businesses.  On the other hand, providers like Peplink can
(and probably should) make a difference by providing custom support for
companies, something that OVH probably won&#x27;t do.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, let us note that there are other solutions to the original
problem, such as &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;zehome.github.io&#x2F;MLVPN&quot;&gt;MLVPN&lt;&#x2F;a&gt; (which is not
based on Multipath TCP).  But OVH clearly has enough weight to make a huge
impact with its nice, integrated solution.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Utiliser IPv6 chez SFR, sans la Neufbox</title>
        <published>2014-08-22T00:00:00+00:00</published>
        <updated>2014-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/ipv6-sfr/"/>
        <id>https://blog.bitsofnetworks.org/ipv6-sfr/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/ipv6-sfr/">&lt;p&gt;&lt;em&gt;Cet article est en français, puisqu&#x27;il est susceptible d&#x27;intéresser
principalement des lecteurs français.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;En France, SFR fournit de l&#x27;IPv6 sur ses accès ADSL et fibre : c&#x27;est très
bien !  En revanche, il ne s&#x27;agit pas d&#x27;une connectivité IPv6 native
(probablement parce que le réseau d&#x27;accès ne fonctionne qu&#x27;en IPv4 pour le
moment).  La connectivité IPv6 est fournie par un tunnel monté au-dessus
d&#x27;IPv4.  Lorsqu&#x27;on utilise la box de SFR, c&#x27;est transparent : la box monte
le tunnel elle-même, et on ne voit rien (à part une MTU un peu faible).&lt;&#x2F;p&gt;
&lt;p&gt;En revanche, si on remplace la box par un routeur à soi (par exemple, sous
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openwrt.org&quot;&gt;OpenWRT&lt;&#x2F;a&gt;), il faut monter le tunnel soi-même si on
veut profiter de l&#x27;IPv6.  Ce n&#x27;est pas si évident à mettre en place
(techniquement, c&#x27;est de l&#x27;IPv6 sur L2TP sur UDP sur IPv4, avec du PPP et
du DHCPv6 pour faire bonne mesure).  Le but de cet article est de
détailler la mise en place du tunnel IPv6 sous OpenWRT, sachant que la
configuration est adaptable pour d&#x27;autre systèmes GNU&#x2F;Linux ou BSD.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configuration-ipv4&quot;&gt;Configuration IPv4&lt;&#x2F;h3&gt;
&lt;p&gt;Obtenir une adresse IPv4 avec un routeur branché sur l&#x27;ONT SFR a déjà été
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.neufbox4.org&#x2F;wiki&#x2F;index.php?title=Bypasser_sa_neufbox#Configurer_le_client_DHCP&quot;&gt;beaucoup&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-tutoriels&#x2F;bypasser-la-neufbox&#x2F;msg101223&#x2F;#msg101223&quot;&gt;documenté&lt;&#x2F;a&gt; :
il suffit de faire du DHCP avec un vendor-id spécifique.  Sous OpenWRT, ça
se traduit par :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# &#x2F;etc&#x2F;config&#x2F;network&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;wan&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; ifname&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;eth0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt; # à adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;dhcp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; vendorid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;neufbox-BypassedNeufBox-DirectConnectionToFTTH-toto@nowhere.xxx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Le vendorid doit en fait simplement commencer par &quot;neufbox&quot;, mais indiquer
que ce n&#x27;est pas une Neufbox semble recommandé, des fois que le support
technique passe par là (même si en pratique, le support de SFR est plutôt
du genre « C&#x27;est bizarre, votre connexion Internet n&#x27;a pas l&#x27;air de
fonctionner. » « Si si, je vous assure, ça marche très bien. » « Ah
bon. »).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;analyse-du-tunnel&quot;&gt;Analyse du tunnel&lt;&#x2F;h3&gt;
&lt;p&gt;La première étape est de déterminer l&#x27;adresse du &lt;strong&gt;LNS&lt;&#x2F;strong&gt; (L2TP Network
Server), qui est le routeur avec lequel le tunnel L2TP est monté.  Pour
monter le tunnel, il y a ensuite deux niveaux d&#x27;authentification :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;une authentification pour monter le tunnel L2TP lui-même.  C&#x27;est
simplement un mot de passe codé en dur, le même pour toutes les
Neufbox : &lt;strong&gt;6pe&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;une authentification PPP, dont le couple login&#x2F;mot de passe est
spécifique à chaque client SFR.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Il faut donc connaître le login et le mot de passe PPP.  Fort
heureusement, la Neufbox envoie ceux-ci en clair lorsqu&#x27;elle établit le
tunnel.&lt;&#x2F;p&gt;
&lt;p&gt;Pour récupérer toutes ces informations, il suffit donc d&#x27;écouter le trafic
de la Neufbox juste après son démarrage.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ecouter-le-trafic-de-la-neufbox&quot;&gt;Écouter le trafic de la Neufbox&lt;&#x2F;h4&gt;
&lt;p&gt;Pour une connexion fibre, c&#x27;est très simple, il suffit de se mettre entre
la Neufbox et l&#x27;ONT.  Voir
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-tutoriels&#x2F;captures-reseau-du-demarrage-et-fonctionnement-de-la-neufbox-6&#x2F;&quot;&gt;cet article&lt;&#x2F;a&gt;
pour plus de détails.&lt;&#x2F;p&gt;
&lt;p&gt;Le plus simple est probablement d&#x27;utiliser une machine sous Linux avec
deux interfaces réseau (par exemple, un laptop avec une carte Ethernet en
USB).  Une interface est branchée sur le port WAN de la Neufbox, l&#x27;autre
est branchée sur l&#x27;ONT.  Ensuite, on bridge les deux interfaces :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo brctl addbr br0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo brctl addif br0 eth0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo brctl addif br0 eth1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo ip link set eth0 up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo ip link set eth1 up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo ip link set br0 up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo sysctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -w&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; net.ipv4.ip_forward=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Il faut aussi s&#x27;assurer que le firewall autorise le forwarding de paquet.
En cas de doute :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; FORWARD ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo iptables&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -F&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Il ne reste plus qu&#x27;à regarder le trafic qui passe :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; sudo tcpdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -n -v -i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;adresse-du-lns&quot;&gt;Adresse du LNS&lt;&#x2F;h4&gt;
&lt;p&gt;Sur ma connexion fibre, l&#x27;adresse du LNS avec lequel la Neufbox établit le
tunnel est &lt;code&gt;109.6.3.95&lt;&#x2F;code&gt;.  Il se peut que le serveur soit différent selon
la région, ou d&#x27;autres critères.  Par exemple, dans la
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-espace-technique&#x2F;captures-reseau-du-demarrage-et-fonctionnement-de-la-neufbox-6&#x2F;msg113347&#x2F;#msg113347&quot;&gt;capture faite par Marin&lt;&#x2F;a&gt;,
le LNS est &lt;code&gt;109.6.1.72&lt;&#x2F;code&gt;.  Un autre utilisateur
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-espace-technique&#x2F;nb6v-edgerouter&#x2F;msg149789&#x2F;#msg149789&quot;&gt;indique&lt;&#x2F;a&gt;
que chez lui, le LNS est &lt;code&gt;109.6.4.36&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Le plus simple est donc d&#x27;écouter le trafic et d&#x27;utiliser le même LNS que
votre Neufbox.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;login-et-mot-de-passe-ppp&quot;&gt;Login et mot de passe PPP&lt;&#x2F;h4&gt;
&lt;p&gt;Le login PPP est manifestement de la forme
&lt;strong&gt;dhcp&#x2F;XX.XX.XX.XX@YYYYYYYYYYYY&lt;&#x2F;strong&gt;, où &lt;code&gt;XX.XX.XX.XX&lt;&#x2F;code&gt; est l&#x27;IPv4 publique de
l&#x27;accès Internet, et &lt;code&gt;YYYYYYYYYYYY&lt;&#x2F;code&gt; est l&#x27;adresse MAC du port WAN de la
Neufbox, sans les &lt;code&gt;:&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Pour le mot de passe PPP, il ne semble pas y avoir de logique
particulière.  Il s&#x27;agit visiblement d&#x27;une chaîne de 16 caractères dans
l&#x27;alphabet &lt;code&gt;[A-Z0-9]&lt;&#x2F;code&gt; (alphanumérique avec uniquement des lettres en
majuscule).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configuration-sous-openwrt-barrier-breaker&quot;&gt;Configuration sous OpenWRT Barrier Breaker&lt;&#x2F;h3&gt;
&lt;p&gt;Tout est dans la &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.openwrt.org&#x2F;doc&#x2F;howto&#x2F;ipv6.softwire&quot;&gt;documentation d&#x27;OpenWRT&lt;&#x2F;a&gt;.  En adaptant pour SFR, ça donne donc :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# &#x2F;etc&#x2F;config&#x2F;network&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; interface 6pe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; proto l2tp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; server&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;109.6.3.95&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt; # à adapter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; username&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;dhcp&#x2F;XX.XX.XX.XX@YYYYYYYYYYYY&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; password&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;ZZZZZZZZZZZZZZZZ&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; keepalive&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;        option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; ipv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;wan6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;    option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; ifname&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;@6pe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;    option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; proto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;dhcpv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ainsi que :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# &#x2F;etc&#x2F;xl2tpd&#x2F;xl2tp-secrets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;* *&lt;&#x2F;span&gt;&lt;span&gt; 6pe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Et hop, ça juste marche (autoconfiguration sur le LAN, règles de firewall,
etc).  Magique, OpenWRT, non ? :)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configuration-pour-d-autres-os-gnu-linux-bsd&quot;&gt;Configuration pour d&#x27;autres OS (GNU&#x2F;Linux, BSD)&lt;&#x2F;h3&gt;
&lt;p&gt;La méthode pédestre, en configurant xl2tpd puis pppd, est également
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.openwrt.org&#x2F;doc&#x2F;howto&#x2F;ipv6.softwire#old.setup.for.aa&quot;&gt;documentée sur le wiki OpenWRT&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Quelqu&#x27;un a également
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-espace-technique&#x2F;nb6v-edgerouter&#x2F;&quot;&gt;essayé avec un EdgeRouter Lite&lt;&#x2F;a&gt;,
et a fini par
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-tutoriels&#x2F;bypasser-la-neufbox-avec-un-routeur-ubiquiti-edgemax&#x2F;msg156358&#x2F;#msg156358&quot;&gt;obtenir une config&lt;&#x2F;a&gt;
pas super propre, mais qui marche.&lt;&#x2F;p&gt;
&lt;p&gt;Notons que le firmware des Neufbox est disponible :
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;neufbox.alwaysdata.net&#x2F;&quot;&gt;http:&#x2F;&#x2F;neufbox.alwaysdata.net&#x2F;&lt;&#x2F;a&gt;.
Notamment, il est possible de récupérer la configuration de &lt;code&gt;xl2tpd&lt;&#x2F;code&gt; et
&lt;code&gt;pppd&lt;&#x2F;code&gt; pour être sûr d&#x27;avoir la même.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;&#x2F;h3&gt;
&lt;p&gt;Le tunnel est monté sur un routeur
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.openwrt.org&#x2F;toh&#x2F;netgear&#x2F;wndr3800#hardware.highlights&quot;&gt;Netgear WNDR3800&lt;&#x2F;a&gt;,
sous OpenWRT Barrier Breaker rc3.  La connexion est une fibre SFR 1G&#x2F;200M.&lt;&#x2F;p&gt;
&lt;p&gt;Les tests sont fait depuis un laptop branché en filaire, vers
&lt;code&gt;ipv6.intuxication.testdebit.info&lt;&#x2F;code&gt;, qui est à environ 10 ms, avec les
commandes suivantes :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Download&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;wget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -O&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;null http:&#x2F;&#x2F;ipv6.intuxication.testdebit.info&#x2F;fichiers&#x2F;1000Mo.dat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6272A4;&quot;&gt;# Upload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -o&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; -F&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt;filecontent=@1000Mo.dat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E9F284;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F1FA8C;&quot;&gt; http:&#x2F;&#x2F;ipv6.intuxication.testdebit.info&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Chaque commande est lancé plusieurs fois en parallèle si nécessaire (pour
remplir le tuyau), et le débit instantané est relevé sur le routeur.
J&#x27;obtiens les débits IP maximaux suivants :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;80 Mbits en upload&lt;&#x2F;li&gt;
&lt;li&gt;105 Mbits en download&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;En upload, un &lt;code&gt;top&lt;&#x2F;code&gt; sur le routeur montre que le CPU passe 100% du temps à
traiter des interruptions logicielles (sirq).  En download, l&#x27;utilisation
CPU est plutôt de l&#x27;ordre de 90%.&lt;&#x2F;p&gt;
&lt;p&gt;Pour comparer, en IPv4 dans les mêmes conditions, j&#x27;obtiens 180 Mbps avec
85% d&#x27;utilisation CPU sur le routeur, le résultat étant identique en
upload et en download.  Visiblement, encapsuler des paquets L2TP est donc
plus coûteux que de les décapsuler.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;Cet article décrit comment utiliser la connectivité IPv6 fournie par SFR
lorsqu&#x27;on remplace la Neufbox par un routeur à soi.  On peut avoir envie
d&#x27;utiliser d&#x27;autres services (téléphone, télévision, etc), mais plein de
gens ont documenté comment faire : voir les liens ci-dessous.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;liens&quot;&gt;Liens&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.openwrt.org&#x2F;doc&#x2F;uci&#x2F;network6&quot;&gt;Configuration IPv6 over L2TP pour OpenWRT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.openwrt.org&#x2F;doc&#x2F;howto&#x2F;ipv6.softwire&quot;&gt;OpenWrt native IPv6-stack&lt;&#x2F;a&gt; (pour OpenWRT Barrier Breaker 14.07)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-tutoriels&#x2F;captures-reseau-du-demarrage-et-fonctionnement-de-la-neufbox-6&quot;&gt;Captures réseau du démarrage et fonctionnement de la Neufbox 6&lt;&#x2F;a&gt; fort intéressant&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.neufbox4.org&#x2F;wiki&#x2F;index.php?title=Bypasser_sa_neufbox&quot;&gt;Bypasser sa neufbox&lt;&#x2F;a&gt; article de référence, même si pas forcément à jour&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lafibre.info&#x2F;sfr-tutoriels&#x2F;bypasser-la-neufbox&#x2F;&quot;&gt;Bypasser la Neufbox Fibre avec un Routeur Linux&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;imil.net&#x2F;wp&#x2F;2013&#x2F;12&#x2F;28&#x2F;bypass-neufbox-6-avec-netbsd&#x2F;&quot;&gt;Bypass neufbox 6 avec NetBSD&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Back to business</title>
        <published>2014-07-23T00:00:00+00:00</published>
        <updated>2014-07-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              zorun
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.bitsofnetworks.org/back-to-business/"/>
        <id>https://blog.bitsofnetworks.org/back-to-business/</id>
        
        <content type="html" xml:base="https://blog.bitsofnetworks.org/back-to-business/">&lt;p&gt;So, writing a blog again.  I had one, years ago.  Hosted at home, like
this one (though it was behind DSL at the time, FTTH wasn&#x27;t as widespread
as it is now).  It was about free software, programming languages
(especially functional), and maybe already some bits of networks.  I
remember writing a long post after discovering network neutrality for the
first time, thanks to a talk by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lqdn.fr&quot;&gt;La Quadrature du Net&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This new blog will be mostly about networks, and how you can use them for
fun and for saving the world (yes, this is overly ambitious).  Overlay
networks, wireless mesh networks, routing protocols, free software, free
hardware, Do-It-Yourself ISPs, community-owned networks...  And probably
other stuff I forgot.&lt;&#x2F;p&gt;
&lt;p&gt;As a general rule, &lt;strong&gt;ideas and principles&lt;&#x2F;strong&gt; behind networks will be
discussed, and not only &quot;how to do this particular thing with that
particular software&quot;.  I strongly believe that networking is not hard,
&lt;strong&gt;provided you understand what you are doing&lt;&#x2F;strong&gt;, which is often the most
difficult part.  Once you know what you are doing, it is relatively easy
to use the available networking tools, or to create new ones.  That being
said, I will definitely provide configuration examples when they are
non-obvious and&#x2F;or use some obscure functionalities.&lt;&#x2F;p&gt;
&lt;p&gt;By the way, this blog will &lt;em&gt;not&lt;&#x2F;em&gt; show &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;ciscoiosxr.tumblr.com&#x2F;&quot;&gt;photos of big Cisco
routers&lt;&#x2F;a&gt;, or explain how to do &lt;em&gt;X&lt;&#x2F;em&gt;
with &lt;em&gt;insert your favourite prioprietary router OS here&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully, this blog will stay up longer than the previous one.  Enjoy
reading, and happy hacking!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
