2018/04/21

又到了周六早上,依然是后半夜属于自己的时间。起床,读了几篇古文,准备梳理一下Linux FQ和RPS方面的原理,正好昨天也有人问到我。本文先从FQ开始。

enqueue入队过程

上一张图:

详细描述了fq队列的入队过程,其中着重理解几个数据结构:

  • sock作为键的红黑树:用于关联skb和flow
  • next_time作为键的红黑树:用于保存未来被调度的flow,并决定timer唤醒时间以调度skb
  • new_list:用于保存新创建尚未发包的flow链表,用于优先调度触发第一包
  • old_list:用于保存正在被调度的flow。

dequeue调度过程

dequeue操作要比enqueue操作更复杂一些,先看一张图:

这是一个相对动态的过程,由Linux的hrtimer来驱动,其超时时间则取决于 每一个flow的最近要发送的skb的时间 ,诸多flow中的时间取最小,这明显倾向于使用红黑树来实现,我们来看一下dequeue的核心代码:

static struct sk_buff *fq_dequeue(struct Qdisc *sch)
{.../* 将红黑树上已经到期的flow从红黑树上摘除,加入old_list准备开始被调度 */fq_check_throttled(q, now);
begin:/* 优先无条件调度新创建的flow上的skb,触发其第一包发送,以计算next_time */head = &q->new_flows;if (!head->first) {/* 如果没有新创建的flow,则调度old_list已经创建且被调度的flow */head = &q->old_flows;if (!head->first) {/* 设置最短的超时,延后执行dequeue */qdisc_watchdog_schedule_ns(&q->watchdog,q->time_next_delayed_flow);return NULL;}}/* 从head到tail的顺序调度 */f = head->first;if (unlikely(f->head && now < f->time_next_packet)) {/* 同一个flow的skb链表依次被调度,然而由于pacing,当前skb允许发送的时间 *//* 在当前时间之后,则终止当前flow,将其插入delay rb-tree,同时调度old_list *//* 下一个flow */head->first = f->next;fq_flow_set_throttled(q, f); // 冒泡找到最近的expiresgoto begin;}/* 取出被调度的skb,根据pacing rate计算下一个包发送的时间 */skb = fq_dequeue_head(sch, f);//if (f->credit > 0 || !q->rate_enable)if (!q->rate_enable)goto out;rate = skb->sk->sk_pacing_rate;plen = qdisc_pkt_len(skb);len = (u64)plen * NSEC_PER_SEC;do_div(len, rate);f->time_next_packet = now + len;out:return skb;
}

此其中的核心是

f->time_next_packet

这就是红黑树节点的键值。

速率pacing rate

Linux FQ中给定一个flow的pacing rate来计算发送下一个skb的时间依然沿用了传统的方案,即***根据当前skb的长度来计算下一个skb发送的时间***,依托于公式:

Δt=ΔSv\Delta t=\dfrac{\Delta S}{v}Δt=vΔS​

很显然的事情,这里的ΔS\Delta SΔS就是当前skb的长度,此公式的含义即,发送当前的skb一共需要Δt\Delta tΔt的时间,Linux的实现显然是粗粒度粗糙的:

len = (u64)plen * NSEC_PER_SEC;
do_div(len, rate);
f->time_next_packet = now + len;

它是基于skb来做pacing发送的,而不是基于字节来做pacing发送的,这也是主机和线路之间的矛盾,不多说。

和O(1)调度器以及CFS调度器比较

其实,FQ机制也CFS进程调度器以及磁盘IO的公平队列是完全一致的实现:

和CFS不同的是,FQ同时维护了一个 正在被调度flow队列 ,即old_list(此处我们忽略作为开场作用的new_list),显然在CFS中,CPU时间同时只能分配给一个task,这是不同。观察这个old_list,会发现这是一个静态优先级数据结构,它和O(1)调度器非常类似:

这个和磁盘IO公平队列几乎是完全一致的,时间片可以分配给多个entry。


后面两个小节说一下pacing的实现,而不是FQ。说白了pacing的实现并不一定非得用FQ,FQ的主要要解决的问题是 如何用单一的timer去驱动任意多和flow,使其都能按照自己的pacing发送数据。然而,我们能不能把这个锅甩给Linux的调度器呢?

我自己实现的TCP Pacing机制

说起FQ,不得不提的是Google BBR拥塞控制算法,前年在初次接触BBR时被这个Pacing建议弄得着迷,说实话Linux TCP Pacing机制以及FQ早已有之,然而直到BBR才结合在一起起作用,我当时在想,既然TCP本身就是per flow的,干嘛还要Qdisc层再维护一个flow表,并且我发现这个FQ实现的公平队列在高并发TCP流时,其调度时间并不准确,所以我倾向于在TCP层直接实现Pacing(也就是社区的Internal pacing):
彻底实现Linux TCP的Pacing发送逻辑-普通timer版 :https://blog.csdn.net/dog250/article/details/54424629
彻底实现Linux TCP的Pacing发送逻辑-高精度hrtimer版 :https://blog.csdn.net/dog250/article/details/54424751
我起初认为这可行,是因为我觉得TCP反正也有那么多timer了,再多一个也不多。然而却忽略了两个问题:

  • 高速率TCP
    pacing rate极大时,timer将会频繁超时,为Linux调度子系统造成压力。
  • 高并发流
    多个TCP流接连超时,将会持续加重Linux调度子系统的负担。

所以说,单流测试OK,不代表真的就可用。

OK,此问题何解?

一个timer调度100000条TCP连接不是吃力吗?100000个timer每一个调度一个TCP连接不是调度器吃力吗?看来简单的甩锅是不妥的,解法是,干嘛不搞固定的10个timer,或者5个,或者20个,或者30个,看你的CPU配置了,只要是固定的数量的timer就行,以10个timer为例,一个timer平均只要对付10000条TCP流就好了,数量级的差异!

FQ只需要多加一个层次就能解决问题!

社区的internal TCP Pacing补丁

你可以先读一下这个:
TCP Pacing :https://lwn.net/Articles/199644/
然后会问,为什么该patch没有被applied,请看我上一节的解释。

好吧,时隔10多年,又来了一个:
[v2,net-next] tcp: internal implementation for pacing :https://patchwork.ozlabs.org/patch/762899/
几乎是一样的东西。不多说。

插队策略

FQ针对retransmit的数据包实现了一个插队策略:

// flow_queue_add
/* add skb to flow queue* flow queue is a linked list, kind of FIFO, except for TCP retransmits* We special case tcp retransmits to be transmitted before other packets.* We rely on fact that TCP retransmits are unlikely, so we do not waste* a separate queue or a pointer.* head->  [retrans pkt 1]*         [retrans pkt 2]*         [ normal pkt 1]*         [ normal pkt 2]*         [ normal pkt 3]* tail->  [ normal pkt 4]*/

这里还有没有别的花式插队或者花式避让策略呢?比方说针对纯ACK,小包,持续大包中的小包,持续小包中的大包。这个就不细说了,嗯,我们还有FQ的internal队列没有用呢,同时,能不能再多实现几个类似的队列呢?


这周感觉非常轻松,然而没有get新的什么idear。

浙江温州皮鞋湿,下雨进水不会胖。

Linux FQ 队列实现原理浅析相关推荐

  1. linux取消线程的原理,浅析 Linux 进程与线程

    简介 进程与线程是所有的程序员都熟知的概念,简单来说进程是一个执行中的程序,而线程是进程中的一条执行路径.进程是操作系统中基本的抽象概念,本文介绍 Linux 中进程和线程的用法以及原理,包括创建.消 ...

  2. linux fq队列,理解fq_codel之概述

    fq_codel这个新的机制进入内核已经有一段时间了,主要是在Linux的Wi-Fi子系统中使用.但是目前好像并没有像样的中文的介绍.正好之前参与开源组织合作开发Airtime fairness(AT ...

  3. Linux FQ队列操作

    在介绍FQ入队列操作之前,先看一下流量的识别部分. 1 流量识别 对于一些协议报文,比如HSR(High-availability Seamless Redundancy).IGMP和HDLC等,其将 ...

  4. linux fq队列,QOS各种队列详解(FIFO,FQ,CBWFQ,PQ).doc

    QOS各种队列详解(FIFO,FQ,CBWFQ,PQ) QOS各种队列详解(FIFO,FQ,CBWFQ,PQ) 对于拥塞管理,一般采用队列技术,使用一个队列算法对流量进行分类,之后用某种优先级别算法将 ...

  5. ActiveMQ使用及原理浅析(消息队列)

    文章目录 引言 正文 一.ActiveMQ是如何产生的? 产生背景 JMS规范 基本概念 JMS体系结构 二.如何使用? 基本功能 消息传递 P2P pub/sub 持久订阅 消息传递的可靠性 事务型 ...

  6. linux软中断是什么机制,Linux软中断原理浅析

    Linux软中断原理浅析 Linux软中断原理浅析 Linux中的软中断机制用于中对时间要求最严格以及最重要的中断下半部进行使用.在系统设计过 程中,大家都清楚中断上下文不能处理太多的事情,需要快速的 ...

  7. 【网络知识】Linux内核桥原理浅析

    1.什么是桥接? 简单来说,桥接就是把一台机器上的若干个网络接口"连接"起来.其结果是,其中一个网口收到的报文会被复制给其他网口并发送出去.以使得网口之间的报文能够互相转发.交换机 ...

  8. Linux公平队列FQ接口实现

    用户层面的tc配置命令如下: $ sudo tc qdisc add dev ens38 root fq $ $ sudo tc -s qdisc show dev ens38 qdisc fq 80 ...

  9. Python标准库threading模块Condition原理浅析

    Python标准库threading模块Condition原理浅析 本文环境python3.5.2 threading模块Condition的实现思路 在Python的多线程实现过程中,在Linux平 ...

最新文章

  1. c语言 mysql_bind,linux C mysql的blob门类字段的插入和读取
  2. matlab生成常用信号(方波、三角波、随机信号、单位冲激)
  3. Mongodb 与 Redis 调教
  4. P3293 [SCOI2016]美味
  5. 手工做迷宫_好玩易上手的自然探索实验,春天必备,宅家就能带孩子做起来!...
  6. 纵坐标是横的还是竖的_600*1200墙砖横贴好,还是竖贴好?讲讲这两种贴法的问题...
  7. 51单片机实现计算器程序
  8. 使用Python写一个简单的服务器
  9. 【强连通分量】 Kosaraju和Tarjan算法 (标准模板+详细注释)
  10. Ansheng的SRE学习之路-linux基础篇
  11. 酷派D530刷机指引
  12. Win10卸载KB5014699补丁教程
  13. 怎么把单个的pdf文件合并在一起?怎么把几个单独的pdf文件合并为一个?
  14. Java最全八股文(2023最新整理)
  15. linux安装pymysql
  16. 响应式织梦模板玩具动漫类网站
  17. 太空射击第15课: 道具
  18. php 第三方认证中心 框架,仿百度钱包源码红色优享钱包网贷借款源码/接入第三方认证,去后门修复缺陷ThinkPHP开发...
  19. 360搜索用上了so.com域名
  20. 算法-二分法和牛顿法求指定精度平方根

热门文章

  1. day22-作业贝壳租房100页数据
  2. 山东大学计算机学院李庆忠,研究生导师李庆忠:山东大学
  3. (更新时间)2021年5月28日 商城高并发秒杀系统(.NET Core版) 01-系统设计介绍
  4. 流程挖掘的价值:头部制造业千万级增长的底牌
  5. 时隔10年,STM32标准外设库再次升级
  6. FreeBSD install
  7. 计算机网络日志保存时间,在网络安全等级保护制度中,网络运营者应当保留网络日志不少于( )...
  8. 助力中国 DevOps 运动,ONES 携手 DevOps 社区举办第12届 Meetup
  9. 下列关于python的说法正确的是_1.??下列关于Python2.x和Python3.x的说法,正确的是()...
  10. 专业LaTeX编辑工具:Texpad for Mac