<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amir Keshavarz</title>
    <description>The latest articles on DEV Community by Amir Keshavarz (@satrobit).</description>
    <link>https://dev.to/satrobit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F25832%2Fe01b59e3-858b-4665-bffd-7924a4509c47.jpg</url>
      <title>DEV Community: Amir Keshavarz</title>
      <link>https://dev.to/satrobit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/satrobit"/>
    <language>en</language>
    <item>
      <title>AWS Summit Amsterdam 2025 – Key Takeaways &amp; Reflections</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Fri, 18 Apr 2025 11:35:49 +0000</pubDate>
      <link>https://dev.to/satrobit/aws-summit-amsterdam-2025-key-takeaways-reflections-3661</link>
      <guid>https://dev.to/satrobit/aws-summit-amsterdam-2025-key-takeaways-reflections-3661</guid>
      <description>&lt;h2&gt;
  
  
  AWS Summit Amsterdam 2025 – Key Takeaways &amp;amp; Reflections
&lt;/h2&gt;

&lt;p&gt;With the AWS Summit Amsterdam 2025 now wrapped up, I thought it was worth writing down some reflections. This isn't your typical event recap—consider it part observation, part opinion.&lt;/p&gt;

&lt;p&gt;After speaking with attendees and walking the floor, it seems many felt this year’s summit was one of the most thought-provoking in recent memory. While not as flashy or extravagant as previous editions, it made up for it with substance and energy.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, the dominant themes were AI and EU–US relations. Conversations repeatedly circled around these two topics, often with a sense of unease about where the industry is headed—plenty of nervous laughter to go around.&lt;/p&gt;

&lt;p&gt;Interestingly, while there appeared to be tighter budgets when it came to marketing and luxuries, there was no lack of investment—especially in hyperscale initiatives backed by major cloud providers and venture capital.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI
&lt;/h2&gt;

&lt;p&gt;AI is no longer a novelty—it's infrastructure. We've clearly entered the second wave of AI adoption, and it’s not a passing trend. It's already delivering measurable gains in engineering productivity, and the sheer scale of investment being poured in is staggering.&lt;/p&gt;

&lt;p&gt;Notably, no one is talking about &lt;em&gt;whether&lt;/em&gt; to use generative AI anymore. If your team hasn’t already embraced it, you’re already behind—and yes, it’s okay to feel a bit of FOMO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Talking Points
&lt;/h3&gt;

&lt;p&gt;The major AI-related discussions revolved around:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choosing the right model for the job
&lt;/li&gt;
&lt;li&gt;Cost management
&lt;/li&gt;
&lt;li&gt;AI agents&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two are fairly self-explanatory, so let’s focus on the third: agents.&lt;/p&gt;

&lt;p&gt;The limitations of traditional chatbots are well-known—they lack contextual awareness, task execution abilities, and multi-step reasoning. AI agents aim to solve this by enabling more autonomous, capable systems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MCP is quickly becoming the standard for context injection. For other use cases, there's still a lot of variation in approaches across teams.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short, this is the new normal.&lt;br&gt;&lt;br&gt;
If your team isn’t using AI yet—start.&lt;br&gt;&lt;br&gt;
If your team isn’t working with AI agents—start.&lt;br&gt;&lt;br&gt;
If you’re building infrastructure for developers and don’t yet offer AI tooling—start.&lt;/p&gt;

&lt;h2&gt;
  
  
  EU–US
&lt;/h2&gt;

&lt;p&gt;No big surprises here. There’s growing concern among European companies and governments about dependency on American hyperscalers. Despite heavy investment from both private and public sectors, tangible alternatives are still lacking.&lt;/p&gt;

&lt;p&gt;Europe has a software problem (read this excellent article: &lt;a href="https://berthub.eu/articles/posts/europes-software-problem/" rel="noopener noreferrer"&gt;Europe's Software Problem&lt;/a&gt;), and it won’t be solved overnight. The US has spent the last three decades—and vast sums—developing its software ecosystem and pulling far ahead.&lt;/p&gt;

&lt;p&gt;The concern is valid: for many critical services, there simply are no viable European alternatives, and geopolitical dynamics are shifting quickly. The upside? There's newfound enthusiasm and funding to explore European-built solutions.&lt;/p&gt;

&lt;p&gt;So, it’s a complicated mix—growing interest, rising budgets, and a tough road ahead. The next few years are likely to be tense but hopefully transformative.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This post is a mix of hallway chats, session takeaways, and personal impressions. I’ve kept it short, so of course, much has been left out. Still, I hope it gives you a good sense of the broader picture.&lt;/p&gt;

&lt;p&gt;People have been saying “the world is changing fast” my whole life—but for the first time, I’m really feeling it. Exciting years lie ahead :)&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>discuss</category>
      <category>news</category>
    </item>
    <item>
      <title>Developing Custom Plugins for CoreDNS</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Sun, 30 Jun 2024 14:05:27 +0000</pubDate>
      <link>https://dev.to/satrobit/developing-custom-plugins-for-coredns-4jnj</link>
      <guid>https://dev.to/satrobit/developing-custom-plugins-for-coredns-4jnj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction To CoreDNS
&lt;/h2&gt;

&lt;p&gt;CoreDNS is a powerful, flexible DNS server written in Go. One of its key features is its plugin-based architecture, which allows users to extend its functionality easily. In this blog post, we'll explore how to write custom plugins for CoreDNS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8nkdkngrvgllfh9ytya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8nkdkngrvgllfh9ytya.png" alt="CoreDNS Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As previously mentioned, CoreDNS utilizes a plugin chain architecture, enabling you to stack multiple plugins that execute sequentially. Most of CoreDNS's functionality is provided by its built-in plugins. You can explore these bundled plugins by &lt;a href="https://github.com/coredns/coredns/tree/master/plugin" rel="noopener noreferrer"&gt;Clicking here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;CoreDNS follows a similar approach to Caddy, as it is based on Caddy v1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load Configuration&lt;/strong&gt;: Configuration is loaded through the &lt;code&gt;Corefile&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugin Setup&lt;/strong&gt;: Plugins must implement a &lt;code&gt;setup&lt;/code&gt; function to load, validate the configuration, and initialize the plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handler Implementation&lt;/strong&gt;: You need to implement the required functions from the &lt;code&gt;plugin.Handler&lt;/code&gt; interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate Your Plugin&lt;/strong&gt;: Add your plugin to CoreDNS by either including it in the &lt;code&gt;plugin.cfg&lt;/code&gt; file or by wrapping everything in an external source code. Further details can be found below.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Develop
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;As mentioned above, everything is done through the &lt;code&gt;Corefile&lt;/code&gt;. If you're not familiar with the syntax, check this short explanation: &lt;a href="https://coredns.io/2017/07/23/corefile-explained/" rel="noopener noreferrer"&gt;https://coredns.io/2017/07/23/corefile-explained/&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

. {
    foo
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the example above, &lt;code&gt;.&lt;/code&gt; defines a server block, and &lt;code&gt;foo&lt;/code&gt; is the name of your plugin. You can specify a port or add arguments to your plugin.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

.:5353 {
    foo bar
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now CoreDNS is running on port &lt;code&gt;5353&lt;/code&gt; and my plugin named &lt;code&gt;foo&lt;/code&gt; is given the argument &lt;code&gt;bar&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's useful to enable the plugins &lt;code&gt;log&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; during the development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Checkout the list of bundled plugins to figure out which ones you need in your setup: &lt;a href="https://coredns.io/plugins/" rel="noopener noreferrer"&gt;https://coredns.io/plugins/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;The first thing you need to do is to register and set up your plugin. Registration is done through a function called &lt;code&gt;init&lt;/code&gt; which you need to include in your go module.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/caddy"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/core/dnsserver"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/plugin"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we need to implement &lt;code&gt;setup()&lt;/code&gt; which parses the configuration and returns our initialized plugin.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/caddy"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/core/dnsserver"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/plugin"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;caddy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// #1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextArg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// #2&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgErr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;dnsserver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="c"&gt;// #3&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="c"&gt;// #4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Skip the first token which is &lt;code&gt;foo&lt;/code&gt;, the name of our argument.&lt;/li&gt;
&lt;li&gt;Return an error if our argument didn't have any value.&lt;/li&gt;
&lt;li&gt;Put the value of our argument &lt;code&gt;bar&lt;/code&gt; in the plugin struct and return it to be put in the plugin chain. Read more details on the plugin struct further down.&lt;/li&gt;
&lt;li&gt;return &lt;code&gt;nil&lt;/code&gt; as an error if everything is good to go.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Handler
&lt;/h3&gt;

&lt;p&gt;All plugins need to implement &lt;code&gt;plugin.Handler&lt;/code&gt; which is the entry point to your plugin.&lt;/p&gt;

&lt;p&gt;First, we need to write a struct containing the necessary arguments, runtime objects, and also the next plugin in the chain.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Bar&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Next&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;This is the actual struct that we created in the previous step.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We also need a method to return the name of the plugin.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now it's time for the most important method which is &lt;code&gt;ServeDNS()&lt;/code&gt;. This is the method that is called for every DNS query routed to your plugin. You can also generate a response here making your plugin work as a data backend.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ServeDNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeDNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What you see here does nothing but call the next plugin in the chain. But we don't have to do that :)&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;r *dns.Msg&lt;/code&gt; to get some info on the DNS query.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;qname&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;List of variables you can get from &lt;code&gt;state&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;state.Name()&lt;/code&gt; name of the query - includes the zone as well&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state.Type()&lt;/code&gt; type of the query - e.g. &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;AAAA&lt;/code&gt;, etc&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state.Ip()&lt;/code&gt; IP address of the client making the request&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state.Proto()&lt;/code&gt; transport protocol - &lt;code&gt;tcp&lt;/code&gt; or &lt;code&gt;udp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;state.Family()&lt;/code&gt; IP version - &lt;code&gt;1&lt;/code&gt; for IPv4 and &lt;code&gt;2&lt;/code&gt; for IPv6
&amp;gt; Read the following file for the complete list: &lt;a href="https://github.com/coredns/coredns/blob/master/request/request.go" rel="noopener noreferrer"&gt;https://github.com/coredns/coredns/blob/master/request/request.go&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also generate a response and return from the chain. For that, you need to use the amazing &lt;code&gt;github.com/miekg/dns&lt;/code&gt; package and build a &lt;code&gt;dns.Msg&lt;/code&gt; to return.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ServeDNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;dummy_ip&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"1.1.1.1"&lt;/span&gt;

    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;qname&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RR_Header&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fqdn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qname&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Rrtype&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClassINET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ttl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ttl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseIP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Authoritative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RecursionAvailable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SizeAndDo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scrub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteMsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RcodeSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the example shown above, we create an &lt;code&gt;A&lt;/code&gt; record response and return it to the client.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the DNS package we used for more details on how to create DNS objects: &lt;a href="https://pkg.go.dev/github.com/miekg/dns" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/miekg/dns&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If successful, we return &lt;code&gt;dns.RcodeSuccess&lt;/code&gt;. To see more return codes, check out here: &lt;a href="https://pkg.go.dev/github.com/miekg/dns#pkg-constants" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/miekg/dns#pkg-constants&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few important return codes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;RcodeSuccess&lt;/code&gt;: No error&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RcodeServerFailure&lt;/code&gt;: Server failure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RcodeNameError&lt;/code&gt;: Domain doesn't exist&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RcodeNotImplemented&lt;/code&gt;: Record type not implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;

&lt;p&gt;You can use the logging package provided by the CoreDNS itself, &lt;code&gt;github.com/coredns/coredns/plugin/pkg/log&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;clog&lt;/span&gt; &lt;span class="s"&gt;"github.com/coredns/coredns/plugin/pkg/log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWithPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you can log anything you need with different levels:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"info log"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"debug log"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"warning log"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error log"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Final Example
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/request"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/miekg/dns"&lt;/span&gt;
    &lt;span class="s"&gt;"golang.org/x/net/context"&lt;/span&gt;
    &lt;span class="n"&gt;clog&lt;/span&gt; &lt;span class="s"&gt;"github.com/coredns/coredns/plugin/pkg/log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewWithPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Bar&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Next&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"foo"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ServeDNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;dummy_ip&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"1.1.1.1"&lt;/span&gt;

    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Req&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;qname&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RR_Header&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fqdn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qname&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Rrtype&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClassINET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ttl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ttl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseIP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dummy_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"answers created"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Authoritative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RecursionAvailable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

    &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SizeAndDo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scrub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteMsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RcodeSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Compile
&lt;/h2&gt;

&lt;p&gt;CoreDNS gives you two different ways to run your plugin, both are static builds.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compile-time Configuration
&lt;/h3&gt;

&lt;p&gt;In this method, you need to clone the CoreDNS source code, add your plugin to the &lt;code&gt;plugin.cfg&lt;/code&gt; file (plugins are ordered), and compile the code.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

etcd:etcd
foo:github.com/you/foo


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then you need to do a &lt;code&gt;go get github.com/you/foo&lt;/code&gt; and build the CoreDNS binary using &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;./coredns -plugins&lt;/code&gt; to ensure your plugin is included in the binary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your plugin is on your local machine you can put something like &lt;code&gt;replace github.com/you/foo =&amp;gt; ../foo&lt;/code&gt; in your &lt;code&gt;go.mod&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Wrapping in External Source Code
&lt;/h3&gt;

&lt;p&gt;You also have the option to wrap the CoreDNS components and your plugin in an external source code and compile from there.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"github.com/you/foo"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/coremain"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/coredns/coredns/core/dnsserver"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;directives&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;"whoami"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"startup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"shutdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;dnsserver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Directives&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;directives&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;coremain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As with any other go app, do a &lt;code&gt;go build&lt;/code&gt; and you should have the binary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coredns.io/2017/06/08/how-queries-are-processed-in-coredns/" rel="noopener noreferrer"&gt;https://coredns.io/2017/06/08/how-queries-are-processed-in-coredns/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coredns.io/2016/12/19/writing-plugins-for-coredns/" rel="noopener noreferrer"&gt;https://coredns.io/2016/12/19/writing-plugins-for-coredns/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coredns.io/2017/07/25/compile-time-enabling-or-disabling-plugins/" rel="noopener noreferrer"&gt;https://coredns.io/2017/07/25/compile-time-enabling-or-disabling-plugins/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mrkaran.dev/posts/coredns-nomad/" rel="noopener noreferrer"&gt;https://mrkaran.dev/posts/coredns-nomad/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>go</category>
      <category>linux</category>
      <category>programming</category>
    </item>
    <item>
      <title>Extending Envoy with WebAssembly Proxy Filters</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Tue, 12 Jul 2022 00:41:33 +0000</pubDate>
      <link>https://dev.to/satrobit/extending-envoy-with-webassembly-proxy-filters-1i96</link>
      <guid>https://dev.to/satrobit/extending-envoy-with-webassembly-proxy-filters-1i96</guid>
      <description>&lt;h2&gt;
  
  
  Introduction To Envoy
&lt;/h2&gt;

&lt;p&gt;Envoy is an open-source edge and service proxy designed for cloud-native applications. &lt;/p&gt;

&lt;p&gt;We can use Envoy as a gateway or a sidecar proxy in scenarios where we need connectivity between services. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt339grmr9dfyp48vnc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt339grmr9dfyp48vnc8.png" alt="Envoy Mesh"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works by applying a number of filters on the data that goes through its proxy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb20hti8yb2q72d6sq1tl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb20hti8yb2q72d6sq1tl.png" alt="Envoy Filter Chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can read or manipulate the data using built-in or custom filters/plugins via a filter chain architecture. This design has a proven record for this kind of application, as we've also seen a similar design in NGINX and other reverse proxies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Envoy Filters
&lt;/h3&gt;

&lt;p&gt;As explained above, we can use filters to do all kinds of stuff on the data received by the listener. Envoy already has many built-in filters written in C++ that you can use.&lt;/p&gt;

&lt;p&gt;You can also write your custom filters if any built-in filters aren't suitable for you. These filters can be written in the native C++, Lua, or WASM.&lt;/p&gt;

&lt;p&gt;We'll focus on WebAssembly filters in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebAssembly
&lt;/h2&gt;

&lt;p&gt;WebAssembly is a portable binary instruction format for virtual stack machines.&lt;/p&gt;

&lt;p&gt;It aims to execute at native or near-native speed by assuming a few characteristics of the execution environment.&lt;/p&gt;

&lt;p&gt;WebAssembly is designed to be executed in a fully sandboxed environment with linear memory. Because of that design, the binary is entirely blind to the host environment. That being said, we can set up some kind of communication by reading memory or importing functions. But don't worry about that since we won't need to implement these interfaces ourselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy-Wasm
&lt;/h3&gt;

&lt;p&gt;Proxy-Wasm is a set of ABI specifications to use between L4/L7 proxies (and/or other host environments) and their extensions delivered as WebAssembly modules.&lt;/p&gt;

&lt;p&gt;Even though it was first designed for Envoy, other proxy projects have also picked it up as the ABI spec for their WASM integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Filters
&lt;/h2&gt;

&lt;p&gt;We've chosen AssemblyScript to write our filter. AssemblyScript is a TypeScript-like designed for WebAssembly.&lt;/p&gt;

&lt;p&gt;To interact with the proxy-wasm host, We'd need to export a set of low-level interfaces to the host, but fortunately, There's a package called &lt;code&gt;solo-io/proxy-runtime&lt;/code&gt; that does the most of the heavy lifting for us. &lt;a href="https://github.com/solo-io/proxy-runtime/tree/master/examples" rel="noopener noreferrer"&gt;See here for code samples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a project by using these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; assemblyscript
npx asinit &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add &lt;code&gt;--use abort=abort_proc_exit&lt;/code&gt; to the &lt;code&gt;asc&lt;/code&gt; in packages.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"asbuild:optimized"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asc assembly/index.ts -b build/optimized.wasm --use abort=abort_proc_exit -t build/optimized.wat --sourceMap --optimize"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;assembly/index.ts&lt;/code&gt; is now our entrypoint to the WebAssembly module.&lt;/p&gt;

&lt;p&gt;Open it and use this sample code as a demo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ts-ignore&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@solo-io/proxy-runtime/proxy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RootContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registerRootContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FilterHeadersStatusValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stream_context&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@solo-io/proxy-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddHeaderRoot&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RootContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AddHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddHeader&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;root_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AddHeaderRoot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;root_context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;onResponseHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end_of_stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;FilterHeadersStatusValues&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;stream_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;FilterHeadersStatusValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;registerRootContext&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AddHeaderRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add_header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;proxy-wasm&lt;/code&gt; has a few hook points you can use to inject your module. We used &lt;code&gt;onResponseHeaders&lt;/code&gt; / &lt;code&gt;proxy_on_response_headers&lt;/code&gt; here to add our custom header to the response. Using this filter, we should see an additional header in the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello: World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now It's time to run Envoy and configure it to use our module.&lt;/p&gt;

&lt;p&gt;I recommend using &lt;code&gt;func-e&lt;/code&gt; as it makes installing and running Envoy extremely easy. &lt;a href="https://func-e.io/" rel="noopener noreferrer"&gt;More Info&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://func-e.io/install.sh | bash &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;envoy.yaml&lt;/code&gt; and configure your Envoy. As we discussed before, Envoy works by chaining several filters, starting from TCP connections to http and more.&lt;/p&gt;

&lt;p&gt;I've put a sample config here, but we'll go through each section to explain what the configuration means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;socket_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;127.0.0.1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;9901&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="na"&gt;static_resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;listeners&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listener_0&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;socket_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;127.0.0.1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;8080&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;filter_chains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.filters.network.http_connection_manager&lt;/span&gt;
        &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager&lt;/span&gt;
          &lt;span class="s"&gt;stat_prefix&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress_http&lt;/span&gt;
          &lt;span class="s"&gt;codec_type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AUTO&lt;/span&gt;
          &lt;span class="s"&gt;route_config&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local_route&lt;/span&gt;
            &lt;span class="na"&gt;virtual_hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local_service&lt;/span&gt;
              &lt;span class="na"&gt;domains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
              &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;cluster&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;service_0&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
        &lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="na"&gt;http_filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.filters.http.wasm&lt;/span&gt;
            &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/udpa.type.v1.TypedStruct&lt;/span&gt;
              &lt;span class="s"&gt;type_url&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm&lt;/span&gt;
              &lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add_header"&lt;/span&gt;
                  &lt;span class="na"&gt;root_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add_header"&lt;/span&gt;
                  &lt;span class="na"&gt;vm_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;vm_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_vm_id"&lt;/span&gt;
                    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;envoy.wasm.runtime.v8"&lt;/span&gt;
                    &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                      &lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/path/to/optimized.wasm"&lt;/span&gt;
                    &lt;span class="na"&gt;allow_precompiled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.filters.http.router&lt;/span&gt;
            &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.http.router.v3.Router&lt;/span&gt;
  &lt;span class="na"&gt;clusters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_0&lt;/span&gt;
    &lt;span class="na"&gt;connect_timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.25s&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STRICT_DNS&lt;/span&gt;
    &lt;span class="na"&gt;lb_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ROUND_ROBIN&lt;/span&gt;
    &lt;span class="na"&gt;load_assignment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cluster_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_0&lt;/span&gt;
      &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;lb_endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;socket_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
                &lt;span class="na"&gt;port_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;admin:&lt;/strong&gt; here, we tell Envoy where to listen for its admin interface. The admin interface exposes some administration and monitoring functionalities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;static_resources:&lt;/strong&gt; here is where the most exciting stuff happens. We set up our listeners and filters here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;static_resources.listeners:&lt;/strong&gt; we setup our actual listeners here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;static_resources.filter_chains:&lt;/strong&gt; All traffic filters are configured here. We have the &lt;code&gt;http_connection_manager&lt;/code&gt; filter as ingress for our http traffic. This filter has &lt;code&gt;http_filters&lt;/code&gt;, which defines what http filters to run. That's the part where we set up our module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;static_resources.filters[0].http_filters[0]:&lt;/strong&gt; this is our WebAssembly module. We specify where to find the module itself (&lt;code&gt;/path/to/optimized.wasm&lt;/code&gt;) and what is the root (&lt;code&gt;add_header&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;clusters:&lt;/strong&gt; we put our origin services here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run Envoy, simply run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func-e run &lt;span class="nt"&gt;-c&lt;/span&gt; /path/to/envoy.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try it out and you should see the additional header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; http://127.0.0.1:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 200 OK
content-type: text/html
date: Mon, 11 Jul 2022 23:59:07 GMT
server: envoy
content-length: 345
x-envoy-upstream-service-time: 196
Hello: World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yay! We just used a WebAssembly module to inject custom headers into the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Even though this post only touches on the tip of the iceberg, It represents what &lt;code&gt;proxy-wasm&lt;/code&gt; is capable of. You can write your filters in whatever language you desire, and It'll run at near-native speeds.&lt;/p&gt;

&lt;p&gt;Many companies are investing hugely in server-side WebAssembly, and more exciting things are to come.&lt;/p&gt;

&lt;p&gt;I'm also trying to write more on WebAssembly and its future if you're interested in the subject.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.envoyproxy.io/docs/envoy/latest/" rel="noopener noreferrer"&gt;https://www.envoyproxy.io/docs/envoy/latest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/proxy-wasm/spec/blob/master/docs/WebAssembly-in-Envoy.md" rel="noopener noreferrer"&gt;https://github.com/proxy-wasm/spec/blob/master/docs/WebAssembly-in-Envoy.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/proxy-wasm/spec/tree/master/abi-versions/vNEXT" rel="noopener noreferrer"&gt;https://github.com/proxy-wasm/spec/tree/master/abi-versions/vNEXT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://func-e.io/" rel="noopener noreferrer"&gt;https://func-e.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solo-io/proxy-runtime" rel="noopener noreferrer"&gt;https://github.com/solo-io/proxy-runtime&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>devops</category>
      <category>linux</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Cache Replacement Algorithms: How To Efficiently Manage The Cache Storage</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Thu, 14 Oct 2021 12:30:22 +0000</pubDate>
      <link>https://dev.to/satrobit/cache-replacement-algorithms-how-to-efficiently-manage-the-cache-storage-2ne1</link>
      <guid>https://dev.to/satrobit/cache-replacement-algorithms-how-to-efficiently-manage-the-cache-storage-2ne1</guid>
      <description>&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;p&gt;Let's start at the beginning and talk about what caching even is.&lt;/p&gt;

&lt;p&gt;Caching is the process of storing some data near where It's supposed to be used rather than accessing them from an expensive origin, every time a request comes in.&lt;/p&gt;

&lt;p&gt;Caches are everywhere. From your CPU to your browser. So there's no doubt that caching is extremely useful. implementing a high-performance cache system comes with its own set of challenges. In this post, we'll focus on cache replacement algorithms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vc0kva0qem036s1tne9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vc0kva0qem036s1tne9.png" alt="Cache"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;from wikipedia.com&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Replacement Algorithms
&lt;/h2&gt;

&lt;p&gt;We talked about what caching is and how we can utilize it but there's a dinosaur in the room; Our cache storage is finite. Especially in caching environments where high-performance and expensive storage is used. So in short, we have no choice but to evict some objects and keep others.&lt;/p&gt;

&lt;p&gt;Cache replacement algorithms do just that. They decide which objects can stay and which objects should be evicted.&lt;/p&gt;

&lt;p&gt;After reviewing some of the most important algorithms we go through some of the challenges that we might encounter.&lt;/p&gt;

&lt;h3&gt;
  
  
  LRU
&lt;/h3&gt;

&lt;p&gt;The least recently used (LRU) algorithm is one of the most famous cache replacement algorithms and for good reason!&lt;/p&gt;

&lt;p&gt;As the name suggests, LRU keeps the least recently used objects at the top and evicts objects that haven't been used in a while if the list reaches the maximum capacity.&lt;/p&gt;

&lt;p&gt;So it's simply an ordered list where objects are moved to the top every time they're accessed; pushing other objects down.&lt;/p&gt;

&lt;p&gt;LRU is simple and providers a nice cache-hit rate for lots of use-cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgfp1bbogn80f2zbj1ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgfp1bbogn80f2zbj1ng.png" alt="LRU"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;from progressivecoder.com&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LFU
&lt;/h3&gt;

&lt;p&gt;the least frequently used (LFU) algorithm works similarly to LRU except it keeps track of how many times an object was accessed instead of how recently it was accessed.&lt;/p&gt;

&lt;p&gt;Each object has a counter that counts how many times it was accessed. When the list reaches the maximum capacity, objects with the lowest counters are evicted.&lt;/p&gt;

&lt;p&gt;LFU has a famous problem. Imagine an object was repeatedly accessed for a short period only. Its counter increases by a magnitude compared to others so it's very hard to evict this object even if it's not accessed for a long time.&lt;/p&gt;

&lt;h3&gt;
  
  
  FIFO
&lt;/h3&gt;

&lt;p&gt;FIFO (first-in-first-out) is also used as a cache replacement algorithm and behaves exactly as you would expect. Objects are added to the queue and are evicted with the same order. Even though it provides a simple and low-cost method to manage the cache but even the most used objects are eventually evicted when they're old enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhy7cokrxe7fj4ycla46b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhy7cokrxe7fj4ycla46b.png" alt="FIFO"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;from wikipedia.com&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Random Replacement (RR)
&lt;/h3&gt;

&lt;p&gt;This algorithm randomly selects an object when it reaches maximum capacity. It has the benefit of not keeping any reference or history of objects and being very simple to implement at the same time.&lt;/p&gt;

&lt;p&gt;This algorithm has been used in ARM processors and the famous Intel i860.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem of One-hit Wonders
&lt;/h2&gt;

&lt;p&gt;Let's talk about a problem that occurs in large-scale caching solutions, one-hit wonders.&lt;/p&gt;

&lt;p&gt;One-hit wonders are objects that are rarely or never accessed twice. This happens quite often in CDNs where the number of unique objects is huge and most objects are rarely used again.&lt;/p&gt;

&lt;p&gt;This becomes a problem when every bit of storage performance matters to us. By caching these objects we basically pollute our storage with junk since these cache objects are always evicted before they're used again. So we waste a large amount of resources just to persist some objects that we're not going to use.&lt;/p&gt;

&lt;p&gt;So what's the solution? Unfortunately, there's no silver bullet here. The most used solution is just not caching an object when it's first accessed!&lt;/p&gt;

&lt;p&gt;By keeping a list of object signatures, we can only cache the objects that are seen more than one time. This might seem weird at first but overall it improves your disk performance significantly.&lt;/p&gt;

&lt;p&gt;After accepting this solution, we immediately encounter another challenge. In many scenarios, the number of object signatures is extremely large so storing the list itself becomes a challenge. In this case, we can use probabilistic data structures such as the bloom filter data structure.&lt;/p&gt;

&lt;p&gt;I've covered probabilistic data structures in a previous post: &lt;a href="https://dev.to/satrobit/rate-limiting-in-ipv6-era-using-probabilistic-data-structures-15on"&gt;Rate Limiting in IPv6 Era Using Probabilistic Data Structures&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8q36et5on48n1mz3fyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8q36et5on48n1mz3fyd.png" alt="Bloom filter"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;from wikipedia.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In short, probabilistic data structures like bloom filter use a lot less memory but in return, they only give a probabilistic answer to our queries. In our case, the bloom filter offers a nice solution since we don't need definite answers to improve our cache performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we went through multiple cache replacement algorithms and understood how we can efficiently manage our cache storage. We also covered the famous problem of one-hit wonders and a solution that helps in most cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Cache_replacement_policies" rel="noopener noreferrer"&gt;Cache replacement policies
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ieeexplore.ieee.org/document/567612?reload=true&amp;amp;arnumber=567612" rel="noopener noreferrer"&gt;Disk caching in large database and timeshared systems
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pdfs.semanticscholar.org/f2af/126b48bb3e16d49636c574720d78a14d6a37.pdf" rel="noopener noreferrer"&gt;Cache Memory: An Analysis on Replacement Algorithms and
Optimization Techniques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2107.14646" rel="noopener noreferrer"&gt;Cache Replacement Algorithm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Bloom_filter" rel="noopener noreferrer"&gt;Bloom filter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://progressivecoder.com/lru-cache-implementation-using-javascript-linked-list-and-objects/" rel="noopener noreferrer"&gt;LRU Cache Implementation using Javascript Linked List and Objects
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Closer Look Into The World of Database Replication</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Sun, 15 Aug 2021 17:45:21 +0000</pubDate>
      <link>https://dev.to/satrobit/a-closer-look-into-the-world-of-database-replication-57k2</link>
      <guid>https://dev.to/satrobit/a-closer-look-into-the-world-of-database-replication-57k2</guid>
      <description>&lt;p&gt;We all have used or heard about database replication at some point but have you ever wondered how It works underneath?&lt;/p&gt;

&lt;p&gt;That's exactly what we'll be doing here.&lt;/p&gt;

&lt;p&gt;Replication is basically copying an object from one space into another. Replicating immutable objects like a movie file is as simple as copying its bytes.&lt;/p&gt;

&lt;p&gt;Replication a database which is a mutable object comes with its own challenges. How do you copy an object that is always changing? You don't!&lt;/p&gt;

&lt;h2&gt;
  
  
  Logs
&lt;/h2&gt;

&lt;p&gt;Logs are the most important part of a database replication process. The basic idea of a log is to record every action database does. We should be able to replay these logs to reconstruct a corrupt database object from scratch so It makes sense to keep them in order.&lt;/p&gt;

&lt;p&gt;Let's imagine a key/value store. In this database, we have 3 different types of operation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;SET&lt;/code&gt;: Sets a value to a key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt;: Retrieves the value of a key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt;: Delete a key&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are the instruction set of our database. Now, let's use them.&lt;/p&gt;

&lt;p&gt;I want to set the value of &lt;code&gt;john&lt;/code&gt; to the key &lt;code&gt;name&lt;/code&gt;, so my operation log would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's change the value of that same key to &lt;code&gt;eli&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eli"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And at last, let's remove it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DELETE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, logs are only the operations that mutate the database in some way. But something is missing from these logs. Order!&lt;/p&gt;

&lt;p&gt;We have to somehow not only keep them in order but to be able to recover from a specific position in the logs.&lt;/p&gt;

&lt;p&gt;2 obvious options are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Incremental integer: Assign an incrementing number to each log&lt;/li&gt;
&lt;li&gt;Timestamp: Record the timestamp when the log was executed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We go with the first option for now. We executed 3 operations so the logs will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eli"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DELETE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our logs are ordered and seekable from an &lt;code&gt;id&lt;/code&gt;. We can recover the database at any point in time.&lt;/p&gt;

&lt;p&gt;I think you get the idea now. When we talk about replication, we're talking about copying these logs into another space. If we're replication the database into another server, we continuously send these logs to the second server and tell it to replay these logs exactly. If the connection drops or something bad happens we always know where to start again because we already have a sortable &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We now know how databases share their state with other instances. In the next section, we talk about 2 very basic types of replication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Synchronous
&lt;/h3&gt;

&lt;p&gt;In synchronous replication, we commit changes to all of the instances before getting back to the client.&lt;/p&gt;

&lt;p&gt;Imagine we have 3 instances in a database cluster and we want to use the synchronous replication type.&lt;/p&gt;

&lt;p&gt;When we send a &lt;code&gt;SET&lt;/code&gt; operation to instance A which is the master, It immediately sends the log to other replica instances. These replicas execute the log and let the master know that they've executed the logs. After making sure all replicas have executed the change, the master itself also executes the log and returns a response to let the user know that the change was done successfully.&lt;/p&gt;

&lt;p&gt;The advantage of this type is the level of consistency that we get by executing the change on all instances before committing the change.&lt;/p&gt;

&lt;p&gt;And the disadvantage is the overhead in latency which causes the whole process to be slow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgeyw1nqn9k8gepbnakof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgeyw1nqn9k8gepbnakof.png" alt="Synchronous Replication"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous
&lt;/h3&gt;

&lt;p&gt;Unlike the synchronous type, in this type, we can't guarantee consistency because we consider the change committed before it's executed on other instances.&lt;/p&gt;

&lt;p&gt;As before, imagine we have 3 instances in a database cluster and we want to use an asynchronous replication type.&lt;/p&gt;

&lt;p&gt;When we send a &lt;code&gt;SET&lt;/code&gt; operation to instance A which is the master, It generates a log and executes it. After that, the asynchronous process of sending the logs to other instances begins but the master won't wait on these and it immediately gets back to the user with a successful response.&lt;/p&gt;

&lt;p&gt;The advantage of this type is the low latency write operations since it only mutates the master before being considered committed.&lt;/p&gt;

&lt;p&gt;The disadvantage of this type is the lack of consistency guarantee since we can't be sure the replication takes place at all. Master might be caught on fire before getting the chance to send log to other replicas :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa08bzy6myle48izw9w7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa08bzy6myle48izw9w7.png" alt="Asynchronous Replication"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency
&lt;/h2&gt;

&lt;p&gt;We talked about how the replication process can be synchronous or asynchronous. But let's get back one step backward and discuss consistency from distributed systems' point of view.&lt;/p&gt;

&lt;p&gt;In a distributed system like a replicated database cluster, we need some type of consistency because that's the whole purpose of replication!&lt;/p&gt;

&lt;p&gt;Consistency is achieved when multiple nodes agree on a single state.&lt;/p&gt;

&lt;p&gt;Let's show it by an example.&lt;/p&gt;

&lt;p&gt;The state of node A is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eli"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state of node B also is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eli"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, both nodes agree that the value of &lt;code&gt;name&lt;/code&gt; is &lt;code&gt;eli&lt;/code&gt; so they're consistent.&lt;/p&gt;

&lt;p&gt;There are multiple levels of consistency and at the most basic level, it correlates to the replications types.&lt;/p&gt;

&lt;p&gt;We'll discuss 2 types of consistency here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strong Consistency
&lt;/h3&gt;

&lt;p&gt;In a distributed system that supports strong consistency, all nodes are always consistent at any given moment. It doesn't matter what node you write to or read from; the result is always guaranteed to be the same.&lt;/p&gt;

&lt;p&gt;This consistency is achieved using consensus protocols like Paxos or Raft.&lt;/p&gt;

&lt;h3&gt;
  
  
  Weak Consistency
&lt;/h3&gt;

&lt;p&gt;In many cases, we don't really need strong consistency or need some other property that can't coexist with strong consistency.&lt;/p&gt;

&lt;p&gt;In this type of consistency, there's no guarantee that the state of your replica is up-to-date with the master.&lt;/p&gt;

&lt;h3&gt;
  
  
  Eventual Consistency
&lt;/h3&gt;

&lt;p&gt;Eventual consistency is a type of weak consistency itself. As the name suggests, eventual consistency guarantees that even though replicas may not be up-to-date but will be consistent with the master eventually.&lt;/p&gt;

&lt;p&gt;Basically, if you stop writing to the master, after some time, all nodes will be consistent and all replicas will answer the most recent values to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sync Replication
&lt;/h2&gt;

&lt;p&gt;We already talked about synchronous and asynchronous replication but in this section, we discuss in more detail and also about its real-world implementation.&lt;/p&gt;

&lt;p&gt;Before committing any transaction, we need to make sure all nodes are on the same page. That's just consensus so we need one.&lt;/p&gt;

&lt;p&gt;Synchronous replication requires a round-trip from master to most or all nodes for every single log and that's why synchronous replication can be really slow compared to asynchronous replication. Strong consistency has a huge cost!&lt;/p&gt;

&lt;p&gt;The most famous consensus protocol is Paxos but It's not the easiest protocol to explain. There's a new shiny protocol called Raft that has gotten lots of traction in the past few years and lots of big projects like etcd are already using it. It's a lot easier to learn compared to Paxos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Raft
&lt;/h3&gt;

&lt;p&gt;Raft is a relatively new asymmetric consensus protocol designed to be really easy to understand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wi86q03fiadk8t1k13a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wi86q03fiadk8t1k13a.png" alt="Raft"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nodes in Raft are always in one of these states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follower&lt;/li&gt;
&lt;li&gt;Candidate&lt;/li&gt;
&lt;li&gt;Leader&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most important things in Raft is the fact that followers trust the leader and will redirect all write operations to the leader. The leader will coordinate all changes.&lt;/p&gt;

&lt;p&gt;Raft slices the time into terms. Think of them exactly as election terms. At the beginning of the term, nodes become candidates, vote for themself and ask others to vote for them. After some time, a leader is elected and Raft begins to exchange messages between nodes.&lt;/p&gt;

&lt;p&gt;An election timeout is specified to make sure there's always a leader present. This timeout is pushed back by ping messages by the leader but If the leader steps back or has failed, another election will take place and all of those steps are repeated until another leader is elected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-world
&lt;/h3&gt;

&lt;p&gt;The etcd key/value store which powers Kubernetes is a good example here. It uses Raft to replicate logs synchronously to achieve strong consistency.&lt;/p&gt;

&lt;p&gt;You can see the etcd implementation of Raft in here:&lt;br&gt;
&lt;a href="https://github.com/etcd-io/etcd/tree/main/raft" rel="noopener noreferrer"&gt;https://github.com/etcd-io/etcd/tree/main/raft&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous replication
&lt;/h2&gt;

&lt;p&gt;Ok, let's talk a bit more about asynchronous replication. You now know how asynchronous replication works in theory. Some logs are sent asynchronously and there's no guarantee of consistency at any given moment.&lt;/p&gt;

&lt;p&gt;We'll discuss Ordered Log Replication here which is really simple with a few challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ordered Log Replication
&lt;/h3&gt;

&lt;p&gt;As the name suggests, this technique involves persisting an ordered list of logs and sending them over the wire, asynchronously.&lt;/p&gt;

&lt;p&gt;Ordering means that writes are usually written to master to ensure the consistency of end result. All logs are tagged with a timestamp or an incremental number.&lt;/p&gt;

&lt;p&gt;Immediately you notice a bottleneck here since all logs need to be ordered. Some databases use sharding in order to increase the throughput.&lt;/p&gt;

&lt;p&gt;Each of these challenges can be a post themself and most of them are also present in the synchronous type of replication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-world
&lt;/h3&gt;

&lt;p&gt;MySQL replication is a really good example of this type of replication.&lt;/p&gt;

&lt;p&gt;MySQL keeps an ordered log of every change in the master by using an incremental integer known as position.&lt;/p&gt;

&lt;p&gt;Logs are kept in binlog-* files and are rotated regularly. Replicas (known as slaves in MySQL - fortunately, it's about to change) receive these logs and execute them.&lt;/p&gt;

&lt;p&gt;The basic process of adding replicas to MySQL is a little bit too hard. It requires you to take a snapshot of the database and recording the master position and then restoring that snapshot in replica and starting the replication process from that exact position. Lots of other databases do that same thing underneath but I think MySQL could do these without requiring users to do these tasks manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we learned a bit more about database replication and its different types. We discussed different levels of consistency and how replication works in the real world.&lt;/p&gt;

&lt;p&gt;I might write more about databases in the future. Let me know If you're interested :)&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://charap.co/reading-group-paxos-vs-raft-have-we-reached-consensus-on-distributed-consensus/" rel="noopener noreferrer"&gt;http://charap.co/reading-group-paxos-vs-raft-have-we-reached-consensus-on-distributed-consensus/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raft.github.io/raft.pdf" rel="noopener noreferrer"&gt;https://raft.github.io/raft.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cl.cam.ac.uk/teaching/0910/ConcDistS/11a-cons-tx.pdf" rel="noopener noreferrer"&gt;https://www.cl.cam.ac.uk/teaching/0910/ConcDistS/11a-cons-tx.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>database</category>
      <category>devops</category>
    </item>
    <item>
      <title>Rate limiting using the Sliding Window algorithm</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Thu, 12 Aug 2021 06:51:27 +0000</pubDate>
      <link>https://dev.to/satrobit/rate-limiting-using-the-sliding-window-algorithm-5fjn</link>
      <guid>https://dev.to/satrobit/rate-limiting-using-the-sliding-window-algorithm-5fjn</guid>
      <description>&lt;p&gt;In this part of the rate-limiting series, we will introduce the Sliding Window algorithm and implement it in Python.&lt;/p&gt;

&lt;p&gt;Even though there are more rate-limiting algorithms out there, I'm going to end the series here since I think These three algorithms are a pretty good gateway to the rate-limiting techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sliding Window
&lt;/h2&gt;

&lt;p&gt;Unlike the previous Fixed Window algorithm, this algorithm does not limit the requests based on a fixed time unit.&lt;/p&gt;

&lt;p&gt;A problem with Fixed Window was that It allowed a huge burst at the edge of windows because you can combine the capacity of the current and the next window to send a burst of requests.&lt;/p&gt;

&lt;p&gt;Sliding Window tries to fix that by taking the previous counter into account, causing the flow to be more smooth.&lt;/p&gt;

&lt;p&gt;Let's explain it with an example. Imagine that we have a rate limiter with a time unit of 60 seconds and a capacity of 50.&lt;/p&gt;

&lt;p&gt;A request has entered at 00:01:20. The current time unit still has capacity left but as we learned the previous counter also affects the outcome.&lt;/p&gt;

&lt;p&gt;The previous counter only affects as much as the space it still has occupied in the window. In our example, that would be ~67%.&lt;/p&gt;

&lt;p&gt;So with that in mind, we use the following formula to calculate an estimated count.&lt;/p&gt;

&lt;p&gt;ec = previous counter * ((time unit - time into the current counter) / time unit) + current counter&lt;/p&gt;

&lt;p&gt;ec = 50 * 0.67 + 20 = 53.5&lt;/p&gt;

&lt;p&gt;Our capacity was 50 and because of that, this request is dropped since 53.5 &amp;gt; 50.&lt;/p&gt;

&lt;p&gt;Now, If another request comes in at 00:01:40, the ec would be:&lt;br&gt;
ec = 50 * 0.34 + 20 = 37&lt;/p&gt;

&lt;p&gt;This request is allowed to pass since 37 &amp;lt; 50.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m2beod49twc4s6177c1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6m2beod49twc4s6177c1.png" alt="Sliding Window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;In this very simple implementation, We will build a rate-limiter that uses Sliding Window to limit packets in 1-second time frames.&lt;/p&gt;

&lt;p&gt;We start by defining a class with 3 arguments when It's being instantiated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;capacity:&lt;/strong&gt; number of the allowed packets that can pass through in a second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;time_unit:&lt;/strong&gt; length of time unit in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;forward_callback:&lt;/strong&gt; this function is called when the packet is being forwarded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;drop_callback:&lt;/strong&gt; this function is called when the packet should be dropped.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlidingWindow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cur_time&lt;/code&gt; is the edge of our current time unit.&lt;br&gt;
&lt;code&gt;pre_count&lt;/code&gt; is the previous counter. We pre-fill this to prevent bursting at the beginning of the rate limiter.&lt;br&gt;
&lt;code&gt;cur_count&lt;/code&gt; is the current counter that will get filled as new requests come in.&lt;/p&gt;

&lt;p&gt;Then, we define &lt;code&gt;handle()&lt;/code&gt; where the magic happens.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#1
&lt;/span&gt;    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#2
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#4
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#5
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;handle&lt;/code&gt; accepts only 1 parameter: the packet.&lt;/li&gt;
&lt;li&gt;If the current time unit is passed, switch over to a new time unit.&lt;/li&gt;
&lt;li&gt;Calculate the estimated count based on the given formula&lt;/li&gt;
&lt;li&gt;Drop the packet if &lt;code&gt;ec&lt;/code&gt; is bigger than the capacity.&lt;/li&gt;
&lt;li&gt;Otherwise, add one to the current counter and forward the packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Final Code
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlidingWindow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pre_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_time&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Forwarded: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Dropped: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="n"&gt;throttle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SlidingWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should be getting something like this:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;Packet Forwarded: 0&lt;br&gt;
Packet Forwarded: 1&lt;br&gt;
Packet Dropped: 2&lt;br&gt;
Packet Forwarded: 3&lt;br&gt;
Packet Dropped: 4&lt;br&gt;
Packet Forwarded: 5&lt;br&gt;
Packet Dropped: 6&lt;br&gt;
Packet Forwarded: 7&lt;br&gt;
Packet Dropped: 8&lt;br&gt;
Packet Forwarded: 9&lt;br&gt;
Packet Dropped: 10&lt;br&gt;
Packet Forwarded: 11&lt;br&gt;
Packet Dropped: 12&lt;br&gt;
Packet Forwarded: 13&lt;br&gt;
Packet Dropped: 14&lt;br&gt;
Packet Forwarded: 15&lt;br&gt;
Packet Dropped: 16&lt;br&gt;
Packet Forwarded: 17&lt;br&gt;
Packet Dropped: 18&lt;br&gt;
Packet Forwarded: 19&lt;br&gt;
Packet Dropped: 20&lt;br&gt;
Packet Forwarded: 21&lt;br&gt;
Packet Dropped: 22&lt;br&gt;
Packet Forwarded: 23&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;In this post, we learned about the Sliding Window algorithm and tried to implement it in Python.&lt;/p&gt;

&lt;p&gt;During this series, we covered Token Bucket, Fixed Window, and Sliding Window. Even though there are famous algorithms like Leaky Bucket or Sliding Log, I decided to end this series here since I believe these three covers the basic ideas of most rate-limiting algorithms, and this series was also expected to be short and simple.&lt;/p&gt;

&lt;p&gt;Thank you for your time and I hope to see you on my other posts :)&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>CPU Time: How To Accurately Benchmark Your Code</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Wed, 04 Aug 2021 17:37:42 +0000</pubDate>
      <link>https://dev.to/satrobit/cpu-time-how-to-accurately-benchmark-your-code-572p</link>
      <guid>https://dev.to/satrobit/cpu-time-how-to-accurately-benchmark-your-code-572p</guid>
      <description>&lt;p&gt;I'm going to assume that everyone reading this post has done some benchmarking here and there. But have you ever thought about how accurate are your readings?&lt;/p&gt;

&lt;p&gt;In this post, we will talk about a few misconceptions, task schedulers, CPU timings, and a real example in C.&lt;/p&gt;

&lt;h2&gt;
  
  
  Misconceptions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time matters
&lt;/h3&gt;

&lt;p&gt;Ok, to be fair, the title is click-bait. Time really matters but not the time you see on your clock! We only care how much time is CPU spending on our process and that's usually not the wall-clock time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow software = Slow code
&lt;/h3&gt;

&lt;p&gt;The speed of your software depends on the environment that's running. I'm not talking about your computer specs. Softwares rely heavily on syscalls or I/O interfaces.&lt;br&gt;
During a benchmark, You really should pay attention to this subject since I/O is really really slow and I've seen too many times when software is considered slow without realizing that a huge part of this problem is caused by slow I/O and can be improved with technics like caching and etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance is not important
&lt;/h3&gt;

&lt;p&gt;Performance is UX but most micro-optimizations are usually time-wasting and not worth it. I think there's a fine line that we shouldn't cross when developing a product. You can pack your product with features but most people will hate it at a glance if It's too slow or sluggish.&lt;br&gt;
I'd say that finding this line may not be as easy as saying it but I don't see another way around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Schedulers
&lt;/h2&gt;

&lt;p&gt;With the notion of multi-tasking operating systems, it came task schedulers. To be able to run multiple programs at the same time we need a "scheduler" to schedule the work between limited CPU cores.&lt;/p&gt;

&lt;p&gt;We will discuss two types of schedulers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preemptive Multitasking
&lt;/h3&gt;

&lt;p&gt;In this model of multitasking, the kernel preemptively schedules tasks and interrupts processes to let other processes run. &lt;/p&gt;

&lt;p&gt;Our software doesn't notice these interrupts since its state is frozen to be used later when there's free CPU time for the process.&lt;/p&gt;

&lt;p&gt;The Linux kernel scheduler is an example of this model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne77o2wlfbcg4fkubuwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne77o2wlfbcg4fkubuwr.png" alt="Preemptive Multitasking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cooperative Multitasking
&lt;/h3&gt;

&lt;p&gt;Unlike preemptive multitasking, this model relies solely on the code itself to free the resources back to the scheduler.&lt;/p&gt;

&lt;p&gt;So the scheduler itself has no control over the process until the process yields back to let the scheduler know that the job is done or It's blocked so the CPU can be used for other processes.&lt;/p&gt;

&lt;p&gt;The Go language goroutine scheduler is an example of this model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferorcyh3wbhgvyv9c137.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferorcyh3wbhgvyv9c137.png" alt="Cooperative Multitasking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CPU Time
&lt;/h2&gt;

&lt;p&gt;CPU Time is the time that is actually spent on the CPU. So no I/O time is included in this.&lt;/p&gt;

&lt;p&gt;For example, if you're doing HTTP requests and each request takes a second to respond, the CPU time doesn't include that second since during that time, we didn't do any CPU work and just waited for the response.&lt;/p&gt;

&lt;p&gt;In Linux, A POSIX compliant kernel, these times are kept for each process or thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7bs4fmfsba11srbpjmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7bs4fmfsba11srbpjmx.png" alt="CPU Time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;In this very simple program, we use the &lt;code&gt;clock()&lt;/code&gt; function to benchmark a simple pi calculation code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// https://crypto.stanford.edu/pbc/notes/pi/code.html&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;pi_calculate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2800&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2800&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2800&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;clock_t&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pi_calculate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;elapsed_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;CLOCKS_PER_SEC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%f seconds&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elapsed_time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A few relevant and useful functions:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;clock()&lt;/code&gt;
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;clock_t&lt;/span&gt; &lt;span class="nf"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is the function that we used in our code to get the clock time of our current process.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;clock_getcpuclockid()&lt;/code&gt;
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;clock_getcpuclockid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clockid_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;clockid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This function returns a CPU clock id by using a PID. By obtaining the clock id you're able to get the CPU usage.&lt;/p&gt;

&lt;p&gt;As you can see, you can easily get the time of a clock.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;pthread_getcpuclockid()&lt;/code&gt;
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;pthread.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;pthread_getcpuclockid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pthread_t&lt;/span&gt; &lt;span class="kr"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clockid_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;clockid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you're working in multi-thread software, You may use this function to get the clock of a POSIX thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;clock_gettime()&lt;/code&gt;
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;clock_gettime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clockid_t&lt;/span&gt; &lt;span class="n"&gt;clockid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;timespec&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;timespec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kt"&gt;time_t&lt;/span&gt;   &lt;span class="n"&gt;tv_sec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="cm"&gt;/* seconds */&lt;/span&gt;
     &lt;span class="kt"&gt;long&lt;/span&gt;     &lt;span class="n"&gt;tv_nsec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="cm"&gt;/* nanoseconds */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Use this function to get the time of a clock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we went through a few terminologies regarding the schedulers and timing and then learned how to accurately benchmark our code using the CPU clock time that kernel provides for us.&lt;/p&gt;

&lt;p&gt;I really hope you enjoyed this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/CPU_time" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/CPU_time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crypto.stanford.edu/pbc/notes/pi/code.html" rel="noopener noreferrer"&gt;https://crypto.stanford.edu/pbc/notes/pi/code.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/pthread_getcpuclockid.3.html" rel="noopener noreferrer"&gt;https://man7.org/linux/man-pages/man3/pthread_getcpuclockid.3.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/clock_getcpuclockid.3.html" rel="noopener noreferrer"&gt;https://man7.org/linux/man-pages/man3/clock_getcpuclockid.3.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man3/clock.3.html" rel="noopener noreferrer"&gt;https://man7.org/linux/man-pages/man3/clock.3.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man2/clock_gettime.2.html" rel="noopener noreferrer"&gt;https://man7.org/linux/man-pages/man2/clock_gettime.2.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>linux</category>
      <category>computerscience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rate limiting using the Fixed Window algorithm</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Wed, 21 Jul 2021 17:21:33 +0000</pubDate>
      <link>https://dev.to/satrobit/rate-limiting-using-the-fixed-window-algorithm-2hgm</link>
      <guid>https://dev.to/satrobit/rate-limiting-using-the-fixed-window-algorithm-2hgm</guid>
      <description>&lt;p&gt;In the previous post, we went through rate-limiting and what it is. Then, we introduced an algorithm called Token Bucket and implemented it in Python.&lt;/p&gt;

&lt;p&gt;I've decided to turn this into a series and dedicate each post to an algorithm.&lt;/p&gt;

&lt;p&gt;And in this post, we will learn about Fixed Window and its implementation in Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixed Window
&lt;/h2&gt;

&lt;p&gt;As the name suggests, It's all about windows. In this algorithm, we divide the time into fixed windows and then map the incoming events into these windows.&lt;/p&gt;

&lt;p&gt;The algorithm itself is pretty simple without any analogy but let's start with one anyway.&lt;/p&gt;

&lt;p&gt;Imagine a moving train. There's a gateway and at any moment, people only can board one wagon (Yep, people are boarding a moving train, nothing weird).&lt;/p&gt;

&lt;p&gt;Assume that the window of boarding for each wagon is 1 minute. So if a wagon gets full you need to wait for up to a minute for the next wagon.&lt;/p&gt;

&lt;p&gt;In this analogy, the train is the time! The time is always moving forward and in each time frame, we have a fixed window of passing through.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi45cox7md3dt9h7t2syf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi45cox7md3dt9h7t2syf.png" alt="Fixed Window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;In this very simple implementation, We will build a rate-limiter that uses Fixed Window to limit packets in 1-second time frames.&lt;/p&gt;

&lt;p&gt;We start by defining a class with 3 arguments when It's being instantiated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;capacity:&lt;/strong&gt; number of the allowed packets that can pass through in a second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;forward_callback:&lt;/strong&gt; this function is called when the packet is being forwarded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;drop_callback:&lt;/strong&gt; this function is called when the packet should be dropped.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We prefill a property named &lt;code&gt;allowance&lt;/code&gt; to allow the packet to pass through in the first second.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;current_time&lt;/code&gt; is the current time frame that the rate-limiter is using.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FixedWindow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, we define &lt;code&gt;handle()&lt;/code&gt; where the magic happens.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#1
&lt;/span&gt;    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#2
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#4
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#5
&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#6
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#6
&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;handle&lt;/code&gt; accepts only 1 parameter: the packet.&lt;/li&gt;
&lt;li&gt;check if we're in the current time frame or not.&lt;/li&gt;
&lt;li&gt;if we're not in the current time frame, update the &lt;code&gt;current_time&lt;/code&gt; and reset the &lt;code&gt;allowance&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;check if we have any allowance left.&lt;/li&gt;
&lt;li&gt;drop the packet if we don't have any allowance left.&lt;/li&gt;
&lt;li&gt;in this part, we already know that there is allowance left, so we remove one from the allowance and forward the packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, Fixed Window is extremely simple. This is the final code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FixedWindow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Forwarded: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Dropped: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="n"&gt;throttle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FixedWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should be getting something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Packet Forwarded: 0
Packet Dropped: 1
Packet Dropped: 2
Packet Forwarded: 3
Packet Dropped: 4
Packet Dropped: 5
Packet Dropped: 6
Packet Dropped: 7
Packet Forwarded: 8
Packet Dropped: 9
Packet Dropped: 10
Packet Dropped: 11
Packet Dropped: 12
Packet Forwarded: 13


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the code above, we built a rate-limiter with a rate of one packet per second. Then, we send a packet every 0.2 seconds to see the rate-limiter do its thing.&lt;/p&gt;

&lt;p&gt;This algorithm is pretty useful to learn about rate-limiting but we rarely see it in the wild since it allows a burst of events at the beginning of the time frame but it really depends on your application.&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rate Limiting in IPv6 Era Using Probabilistic Data Structures</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Thu, 17 Jun 2021 15:01:01 +0000</pubDate>
      <link>https://dev.to/satrobit/rate-limiting-in-ipv6-era-using-probabilistic-data-structures-15on</link>
      <guid>https://dev.to/satrobit/rate-limiting-in-ipv6-era-using-probabilistic-data-structures-15on</guid>
      <description>&lt;p&gt;In any system where two parties communicate with each other, we hear things like rate-limiting, flow control, etc. The problem is that all systems have limits and to protect the system, you'd need to somehow control the flow of information passing through.&lt;/p&gt;

&lt;p&gt;As you may have already figured out, we're going to talk about a specific problem regarding rate-limiting in IPv6 networks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packets
&lt;/h2&gt;

&lt;p&gt;When we communicate through computer networks, we need to break down our data into smaller pieces called packets. These packets are basically like the letters you send through the post.&lt;/p&gt;

&lt;p&gt;Each letter (packet) has 3 important components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Source Address&lt;/li&gt;
&lt;li&gt;Destination Address&lt;/li&gt;
&lt;li&gt;The actual data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rwpoxa2kkufakbiiort.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rwpoxa2kkufakbiiort.gif" alt="Packet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, real packets also have those things. (The picture only shows the IP header which doesn't include the data body)&lt;/p&gt;

&lt;p&gt;We only care about the source and destination addresses in this context, so we call them a 2-tuple.&lt;/p&gt;

&lt;h2&gt;
  
  
  IP Addresses
&lt;/h2&gt;

&lt;p&gt;Until now, IPv4 is still dominant in most countries but its address pool is limited, thus, It's not future-proof.&lt;/p&gt;

&lt;p&gt;IPv6 is the successor to the IPv4 and instead of a 32-bit address, it provides 128-bit addresses so It's a huge bump in the case of the address pool.&lt;/p&gt;

&lt;p&gt;IPv4 address pool: 4,294,967,296&lt;br&gt;
IPv6 address pool: 340,282,366,920,938,463,463,374,607,431,768,211,456&lt;/p&gt;

&lt;p&gt;Yep, that's a huge difference.&lt;/p&gt;

&lt;p&gt;Even though IPv6 itself is not a new protocol, but the process of migrating to IPv6 from IPv4 has been a tedious and very long battle. The issue is that IPv6 is not backward compatible and lots of old hardware and software don't and will not support IPv6.&lt;/p&gt;

&lt;p&gt;Nonetheless, IPv6 is already here and its users are rising by the day. Google's statistics show IPv6 availability of its users at around 30.30–35.10% depending on the day of the week (greater on weekends), as of April 2021.&lt;/p&gt;

&lt;p&gt;Before continuing, you can also read another post of mine which goes through different technics on how to implement a rate-limiter:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/satrobit/rate-limiting-using-the-token-bucket-algorithm-3cjh"&gt;Rate limiting using the Token Bucket algorithm&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we talked about before, that's not the case for IPv6 addresses because of its huge address pool. Even if you may see no difference in normal times, the existing risk won't be accepted by lots of people.&lt;/p&gt;

&lt;p&gt;So what's the solution? How can we store the frequency of these events in a space-efficient data structure?&lt;br&gt;
Like all solutions, we compromise.&lt;/p&gt;
&lt;h2&gt;
  
  
  Challenge
&lt;/h2&gt;

&lt;p&gt;Even in the simplest forms of rate-limiting, we're required to store the number of times that packets with similar 2-tuple have been processed.&lt;/p&gt;

&lt;p&gt;In most IPv4-era systems, that information is stored in an array or a tree, or some other normal data structure. They'll do the job perfectly since the IPv4 address pool is not that big so keeping all of the data won't be an issue.&lt;/p&gt;

&lt;p&gt;For this purpose, we can use probabilistic data structures, specifically Count-Min Sketch.&lt;/p&gt;
&lt;h2&gt;
  
  
  Probabilistic Data Structures
&lt;/h2&gt;

&lt;p&gt;Unlike normal data structures which are deterministic, probabilistic data structures are not deterministic and won't give you definite answers but only an estimation or a probability.&lt;/p&gt;

&lt;p&gt;This kind of data structure is useful when an unknown stream of data is being processed.&lt;/p&gt;

&lt;p&gt;You'd be amazed to find out in how many cases we don't really need deterministic data structures especially when we're processing data streams.&lt;/p&gt;

&lt;p&gt;Probabilistic data structures are lossy but that's not really an issue for our use case since we only need to know the heavy-hitters. With an enough large space, the risk of collision should be low enough for most people.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpyqhit4pacxqje9p8rg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpyqhit4pacxqje9p8rg.jpg" alt="Probabilistic data structures from sciencedirect.com"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Count-Min Sketch
&lt;/h2&gt;

&lt;p&gt;The Count-Min Sketch, or CMS for short, is a probabilistic data structure to count the frequencies of events.&lt;/p&gt;

&lt;p&gt;We can argue that the whole CMS is like a 3-D table.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;w&lt;/code&gt;: a fixed width&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;d&lt;/code&gt;: pairwise-independent hash functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c&lt;/code&gt;: total count of an event&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqhr2ree2b2lvmobqabx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqhr2ree2b2lvmobqabx.png" alt="Count-Min Sketch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;w&lt;/code&gt; is basically an arbitrary width. The bigger it is, the lower the overestimation is.&lt;br&gt;
&lt;code&gt;d&lt;/code&gt; is a list of hash functions that shouldn't have many collisions with each other.&lt;br&gt;
&lt;code&gt;c&lt;/code&gt; is the number that we increment when an event is repeated.&lt;/p&gt;

&lt;p&gt;The process of incrementing or estimation is really simple.&lt;/p&gt;
&lt;h3&gt;
  
  
  Incrementing
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Calculate the hash of your event using the hash function &lt;code&gt;h1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Normalize the hash value to the &lt;code&gt;w&lt;/code&gt; so you would get an index.&lt;/li&gt;
&lt;li&gt;Increment the element &lt;code&gt;w[hash]&lt;/code&gt; by 1.&lt;/li&gt;
&lt;li&gt;Repeat the process for all hash functions in &lt;code&gt;d&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Estimation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Calculate the hash of your event using the hash function &lt;code&gt;h1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Normalize the hash value to the &lt;code&gt;w&lt;/code&gt; so you would get an index.&lt;/li&gt;
&lt;li&gt;Get the value of element &lt;code&gt;w[hash]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Repeat the process for all hash functions and then jump to &lt;code&gt;5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Between all the values that you got, the lowest one is your estimation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you may have already guessed, the whole CMS is quite similar to other probabilistic data structures like bloom filters. It's relatively simple and quite fast.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Now we can implement a dead simple Count-Min Sketch data structure in Python.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mmh3&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CountMinSketch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#1
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#2
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mmh3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#4
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#5
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#6
&lt;/span&gt;            &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="c1"&gt;#7
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;We require 2 parameters to create a CMS object. &lt;code&gt;w&lt;/code&gt;: the width of our table and &lt;code&gt;d&lt;/code&gt;: number of hash functions.&lt;/li&gt;
&lt;li&gt;We pre-populate the tables with zeros. Notice that one dimension is &lt;code&gt;s&lt;/code&gt; and the other &lt;code&gt;w&lt;/code&gt; which is basically a matrix.&lt;/li&gt;
&lt;li&gt;This is our hash function. It requires 2 parameters. &lt;code&gt;x&lt;/code&gt; which is the input and &lt;code&gt;seed&lt;/code&gt; that is used to seed the mmh3 hash function. &lt;code&gt;seed&lt;/code&gt; needs to be unique for each &lt;code&gt;d&lt;/code&gt;. Later you'll see that I used the index of &lt;code&gt;d&lt;/code&gt; elements for seed but that's not good :) You need to generate random numbers when creating the CMS object for each element. After generating the hash, we normalize it relative to &lt;code&gt;w&lt;/code&gt; to generate an index for &lt;code&gt;w&lt;/code&gt; arrays.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;add&lt;/code&gt; function, we should iterate over all hash function elements (&lt;code&gt;d&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;For each element, we calculate a hash which itself is an index for &lt;code&gt;w&lt;/code&gt; arrays. Now we have an index for both dimension and increment the value by one.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;get&lt;/code&gt; function like the one in &lt;code&gt;add&lt;/code&gt;, we iterate over all hash function elements (&lt;code&gt;d&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Like before, we calculate the hash, and using the table index, we get the value inside and put it in a temporary array named &lt;code&gt;items&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After going through all hash function elements (&lt;code&gt;d&lt;/code&gt;), we select the minimum of all items and return it. This is basically our estimation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sketch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CountMinSketch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sketch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2001:0db8:85a3:0000:0000:8a2e:0370:7334&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sketch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2001:0db8:85a3:0000:0000:8a2e:0370:7334&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sketch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2001:0db8:85a3:0000:0000:8a2e:0370:7334&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# prints 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By combining this and a simple rate-limiter explained in another post (&lt;a href="https://dev.to/satrobit/rate-limiting-using-the-token-bucket-algorithm-3cjh"&gt;Rate limiting using the Token Bucket algorithm&lt;br&gt;
&lt;/a&gt;), You'll have a rate-limiter ready for IPv6.&lt;/p&gt;

&lt;p&gt;There's lots of optimization you can do and one of them is making the object, CIDR-aware. You can also tweak the implementation or use different hash functions to get the best performance possible.&lt;/p&gt;

&lt;p&gt;Even though we used Count-Min Sketch to store the frequency of incoming packets, but its application is extremely broad, especially when you're dealing with stream processing workloads.&lt;/p&gt;

&lt;p&gt;This post was so fun to write and I hope you found it fun to read. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/IPv6_deployment" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/IPv6_deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.researchgate.net/figure/The-Count-Min-sketch-combines-the-counts-of-multiple-items-and-returns-the-counter_fig1_261130855" rel="noopener noreferrer"&gt;https://www.researchgate.net/figure/The-Count-Min-sketch-combines-the-counts-of-multiple-items-and-returns-the-counter_fig1_261130855&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cse.unsw.edu.au/%7Ecs9314/07s1/lectures/Lin_CS9314_References/cm-latin.pdf" rel="noopener noreferrer"&gt;https://www.cse.unsw.edu.au/~cs9314/07s1/lectures/Lin_CS9314_References/cm-latin.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>python</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Function as a service: behind the scenes</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Sun, 28 Mar 2021 14:49:05 +0000</pubDate>
      <link>https://dev.to/satrobit/function-as-a-service-behind-the-scenes-10</link>
      <guid>https://dev.to/satrobit/function-as-a-service-behind-the-scenes-10</guid>
      <description>&lt;h1&gt;
  
  
  Function as a service: behind the scenes
&lt;/h1&gt;

&lt;p&gt;It's been months when I first decided to write this post but I honestly didn't know to structure all the materials. With that in mind, I started writing it so let's see how It goes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article tends to be a little bit unfair because I won't cover all topics equally. There are some things that interest me more than others.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Introduction to Function as a service
&lt;/h1&gt;

&lt;p&gt;As the name suggests, in this model we deploy units of "function" or "code". These platforms are designed to make developers stop worrying about the underlying infrastructure needed to run their code.&lt;/p&gt;

&lt;p&gt;In this model, the FaaS platform is language-aware so the only thing developers need to do is exposing a function to the FaaS runtime and the rest will be taken care of by the FaaS platform. So no servers, only an entry point function!&lt;/p&gt;

&lt;p&gt;This doesn't mean that your code magically is deployed without any kind of server. The server stuff is provided and managed by the FaaS platform so you don't have to worry about it.&lt;/p&gt;

&lt;p&gt;By using a FaaS platform, You can achieve Serverless, the buzzword of the year! In a true Serverless platform, some concepts like servers, containers, scaling, reserved resources and etc simply don't exist in users' world. Also in most platforms, billing is done on a per-request basis which is awesome :)&lt;/p&gt;

&lt;p&gt;These things sound amazing and I do believe it is. But most legacy systems are not designed to be deployed using this model and lots of them for good reasons. It's worth noting that most FaaS platforms assume that your software is stateless so their use case might be limited for now.&lt;/p&gt;

&lt;p&gt;Anyway, we're not here to discuss the pros and cons of FaaS. So let's dive in and find out how a FaaS platform is made.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj97tefctqki2yp1d4iyb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj97tefctqki2yp1d4iyb.jpg" alt="FaaS from dashbird"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FaaS is used for a variety of use cases including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data Processing&lt;/li&gt;
&lt;li&gt;IoT Backend Services&lt;/li&gt;
&lt;li&gt;Cron Jobs&lt;/li&gt;
&lt;li&gt;All kinds of web access control&lt;/li&gt;
&lt;li&gt;Middlewares&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Serving static sites&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Categorization
&lt;/h1&gt;

&lt;p&gt;Depending on the context, we can define multiple categories for FaaS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Locality
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Central and local deployments&lt;/li&gt;
&lt;li&gt;Edge Computing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Central and local deployments&lt;/strong&gt; is what we think of FaaS platforms when we first think about them. A central and local system that runs our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edge Computing&lt;/strong&gt; truly deserves its own blog post but to make it short, we can say that edge computing is when our code is deployed to multiple regions, and when a user calls our code, we serve them from the nearest location. This model is usually well integrated into CDNs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;VM-based&lt;/li&gt;
&lt;li&gt;Container-based&lt;/li&gt;
&lt;li&gt;Sandbox-based&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No matter what kind of infrastructure, one of the most important goals is isolation. This can be achieved in different ways which we will be discussing in the next section.&lt;/p&gt;

&lt;h1&gt;
  
  
  Infrastructures
&lt;/h1&gt;

&lt;h2&gt;
  
  
  VM-based Platforms
&lt;/h2&gt;

&lt;p&gt;VMs provide a large amount of isolation between instances without any noticeable performance penalty but it has a huge flaw which is the overhead of an OS!&lt;/p&gt;

&lt;p&gt;FaaS platforms are event-based systems so it needs an extremely fast orchestrator. It's quite a challenge to design a VM-based orchestrator that's fast!&lt;/p&gt;

&lt;p&gt;VM-based orchestrators are usually sluggish and don't perform well under stress and yet you just might be able to design a VM-based orchestrator suitable for FaaS platforms if you play your cards well :)&lt;/p&gt;

&lt;p&gt;But the appealing level of isolation and performance in VMs is not something we can forget about. Here's where microVMs enter the game!&lt;/p&gt;

&lt;p&gt;microVM is a lightweight and stripped-down version of a VM. The goal is to reduce the overhead associated with VMs.&lt;/p&gt;

&lt;p&gt;Here are some links to get you started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/opensource/firecracker-open-source-secure-fast-microvm-serverless/" rel="noopener noreferrer"&gt;Announcing the Firecracker Open Source Technology: Secure and Fast microVM for Serverless Computing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/firecracker-microvm/firecracker" rel="noopener noreferrer"&gt;firecracker-microvm/firecracker&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://itnext.io/microvm-another-level-of-abstraction-for-serverless-computing-5f106b030f15" rel="noopener noreferrer"&gt;microVM: Another Level of Abstraction for Serverless Computing&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://katacontainers.io/" rel="noopener noreferrer"&gt;Kata Containers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Container-based Platforms
&lt;/h2&gt;

&lt;p&gt;Some platforms settle for containers to reduce their overhead. In Linux, containers use cgroups and namespaces to provide a "good enough" level of isolation between instances and the host. The small size of container instances and their native performance has turned this method into the most desirable way to provide infrastructure for FaaS.&lt;/p&gt;

&lt;p&gt;But there's a catch. Containers are not sandboxed! They don't have the same level of isolation as in VMs or sandboxes. That's why we have been seeing some new projects which provide sandboxing for containers like &lt;a href="https://gvisor.dev/" rel="noopener noreferrer"&gt;gVisor&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sandbox-based platforms
&lt;/h2&gt;

&lt;p&gt;Sandboxes provide limited space for processes to play in like when you played in one when you were a kid. (Fun fact: we didn't have sandboxes in our country while growing up)&lt;/p&gt;

&lt;p&gt;Processes that run in a sandbox can't interact with OS directly, instead, they rely on the interface that the sandbox runtime provides. This allows us to trace interface calls and prevent malicious processes to access the host.&lt;/p&gt;

&lt;p&gt;Sandboxes are hard! It's not easy to design and implement a sandbox with decent performance but in the end, the result is worth it.&lt;/p&gt;

&lt;p&gt;Some of the most noticeable sandbox implementation currently used in the FaaS world:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;WebAssembly runtimes&lt;/li&gt;
&lt;li&gt;V8 JavaScript engine&lt;/li&gt;
&lt;li&gt;gVisor&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  FaaS Sandbox Implamantations
&lt;/h1&gt;

&lt;p&gt;In this section, We review 2 FaaS implementations using sandboxes: V8 and WebAssembly.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebAssembly
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;WebAssembly is a portable binary instruction format for virtual stack machines.&lt;/p&gt;

&lt;p&gt;It aims to execute at native or near-native speed by assuming a few characteristics about the execution environment.&lt;/p&gt;

&lt;p&gt;WebAssembly is designed to be executed in a fully sandboxed environment with linear memory. The binary is completely blind to the host environment by default because of that design. That being said, we can set up some kind of communication by reading memory or importing functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've written about WebAssembly before. You can read about it before continuing:&lt;br&gt;
&lt;a href="https://dev.to/satrobit/webassembly-wasmer-and-embedding-wasmer-in-c-program-31p2"&gt;WebAssembly, Wasmer And Embedding Wasmer in C program&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;WebAssembly is extremely appealing for FaaS since It's designed with sandboxing in mind, It's light and It has many compiler implementations including an LLVM backend which means you can compile any language that has an LLVM compiler to WebAssembly.&lt;/p&gt;

&lt;p&gt;There are a few challenges though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Running WASM modules is inherently a blocking operation. You should consider this and find a solution suitable for your environment If you plan to use WASM for long-running executions.&lt;/li&gt;
&lt;li&gt;Memory is completely isolated. So input data should be copied into the WASM memory.&lt;/li&gt;
&lt;li&gt;CPU limitation! You'll need a plan to limit CPU usages like timeouts or metering. There's no native support for that.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even though these challenges may limit the use of WASM for some use cases but, in my opinion, It's still the best candidate for FaaS platforms.&lt;/p&gt;

&lt;p&gt;There's currently one implementation in the wild that I know of. Fastly Serverless uses lucet to run WASM modules at the edge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41jodhxp4wmk39vloe58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41jodhxp4wmk39vloe58.png" alt="WebAssembly from arghya.xyz"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  V8
&lt;/h2&gt;

&lt;p&gt;Chrome V8 is a JavaScript engine by Google used in Google Chrome, Node.js and etc. In addition to JavaScript V8 is also able to run WASM modules too. V8 is a huge project and It's one of the best JavaScript engines you can find in terms of performance and security. Its development is also guaranteed by the fact is It's used in hundreds of millions of devices. (Java installation flashback :D)&lt;/p&gt;

&lt;p&gt;Isolation in V8 is achieved by using Isolates. Isolates basically create an isolated environment for your codes to run in.&lt;/p&gt;

&lt;p&gt;Implementing a FaaS platform using V8 is a complex task but the reward is an easy and fast entryway for end-users since They can use plain JavaScript and It just works.&lt;/p&gt;

&lt;p&gt;Cloudflare Worker is the only user of V8 at the edge. &lt;/p&gt;

&lt;h1&gt;
  
  
  Commercial Products
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Amazon Lambda: VM-based&lt;/li&gt;
&lt;li&gt;Cloudflare Workers: Sandbox / V8-based&lt;/li&gt;
&lt;li&gt;Fastly Serverless: Sandbox / WASM-based&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are many more like Google Cloud Functions, Fly.io, Stackpath EdgeEngine but I wasn't able to confirm what kind of infrastructure they use.&lt;/p&gt;

&lt;h1&gt;
  
  
  Future
&lt;/h1&gt;

&lt;p&gt;It's hard to say what will happen in the future. Even though FaaS brings many advantages but migrating legacy and existing code may not be easy. In my mind its future is bright but in reality, it might be nothing more than a hype. But I'd say that even If this turned out to a terrible service, We can apply the good parts of FaaS to other services like serverless.&lt;/p&gt;

&lt;p&gt;People don't like to manage their infrastructure and that's just a fact. They don't want to know what is a container, They don't want to know how to scale their service, They only want to worry about their code and I think that's fair. Current PaaS products don't have enough abstractions and the success of services like Vercel shows just that.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this article, I tried to categorize different kinds of FaaS implementations and the technology used in them. I tried to make it short without many details because If I included the details, It had the potential to be a book! And as I said at the beginning, This has been an unfair post since I didn't cover all topics equally.&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>devops</category>
      <category>linux</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Rate limiting using the Token Bucket algorithm</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Thu, 17 Dec 2020 13:33:59 +0000</pubDate>
      <link>https://dev.to/satrobit/rate-limiting-using-the-token-bucket-algorithm-3cjh</link>
      <guid>https://dev.to/satrobit/rate-limiting-using-the-token-bucket-algorithm-3cjh</guid>
      <description>&lt;h1&gt;
  
  
  Rate Limiting
&lt;/h1&gt;

&lt;p&gt;The term "rate-limiting" is known to almost everyone who has worked with web servers. I think It's one of those subjects that we often just use and don't think about it. But I think knowing how rate limiting works is useful If you have ever used it.&lt;/p&gt;

&lt;p&gt;As you may know, "rate-limiting" is basically monitoring the incoming requests and making sure they don't violate a threshold. Basically, we define a rate of requests per time-unit and discard packets of a stream that is sending more packets than the one defined in our rate.&lt;/p&gt;

&lt;p&gt;You probably noticed that I used the word "discard" when our threshold is reached. That's not always the case. In a lot of cases, we put the packets in a queue to keep the packets at a constant output rate. (And packets won't be discarded.)&lt;/p&gt;

&lt;p&gt;What we'll be discussing doesn't require a queue and I dare say It's probably the simplest way to implement rate-limiting.&lt;/p&gt;

&lt;p&gt;The most famous ways of implementing rate-limiting (Traffic Shaping) are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Token Bucket&lt;/li&gt;
&lt;li&gt;Leaky Bucket&lt;/li&gt;
&lt;li&gt;(r, t) Traffic Shaping&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Leaky Bucket is somewhat similar to the Token Bucket but right now we don't care about the constant output rate and Token Bucket is the only algorithm we will talk about.&lt;/p&gt;

&lt;h1&gt;
  
  
  Token Bucket
&lt;/h1&gt;

&lt;p&gt;The Token Bucket analogy is very simple. It's all about a bucket and tokens in it. Let's discuss it step by step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Picture a bucket in your mind.&lt;/li&gt;
&lt;li&gt;Fill the buckets with tokens at a constant rate.&lt;/li&gt;
&lt;li&gt;When a packet arrives, check if there is any token in the bucket.&lt;/li&gt;
&lt;li&gt;If there was any token left, remove one from the bucket and forward the packet. If the bucket was empty, simply drop the packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Wasn't it simple?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmkifh9c3ze4i9ir5j4mo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmkifh9c3ze4i9ir5j4mo.png" alt="Token Bucket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;

&lt;p&gt;Enough talking. Let's write a simple Token Bucket throttler in Python.&lt;/p&gt;

&lt;p&gt;We start by defining a class with 4 arguments when It's being instantiated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;tokens:&lt;/strong&gt; number of tokens added to the bucket in each time unit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;time_unit:&lt;/strong&gt; the tokens are added in this time frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;forward_callback:&lt;/strong&gt; this function is called when the packet is being forwarded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;drop_callback:&lt;/strong&gt; this function is called when the packet should be dropped.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We also prefill the bucket with the given tokens. This allows for a burst of packets when the throttler first starts working.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;last_check&lt;/code&gt; is the timestamp that we previously handled a packet. For initialization, we set the time when we created the bucket.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TokenBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, we define &lt;code&gt;handle()&lt;/code&gt; where the magic happens.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#1
&lt;/span&gt;    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#2
&lt;/span&gt;    &lt;span class="n"&gt;time_passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="c1"&gt;#4
&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
        &lt;span class="n"&gt;time_passed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#5
&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#6
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;

    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#7
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#8
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;handle&lt;/code&gt; accepts only 1 parameter: the packet.&lt;/li&gt;
&lt;li&gt;The current timestamp is put into &lt;code&gt;current&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The time passed between now and the previous &lt;code&gt;handle&lt;/code&gt; call is put into &lt;code&gt;time_passed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We update the &lt;code&gt;last_check&lt;/code&gt; to the current timestamp.&lt;/li&gt;
&lt;li&gt;This is the most important part. By multiplying the &lt;code&gt;time_passed&lt;/code&gt; and our rate (which is &lt;code&gt;tokens&lt;/code&gt; / &lt;code&gt;time_unit&lt;/code&gt;) we find out how many token needs to be added to the bucket.&lt;/li&gt;
&lt;li&gt;Reset the bucket if it has more tokens than the default value.&lt;/li&gt;
&lt;li&gt;If the bucket doesn't have enough token, drop the packet.&lt;/li&gt;
&lt;li&gt;Otherwise, remove one token and forward the packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's all. This is the final working version:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TokenBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time_unit&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forward_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drop_callback&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;time_passed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
            &lt;span class="n"&gt;time_passed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time_unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Forwarded: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Packet Dropped: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="n"&gt;throttle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TokenBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should be getting something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Packet Forwarded: 0
Packet Dropped: 1
Packet Dropped: 2
Packet Dropped: 3
Packet Dropped: 4
Packet Forwarded: 5
Packet Dropped: 6
Packet Dropped: 7
Packet Dropped: 8
Packet Dropped: 9
Packet Forwarded: 10
Packet Dropped: 11
Packet Dropped: 12
Packet Dropped: 13
Packet Dropped: 14
Packet Forwarded: 15


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see in the code, our rate is 1 packet per second. We also send a packet every 0.2 seconds. When we first send a packet it quickly empties the bucket and it takes some time for the bucket to be filled again and that's why 4 packets are dropped between each successful forward.&lt;/p&gt;

&lt;p&gt;Rate limiting and traffic policing, in general, is a very vast subject so If you liked what you just read, there are many materials available online about this subject that you can use to have a much deeper understanding of traffic policing.&lt;/p&gt;

&lt;p&gt;Thank you for your time.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>computerscience</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Absolute Beginner's Guide to BCC, XDP, and eBPF</title>
      <dc:creator>Amir Keshavarz</dc:creator>
      <pubDate>Thu, 26 Nov 2020 10:52:03 +0000</pubDate>
      <link>https://dev.to/satrobit/absolute-beginner-s-guide-to-bcc-xdp-and-ebpf-47oi</link>
      <guid>https://dev.to/satrobit/absolute-beginner-s-guide-to-bcc-xdp-and-ebpf-47oi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you're reading this, chances are you have some idea of eBPF and XDP. In this article, we'll write an eBPF program that will count and categorize packets based on the destination port.&lt;/p&gt;

&lt;h3&gt;
  
  
  eBPF
&lt;/h3&gt;

&lt;p&gt;Writing low-level tracing, monitoring, or network programs in Linux is not easy. Through all the layers of the kernel, people have been squeezing every bit of performance they could get.&lt;/p&gt;

&lt;p&gt;And that's where eBPF comes in. eBPF is basically an extended and modern variation of BPF which is like a virtual machine inside the Linux kernel. It can execute user-defined programs inside a sandbox in the kernel. &lt;/p&gt;

&lt;p&gt;These programs can be executed in various hook points but we will focus on XDP for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  XDP
&lt;/h3&gt;

&lt;p&gt;XDP provides a data path which we can intercept or even edit packets using an eBPF program. The execution can happen in 3 different places depending on your setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Offloaded - NIC:&lt;/strong&gt; eBPF program can be offloaded to the network card itself, provided that the card supports XDP offloading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native - NIC Driver:&lt;/strong&gt; eBPF will fallback to the driver if your card doesn't support offloading. The good news is that most drivers support this and performance is still impressive since this is all before entering the Linux network stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic - Linux Network Stack:&lt;/strong&gt; This is the last option if the mentioned methods are not supported. Performance is not as good since the packet has entered the network stack.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fate of packets is decided by action codes that your program returns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;XDP_PASS:&lt;/strong&gt; let the packet continue through the network stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XDP_DROP:&lt;/strong&gt; silently drop the packet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XDP_ABORTED:&lt;/strong&gt; drop the packet with trace point exception&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XDP_TX:&lt;/strong&gt; bounce the packet back to the same NIC it arrived on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XDP_REDIRECT:&lt;/strong&gt; redirect the packet to another NIC or user space socket via the &lt;code&gt;AF_XDP&lt;/code&gt; address family&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  BCC
&lt;/h3&gt;

&lt;p&gt;BCC is a toolkit for creating eBPF programs with bindings to a few languages like Python, Lua and etc. BCC makes it pleasantly easy to write eBPF programs and their GitHub page is filled with examples to get you started.&lt;/p&gt;

&lt;p&gt;We'll use BCC in Python to write our program.&lt;/p&gt;

&lt;h2&gt;
  
  
  eBPF Program in C
&lt;/h2&gt;

&lt;p&gt;We start by writing the eBPF program itself before getting into the bcc stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entry Point
&lt;/h3&gt;

&lt;p&gt;eBPF is event-driven so it'll call our exposed function when a packet arrives. Hence, we'll define a function that receives packet metadata and returns an XDP action code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define KBUILD_MODNAME "udp_counter"
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/bpf.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/if_ether.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/ip.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/udp.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;udp_counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;xdp_md&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bpf_trace_printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"packet received&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// MORE CODE HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UDP Packet Data
&lt;/h3&gt;

&lt;p&gt;using the &lt;code&gt;ctx&lt;/code&gt; we can extract everything we need about the arrived packet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ethhdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;iphdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;IPPROTO_UDP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;udphdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// MORE CODE HERE&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we go through the eth and IP packet to get to the UDP packet. Here, we can get the destination port that needs to be stored in a histogram. But what histogram!? In the next section, we learn about BPF maps.&lt;/p&gt;

&lt;h3&gt;
  
  
  BPF Maps
&lt;/h3&gt;

&lt;p&gt;If you were wondering how will we be able to store our results, there is amazing news. BPF provides multiple useful data structures that we can use to store persisted data or even exchange data to and from userland.&lt;/p&gt;

&lt;p&gt;Here is a list of some of the most noticeable data BPF data structures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;BPF_TABLE&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BPF_HASH&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BPF_ARRAY&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BPF_HISTOGRAM&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BPF_PERF_ARRAY&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll use &lt;code&gt;BPF_HISTOGRAM&lt;/code&gt; to count UDP packets based on their port.&lt;/p&gt;

&lt;p&gt;Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BPF_HISTOGRAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="n"&gt;key_type&lt;/span&gt; &lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we define the histogram outside of the &lt;code&gt;udp_counter&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;BPF_HISTOGRAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need only one method to work with histograms: &lt;code&gt;increment()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;increment&lt;/code&gt; will increment the value based on the key that you provided.&lt;br&gt;
Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="n"&gt;increment_amount&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next section, we go back to the UDP packet and try to count them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Counter
&lt;/h3&gt;

&lt;p&gt;In the &lt;code&gt;UDP Packet Data&lt;/code&gt; section, we extracted the UDP packet and left a place to count them.&lt;/p&gt;

&lt;p&gt;Since we have a histogram ready, the only thing you need to do is to increment the value based on the port that you extract from the UDP packet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;u64&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The htons() function converts the unsigned short integer hostshort from host byte order to network byte order.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  XDP Action Code
&lt;/h3&gt;

&lt;p&gt;Now that we're done with the packet, we need to pass the packet so it can go through the network stack. We can just return &lt;code&gt;XDP_PASS&lt;/code&gt; at the end of our function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define KBUILD_MODNAME "udp_counter"
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/bpf.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/if_ether.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/ip.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;linux/udp.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;BPF_HISTOGRAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;udp_counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;xdp_md&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ethhdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;iphdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;IPPROTO_UDP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;

                &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;udphdr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;data_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;u64&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;udp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;XDP_PASS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  BCC Program
&lt;/h2&gt;

&lt;p&gt;The only thing left to write is a simple bcc program to load our eBPF code and attach it to a device like loopback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bcc&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BPF&lt;/span&gt; &lt;span class="c1"&gt;#1
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bcc.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;printb&lt;/span&gt;

&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lo"&lt;/span&gt; &lt;span class="c1"&gt;#2
&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BPF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"udp_counter.c"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#3
&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"udp_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BPF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XDP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#4
&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attach_xdp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#5
&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace_print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#6
&lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#7
&lt;/span&gt;
    &lt;span class="n"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#8
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt; &lt;span class="c1"&gt;#9
&lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DEST_PORT : %10d, COUNT : %10d"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;#10
&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove_xdp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#11
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the program is fairly simple.&lt;/p&gt;

&lt;p&gt;Steps explained:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import the BPF python lib.&lt;/li&gt;
&lt;li&gt;Specify which device you want your eBPF code to get attached to.&lt;/li&gt;
&lt;li&gt;Create the BPF object and load the file.&lt;/li&gt;
&lt;li&gt;Load the function.&lt;/li&gt;
&lt;li&gt;Attach the function to the xdp hook of the device that was specified earlier.&lt;/li&gt;
&lt;li&gt;Read the trace_pipe file so we can trace what's happening.&lt;/li&gt;
&lt;li&gt;Catch the exit signal so we can exit gracefully.&lt;/li&gt;
&lt;li&gt;Get the contents of the histogram.&lt;/li&gt;
&lt;li&gt;Iterate over the content.&lt;/li&gt;
&lt;li&gt;Print the results.&lt;/li&gt;
&lt;li&gt;Deattach our code from the device.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Execution
&lt;/h3&gt;

&lt;p&gt;Simple run the python code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for some data to be gathered. You can send out some packets using &lt;code&gt;nc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-u&lt;/span&gt; 127.0.0.1 5005
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send multiple packets to different ports and then exit from the python program. You should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEST_PORT : 5007, COUNT : 1
DEST_PORT : 5005, COUNT : 5
DEST_PORT : 5006, COUNT : 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the result shows how many packets were sent to these ports separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we learned about eBPF and XDP and why they matter so much. We also were able to write a program to count UDP packets based on their ports using the amazing BCC toolkit.&lt;/p&gt;

&lt;p&gt;I really hope this article has been helpful. Thank you for your time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Berkeley_Packet_Filter#Extensions_and_optimizations"&gt;https://en.wikipedia.org/wiki/Berkeley_Packet_Filter#Extensions_and_optimizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cilium.io/en/stable/bpf/"&gt;https://docs.cilium.io/en/stable/bpf/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Express_Data_Path"&gt;https://en.wikipedia.org/wiki/Express_Data_Path&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ebpf.io/what-is-ebpf"&gt;https://ebpf.io/what-is-ebpf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iovisor/bcc"&gt;https://github.com/iovisor/bcc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md"&gt;https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/3/hton"&gt;https://linux.die.net/man/3/hton&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>ebpf</category>
      <category>xdp</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
