offload
offload特性,主要是指将本来在操作系统协议栈中进行的一些数据包处理(如IP分片、TCP分片、重组、checksum校验等)放到网卡硬件中去做,降低系统 CPU 消耗,提高处理的性能。
我们知道计算机网络上传输的数据基本单位是离散的网包,既然是网包,就有大小限制,这个限制就是 MTU(Maximum Transmission Unit)的大小,一般是1518字节。比如我们想发送很多数据出去,经过os协议栈的时候,会自动帮你拆分成几个不超过MTU的网包。然而,这个拆分是比较费计算资源的(比如很多时候还要计算分别的checksum),由 CPU 来做的话,往往会造成使用率过高。那怎么可以把这些简单重复的操作 offload 到网卡上呢?
LSO/LRO
LSO/LRO,分别对应到发送和接收两个方向,即 Large Segment Offload 和 Large Receive Offload。
首先看LSO,在发送数据超过 MTU 限制的时候(太容易发生了),OS 只需要提交一次传输请求给网卡,网卡会自动的把数据拿过来,然后进行切割,并封包发出,发出的网包不超过 MTU 限制。
接下来看 LRO,当网卡收到很多碎片包的时候,LRO 可以辅助自动组合成一段较大的数据,一次性提交给 OS处理。
一般的,LSO 和 LRO 主要面向 TCP 报文。
GSO/GRO
Generic Segmentation Offload 和 Generic Receive Offload,分别比 LSO 和 LRO 更通用,自动检测网卡支持特性,支持分包则直接发给网卡,否则先分包后发给网卡。新的驱动一般用 GSO/GRO。
TSO/UFO
TCP Segmentation Offload 和 UDP fragmentation offload,分别对应 TCP 报文和 UDP 报文。
很典型的发送模式,TCP 协议中就考虑了分片存在的情况,往往是切分 TCP 的数据包,叫做 TSO。而一般的情况,则称为 LSO 或者 GSO。
对于其他不支持切片的协议例如 UDP,则只能进行 IP 层上的切片。
**TSO (tcp-segmentation-offload) **
从名字来看很直观,就是把tcp分段的过程转移到网卡中进行。当网卡支持TSO机制时,可以直接把不超过滑动窗口大小的payload下传给协议栈,即使数据长度大于MSS,也不会在TCP层进行分段,同样也不会进行IP分片,而是直接传送给网卡驱动,由网卡驱动进行tcp分段操作,并执行checksum计算和包头、帧头的生成工作。
**UFO(udp-fragmentation-offload) **
是一种专门针对udp协议的特性,主要机制就是将IP分片的过程转移到网卡中进行,用户层可以发送任意大小的udp数据包(udp数据包总长度最大不超过64k),而不需要协议栈进行任何分片操作。目前貌似没找到有支持UFO机制的网卡,主要是应用在虚拟化设备上。
**GSO(generic-segmentation-offload) **
相对于TSO和UFO,GSO机制是针对所有协议设计的发送模式,更为通用。同时,与TSO、UFO不同的是,GSO主要依靠软件的方式实现,对于网卡硬件没有过多的要求。其基本思想就是把数据分片的操作尽可能的向底层推迟直到数据发送给网卡驱动之前,并先检查网卡是否支持TSO或UFO机制,如果支持就直接把数据发送给网卡,否则的话再进行分片后发送给网卡,以此来保证最少次数的协议栈处理,提高数据传输和处理的效率。
接收模式除了LRO、GRO,多核服务器中的网卡还推荐考虑 RSS(Receive Side Scaling),将网流分配到多个 RSS 队列上,多个队列绑定到不同的核心上,分散负载。
virtio协议1.0
virtio network device 是一种虚拟以太网卡
迄今为止virtio支持的最复杂的设备(其他设备可挖掘的内容很多)
空缓冲区被提前放置在RX virtqueue中用于接收数据包,收包一个队列
发送的数据包被排队到TX virtqueue中以便按该顺序传输,发送一个队列
控制队列用于控制和高级过滤功能
- virtio作为通用的IO虚拟化模型,是如何定义通用的IO控制面和数据面接口的?或者说,基于virtio的网络设备virtio-net和块存储设备virtio-blk,有哪些共通点?
对于控制面,virtio为每个设备封装了virtio_config_ops接口,用于配置和启动设备。
对于数据面,virtio定义了virtqueue抽象传输模型,virtqueue提供了一系列操作接口来完成数据收发和事件通知。virtio_config_ops中的find_vqs接口提供了virtqueue的创建和获取能力。virtqueue具体通过virtio-ring实现,driver向available ring中输入请求,host backend处理请求后向used ring中输入回应。
上述模型和实现是virtio设备通用的,virtio-net和virtio-blk都基于这套模型和接口实现。不同之处只在于使用的virtqueue数量,以及virtqueue/vring中的请求/回应的结构与内容不同,这些都和设备的具体功能和行为密切相关。
- 在linux内核下,有virtio、virtio-pci、virtio-net、virtio-blk等virtio相关驱动。这些驱动是如何组织的,多个驱动间是什么关系?
linux内核中和virtio相关的驱动主要有:virtio、virtio_ring、virtio_pci、virtio_net、virtio_blk等。其中:
virtio提供了virtio总线和设备控制面的接口。
virtio_ring提供了数据面,也就是virtqueue接口和对应的vring实现。
virtio_pci提供了virtio设备作为PCI设备加载时的通用驱动入口,它依赖virtio和virtio_ring提供的接口。
virtio_net提供了virtio网络设备的标准驱动,它依赖virtio和virtio_ring提供的接口。virtio_net将自己注册为virtio总线的一种设备驱动。
virtio_blk提供了virtio块存储设备的标准驱动,它依赖virtio和virtio_ring提供的接口。virtio_blk将自己注册为virtio总线的一种设备驱动。
- 一个virtio设备,是如何加入到虚拟机设备模型中,被内核发现和驱动的?
一个virtio PCI设备加载时,内核会尝试所有注册的PCI设备驱动,最后发现可以被virtio_pci驱动。virtio_pci再调用注册到virtio总线上的设备驱动,最后发现可以被virtio_net驱动。virtio_net通过virtio_pci的标准配置接口和host协商设备特性和初始化设备,之后通过virtio_ring提供的接口收发网络数据。
- virtio-net具体又提供了哪些标准接口?控制面和数据面接口是如何定义的?
virtio设备的控制面和数据面接口都是标准的,只是具体数据格式和含义有区别。virtio-net有自己的feature bit集合,每个virtio-net设备至少使用两个virtqueue用于报文的收和发。virtio-net收发的数据buffer都包括virtio_net_hdr作为头部,用于表示driver和host设置的offload参数。
Virtqueues
队列分布布局
VIRTIO_NET_F_MQ 协商了,N = max_virtqueue_pairs;如果 VIRTIO_NET_F_MQ 没有协商,N = 1
VIRTIO_NET_F_CTRL_VQ 协商了,才会有 control queue
Feature bits说明
虚拟机前后端, 一般前端叫驱动,后端叫设备
VIRTIO_NET_F_CSUM (0) 设备支持进行部分校验数据包。虚拟机可以发送cksum offload的包,主机可以帮助其计算cksum
VIRTIO_NET_F_GUEST_CSUM (1) 驱动支持进行部分校验数据包。主机可以向虚拟机发送pseudo-header的包
VIRTIO_NET_F_GUEST_TSO4 (7) 驱动支持TSOv4。即主机可以向虚拟机发tcp大包
VIRTIO_NET_F_HOST_TSO4 (11) 设备支持 TSOv4,即虚拟机可以往外发tcp大包
VIRTIO_NET_F_MRG_RXBUF (15) 驱动支持 Merge Buffer
通过qemu的VHOST_USER_SET_FEATURES消息,虚拟机和主机支持的feature进行协商,找到最大支持的集合,作为vhostuser端口的feature
virtio header
struct virtio_net_hdr {
#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1
u8 flags;
#define VIRTIO_NET_HDR_GSO_NONE 0
#define VIRTIO_NET_HDR_GSO_TCPV4 1
#define VIRTIO_NET_HDR_GSO_UDP 3
#define VIRTIO_NET_HDR_GSO_TCPV6 4
#define VIRTIO_NET_HDR_GSO_ECN 0x80
u8 gso_type;
u16 hdr_len;
u16 gso_size;
u16 csum_start;
u16 csum_offset;
/* Only if VIRTIO_NET_F_MRG_RXBUF: */
u16 num_buffers
};
flags、csum_start、csum_offset用于checksum offload,当flags为VIRTIO_NET_HDR_F_NEEDS_CSUM时后端从csum_start位置开始计算checksum并填入csum_offset位置处。
gso_type、hdr_len、gso_size用于segmentation offload,gso_type指示分段的类型,hdr_len表示首部的长度(首部是不能分段的部分,每个报文都要携带),gso_size表示分段后的数据长度(不包括首部)。
后端根据上述字段对descriptor链中的报文数据进行offload的功能处理,当然前提是virtio-net初始化时guest和host协商使用了这些offload功能。
virtio-vhost前后端这块主要涉及三大块:
前后端消息协商机制、前后端内存机制和前后端收发包机制
今天的文章网络功能虚拟化nfv_虚拟化平台有哪些分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/85248.html