GSO和TSO
http://www.cnhalo.net/2016/09/13/linux-tcp-gso-tso/
TSO(TCP Segmentation Offload):
是一种利用网卡来对大数据包进行自动分段,降低CPU负载的技术。 其主要是延迟分段
GSO(Generic Segmentation Offload):
GSO是协议栈是否推迟分段,在发送到网卡之前判断网卡是否支持TSO,如果网卡支持TSO则让网卡分段,否则协议栈分完段再交给驱动。 如果TSO开启,GSO会自动开启
- GSO开启, TSO开启: 协议栈推迟分段,并直接传递大数据包到网卡,让网卡自动分段
- GSO开启, TSO关闭: 协议栈推迟分段,在最后发送到网卡前才执行分段
- GSO关闭, TSO开启: 同GSO开启, TSO开启
- GSO关闭, TSO关闭: 不推迟分段,在tcp_sendmsg中直接发送MSS大小的数据包
驱动程序在注册网卡设备的时候默认开启GSO: NETIF_F_GSO
驱动程序会根据网卡硬件是否支持来设置TSO: NETIF_F_TSO
可以通过ethtool -K来开关GSO/TSO
#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO)
int register_netdevice(struct net_device *dev)
{
----------------------------------------------- /* Transfer changeable features to wanted_features and enable
* software offloads (GSO and GRO).
*/
dev->hw_features |= NETIF_F_SOFT_FEATURES;
dev->features |= NETIF_F_SOFT_FEATURES;//默认开启GRO/GSO
dev->wanted_features = dev->features & dev->hw_features; if (!(dev->flags & IFF_LOOPBACK)) {
dev->hw_features |= NETIF_F_NOCACHE_COPY;
} /* Make NETIF_F_HIGHDMA inheritable to VLAN devices.
*/
dev->vlan_features |= NETIF_F_HIGHDMA; /* Make NETIF_F_SG inheritable to tunnel devices.
*/
dev->hw_enc_features |= NETIF_F_SG; /* Make NETIF_F_SG inheritable to MPLS.
*/
dev->mpls_features |= NETIF_F_SG;
GSO/TSO是否开启是保存在dev->features中,而设备和路由关联,当我们查询到路由后就可以把配置保存在sock中
比如在tcp_v4_connect和tcp_v4_syn_recv_sock都会调用sk_setup_caps来设置GSO/TSO配置
/* This will initiate an outgoing connection. */
int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
--------------------------------
orig_sport = inet->inet_sport;
orig_dport = usin->sin_port;
fl4 = &inet->cork.fl.u.ip4;
rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_TCP,
orig_sport, orig_dport, sk);
--------------------------------------
//调用sk_setup_caps来设置GSO/TSO配置
/* OK, now commit destination to socket. */
sk->sk_gso_type = SKB_GSO_TCPV4;
sk_setup_caps(sk, &rt->dst); ----------------------------------------- err = tcp_connect(sk); rt = NULL;
if (err)
void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
/* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \
NETIF_F_TSO6 | NETIF_F_UFO)
u32 max_segs = 1; sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features;
if (sk->sk_route_caps & NETIF_F_GSO)//软件GSO,默认开启
sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;//开启延时gso延时选项,包括NETIF_F_TSO
sk->sk_route_caps &= ~sk->sk_route_nocaps;
if (sk_can_gso(sk)) {
if (dst->header_len) {
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
} else {
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;// 开启gso后,设置sg和校验
sk->sk_gso_max_size = dst->dev->gso_max_size;//GSO_MAX_SIZE=65536
max_segs = max_t(u32, dst->dev->gso_max_segs, 1);
}
}
sk->sk_gso_max_segs = max_segs;
}
//判断GSO或TSO是否开启
static inline bool sk_can_gso(const struct sock *sk)
{
return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
}
static inline bool net_gso_ok(netdev_features_t features, int gso_type)
{
netdev_features_t feature = gso_type << NETIF_F_GSO_SHIFT;
//对于tcp4, 判断NETIF_F_TSO是否被设置, 即使硬件不支持TSO,开启GSO的情况下也会被设置 /* check flags correspondence */
BUILD_BUG_ON(SKB_GSO_TCPV4 != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_UFO >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT)); return (features & feature) == feature;
}
对紧急数据包或GSO/TSO都不开启的情况,才不会推迟发送, 默认使用当前MSS
开启GSO后,tcp_send_mss返回mss和单个skb的GSO大小,为mss的整数倍
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
{
------------------------------------------------------------
/* This should be in poll */
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); mss_now = tcp_send_mss(sk, &size_goal, flags); }
GSO和TSO的更多相关文章
- CEPH经常出现slow request的排查解决
现象: 通过ceph -w日志经常发现有request blocked的问题(如果虚拟机系统跑在ceph上时,就会发现严重的卡顿现象) 排查: 1.通过dstat未发现有明显的瓶颈 (dstat -t ...
- TCP系列50—拥塞控制—13、Eifel探测下的拥塞撤销
一.概述 我们之前在SACK关闭场景下的拥塞撤销那篇文章中提到过Eifel探测算法(Eifel Detection Algorithm),最早在介绍DSACK和FRTO的时候我们就有提到过Eifel探 ...
- virtio使用
Windows 参考文档 下载virtio驱动 下载地址 如果是在Fedora或CentOS环境下,可使用yum的方式下载驱动 [root@centos centos]#wget https://fe ...
- Linux3.5内核以后的路由下一跳缓存
在Linux3.5版本号(包括)之前.存在一个路由cache.这个路由cache的初衷是美好的,可是现实往往是令人遗憾的.下面是陈列得出的两个问题:1.面临针对hash算法的ddos问题(描写叙述该问 ...
- 从C10K到C10M高性能网络的探索与实践
在高性能网络的场景下,C10K是一个具有里程碑意义的场景,15年前它给互联网领域带来了非常大的挑战.发展至今,我们已经进入C10M的场景进行网络性能优化. 这期间有怎样的发展和趋势?环绕着各类指标分别 ...
- KVM原理及使用
Qemu 和 Qemu-kvm Qemu: http://qemu-project.org/Download Qemu-kvm:https://sourceforge.net/projects/kvm ...
- [ kvm ] 学习笔记 4:KVM 高级功能详解
1. 半虚拟化驱动 1.1 virtio 概述 KVM 是必须使用硬件虚拟化辅助技术(如 Intel VT-x .AMD-V)的 Hypervisor,在CPU 运行效率方面有硬件支持,其效率是比较高 ...
- 网络虚拟化中的 offload 技术:LSO/LRO、GSO/GRO、TSO/UFO、VXLAN
offload 现在,越来越多的网卡设备支持 offload 特性,来提升网络收/发性能.offload 是将本来该操作系统进行的一些数据包处理(如分片.重组等)放到网卡硬件中去做,降低系统 CPU ...
- GSO/TSO/GRO等对VirtIO虚机的网络性能影响分析(by quqi99)
作者:张华 发表于:2016-04-05版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) IP层 ...
随机推荐
- java安全编码指南之:锁的双重检测
目录 简介 单例模式的延迟加载 double check模式 静态域的实现 ThreadLocal版本 简介 双重检测锁定模式是一种设计模式,我们通过首次检测锁定条件而不是实际获得锁从而减少获取锁的开 ...
- 《罗辑思维》试读:U盘化生存
<罗辑思维>试读:U盘化生存 何为"U盘" 记得有一次我到一个大学去讲课,我随机做了一个调查.我说大四啦,咱们班同学谁找着工作了,一堆人举手.我又问都加入什么样的组织了 ...
- MeteoInfoLab脚本示例:MODIS Sinusoidal投影HDF数据
MODIS卫星很多陆面数据都是Sinusoidal投影,数据被分为一个个10*10度(赤道地区)的瓦片(http://modis-land.gsfc.nasa.gov/MODLAND_grid.htm ...
- day14 Pyhton学习
一.迭代器-概念 可迭代协议:内部含有__iter__方法的值/变量都是可迭代的 如何得到一个迭代器:可迭代变量.__iter__()返回一个迭代器 迭代器协议:内部含有__iter__方法和__ne ...
- Termux基础教程(二):软件包安装
Termux基础教程(二):软件包安装 Termux是一个在安卓手机上模拟Linux系统的高级终端,这个终端十分强大,实用. Termux可以安装Liunx的各种软件包,这就是Termux的灵魂所在. ...
- linux下php安装php-kafka扩展和php-rdkafka扩展
具体步骤: 1.安装librdkafka cd /usr/local/src #进入安装包存放目录 wget https://github.com/edenhill/librdkafka/archi ...
- Unity实现代码控制音频播放
前言 很久没说过Unity了,现在说一下Unity用代码控制音频播放 准备工作 1.需要播放的音频 2.给需要加声音的对象加Audio Source组件 3.新建Play脚本,并绑定需要播放声音的对象 ...
- javaScript 必会基础知识
1.JavaScript是一种浏览器解析的轻量级脚本语言. 2.html.jsp等内部js代码写在<script></script>之间:外部js文件中书写js代码不能有< ...
- 使用MediaRecorder录音
Android提供了两个API用于录音的实现:MediaRecorder 和AudioRecord. MediaRecorder:录制的音频文件是经过压缩后的,需要设置编码器.并且录制的音频文件可以用 ...
- Hive源码解析
date: 2020-07-08 15:12:00 updated: 2020-08-21 17:38:00 Hive源码解析 入口:hive-cli-1.1.0-cdh5.14.4.jar!/org ...