在 UDP 数据报数据字段的开头添加自定义数据(在 linux 内核中)

Adding custom data at the beginning of UDP datagram data field (in linux kernel)

我正在尝试实现一个在 UDP 之上运行的自定义传输协议。我想在用户 space 的数据复制到 skbuff.I 之前在 UDP 数据字段的开头添加此协议的 header 还想在 UDP 处理之前处理此数据它关闭到套接字,以便我可以提取 header 并在内核中进行所需的处理。所以,

  1. 如何确保我的 header(比如 struct new_header)被添加到 udp_sendmsg() 函数中数据的开头。我假设在将来自用户 space 的任何实际数据复制到它之前,或者最迟在对数据计算 UDP 校验和之前,应该将它复制到 skbuff 的数据字段。这究竟发生在代码的什么地方?
  2. udp_recvmsg() 函数中,数据传递到套接字的确切位置是什么?我认为是 skb_copy_datagram_iovec().

How do I ensure that my header (say struct new_header) is added at the beginning of the data in the udp_sendmsg() function. I assume this should be copied to the data field of skbuff before any actual data from user space is copied to it or at the latest, before the UDP checksum is calculated on the data. Where exactly does this happen in the code?

您可以考虑的 2 个选项:
1.If 你在用户 space 中实现你的协议,然后你可以只使用 UDP 套接字与内核通信,并在从 UDP 套接字接收数据报后进行协议解封,或者在将数据发送到 UDP 套接字之前进行封装。
2.If 你想在内核中实现你的协议 space.Then 你必须实现你自己的套接字 type.You 可以查看内核源代码中已经存在的一些隧道套接字代码作为示例(例如 L2TP)。一旦你在内核中注册了你的套接字类型,那么你从用户space发送到内核space的套接字数据将由你的encap代码处理(相当于udp_sendmsg()),然后你封装代码依次调用 udp_sendmsg() 进一步向下到网络堆栈。

Where exactly in udp_recvmsg() function is the data handed off to the socket? I think it's skb_copy_datagram_iovec().

不确定您正在查看哪个版本的内核。对于内核 4.6,它是 skb_copy_datagram_msg() --> skb_copy_datagram_iter()。这是将数据报复制到 buff,然后 return 到用户 space.
的地方 实际上,当用户space 尝试从套接字接收数据时,会调用udp_recvmsg(),因此udp_recvmsg() 已经在套接字上下文中。 网络堆栈通过将数据报放在 sk_receive_queue 中,将数据报交给 sock_queue_rcv_skb() 中的套接字。

内核 4.6 中的调用链如下:

__udp4_lib_rcv -->
  udp_queue_rcv_skb(sk, skb); -->  sock_queue_rcv_skb()

然后用户空间通过以下方式获取数据:

recv();
... ...
-------system call --------- 
... ...
udp_recvmsg -->
__skb_recv_datagram -->
__skb_try_recv_datagram -->    (get the datagram from sk_receive_queue)