freifunk-gluon / gluon

a modular framework for creating OpenWrt-based firmwares for wireless mesh nodes
https://gluon.readthedocs.io
Other
550 stars 325 forks source link

Fastd Performance Tweaking using MMSG API #2019

Open lemoer opened 4 years ago

lemoer commented 4 years ago

I did this already about a year ago, but not to forget this, I will document it here.

Currently fastd needs one syscall per packet to obtain/deliver a single packet from/to the kernel. The idea is to avoid this by obtaining and delivering multiple packages per syscall. Unfortunately using recvmmsg and sendmmsg only works for regular sockets, but not for tun/tap files in the current linux kernel.

It is not very complex to enable these syscalls for tun/tap files in the kernel, because internally the tun file is already accessible as socket (see patch below). However, this patch only works if tun is hardlinked into the kernel (as we are doing it in gluon).

Results:

I do not exactly remember which test hardware I used, but if I remember correctly, it was a TPLink 1043v3. However the exact throughput values are not that relevant. The relative throughput increase is significant. The BUFCNT column indicates how many packets were sent/received in one syscall.

CNT Avg (Mbit/s) Std Dev (Mbit/s) BUFCNT Throughput Increase
100 16,82 1,76 1 0,00 %
100 17,02 1,76 1 1,19 %
100 19,38 1,99 4 15,22 %
100 19,15 1,97 4 13,85 %
100 20,53 2,1 8 22,06 %
100 20,42 2,07 8 21,40 %
100 20,63 2,21 16 22,65 %
100 21,17 2,17 16 25,86 %
100 22,14 2,27 32 31,63 %
100 22,02 2,25 32 30,92 %
100 22,57 2,3 64 34,19 %
100 22,26 2,28 64 32,34 %

Patches:

Fastd Patches: https://github.com/lemoer/fastd/commits/master

Linux Patch:

--- a/net/socket.c
+++ b/net/socket.c
@@ -453,6 +453,19 @@ struct socket *sock_from_file(struct fil
    if (file->f_op == &socket_file_ops)
        return file->private_data;  /* set in sock_map_fd */

+   // can return:
+   // - ERR_PTR(-EBADFD)
+   // - ERR_PTR(-EINVAL)
+   struct socket *ret = tun_get_socket(file);
+   
+   if (!IS_ERR(ret))
+       return ret;
+   
+   *err = PTR_ERR(ret);
+   if (*err == -EBADFD)
+       return NULL;
+   
+   // convert -EINVAL to -ENOTSOCK
    *err = -ENOTSOCK;
    return NULL;
 }

Discussion

Of course, it would not be a good idea to track/maintain such a downstream patch to the linux kernel. But to upstream it, somebody should pick this and have a look whether the patch could be done in such a way that it also works if tun is not hardlinked. I already tried to do this, but unfortunately my kernel hacking skills are not sufficient enough at the moment.

neocturne commented 4 years ago

I think this should be moved over to https://github.com/NeoRaider/fastd/issues (and maybe keep this issue open with a link to the new ticket, as it is most relevant for Gluon).

With Kernel 5.4, we have everything we need in io_uring, making any sendmmsg/recvmmsg-based solution inferior (and we don't need additional kernel patches). So if we make the effort to rework the way fastd handles packets, it should be based on io_uring.

lemoer commented 4 years ago

Well, interesting to learn about io_uring. I wasn't aware that fastd is now also hosted on github. I moved the subject there:

mweinelt commented 2 years ago

@NeoRaider I think you could use the Transfer issue feature in the sidebar to move this over to fastd.