Jeff Epler's blog

20 April 2019, 15:11 UTC

Hello, Allo

In the last two years, a new internet provider has entered the market in my hometown. Allo Commmunications has been laying fiber optic cables all over town for forever, and finally notified me last month that my neighborhood was ready for installation. This week, I got the service installed. Overall, I'm happy, though I'll be paying just a few bucks more a month than I'd anticipated.

The good:

  • 20, 300, and 1000Mbit/s rates available ($45 - $100/month base rate)
  • Router/WiFi AP included in base rate
  • Static IP is just $5/month
  • symmetric connection speeds
  • helpful staff
  • No bandwidth caps, but "if you’re breaking the law, be assured you’ll be hearing from us."
  • TV and telephone, if you're into that sort of thing

The bad:

  • Except for static IP, you're behind "Carrier Grade NAT", so no "I'll cope with dynamic IP but still be able to SSH in"
  • Your existing eqipment might not be able to keep up
  • Given google's chat product also called "allo", these guys can be hard to search for
  • No bandwidth caps, but "if you’re breaking the law, be assured you’ll be hearing from us."
  • Small service area (9 Nebraska towns + Fort Morgan Colorado)
  • No IPv6(!?), possibly deploying v6 in 2020.
  • My static IP is listed in spamhaus "PBL" (but there is a self-service removal process, so it's fine)

The main headache I had was that first "the bad" bullet point: Despite having a phone app(!!) that acts like it can set up port forwarding, nothing I did could open up an incoming port. Staff were interested in helping me (including calling me back later to try one last idea), but ultimately the solution was just to add the Static IP option to my service.

The lesser headache, and the one which was totally my problem to solve, is that my firewall and NAT was being done by an older Buffalo wifi access point, WZR-HP-G300NH2 with an ancient version of DD-WRT. It simply couldn't get beyond about 160Mbit/s when doing NAT/forwarding. So I rejiggered my wires a little bit so that my i7 Linux desktop would take over those tasks. Additionally, all the "modern wifi" devices were already connecting to a newer Netgear R6220 in Access Point mode (routing functions disabled).

I had a second headache, which is apparently a decade-old bug in Linux's Intel e1000e driver. I was getting really poor rates on my internal network, and the kernel was logging "eth2: Detected Hardware Unit Hang". There are two main fixes that the internet suggests: modifying something about power saving modes, or disabling several advanced features of the NIC. In my case, I determined that using "ethtool --offload eth2 tso off" to disable tcp-segmentation-offload resolved the problem I was seeing. What's weird is that this NIC, eth2, is the one that I had been using all along; I had lots of network traffic on it for months. But the message never appeared in my local logs before I started also using "eth1" and doing NAT/packet forwarding yesterday.

Now from my desktop I get 960Mbit/s down, 720Mbit/s up (according to speedtest-cli), and 6ms pings to my office. My fastest wireless device gets somewhat over 200Mbit/s in each direction. Connecting to a VNC session at my office feels just as good as being there, which is primarily due to the extremely short packet turnaround; the bandwidth is a nice bonus though.

Right now it all feels pretty magical, and I'm looking forward to calling the cable company (spectrum) on Monday to cancel the service. I'm paying more (not quite 2x as much) but getting MUCH more service.

I'm contemplating buying one of these little embedded PCs with 2 NICs, they cost around $200 with RAM and a small SSD and it is claimed that they can forward at gigabit rates. They're literally just PCs inside (x86 CPU and BIOS booting), so all the headaches that attend little embedded ARM systems are nonexistent. But is an Intel Celeron "J1800" CPU actually up to pushing (including NAT) a quarter million packets a second?

I have a bittorrent client running with a bunch of Linux ISOs being seeded. I saw peak download rates of up to 92MB/s and typically 30-60MB/s, which is great. Right at the moment it's only clocking about 2MB/s of data "up"—the torrents seem to be pretty adequately seeded. I'm doing this primarily to see whether Allo treats "any traffic identifiable as bittorrent" as something that they'll tell you off about, or whether they are trying to distinguish "licit" from "illicit" when it comes to bittorrent traffic. I'm not sure which idea I like less.


7 April 2019, 20:42 UTC

Linux: don't wake display on mouse motion

I have one machine which repeatedly wakes its display at night. My assumption is that this is due to spurious movement from the mouse.

There is not an explicit way to configure Linux (X11) so that it doesn't exit DPMS sleeps on mouse movement, but I found a tip on the internet to disable the mouse device at the XInput level when activating the screensaver, and reactivating it when the screensaver exits.

I don't run a "screensaver application" so wiring into things like dbus for notification doesn't work. Instead, I wrote an X program which polls the requested DPMS state and enables or disables the mouse device accordingly.

It remains to be seen whether this solves the problem which causes the display to turn on multiple times per night, but it might just fix it.

You'll need to customize the program by changing the "device_name" string in the source to match your own input device. If you have multiple input devices, then more extensive work will be required.

License: GPL v3+

Files currently attached to this page:



1 March 2016, 2:56 UTC

Literal copying of GPL code into ZFS on Linux

Recently, Canonical has announced that they plan to ship zfsonlinux in compiled form from their "main" repository. They rely on advice from their lawyers that the compiled form of zfs.ko, the kernel loadable module implementing zfs, is not a derivative of the linux kernel. This is important, because if zfsonlinux is a derivative of both GPL code and CDDL code, the two licenses impose incompatible requirements on the compiled form of the software, and distribution is not possible. (This is in contrast to Debian's plan to ship zfs in source form only in their next release (and also in the somewhat ghettoized "contrib" section rather than "main"); this is considered safer by many because the GPL's restrictions on code in source format are less stringent than code in object code or executable format)

There are two main ways that zfsonlinux's zfs.ko could be a derivative work of linux: First, and the option that many commenters have concentrated on, is if the act of compiling zfs also includes copyrighted portions of linux in a way that activates the GPL's restrictions because the combined work is "a work based on [the Linux kernel]". However, there is a second way that zfsonlinux could be subject to the GPL and CDDL simultaneously: if source code licensed exclusively under the GPL has been copied into the zfsonlinux source tree.

In this article, I collect some samples of code from zfsonlinux and compare those samples to code committed earlier to linux. I present the samples using a customized word diff algorithm. To reproduce my results, you will need to manually find the associated refs in linux.git and zfsonlinux/zfs.git and use your own word-diff algorithm.

I don't know whether I've found the worst of the code copying; I found the two examples given below pretty quickly, imagined that I had found just the tip of the iceberg, and then decided to write this article before looking for more. But I haven't found any more that are as clear-cut as these two examples are in my mind, while also being over ten lines long. Beginner's luck? Or did I find the 50 copied lines out of 260,000 lines in a half hour and that's the whole story?

Because I cannot speak for the authors of the code committed to linux.git which appear to be duplicated in zfsonlinux, it is impossible for me to say whether they have some private arrangement with the code authors that permit the use of the code snippets under the CDDL. If not, it's a legal question whether the amount of code copied is relevant under copyright law. In this area, I imagine caution is best; after all, in the US, Google's copying of the 9-line "RangeCheck" function (out of how many million lines in the JRE?) has been determined not to be de minimis, though in a new trial Google will assert a fair use defense regarding that copying.

(note: some popular RSS readers do not show the color coding of insertions and deletions)

Snippet A: linux at commit 5f99f4e79abc64ed9d93a4b0158b21c64ff7f478
Snippet B: zfsonlinux at commit 0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66
Common text

static inline bool dir_emit(struct dir_context *ctx,
                           const char *name, int namelen,
    uint64_t ino, unsigned type)
       return ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type) == 0;
static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
       return ctx->actor(ctx->dirent, ".", 1, ctx->pos,
                         file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0;
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
       return ctx->actor(ctx->dirent, "..", 2, ctx->pos,
                         parent_ino(file->f_path.dentry), DT_DIR) == 0;
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
       if (ctx->pos == 0) {
               if (!dir_emit_dot(file, ctx))
                       return false;
               ctx->pos = 1;
       if (ctx->pos == 1) {
               if (!dir_emit_dotdot(file, ctx))
                       return false;
               ctx->pos = 2;
       return true;

Snippet A: linux at c3c532061e46156e8aab1268f38d66cfb63aeb2d
Snippet B: zfsonlinux at 5547c2f1bf49802835fd6c52f15115ba344a2a8b
Common text

static inline int bdi_setup_and_register(struct backing_dev_info *bdi, char *name,
                           unsigned int cap)
        char tmp[32];
        int errerror;

        bdi->name = name;
        bdi->capabilities = cap;
        errerror = bdi_init(bdi);
        if (errerror)
                return err;(error);

        sprintf(tmp, "%.28s%s", name, "-%d");
        errerror = bdi_register(bdi, NULL, tmp, atomic_long_inc_return(&bdi_seqzfs_bdi_seq));
        if (errerror) {
                return err;(error);

        return 0;(error);


1 September 2015, 14:39 UTC

DragonBoard™ 410c with rt-preempt failure

I was excited to obtain a DragonBoard, an affordable 64-bit ARM single-board computer, but unfortunately it hasn't lived up to my hopes.

First of all, it shipped with one terrible problem, making it useless for headless development: The onboard wireless doesn't receive multicast traffic, including ARP requests! And their kernel doesn't provide many modular drivers, so adding any old USB wireless dongle doesn't work until you rebuild the kernel. As of this writing, there is no useful workaround.

And that's when I hit the second show-stopper problem. I planned to build kernels for this thing anyway, because the goal is to run LinuxCNC on it with rt-preempt realtime. So I stuck in a large capacity micro-sd card, obtained the kernel source, built it, and rebooted with my new kernel.

(incidentally, testing kernels is a PITA. You have two choices: one, flash the one and only boot area with your new and untested kernel and hope for the best; two, tether to a PC (losing USB keyboard and mouse on the dragonboard!) and use fastboot every time you boot. ugh)

.. but the new kernel just didn't work. It scrolled kernel messages, but got stuck partway through booting. dmesg implicated the wireless card. This one at least has a workaround: cherry-pick a certain commit from their kernel git. As I understand it, this bug is triggered by using the compiler on the dragonboard, and not encountered with the linaro cross-compiler running on a traditional x86 desktop.

Anyway, having found out about this I was briefly celebratory. I booted with my own kernel and had a working USB dongle. Unfortunately, that celebration was short-lived. The USB dongle hasn't been terribly reliable either, particularly under high CPU load.

I soldiered on and patched the linaro 4.0 kernel with the 4.0-rt5 patchset. There were a few minor conflicts which I believe I resolved correctly. Unfortunately, the LinuxCNC latency-test readily encounters latencies above 15ms (15000us). LinuxCNC really would like sub-100us max latencies.

I briefly enabled tracers, and have traces that seem to implicate a variety of subsystems: networking, usb, and video *all* figure. More experienced developers than I will have to be the ones to sort out RT on 64-bit ARM.


4 March 2015, 19:45 UTC

Hide non-linux titles in humble bundle sales

Like many people over the age of 30, I remember when the Humble Bundle consistently offered Linux versions of almost everything in their bundles.

Those days are long gone, and now it's necessary to scrub over the "DRM FREE!" button of every title to find out whether it's on Linux.

But with this userscript (tested only on firefox with greasemonkey), titles that are not available on Linux are automatically greyed out and need trouble you no more.

If you're like me, and the number of times you boot a Windows machine to play video games is way under twice a year, remember to vote with your wallet: before checking out, open "choose where your money goes" and "developers", then slide the slider for all non-linux titles right down to zero.


24 June 2014, 12:35 UTC

Better pasting for irssi in X

While it's otherwise an excellent irc client, I've been frustrated by pasting in irssi. There are two main problems:

read more…

15 May 2014, 16:28 UTC

Samsung ARM Chromebook: the portable I've always wanted

As you might remember, I got a chromebook back in January. A few months later, I just want to say: this is the portable I've always wanted.

read more…

24 February 2014, 13:10 UTC

How do you check a signature on a PGP/Mime message

…I'll answer in Python. First, put your whole message in a file in unix "mbox" format (this will be the problem if you use some brain-dead GUI mailer!), then in Python extract the signature and the signed message, and finally invoke gpg:

import email
import os
import sys

with open(sys.argv[1]) as mfile: message = email.message_from_file(mfile)

if message.get_content_type() != "multipart/signed":
    raise SystemExit, "message not signed"

# Really, you'd want safe temporary filenames, and you'd want to clean them up
with open("msg", "wb") as msg: msg.write(message.get_payload(0).as_string())
with open("sig", "wb") as sig: sig.write(message.get_payload(1).get_payload())

# Delegate the real business to gpg
os.execvp("gpg", ["gpg", "--verify", "sig", "msg"])


31 January 2014, 18:05 UTC

Mosh automatic cleanup of dead sessions

24 January 2014, 17:06 UTC

Got A Chromebook

23 January 2014, 22:18 UTC

pnacl vs Debian Jessie

21 December 2013, 3:53 UTC

First few weeks on Digital Ocean

13 December 2013, 23:26 UTC

Benchmarking ungeli on real data

6 December 2013, 19:31 UTC

Changing hosting providers

2 December 2013, 19:30 UTC

mailpie moves to github

All older entries
Website Copyright © 2004-2018 Jeff Epler