英文:
How to use GSO for sending UDP packets
问题
可以利用Linux通用分段卸载(GSO)吗?
英文:
Is it possible to make use of Linux Generic Segmentation Offload (GSO)?
答案1
得分: 1
是的和不是
GSO是在内核中设置的,具体是在网络驱动程序中。这篇文章详细介绍了相关内容。在Linux中,通常通过ethtool
实用程序来启用GSO:
ethtool --offload eth0 gso on
所以假设已经设置了这个选项,那么它将影响通过接口传输的所有流量,包括由Go应用程序生成的流量。
更困难一些,但也可以使用Go程序通过ethtool协议启用GSO。你可能可以找到一个适用于此的ethtool Go包。
更新
正如你指出的,你可以进一步优化GSO(在上述信息中启用它之后)通过设置分段大小套接字选项。从你分享的Cloudflare博客中,他们展示了如何在C中实现:
setsockopt(fd, SOL_UDP, UDP_SEGMENT, &gso_size, sizeof(gso_size)))
在底层,这是通过操作系统Syscall来完成的。
我假设你正在使用go-quic
,因为Cloudflare博客中提到了QUIC。go-quic
可以接受一个预先制作的net.PacketConn,所以你需要从头开始创建一个并添加分段套接字选项:
s, err := syscall.Socket(...)
if err != nil {
// 错误处理
}
if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.UDP_SEGMENT, gso_size); err != nil {
syscall.Close(s)
// 错误处理
}
if err := syscall.Bind(s, ...); err != nil {
syscall.Close(s)
// 错误处理
}
if err := syscall.Listen(s, ...); err != nil { // 或者 syscall.Connect
syscall.Close(s)
// 错误处理
}
f := os.File(s, ...)
ln, err := net.FileLitsener(f) // 或者 net.FileConn, net.FilePacketConn
//ln现在可以被go-quic使用
注意:gso_size是一个int类型的变量,在之前必须已知。
英文:
Yes and No
GSO is set in the Kernel, specifically the Network Driver. This article goes into the specifics. Enabling GSO is typically done via the ethtool
utility in Linux:
ethtool --offload eth0 gso on
So assuming this is set, then it will effect all traffic going through the interface including that which is generated by a Go application.
It would be more difficult, but it is also possible to use the go program to enable GSO via the ethtool protocol. You can probably find an ethtool go package for this.
Update
As you pointed out, you can optimize for GSO (after enabling it per the above information) even further by setting the segment size socket options. From the cloudflare blog you shared, the show how to do it in C:
setsockopt(fd, SOL_UDP, UDP_SEGMENT, &gso_size, sizeof(gso_size)))
Under the hood, this is done via an operating system Syscall.
I am assuming you are using go-quic
as QUIC is referenced in the Cloudflare blog. go-quic
can take a premade net.PacketConn, so you will need to create one from scratch and add the Segmentation socket option:
s, err := syscall.Socket(...)
if err != nil {
// error handling
}
if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.UDP_SEGMENT, gso_size); err != nil {
syscall.Close(s)
// error handling
}
if err := syscall.Bind(s, ...); err != nil {
syscall.Close(s)
// error handling
}
if err := syscall.Listen(s, ...); err != nil { // or syscall.Connect
syscall.Close(s)
// error handling
}
f := os.File(s, ...)
ln, err := net.FileLitsener(f) // or net.FileConn, net.FilePacketConn
//ln can now be used by go-quic
Note: gso_size is an int and must be known prior
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论