
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Wed, 08 Apr 2026 19:56:11 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Three little tools: mmsum, mmwatch, mmhistogram]]></title>
            <link>https://blog.cloudflare.com/three-little-tools-mmsum-mmwatch-mmhistogram/</link>
            <pubDate>Tue, 04 Jul 2017 10:32:20 GMT</pubDate>
            <description><![CDATA[ In a recent blog post, my colleague Marek talked about some SSDP-based DDoS activity we'd been seeing recently. In that blog post he used a tool called mmhistogram to output an ASCII histogram. ]]></description>
            <content:encoded><![CDATA[ <p>In a recent blog post, my colleague <a href="/author/marek-majkowski/">Marek</a> talked about some <a href="/ssdp-100gbps/">SSDP-based DDoS</a> activity we'd been seeing recently. In that blog post he used a tool called <code>mmhistogram</code> to output an ASCII histogram.</p><p>That tool is part of a small suite of command-line tools that can be handy when messing with data. Since a reader asked for them to be open sourced... here they are.</p>
    <div>
      <h3>mmhistogram</h3>
      <a href="#mmhistogram">
        
      </a>
    </div>
    <p>Suppose you have the following CSV of the ages of major Star Wars characters at the time of Episode IV:</p>
            <pre><code>Anakin Skywalker (Darth Vader),42
Boba Fett,32
C-3PO,32
Chewbacca,200
Count Dooku,102
Darth Maul,54
Han Solo,29
Jabba the Hutt,600
Jango Fett,66
Jar Jar Binks,52
Lando Calrissian,31
Leia Organa (Princess Leia),19
Luke Skywalker,19
Mace Windu,72
Obi-Wan Kenobi,57
Palpatine,82
Qui-Gon Jinn,92
R2-D2,32
Shmi Skywalker,72
Wedge Antilles,21
Yoda,896</code></pre>
            <p>You can get an ASCII histogram of the ages as follows using the <code>mmhistogram</code> tool.</p>
            <pre><code>$ cut -d, -f2 epiv | mmhistogram -t "Age"
Age min:19.00 avg:123.90 med=54.00 max:896.00 dev:211.28 count:21
Age:
 value |-------------------------------------------------- count
     0 |                                                   0
     1 |                                                   0
     2 |                                                   0
     4 |                                                   0
     8 |                                                   0
    16 |************************************************** 8
    32 |                         ************************* 4
    64 |             ************************************* 6
   128 |                                            ****** 1
   256 |                                                   0
   512 |                                      ************ 2</code></pre>
            <p>Handy for getting a quick sense of the data. (These charts are inspired by the <a href="/revenge-listening-sockets/">ASCII output from systemtap</a>).</p>
    <div>
      <h3>mmwatch</h3>
      <a href="#mmwatch">
        
      </a>
    </div>
    <p>The <code>mmwatch</code> tool is handy if you want to look at output from a command-line tool that provides some snapshot of values, but need to have a rate.</p><p>For example, here's <code>df -H</code> on my machine:</p>
            <pre><code>$ df -H
Filesystem             Size   Used  Avail Capacity  iused   ifree %iused  Mounted on
/dev/disk1             250G   222G    28G    89% 54231161 6750085   89%   /
devfs                  384k   384k     0B   100%     1298       0  100%   /dev
map -hosts             0B     0B     0B   100%        0       0  100%   /net
map auto_home          0B     0B     0B   100%        0       0  100%   /home
/dev/disk4             7.3G    50M   7.2G     1%    12105 1761461    1%   
/Volumes/LANGDON</code></pre>
            <p>Now imagine you were interested in understanding the rate of change in iused and ifree. You can with <code>mmwatch</code>. It's just like <code>watch</code> but looks for changing numbers and interprets them as rates:</p>
            <pre><code>$ mmwatch 'df -H'</code></pre>
            <p>Here's a short GIF showing it working:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7n0JNaLVIvtD7cqC9kfasI/c1626e6be3fb8bf8b5086ddf7ecde187/mmwatch.gif" />
            
            </figure>
    <div>
      <h3>mmsum</h3>
      <a href="#mmsum">
        
      </a>
    </div>
    <p>And the final tool is <code>mmsum</code> that simply sums a list of floating point numbers (one per line).</p><p>Suppose you are downloading real-time rainfall data from the UK's Environment Agency and would like to know the total current rainfall. <code>mmsum</code> can help:</p>
            <pre><code>$ curl -s 'https://environment.data.gov.uk/flood-monitoring/id/measures?parameter=rainfall' | jq -e '.items[].latestReading.value+0' | ./mmsum
40.2</code></pre>
            <p>All these tools can be found on the Cloudflare <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2017-06-29-ssdp/">Github</a>.</p> ]]></content:encoded>
            <category><![CDATA[Tools]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[ASCII]]></category>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">4y5kxTJk106JdQKEiQDj95</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
        <item>
            <title><![CDATA[The oldest trick in the ASCII book]]></title>
            <link>https://blog.cloudflare.com/the-oldest-trick-in-the-ascii-book/</link>
            <pubDate>Sun, 12 Apr 2015 20:23:15 GMT</pubDate>
            <description><![CDATA[ If you're old enough (or interested enough) to have spent a lot of time messing around with the ASCII table then you might have run into a strange fact: it's possible to uppercase ASCII text using just bitwise AND. ]]></description>
            <content:encoded><![CDATA[ <p>If you're old enough (or interested enough) to have spent a lot of time messing around with the ASCII table then you might have run into a strange fact: it's possible to uppercase ASCII text using just bitwise AND.</p><p>And it turns out that in some situations this isn't just a curiosity, but actually useful. Here are the ASCII characters 0x20 (space) to 0x7E (tilde).</p>
            <pre><code>     0123456789ABCDEF0123456789ABCDEF
    +--------------------------------
0x20| !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?
0x40|@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
0x60|`abcdefghijklmnopqrstuvwxyz{|}~</code></pre>
            <p>It's immediately obvious that each lowercase letter has an ASCII code 0x20 more than the corresponding uppercase letter. For example, lowercase m is 0x6D and uppercase M is 0x4D. And since 0x20 is a single bit then it's possible to uppercase an ASCII letter by taking its code and applying <code>AND 0xDF</code> (masking out the 0x20 bit).</p><p>Performing <code>AND 0xDF</code> has no effect on the first two rows above: they, including the uppercase letters, are unchanged. Only the third row is affected. There the lowercase letters get uppercased but there's some collateral damage: `` { | } ~<code>change to</code>@ [ \ ] ^`.</p><p>But if you know that a string has a limited character set then this trick can come in handy. Lots of old protocols (SMTP, POP3, ...) use USASCII characters for their commands. DNS names are typically restricted to letters, numbers and -. Even HTTP recommends that use of USASCII for the HTTP header.</p><p>So, if you know that your string is <code>AND 0xDF</code>-safe then the following C code makes a very fast case-insensitive comparison:</p>
            <pre><code>// Returns 1 if x == y (case insensitive)
int cmp(const char *x, const char* y) {
  while (*x &amp;&amp; *y) {
    if ((*x++ &amp; 0xdf) != (*y++ &amp; 0xdf)) {
      return 0;
    }
  }
  return (*x == 0) &amp;&amp; (*y == 0);
}</code></pre>
            <p>And that sort of low-level trickery turns out to matter when you are being hit by millions of DNS packets per second and need to make very, very fast filtering decisions.</p> ]]></content:encoded>
            <category><![CDATA[ASCII]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">3PnNzPJEZDsdNgYXkyH19K</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
    </channel>
</rss>