<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="https://flocknetworks.com/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>https:&#x2F;&#x2F;flocknetworks.com</tabi:base_url>
        <tabi:separator>
            •
        </tabi:separator>
        <tabi:about_feeds>This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader. Visit About Feeds to learn more and get started. It&#x27;s free.</tabi:about_feeds>
        <tabi:visit_the_site>Visit website</tabi:visit_the_site>
        <tabi:recent_posts>Recent posts</tabi:recent_posts>
        <tabi:last_updated_on>Updated on $DATE</tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>Flock Networks</tabi:current_section>
    </tabi:metadata><title>Flock Networks</title>
        <subtitle>Next Generation IP Routing Suite</subtitle>
    <link href="https://flocknetworks.com/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://flocknetworks.com" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-02-03T00:00:00+00:00</updated>
    <id>https://flocknetworks.com/atom.xml</id><entry xml:lang="en">
        <title>Moving to a static website using zola and github pages</title>
        <published>2025-02-03T00:00:00+00:00</published>
        <updated>2025-02-03T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/static-website/" type="text/html"/>
        <id>https://flocknetworks.com/blog/static-website/</id>
        
            <content type="html">&lt;p&gt;Static site generators create a website by converting human readable format files i.e &lt;a href=&quot;https:&#x2F;&#x2F;www.markdownguide.org&#x2F;&quot;&gt;markdown&lt;&#x2F;a&gt; into a web page hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;We recently moved our website from being hosted on a Debian virtual machines using Wordpress to be a static site that we generate and push to github pages for hosting.&lt;&#x2F;p&gt;
&lt;p&gt;We are very happy with the outcome as now we can;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Keep the website content under version control&lt;&#x2F;li&gt;
&lt;li&gt;Forget about having to host or maintain virtual machines&lt;&#x2F;li&gt;
&lt;li&gt;Forget about having to keep updating Debian and Wordpress&lt;&#x2F;li&gt;
&lt;li&gt;Trivially update the web site with a single &lt;code&gt;git push&lt;&#x2F;code&gt; command.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To help others make the transition we have posted some brief notes below, along with our working configurations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;install-the-required-tools-on-your-workstation&quot;&gt;Install the required tools on your workstation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;tools-used&quot;&gt;Tools used&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;zola&lt;&#x2F;a&gt; is a web static site generator written in &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;rust&lt;&#x2F;a&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;themes&#x2F;tabi&#x2F;&quot;&gt;tabi&lt;&#x2F;a&gt; is a zola theme used to customize the look and layout of a zola generated website.
&lt;a href=&quot;https:&#x2F;&#x2F;pages.github.com&#x2F;&quot;&gt;github pages&lt;&#x2F;a&gt; supports hosting web pages directly from a github repository.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;install-zola-and-tabi&quot;&gt;Install zola and tabi&lt;&#x2F;h3&gt;
&lt;p&gt;Instal zola and tabi using the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;welpo&#x2F;tabi-start&quot;&gt;tabi-start&lt;&#x2F;a&gt; repository.  If you will be hosting your static site on github pages then call your new github repository &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;&amp;lt;username&amp;gt;&#x2F;&amp;lt;username&amp;gt;.github.io&lt;&#x2F;code&gt; (so we used &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;flocknetworks&#x2F;flocknetworks.github.io&lt;&#x2F;code&gt;).  This is a reserved name in github that indicates you want the output of this repository to be hosted on github pages as your main domain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-the-website-content&quot;&gt;Create the website content&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;zola-configuration-file&quot;&gt;zola configuration file&lt;&#x2F;h3&gt;
&lt;p&gt;You will find the main zola config file in the root of your repository.  This config file also holds the config settings for the zola theme you have chosen, in our case tabi.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ ls config.toml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;config.toml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This configuration file was created when you ran &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;getting-started&#x2F;cli-usage&#x2F;#init&quot;&gt;&lt;code&gt;zola init&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.  Below are the settings you are most likely to want to edit.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# TODO: Change base_url once flocknetworks.com DNS points to the new site at github.io.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# base_url = &amp;quot;https:&#x2F;&#x2F;flocknetworks.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;base_url = &amp;quot;https:&#x2F;&#x2F;flocknetworks.github.io&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;title = &amp;quot;Flock Networks&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;description = &amp;quot;Next Generation IP Routing Suite&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;author = &amp;quot;Nick Carter&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;theme = &amp;quot;tabi&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;menu = [
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;brochure&amp;quot;, url = &amp;quot;brochure&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;products&amp;quot;, url = &amp;quot;products&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;white papers&amp;quot;, url = &amp;quot;whitepapers&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;blog&amp;quot;, url = &amp;quot;blog&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;tags&amp;quot;, url = &amp;quot;tags&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    { name = &amp;quot;about&amp;quot;, url = &amp;quot;about&amp;quot;, trailing_slash = true },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;check-website-content-is-correctly-generated&quot;&gt;Check website content is correctly generated&lt;&#x2F;h3&gt;
&lt;p&gt;Run &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;getting-started&#x2F;cli-usage&#x2F;#serve&quot;&gt;&lt;code&gt;zola serve&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which will build and then serve your website on your development workstations loopback interface on &lt;a href=&quot;http:&#x2F;&#x2F;127.0.0.1:1111&#x2F;&quot;&gt;port 1111&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ zola serve
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Building site...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking all internal links with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Successfully checked 0 internal link(s) with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-&amp;gt; Creating 7 pages (0 orphan) and 7 sections
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Done in 99ms.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Listening for changes in &#x2F;home&#x2F;ncarter&#x2F;src&#x2F;flocknetworks.github.io&#x2F;{config.toml,content,static,themes}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Press Ctrl+C to stop
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Web server is available at http:&#x2F;&#x2F;127.0.0.1:1111 (bound to 127.0.0.1:1111)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;where-to-store-your-content&quot;&gt;Where to store your content&lt;&#x2F;h3&gt;
&lt;p&gt;The content used to generated your website is held in the well named &lt;code&gt;content&lt;&#x2F;code&gt; directory.  If you have content that you want to include that is already in its final form (i.e. PDF documents, PNG images, etc) they should be placed under the &lt;code&gt;static&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ ls content&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;about  archive  blog  brochure  _index.md  privacypolicy  products  whitepapers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ ls static
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;docs  img
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;content&#x2F;_index.md&lt;&#x2F;code&gt; is your websites homepage stored in markdown format.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ head -n 6 content&#x2F;_index.md
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+++
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[extra]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;header = { title = &amp;quot;Next Generation IP Routing&amp;quot;, img = &amp;quot;img&#x2F;flock-favicon.jpg&amp;quot; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+++
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Flock Networks have upgraded the IP routing suite to match the demands of the modern network. Using 30 years of network architecture and network operations experience, we have created the [third generation](https:&#x2F;&#x2F;www.flocknetworks.com&#x2F;docs&#x2F;third-gen-routing-suite-2020-07-27.pdf) of IP routing suite.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;publish-the-website-content-to-your-custom-domain&quot;&gt;Publish the website content to your custom domain&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;dns-changes&quot;&gt;DNS changes&lt;&#x2F;h3&gt;
&lt;p&gt;Change the DNS settings for your domain name to point at github pages&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Github pages IPv4 DNS servers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A @ 185.199.108.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A @ 185.199.109.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A @ 185.199.110.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;A @ 185.199.111.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Github pages IPv6 DNS servers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AAAA @ 2606:50c0:8000:0:0:0:0:153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AAAA @ 2606:50c0:8001:0:0:0:0:153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AAAA @ 2606:50c0:8002:0:0:0:0:153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AAAA @ 2606:50c0:8003:0:0:0:0:153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# map canonical subdomain name www.flocknetworks.com to flocknetworks.github.io
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Do not use an `A` or `AAAA` record to map subdomains or github pages will fail the subdomain DNS check
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;CNAME www flocknetworks.github.io
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you already have DNS settings registered with another hosting company then delete all those records.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-cname-file-in-the-static-dir-in-your-main-git-branch&quot;&gt;Add CNAME file in the static dir in your main git branch&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git status
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;On branch main
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ cat static&#x2F;CNAME
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flocknetworks.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you don’t have a &lt;code&gt;CNAME&lt;&#x2F;code&gt; file then github will create one (in the auto created gh-pages branch).  But be warned github pages custom domain settings will be lost on every git push and your site will become unavailable until you manually reinstate the domain settings.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;update-zola-base-url-to-point-at-your-domain-name&quot;&gt;Update zola base_url to point at your domain name&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;diff --git a&#x2F;config.toml b&#x2F;config.toml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;index 7c2819d..e17f9a1 100644
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;--- a&#x2F;config.toml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+++ b&#x2F;config.toml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;@@ -1,5 +1,5 @@
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-base_url = &amp;quot;https:&#x2F;&#x2F;flocknetworks.github.io&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;+base_url = &amp;quot;https:&#x2F;&#x2F;flocknetworks.com&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;add-github-actions-yaml-file-to-build-and-publish-your-site&quot;&gt;Add github actions YAML file to build and publish your site&lt;&#x2F;h3&gt;
&lt;p&gt;Note that the zola version specified should match the version of zola you are running on your workstation.  You also need to give github actions write permissions &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;&amp;lt;username&amp;gt;.github.io&#x2F;&amp;lt;username&amp;gt;&#x2F;settings&#x2F;actions&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ cat .github&#x2F;workflows&#x2F;build.yml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;name: build.yml Deploy Zola site to Pages
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;on:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  push:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    branches:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - main
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;jobs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  deploy:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    runs-on: ubuntu-latest
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    steps:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - name: Checkout
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        uses: actions&#x2F;checkout@v4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - name: Build and deploy
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # @v0.19.2 is the zola version to use, when running zola build.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # So match the version we are using locally (zola --version)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        uses: shalzz&#x2F;zola-deploy-action@v0.19.2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        env:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          PAGES_BRANCH: gh-pages
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          TOKEN: ${{ secrets.GITHUB_TOKEN }}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;add-a-git-pre-push-hook&quot;&gt;Add a git pre-push hook&lt;&#x2F;h3&gt;
&lt;p&gt;By running &lt;code&gt;zola check&lt;&#x2F;code&gt; we prevent pushing a branch that has broken links.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ cat .git&#x2F;hooks&#x2F;pre-push
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Verify what is about to be pushed.  Called by &amp;quot;git push&amp;quot; after it has
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# checked the remote status, but before anything has been pushed.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# If this script exits with a non-zero status nothing will be pushed.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;zola check
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ $? -ne 0 ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	exit 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;exit 0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;publish-your-site&quot;&gt;Publish your site&lt;&#x2F;h3&gt;
&lt;p&gt;This is simply a case of git pushing your main branch.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git status
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;On branch main
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git push
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking site...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking all internal links with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Successfully checked 0 internal link(s) with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking 31 external link(s). Skipping 0 external link(s).
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Checked 31 external link(s): 0 error(s) found.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-&amp;gt; Site content: 7 pages (0 orphan), 7 sections
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Done in 3.0s.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Enumerating objects: 8, done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Counting objects: 100% (8&#x2F;8), done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Delta compression using up to 8 threads
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Compressing objects: 100% (5&#x2F;5), done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Writing objects: 100% (5&#x2F;5), 3.55 KiB | 3.55 MiB&#x2F;s, done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Total 5 (delta 3), reused 0 (delta 0), pack-reused 0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;remote: Resolving deltas: 100% (3&#x2F;3), completed with 3 local objects.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;To github.com:flocknetworks&#x2F;flocknetworks.github.io.git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; + 3e5e868...646f631 main -&amp;gt; main
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your website content will be built in the &lt;code&gt;gh-pages&lt;&#x2F;code&gt; branch (as specified in build.yml)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git log origin&#x2F;gh-pages
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;commit 32d4a17f463bbbcf84ea6d3cfed20ca701d93e73 (origin&#x2F;gh-pages)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Author: GitHub Actions &amp;lt;github-actions-bot@users.noreply.github.com&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Date:   Wed Feb 26 10:47:17 2025 +0000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    Deploy flocknetworks&#x2F;flocknetworks.github.io to flocknetworks&#x2F;flocknetworks.github.io:gh-pages
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;tell-github-pages-to-use-your-custom-domain&quot;&gt;Tell github pages to use your custom domain&lt;&#x2F;h3&gt;
&lt;p&gt;Visit &lt;code&gt;https:&#x2F;&#x2F;github.com&#x2F;&amp;lt;username&amp;gt;&#x2F;&amp;lt;username&amp;gt;.github.io&#x2F;settings&#x2F;pages&lt;&#x2F;code&gt;
and set the “Custom Domain” to your domain name.&lt;&#x2F;p&gt;
&lt;p&gt;If the “Custom Domain” DNS check is failing then check your DNS changes are correct and have come live (DNS records are widely cached so the old entries need time to go stale and expire).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@condor:~$ dig flocknetworks.com | grep flocknetworks.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.18.33-1~deb12u2-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; flocknetworks.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;;flocknetworks.com.		IN	A
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flocknetworks.com.	2954	IN	A	185.199.108.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flocknetworks.com.	2954	IN	A	185.199.111.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flocknetworks.com.	2954	IN	A	185.199.110.153
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flocknetworks.com.	2954	IN	A	185.199.109.153
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enable SSL by clicking on the button.  github pages will then get a certificate from the lovely folks at &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;&quot;&gt;lets encrypt&lt;&#x2F;a&gt; and github pages will automatically renew it for you before the certificate expires.&lt;&#x2F;p&gt;
&lt;p&gt;Your website should now be globally accessible at &lt;code&gt;https:&#x2F;&#x2F;&amp;lt;your-domain-name&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;updating-the-website-with-new-content&quot;&gt;Updating the website with new content&lt;&#x2F;h2&gt;
&lt;p&gt;Now everything is set up, updating content on the web site is as simple as;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git commit&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;git push&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git status
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;On branch main
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git commit -a -m &amp;quot;my new content&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[main 8a3b1ab] my new content
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; 1 file changed, 7 insertions(+)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ncarter@zola:~&#x2F;src&#x2F;flocknetworks.github.io$ git push
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking site...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking all internal links with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Successfully checked 0 internal link(s) with anchors.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Checking 32 external link(s). Skipping 0 external link(s).
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt; Checked 32 external link(s): 0 error(s) found.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-&amp;gt; Site content: 7 pages (0 orphan), 7 sections
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Done in 2.9s.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Enumerating objects: 9, done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Counting objects: 100% (9&#x2F;9), done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Delta compression using up to 8 threads
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Compressing objects: 100% (5&#x2F;5), done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Writing objects: 100% (5&#x2F;5), 570 bytes | 570.00 KiB&#x2F;s, done.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Total 5 (delta 4), reused 0 (delta 0), pack-reused 0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;remote: Resolving deltas: 100% (4&#x2F;4), completed with 4 local objects.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;To github.com:flocknetworks&#x2F;flocknetworks.github.io.git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   97b67e5..8a3b1ab  main -&amp;gt; main
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedataquarry.com&#x2F;posts&#x2F;static-site-zola&#x2F;&quot;&gt;https:&#x2F;&#x2F;thedataquarry.com&#x2F;posts&#x2F;static-site-zola&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Great observability via fast JSON serialization</title>
        <published>2020-09-30T00:00:00+00:00</published>
        <updated>2020-09-30T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/great-observability/" type="text/html"/>
        <id>https://flocknetworks.com/blog/great-observability/</id>
        
            <content type="html">&lt;p&gt;As we come to the end of this phase of our performance and scale testing, we have turned our attention to the Flock Networks Operations REST API.&lt;&#x2F;p&gt;
&lt;p&gt;Flock Networks routing suite v20.3.5 is out now and it can sort and serialize the 763k BGP routes (as seen at LINX) into JSON and then stream them over HTTP in under 2s.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ time flockc bgp --prefix --host 192.168.101.194 &amp;gt; bgp_table.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;real    0m1.972s
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ wc bgp_table.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   763307    763307 223051579 bgp_table.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because BGP routes have so much meta data (BGP path attributes etc) that is 223 MB of data.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; you@your-host:~$ ls -l bgp_table.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; -rw-r--r-- 1 you you 223051579 Sep 30 09:51 bgp_table.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we are feeling a bit crazy we can now diff the internet backbone in real time !&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ flockc bgp --prefix --host 192.168.101.194 &amp;gt; bgp_table_later.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ diff bgp_table.json bgp_table_later.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; 2888d2887
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt; {&amp;quot;ip_net&amp;quot;:&amp;quot;2.16.12.0&#x2F;23&amp;quot;,&amp;quot;best_entry&amp;quot;:{&amp;quot;neigh&amp;quot;:{&amp;quot;neigh_ipv4_addr&amp;quot;:&amp;quot;10.20.0.1&amp;quot;,&amp;quot;attrs&amp;quot;:{&amp;quot;origin&amp;quot;:&amp;quot;Igp&amp;quot;,&amp;quot;as_path&amp;quot;:{&amp;quot;segments&amp;quot;:[{&amp;quot;segment_type&amp;quot;:&amp;quot;AsSequence&amp;quot;,&amp;quot;segment_value&amp;quot;:[65020,8607,2914,3257,20940,20940,16625]}]},&amp;quot;next_hop&amp;quot;:&amp;quot;10.20.0.1&amp;quot;,&amp;quot;atomic_aggregate&amp;quot;:false}},&amp;quot;reason&amp;quot;:&amp;quot;OnlyValidPeer&amp;quot;}}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or we can deserialize using the language of our choice and take control of the data.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ flockc bgp --prefix --host 192.168.101.194 -J --show-url
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;http:&#x2F;&#x2F;192.168.101.194:8000&#x2F;bgp&#x2F;prefix?ipv4_net=*&#x2F;sort&#x2F;json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;you@your-host:~$ python3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import requests
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt;&amp;gt;&amp;gt; r = requests.get(&amp;#39;http:&#x2F;&#x2F;192.168.101.194:8000&#x2F;bgp&#x2F;prefix?ipv4_net=*&#x2F;sort&#x2F;json&amp;#39;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt;&amp;gt;&amp;gt; deserialized_json = r.json()
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt;&amp;gt;&amp;gt; len(deserialized_json)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;763307
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;gt;&amp;gt;&amp;gt; deserialized_json[42]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{&amp;#39;ip_net&amp;#39;: &amp;#39;1.0.201.0&#x2F;24&amp;#39;, &amp;#39;best_entry&amp;#39;: {&amp;#39;neigh&amp;#39;: {&amp;#39;neigh_ipv4_addr&amp;#39;: &amp;#39;10.20.0.1&amp;#39;, &amp;#39;attrs&amp;#39;: {&amp;#39;origin&amp;#39;: &amp;#39;Igp&amp;#39;, &amp;#39;as_path&amp;#39;: {&amp;#39;segments&amp;#39;: [{&amp;#39;segment_type&amp;#39;: &amp;#39;AsSequence&amp;#39;, &amp;#39;segment_value&amp;#39;: [65020, 8607, 3356, 3491, 38040, 23969]}]}, &amp;#39;next_hop&amp;#39;: &amp;#39;10.20.0.1&amp;#39;, &amp;#39;atomic_aggregate&amp;#39;: False}}, &amp;#39;reason&amp;#39;: &amp;#39;OnlyValidPeer&amp;#39;}}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Flock Networks Routing Suite has excellent observability because all operational state queries can be returned in JSON format using a machine friendly API.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>How many OSPF routers can be deployed in one area ?</title>
        <published>2019-12-17T00:00:00+00:00</published>
        <updated>2019-12-17T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/ospf-routers-per-area/" type="text/html"/>
        <id>https://flocknetworks.com/blog/ospf-routers-per-area/</id>
        
            <content type="html">&lt;p&gt;This question fits in the same category as “How long is a piece of string ?”. The answer is of course, “it depends”.&lt;&#x2F;p&gt;
&lt;p&gt;Back in 1998 whilst working for a router vendor, I was helping design a backbone network for a European ISP. Our web site was recommending a maximum of 40 – 60 routers per OSPF area, but the customer was designing for 180 in a single backbone area. The network was deployed and went live fine. I was curious as to how it would perform over the long term, so 6 months later I contacted the customers operations team for an update. (If you want to verify a network design, then there are few better ways than asking the Operations team. If there have been problems at 2am, you will definitely get some candid feedback). The customers operations team said the network was stable, and were happy with its performance. So the “official” 40 – 60 routers per area recommendation looked pretty conservative.&lt;&#x2F;p&gt;
&lt;p&gt;Today, if you google the title of this blog, the top hit says an area should have no more than &lt;a href=&quot;http:&#x2F;&#x2F;www.ciscopress.com&#x2F;articles&#x2F;article.asp?p=1763921&amp;amp;seqNum=6&quot;&gt;50&lt;&#x2F;a&gt; routers. That is from a design guide written in 2011. So over the 13 years from 1998 to 2011 the recommendation had surprisingly not increased. Now it’s almost 2020. 22 years later, what can we expect ?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;networking-in-2020&quot;&gt;Networking in 2020&lt;&#x2F;h2&gt;
&lt;p&gt;Being a Link State protocol OSPF will consume as much CPU and Bandwidth as it needs until the network is converged. After that, whilst the network is stable, a good implementation will sit idle except for sending periodic hello’s to its neighbors. So (WAN) link stability will have a large impact on how well OSPF scales. We can probably assume that WAN links today are more stable than WAN links in 1998 &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;285&quot;&gt;citation needed&lt;&#x2F;a&gt;. Anyway lets be conservative and assume they are no worse.&lt;&#x2F;p&gt;
&lt;p&gt;The critical resources OSPF needs are CPU to run the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Dijkstra%27s_algorithm&quot;&gt;SPF&lt;&#x2F;a&gt; algorithm, and CPU &#x2F; Bandwidth to flood the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Link-state_advertisement&quot;&gt;LSA’s&lt;&#x2F;a&gt;. Back in 1998 the Route Processors in the customers network used a 667 MHz Power PC CPU and the WAN links were either 2.5G (STM-16) or 10G (STM-64).&lt;&#x2F;p&gt;
&lt;p&gt;Over the 22 years from 1998-2020, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Moore%27s_law&quot;&gt;Moore’s law&lt;&#x2F;a&gt; states the CPU transistor count doubles every 2 years. Due to the increased transistor count the performance is expected to double around every 18 months. So the performance should have doubled around 14 times. In terms of CPU we should be able to support 180 x 2^14 = ~~3 million routers per area !&lt;&#x2F;p&gt;
&lt;p&gt;The lowest bandwidth link in the customer network in 1998 was 2.5G. In 2020 we can expect ISP backbones to be provisioned at 40G and 100G. So this is a much more modest 40&#x2F;2.5 = 16X speedup. In terms of bandwidth for flooding LSA’s we should be able to support 180 x 16 = ~~3000 routers per area.&lt;&#x2F;p&gt;
&lt;p&gt;So in 2020, in theory you can have up to 3000 routers in a single area, in practice maybe not so much. Complex systems scale in surprising ways that are hard to model. But in 2020 OSPF should easily be able to scale to the 100’s of routers per area.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-if&quot;&gt;What if ?&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;What if we created a modern implementation of OSPF, developed with 21st Century Hardware in mind ?&lt;&#x2F;li&gt;
&lt;li&gt;What if the SPF Algorithm, the Link State Database and the Flood Queues used cache friendly data structures, so the CPU spends less time idling waiting for data ?&lt;&#x2F;li&gt;
&lt;li&gt;What if all incoming signalling was processed before running SPF and servicing the LSA flood queues ?&lt;&#x2F;li&gt;
&lt;li&gt;What if the OSPF route table remembered all the paths it has computed, rather than just the best ?&lt;&#x2F;li&gt;
&lt;li&gt;What if you could transfer 10,000 routes from OSPF to the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Routing_table&quot;&gt;RIB&lt;&#x2F;a&gt; by moving an 8 byte pointer, rather than copying a gazillion bytes between processes using &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Inter-process_communication&quot;&gt;IPC&lt;&#x2F;a&gt; ?&lt;&#x2F;li&gt;
&lt;li&gt;What if the RIB only signalled the forwarding plane when a route had really changed, rather than when some route meta data had changed that the forwarding plane has no interest in ?&lt;&#x2F;li&gt;
&lt;li&gt;What if I stopped asking all these annoying “what if” questions and got to the point ?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In 1Q 2020 Flock Networks are shipping Routing Suite v20.0. If you would like to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Be part of the early field trials.&lt;&#x2F;li&gt;
&lt;li&gt;Deploy over 1000 routers in a single OSPF area and not have the expected result being your vendor saying “You did what ?”&lt;&#x2F;li&gt;
&lt;li&gt;Save power by running a routing suite that mostly sleeps once the network is converged.&lt;&#x2F;li&gt;
&lt;li&gt;Gain observability into your existing OSPF network using a Read-Only JSON API.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then please email info@flocknetworks.com.&lt;&#x2F;p&gt;
&lt;p&gt;In the mean time here’s wishing everyone a Happy Solstice and a converged and stable 2020. If you are short of gift ideas I can highly recommend the book &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;what-if&#x2F;&quot;&gt;what if ?&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Nick&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Moving from C to Rust</title>
        <published>2019-11-27T00:00:00+00:00</published>
        <updated>2019-11-27T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/moving-from-c-to-rust/" type="text/html"/>
        <id>https://flocknetworks.com/blog/moving-from-c-to-rust/</id>
        
            <content type="html">&lt;p&gt;I have spent many years systems programming in C. I have been playing around with Rust since 2015 and this year I decided to switch to primarily programming in Rust. This blog post is an attempt to explain why I have made this decision.&lt;&#x2F;p&gt;
&lt;p&gt;Although I have a background in Computer Science, at heart I’m a Developer &#x2F; Network Engineer who just wants to “get stuff done” ™. I’ve played with many languages over the years and for me it was C and Python that stuck. I’m still a big fan of both of those languages.&lt;&#x2F;p&gt;
&lt;p&gt;When I first started playing with Rust, all my initial projects were checking how it felt as a systems programming language. That is, could I layout structures in memory as required ? How easy was it to call into C libraries using FFI ? And in particular how easy was it to interface with the Linux Kernel and put IP packets ‘on the wire’ ? I found Rust a good fit for this, probably because it is a C like language, so looked and felt familiar. As an aside, many developers who try Rust initially end up “fighting the borrow checker” that is built into the compiler. [In very rough terms the borrow checker makes sure that your code either has a single pointer to a mutable object, or multiple pointers to an immutable object, but never both]. If you are coming from programming in C then you can quite quickly work out why it’s complaining. However, it really makes you think hard about your data model, and who really owns each allocation of data. This can be painful if you are just trying to prototype something, but it is time well spent on anything that will end up in production.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-two-compelling-reasons-for-moving-to-rust&quot;&gt;My two compelling reasons for moving to Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Having decided that Rust was a capable systems programming language, I found there were 2 compelling reasons to make the move to Rust.&lt;&#x2F;p&gt;
&lt;p&gt;The first reason is that Rust is memory safe at compile time. This means you can say goodbye to the runtime memory corruption bugs you get in C. In safe Rust there is no ‘reading of’ or ‘writing to’ an invalid pointer. As I said earlier, I like C as a language, but hitting memory corruption bugs in production code is not fun. The worst part is that the point at which the program terminates, say due to a segfault to an invalid address, is likely to be thousands or millions of instructions after the code with the bug has executed. This makes finding the offending code difficult. I once spent over 3 weeks fixing a memory corruption bug in some IP Router software. That’s not something I’m proud of, but nor is it something I’m ashamed of. We could only reproduce the corruption when the device was running in production, and with all logging turned off. Fixing the bug came down to reasoning about 100,000’s of lines of C code. Eventually we came up with a theory about what was happening, wrote a ‘fix’ and the problem was never seen again. Whether we actually fixed the issue, or just changed some timing of events, I will never know. As an engineer this feels wholly inadequate.&lt;&#x2F;p&gt;
&lt;p&gt;The second reason is that Rust is data race free at compile time. As discussed above, memory corruption in single threaded code can be very hard to debug. Memory corruption in multi-threaded code is an order of magnitude more complicated. In my experience, it is possible to write reliable multi-threaded C, but you need to be very conservative and keep the threading model very simple (no bad thing), but refactoring the code is a major undertaking. In multi-threaded code there is such an explosion of event sequences that can happen, it is not possible to have exhaustive testing in place. With CPU frequencies levelling off and being replaced by multiple cores, the future of systems programming will need to be multi-threaded.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drawbacks-of-moving-to-rust&quot;&gt;Drawbacks of moving to Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Rust certainly has some drawbacks when compared to C. For me the main one is the size of the executable produced by the compiler. In my experience of writing similar applications in C and in Rust, Rust release binaries tend to be around 5x larger than C release binaries. This is a combination of the fact that the Rust compiler optimizes for speed not &lt;a href=&quot;https:&#x2F;&#x2F;lifthrasiir.github.io&#x2F;rustlog&#x2F;why-is-a-rust-executable-large.html&quot;&gt;size&lt;&#x2F;a&gt; and Rust projects suffer from dependency &lt;a href=&quot;https:&#x2F;&#x2F;raphlinus.github.io&#x2F;rust&#x2F;2019&#x2F;08&#x2F;21&#x2F;rust-bloat.html&quot;&gt;bloat&lt;&#x2F;a&gt;. The Rust binary can be made &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;johnthagen&#x2F;min-sized-rust&quot;&gt;smaller&lt;&#x2F;a&gt;, and the dependency bloat problem actually comes from the advantage that you can so easily reuse other people’s libraries. But with Rust there is an extra step you need to take before releasing code, and that is to audit what is contributing to the binary size and is it a reasonable trade off? In the same way performance needs to be benchmarked between releases, with Rust binary size also needs to be tracked, to catch and investigate any large increases.&lt;&#x2F;p&gt;
&lt;p&gt;Rust also currently suffers from long compile times, and IDE support using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rls&quot;&gt;RLS&lt;&#x2F;a&gt; is slow and a CPU hog.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;moving-a-development-team-from-c-to-rust&quot;&gt;Moving a development team from C to Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Moving a development team from implementing in language A to language B is always going to be a hard sell if they do not already know language B. The team will have years &#x2F; decades of experience in language A. Rust is a new language so it is likely a team of C programmers will not know Rust.&lt;&#x2F;p&gt;
&lt;p&gt;On top of this, Rust tends to pay back during the final stages of the development life cycle. I would guess that a team that knows both C and Rust, who started working on a new project, would be able to ship the first version of the software earlier if they wrote it in C rather than Rust. Rust tends to catch bugs earlier, at compile time rather than run time, which delays the production of the next binary. Rust forces the developer to iterate over the data model, until it is clean, before the code gets too complex, again delaying the production of the next binary. With Rust the team will probably implement Unit tests and Integration tests as they develop because all the infrastructure is in hand. With C the team may choose to produce the binary first and then possibly wrap some testing around it after. The QA teams will hit runtime panics in Rust that are hidden in C, again pushing out the date that the project ships.&lt;&#x2F;p&gt;
&lt;p&gt;So the sales pitch to management would go something like this. We have a team of highly skilled C developers. I suggest our new product “The IP packet mangler” should be written in Rust. On one hand if we write it in C we will ship it earlier and bring in revenue earlier. On the other hand Rust is shiny and new and would look good on our CV’s. Also the Rust compiler gives very pleasant error messages.&lt;&#x2F;p&gt;
&lt;p&gt;But wait, by catching bugs early, Rust gives you a huge payback in the long term. The C team have shipped a release with more bugs than the Rust team. Customers will be hitting bugs in the C product that don’t exist in the Rust product. As each team is working on the v1.1 features the C team will be interrupted more on bug fixes. This will cause frustration as most bug fixes are more important than implementing new features. The C development team will be getting more randomly timed, high level interrupts of various length, stopping them doing the ‘real work’ of implementing the new features.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe the v1.1 C and Rust versions will ship around the same time. After that the Rust team will pull ahead, as the bug backlog for both teams will now cover multiple releases. The Rust team will probably ship v1.2 and all subsequent releases earlier and to a higher quality.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously there is a lot of conjecture in the above argument, and it is slightly tongue in cheek. However I think the main point stands that it is preferable to pay your development costs upfront and as early as possible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-summary&quot;&gt;In summary&lt;&#x2F;h2&gt;
&lt;p&gt;You might be able to prototype faster in C, but I believe you will reach production quality faster in Rust. Also with Rust, keeping that production quality high going forward will be easier.&lt;&#x2F;p&gt;
&lt;p&gt;And that is why I have moved from C to Rust.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Rust in 2020</title>
        <published>2019-11-06T00:00:00+00:00</published>
        <updated>2019-11-06T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/rust-in-2020/" type="text/html"/>
        <id>https://flocknetworks.com/blog/rust-in-2020/</id>
        
            <content type="html">&lt;p&gt;I’m a Rust user rather than a Rust developer. I have been writing Rust code since just before the 1.0 release, and have followed the development of the language since then. I believe the future of systems programming is likely to be in Rust. I am certainly invested in the Rust language. Last month I resigned from my job writing embedded C, so I could start my own company, producing IP Networking software in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;The “Rust 2018” theme was Productivity, and there is still work to be done there. In my day to day programming the much mentioned “long compile times” and “RLS performance” have the most immediate impact. But the trend on both of these looks good.&lt;&#x2F;p&gt;
&lt;p&gt;I feel having frequent (3 yearly) releases is beneficial as it makes the upgrade between releases a moderate piece of work. I moved from 2015 to 2018 when I had a spare couple of hours. I did not plan the upgrade, I just had some time free so decided to do it. (The upgrade was flawless, thanks to all involved). If releases are infrequent, then the task becomes &amp;gt; 1 day, and its never going to be the highest priority work.&lt;&#x2F;p&gt;
&lt;p&gt;If there is to be a “Rust 2021” then I think the theme should be along the lines of “scoping”. That is, what is part of the Rust language now, what might become part of it, and what will never be part of it. A similar exercise could cover the Rust standard libraries.&lt;&#x2F;p&gt;
&lt;p&gt;I have spent many years programming in C and (despite carrying around the loaded gun) I’ve enjoyed it. I like C as a language, it is fast, compact, portable. You can look at C code and have some idea what Assembly will be produced (as long as optimizations are off!). You can predict roughly how it will perform. For me Rust 2018 is already a drop in replacement for C, and at the moment I can reason about Rust programs in roughly the same way.&lt;&#x2F;p&gt;
&lt;p&gt;As languages mature there is a tendency to add more and more features as each users needs are unique. Often it is easier to just say yes to a new feature to keep everyone happy, and well why not ? But the language gets bloated, the language loses a coherent style, and the subset of the language used starts to vary greatly between projects.&lt;&#x2F;p&gt;
&lt;p&gt;So could “Rust 2021” draw a periphery around the Rust language ? If an RFC wants to add a feature outside of this area then it should be held to a higher standard.&lt;&#x2F;p&gt;
&lt;p&gt;One thing that I hope won’t change in Rust going forward is the open constructive technical discussions that take place. The Rust core teams seem to be full of highly skilled engineers who are also humble and genuinely want to find the best technical solution, regardless of where it originated. This is a very productive and healthy culture, but easily lost, so long may it continue. Hopefully new members to the core teams will share similar traits. Sorry couldn’t resist finishing on a pun.&lt;&#x2F;p&gt;
&lt;p&gt;Nick&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Hello, World!</title>
        <published>2019-10-24T00:00:00+00:00</published>
        <updated>2019-10-24T00:00:00+00:00</updated>
        <author>
            <name>Nick Carter</name>
        </author>
        <link rel="alternate" href="https://flocknetworks.com/blog/hello-world/" type="text/html"/>
        <id>https://flocknetworks.com/blog/hello-world/</id>
        
            <content type="html">&lt;p&gt;Flock Networks IP Routing Suite is now in systems test, getting ready for product launch in 2020.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;flock@flocknet:~$ .&#x2F;flockrsc system -p
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;quot;version&amp;quot;: &amp;quot;19.0.0&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;quot;pid&amp;quot;: 4045,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;quot;compile_mode&amp;quot;: &amp;quot;Debug&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;quot;uptime&amp;quot;: {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;quot;days&amp;quot;: 0,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;quot;hours&amp;quot;: 1,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;quot;mins&amp;quot;: 18,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;quot;secs&amp;quot;: 36
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        <summary type="html">First Post.</summary>
        </entry>
</feed>
