热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux3.10gro的理解和改进

gro,将同一个flow的一定时间范围之内的skb进行合并,减少协议栈的消耗,用于收包性能提升。gro网上的资料很多,但是都

gro,将同一个flow的一定时间范围之内的skb进行合并,减少协议栈的消耗,用于收包性能提升。gro网上的资料很多,但是都很少谈到gro的改进,刚好身边有个同事也想改这块的内容,

所以将最近看的gro内容总结一下,作为记录。

gro的层次,很少有资料提到,可能是大牛们觉得太简单,但我还是记录一下,毕竟我基础不好。

 先看关键的数据结构,然后分析流程:

为了在skb中记录相关的gro信息,使用了skb的cb字段。

crash> napi_gro_cb
struct napi_gro_cb {void *frag0;unsigned int frag0_len;int data_offset;u16 flush;u16 flush_id;u16 count;u16 gro_remcsum_start;unsigned long age; u16 proto; u8 encap_mark : 1; u8 csum_valid : 1; u8 csum_cnt : 3; u8 is_ipv6 : 1; u8 free : 2; u8 same_flow : 1; u8 recursion_counter : 4; u8 is_atomic : 1; __wsum csum; struct sk_buff *last; } SIZE: 48

48字节的cb字段,被用完了。

所有的packet 级别的gro的类型,放在一个公共链表头 offload_base 变量中管理,我测试的系统中的packet级别的gro类型有:

crash> list packet_offload.list -H offload_base -s packet_offload
ffffffff81b41bc0
struct packet_offload {type = 8,priority = 0,callbacks = {gso_segment = 0xffffffff816155b0 ,gro_receive = 0xffffffff816159a0 ,gro_complete = 0xffffffff816148c0 },list = {next = 0xffffffff81b43b40 32>,prev = 0xffffffff81b3f0e0 }
}
ffffffff81b43b20
struct packet_offload {type = 56710,priority = 0,callbacks = {gso_segment = 0xffffffff8168c670 ,gro_receive = 0xffffffff8168c300 ,gro_complete = 0xffffffff8168c120 },list = {next = 0xffffffff81b3f7c0 32>,prev = 0xffffffff81b41be0 32>}
}
ffffffff81b3f7a0
struct packet_offload {type = 22629,priority = 10,callbacks = {gso_segment = 0x0,gro_receive = 0xffffffff815bbd60 ,gro_complete = 0xffffffff815bbbe0 },list = {next = 0xffffffff81b3f0e0 ,prev = 0xffffffff81b43b40 32>}
}

所有的inet层的gro回调,都存储在inet_offloads 数组中,根据当前加载的模块,本机器对应支持的gro就有:

p inet_offloads
inet_offloads
= $48 ={0x0, 0x0, 0x0, 0x0, 0xffffffff8176fd80 , 0x0, 0xffffffff8176f220 , 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff8176f560 , 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff81777680 , 0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffff81770be0 , 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
。。。。
0x0, 0x0, 0x0}

gro的调用查找过程如下:

从dev层,根据到来的skb,可以根据skb->protocol 作为type的类型,比如type是 .type = cpu_to_be16(ETH_P_IP),然后才会进入 ip_packet_offload 这个层次,

在 offload_base这个链表头找到对应的type,然后获取对应的callback.gro_receive 函数。

找到了对应的inet_gro_receive,就进入了packet层,那么根据iph->protocol,就在 net_offload 数组中,找到对应协议类型的gro结构,比如找到的是 tcpv4_offload。

那么针对tcp的gro,其i40e驱动的调用顺序就是:

i40e_napi_poll--->|i40e_clean_tx_irq

                        --->|i40e_clean_rx_irq-->napi_gro_receive-->dev_gro_receive-->inet_gro_receive-->tcp4_gro_receive

对应的堆栈如下:

[root@localhost caq]# stap -d i40e netif_rx.stp
System Call Monitoring Started (
10 seconds)...
WARNING: DWARF expression stack underflow
in CFI0xffffffff816041a0 : tcp4_gro_receive+0x0/0x1b0 [kernel]0xffffffff81615be9 : inet_gro_receive+0x249/0x290 [kernel]0xffffffff815951b0 : dev_gro_receive+0x2b0/0x3e0 [kernel]0xffffffff815955d8 : napi_gro_receive+0x38/0x130 [kernel]-------------gro处理开始0xffffffffc01f4bde : i40e_clean_rx_irq+0x3fe/0x990 [i40e]0xffffffffc01f5440 : i40e_napi_poll+0x2d0/0x710 [i40e]0xffffffff81594cf3 : net_rx_action+0x173/0x380 [kernel]0xffffffff8109404d : __do_softirq+0xfd/0x290 [kernel]0xffffffff816c8afc : call_softirq+0x1c/0x30 [kernel]0xffffffff8102d435 : do_softirq+0x65/0xa0 [kernel]0xffffffff81094495 : irq_exit+0x175/0x180 [kernel]0xffffffff816c9da6 : __irqentry_text_start+0x56/0xf0 [kernel]0xffffffff816bc362 : ret_from_intr+0x0/0x15 [kernel]

 

理清楚了大的流程,我们再来看目前的gro小的流程。在收到一个skb的时候,我们把它和napi_struct中的gro_list的skb进行比较,看能否合并,当然合并的前提是同一个flow的,

除此之外,除了满足同一个flow,还有很多要求。

那这个gro_list最大多长呢?

/* Instead of increasing this, you should create a hash table. */
#define MAX_GRO_SKBS 8

才8个,这8个skb跟新进来的skb是flow相同的概率其实真不高,比如在tcp4_gro_receive中,我想跟踪它接着调用的 skb_gro_receive,无奈由于合并的几率太低而无法跟到,

毕竟还有一个在gro_list中停留的时间限制,为一个jiffies。后来修改了jiffies并且修改了合并的条件才能抓到。

 当然,根据作者的注释,与其将这8改大,不如改成一个hash表,不同的skb先哈希到一个flow链,然后在链中比较看能否合并,这样对于gro流程需要改动为:

1.创建flow的hash表,让skb中看到flow,然后在flow的冲突链中找对应的gro_list,然后看能否合并。

2.percpu模式,不适用napi_struct来管理gro_list.

3.修改合并条件,比如对于tcp的ack来说,目前不带数据的ack无法合并,因为才54个字节,而以太网发出的时候会填充,导致不满足如下条件:

flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));

但对于流媒体服务器来说,纯ack占入向的比例很高,需要将条件改动,由于ack还涉及到快发流程的进入和退出,所以ack合并还是有一些工作要做的。

4.修改间隔,目前限制死了是一个jiffies,比如服务器8M左右的发送码率,收到的ack间隔可以释放放大,不然合并几率也比较低,当然这个是以tcp的send_buf中的数据占用更多内存为前提的。

   所以需要一个导出到/proc文件系统的间隔字段来控制。

5.对于低速发送码率的服务器来说,可以关闭gro,对于lvs服务器来说,应该关闭gro。

转:https://www.cnblogs.com/10087622blog/p/9922121.html



推荐阅读
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 开发笔记:计网局域网:NAT 是如何工作的?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了计网-局域网:NAT是如何工作的?相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 三、寻找恶意IP并用iptables禁止掉找出恶意连接你的服务器80端口的IP,直接用iptables来drop掉它;这里建议写脚本来运行, ... [详细]
  • NFS文件共享系统
    1、概述:NFS(NetworkFileSystem)意为网络文件系统,它最大的功能就是可以通过网络,让不同的机器不同的操作系统可以共享 ... [详细]
  • c# java socketn 字节流_C#Socket编程详解(一)TCP与UDP简介
    一、TCP与UDP(转载)1、TCP1.1定义TCP(TransmissionControlProtocol)传输控制协议。是一种可靠的、面向连接的协议(eg:打电话)、传输效率低 ... [详细]
  • IP双栈环境下网络应用迁移
    IPv4向IPv6迁移有多种途径,在选择具体的迁移方式时,当前环境中运行的应用是否支持IPv6是重要的考量因素之一,同时在编写新的应用时,需要考虑新编写的应用不仅可以适应当前主流的IPv4环境, ... [详细]
  • 数据结构系列1 数组和链表
    数组,链表,l ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • UDP千兆以太网FPGA_verilog实现(四、代码前期准备UDP和IP协议构建)
    UDP:userDatagramprotocol用户数据报协议无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETFRFC76 ... [详细]
  • SQL Server 2008 到底需要使用哪些端口?
    SQLServer2008到底需要使用哪些端口?-下面就来介绍下SQLServer2008中使用的端口有哪些:  首先,最常用最常见的就是1433端口。这个是数据库引擎的端口,如果 ... [详细]
  • python计算数据包校验和(python接口数据校验)
    本文目录一览:1、怎么用python算p值和t检验 ... [详细]
  • windows平台使用NSP拦截具体进程的域名解析过程(xFsRedir的代理功能之域名代理)
    byfanxiushu2022-10-17转载或引用请注明原始作者。xFsRedir软件其中之一的功能就是实现了全方位的网络代理,从主机代理,到本地代理 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有