Quantcast
Channel: Active questions tagged linux-kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 12244

Zerocopy TCP message sending from kernel module error EFAULT

$
0
0

I am working on a kernel module which receives data over DMA from an FPGA and stores it in a ring buffer allocated with dma_alloc_attrs(dev, size, &data->dma_addr, GFP_KERNEL, DMA_ATTR_FORCE_CONTIGUOUS). Everytime when new data is available in the ring buffer, a completion is fired.

In the same kernel module, I am running a TCP server and during the lifetime of the kernel module only one client (on a different machine) connects to the server(and stays connected). A separate thread in the kernel module sends data received in the ring buffer to the connected client whenever the completion was fired. The idea behind having a tcp server in the kernel space is to get rid of the unnecessary context switches from kernel space and user space whenever the data should be sent to the client, thus increasing performance. So far everything works, but the performance isn't as expected (on the TCP side).

After looking a bit into how to increase performance, i found the ZEROCOPY option.

I changed the settings of the server socket to set the SO_ZEROCOPY flag: kernel_setsockopt(socket, SOL_SOCKET, SO_ZEROCOPY, (char *)&one, sizeof(one)) and the implementation of the sending to client to:

static DEFINE_MUTEX(tcp_send_mtx);                                            static int send(struct socket *sock, const char *buf,                         const size_t length, unsigned long flags)                {                                                                                 struct msghdr msg;                                                            struct kvec vec;                                                              int len, written = 0;                                                         int left = length;                                                            if(sock == NULL)                                                              {                                                                                 printk(KERN_ERR MODULE_NAME ": tcp server send socket is NULL\n");            return -EFAULT;                                                           }                                                                                                                                                     msg.msg_name    = 0;                                                          msg.msg_namelen = 0;                                                          msg.msg_control = NULL;                                                       msg.msg_controllen = 0;                                                       msg.msg_flags   = MSG_ZEROCOPY;                                        repeat_send:                                                                     vec.iov_len = left;                                                           vec.iov_base = (char *)buf + written;                                         len = kernel_sendmsg(sock, &msg, &vec, left, left);                           if((len == -ERESTARTSYS) || (!(flags & MSG_DONTWAIT) && (len == -EAGAIN)))        goto repeat_send;                                                         if(len > 0)                                                                   {                                                                                 written += len;                                                               left -= len;                                                                  if(left)                                                                          goto repeat_send;                                                     }                                                                             return written?written:len;                                               }                                                                             

Note the msg.msg_flags = MSG_ZEROCOPY; assignment in the send function.

Now when i am trying to use this, I am getting EFAULT(-14) error code from kernel_sendmsg just by adding the MSG_ZEROCOPY flag.

UPDATE:

I understand now that the ZEROCOPY flag is wrongly used in the kernel space since it's designed to remove the additional copy between the user-space and kernel-space.

My initial problem still exists. TCP transfer is still slow and the ring buffer overflows when the DMA transfer speed exceeds 120mb/s. The thread that forwards the messages to the client is not able to send the 8kb messages faster than 120mb/s.

Anyone knows what is wrong here? Maybe that the idea is wrong in the first place


Viewing all articles
Browse latest Browse all 12244

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>