<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 16, 2018, at 12:30 AM, Dave Taht <<a href="mailto:dave.taht@gmail.com" class="">dave.taht@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Eric just suggested using the iptables NFQUEUE ability to toss</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">packets to userspace.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://home.regit.org/netfilter-en/using-nfqueue-and-libnetfilter_queue/" class="">https://home.regit.org/netfilter-en/using-nfqueue-and-libnetfilter_queue/</a></div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">For wifi, at least, timings are not hugely critical, a few hundred</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">usec is something userspace can handle reasonably accurately. I like</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">very much being able to separate out mcast and treat that correctly in</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">userspace, also. I did want to be below 10usec (wifi "bus"</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">arbitration), which I am dubious about....</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Now as for an implementation language? C++ C? Go? Python? The</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">condition of the wrapper library for go leaves a bit to be desired</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">(<span class="Apple-converted-space"> </span></span><a href="https://github.com/chifflier/nfqueue-go" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://github.com/chifflier/nfqueue-go</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space"> </span>) and given a choice I'd</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">MUCH rather use a go than a C.</span></div></blockquote><div><br class=""></div><div>This sounds cool... So for fun, I compared ping and iperf3 with no-op nfqueue callbacks in both C and Go. As for the hardware setup, I used two lxc containers (effectively just veth) on an APU2.</div><div><br class=""></div><div>For the Go program, I used test_nfqueue from the wrapper above (which yes, does need some work) and removed debugging / logging.</div><div><br class=""></div><div>For the C program I used this:</div><div><a href="https://github.com/irontec/netfilter-nfqueue-samples/blob/master/sample-helloworld.c" class="">https://github.com/irontec/netfilter-nfqueue-samples/blob/master/sample-helloworld.c</a></div><div>I removed any per-packet printf calls and compiled with "gcc sample-helloworld.c -o nfq -lnfnetlink -lnetfilter_queue”.</div><div><br class=""></div><div>Ping results:</div><div><br class=""></div><div>ping without nfqueue:</div><div><div>root@lsrv:~# iptables -F OUTPUT</div><div>root@lsrv:~# ping -c 500 -i 0.01 -q 10.182.122.11<br class="">500 packets transmitted, 500 received, 0% packet loss, time 7985ms<br class="">rtt min/avg/max/mdev = 0.056/0.058/0.185/0.011 ms<br class=""><br class=""></div><div><div>ping with no-op nfqueue callback in C:</div><div>root@lsrv:~# iptables -A OUTPUT -d 10.182.122.11/32 -j NFQUEUE --queue-num 0</div><div>root@lsrv:~/nfqueue# ping -c 500 -i 0.01 -q 10.182.122.11<br class="">500 packets transmitted, 500 received, 0% packet loss, time 7981ms<br class="">rtt min/avg/max/mdev = 0.117/0.123/0.384/0.020 ms<br class=""><br class=""></div></div><div>ping with no-op nfqueue callback in Go:</div><div><div class="">root@lsrv:~# iptables -A OUTPUT -d 10.182.122.11/32 -j NFQUEUE --queue-num 0</div></div><div>root@lsrv:~# ping -c 500 -i 0.01 -q 10.182.122.11<br class="">500 packets transmitted, 500 received, 0% packet loss, time 7982ms<br class="">rtt min/avg/max/mdev = 0.095/0.172/0.532/0.042 ms<br class=""><br class=""></div><div class="">The mean induced latency of 65us for C or 114us for Go might be within your parameters, except you mentioned 10us for WiFi bus arbitration, which does indeed look impossible with this setup, even in C.</div><div class=""><br class=""></div><div class="">Iperf3 results:</div><div class=""><br class=""></div><div class="">iperf3 without nfqueue:</div><div>root@lsrv:~# iptables -F OUTPUT</div><div class="">root@lsrv:~# iperf3 -t 5 -c 10.182.122.11<br class="">Connecting to host 10.182.122.11, port 5201<br class="">[  4] local 10.182.122.1 port 55810 connected to 10.182.122.11 port 5201<br class="">[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd<br class="">[  4]   0.00-1.00   sec   452 MBytes  3.79 Gbits/sec    0    178 KBytes       <br class="">[  4]   1.00-2.00   sec   454 MBytes  3.82 Gbits/sec    0    320 KBytes       <br class="">[  4]   2.00-3.00   sec   450 MBytes  3.77 Gbits/sec    0    320 KBytes       <br class="">[  4]   3.00-4.00   sec   451 MBytes  3.79 Gbits/sec    0    352 KBytes       <br class="">[  4]   4.00-5.00   sec   451 MBytes  3.79 Gbits/sec    0    352 KBytes       <br class="">- - - - - - - - - - - - - - - - - - - - - - - - -<br class="">[ ID] Interval           Transfer     Bandwidth       Retr<br class="">[  4]   0.00-5.00   sec  2.21 GBytes  3.79 Gbits/sec    0             sender<br class="">[  4]   0.00-5.00   sec  2.21 GBytes  3.79 Gbits/sec                  receiver<br class="">iperf Done.</div><div class=""><br class=""></div><div class="">iperf3 with no-op nfqueue callback in C:<br class=""><div class="">root@lsrv:~# iptables -A OUTPUT -d 10.182.122.11/32 -j NFQUEUE --queue-num 0</div>root@lsrv:~/nfqueue# iperf3 -t 5 -c 10.182.122.11<br class="">Connecting to host 10.182.122.11, port 5201<br class="">[  4] local 10.182.122.1 port 55868 connected to 10.182.122.11 port 5201<br class="">[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd<br class="">[  4]   0.00-1.00   sec  17.4 MBytes   146 Mbits/sec    0    107 KBytes       <br class="">[  4]   1.00-2.00   sec  16.9 MBytes   142 Mbits/sec    0    107 KBytes       <br class="">[  4]   2.00-3.00   sec  17.0 MBytes   142 Mbits/sec    0    107 KBytes       <br class="">[  4]   3.00-4.00   sec  17.0 MBytes   142 Mbits/sec    0    107 KBytes       <br class="">[  4]   4.00-5.00   sec  17.0 MBytes   143 Mbits/sec    0    115 KBytes       <br class="">- - - - - - - - - - - - - - - - - - - - - - - - -<br class="">[ ID] Interval           Transfer     Bandwidth       Retr<br class="">[  4]   0.00-5.00   sec  85.3 MBytes   143 Mbits/sec    0             sender<br class="">[  4]   0.00-5.00   sec  84.7 MBytes   142 Mbits/sec                  receiver<br class=""><br class=""></div><div class="">iperf3 with no-op nfqueue callback in Go:</div><div class="">root@lsrv:~# iptables -A OUTPUT -d 10.182.122.11/32 -j NFQUEUE --queue-num 0</div><div class="">root@lsrv:~# iperf3 -t 5 -c 10.182.122.11<br class="">Connecting to host 10.182.122.11, port 5201<br class="">[  4] local 10.182.122.1 port 55864 connected to 10.182.122.11 port 5201<br class="">[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd<br class="">[  4]   0.00-1.00   sec  14.6 MBytes   122 Mbits/sec    0   96.2 KBytes       <br class="">[  4]   1.00-2.00   sec  14.1 MBytes   118 Mbits/sec    0   96.2 KBytes       <br class="">[  4]   2.00-3.00   sec  14.0 MBytes   118 Mbits/sec    0    102 KBytes       <br class="">[  4]   3.00-4.00   sec  14.0 MBytes   117 Mbits/sec    0    102 KBytes       <br class="">[  4]   4.00-5.00   sec  13.7 MBytes   115 Mbits/sec    0    107 KBytes       <br class="">- - - - - - - - - - - - - - - - - - - - - - - - -<br class="">[ ID] Interval           Transfer     Bandwidth       Retr<br class="">[  4]   0.00-5.00   sec  70.5 MBytes   118 Mbits/sec    0             sender<br class="">[  4]   0.00-5.00   sec  69.9 MBytes   117 Mbits/sec                  receiver<br class="">iperf Done.<br class=""></div><div class=""><br class=""></div><div class="">So rats, throughput gets brutalized for both C and Go. For Go, a rate of 117 Mbit with a 1500 byte MTU is 9750 packets/sec, which is 103us / packet. Mean induced latency measured by ping is 114us, which is not far off 103us, so the rate slowdown looks to be mostly caused by the per-packet nfqueue calls. The core running test_nfqueue is pinned at 100% during the test. "nice -n -20" does nothing.</div><div class=""><br class=""></div><div class="">Presumably you’ll sometimes be releasing more than one packet at a time(?) so I guess whether or not this is workable depends on how many you release at once, what hardware you’re on and what rates you need to test at. But when you’re trying to test a qdisc, I guess you’d want to minimize the burden you add to the CPU, or else move it to a core the qdisc isn’t running on, or something, so the qdisc itself isn’t affected by the test rig.</div></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">There is of course a hideous amount of complexity moved to the daemon,</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>I can only imagine.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">as a pure fifo ap queue forms aggregregates much differently</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">than a fq_codeled one. But, yea! userspace....</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote></div><br class=""><div class="">This would be awesome if it works out! After that iperf3 test though, I think I may have smashed my dreams of writing a libnetfilter_queue userspace qdisc in Go, or C for that matter.</div><div class=""><br class=""></div><div class="">If this does somehow turn out to be good enough performance-wise, I think you’d have a lot more fun and spend a lot less time on it in Go than C, but that’s just an opinion... :)</div><div class=""><br class=""></div></body></html>