FQ队列中对发送时间未到的流结构单独存放在delayed红黑树中,这样的流结构即不在new_flow链表,也不在old_flow链表,其next指针执行一个特定的值:throttled。内核函数通过检查流结构的next指针,来判断流是否处于throttled状态。

new_flow链表中的流结构的优先级高于old_flows中的流。

/* special value to mark a detached flow (not on old/new list) */
static struct fq_flow detached, throttled;static bool fq_flow_is_throttled(const struct fq_flow *f)
{return f->next == &throttled;
}

当流结构中的报文到达发送时间之后,函数fq_flow_unset_throttled将其由红黑树中删除,并将其添加到old_flows链表中。函数fq_flow_add_tail会更新流结构的next指针。

static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f)
{rb_erase(&f->rate_node, &q->delayed);q->throttled_flows--;fq_flow_add_tail(&q->old_flows, f);
}

1. 流分类时退出throttled

如果新接收的报文所属的套接口与FQ中对应的套接口相等,但是两者的hash值不同,表明内核的套接口经过了重新分配(reallocated),此时,如果流处于throttled状态,将其退出throttled,并且设置time_next_packet为零0,重新开始发送此流结构的报文。

static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
{...p = &root->rb_node;parent = NULL;while (*p) {parent = *p;f = rb_entry(parent, struct fq_flow, fq_node);if (f->sk == sk) {/* socket might have been reallocated, so check if its sk_hash is the same.* It not, we need to refill credit with initial quantum*/if (unlikely(skb->sk && f->socket_hash != sk->sk_hash)) {f->credit = q->initial_quantum;f->socket_hash = sk->sk_hash;if (fq_flow_is_throttled(f))fq_flow_unset_throttled(q, f);f->time_next_packet = 0ULL;}return f;

2. 出队列中throttled流处理

在fq_dequeue中,调用fq_check_throttled检查delayed树中是否有可发送报文的流结构。变量time_next_delayed_flow大于当前时刻,表明整个delayed树中没有到期可发送报文。否则,遍历delayed树,如果当前遍历的流结构的应发送时间戳小于当前时刻,将其退出throttled状态,否则,更新time_next_delayed_flow记录的delayed树中最早应发送报文的时间戳,并退出遍历。

另外,统计值unthrottle_latency_ns使用EWMA算法生成,最近一次采样的占比为1/8。

static void fq_check_throttled(struct fq_sched_data *q, u64 now)
{unsigned long sample;struct rb_node *p;if (q->time_next_delayed_flow > now) return;/* Update unthrottle latency EWMA.* This is cheap and can help diagnosing timer/latency problems.*/sample = (unsigned long)(now - q->time_next_delayed_flow);q->unthrottle_latency_ns -= q->unthrottle_latency_ns >> 3;q->unthrottle_latency_ns += sample >> 3;q->time_next_delayed_flow = ~0ULL;while ((p = rb_first(&q->delayed)) != NULL) {struct fq_flow *f = rb_entry(p, struct fq_flow, rate_node);if (f->time_next_packet > now) {q->time_next_delayed_flow = f->time_next_packet;break;}fq_flow_unset_throttled(q, f);

在每次fq_dequeue执行时,首先检查fq中throttled状态的流结构,由以上函数fq_check_throttled实现。接下来,如果new_flows和old_flows都为空,并且delayed树中有待发送的流结构,此时启动watchdog定时器。

static struct sk_buff *fq_dequeue(struct Qdisc *sch)
{struct fq_sched_data *q = qdisc_priv(sch);struct fq_flow_head *head;struct fq_flow *f;if (!sch->q.qlen) return NULL;skb = fq_dequeue_head(sch, &q->internal);if (skb) goto out;now = ktime_get_ns();fq_check_throttled(q, now);
begin:head = &q->new_flows;if (!head->first) {head = &q->old_flows;if (!head->first) {if (q->time_next_delayed_flow != ~0ULL)qdisc_watchdog_schedule_ns(&q->watchdog,q->time_next_delayed_flow);return NULL;}}f = head->first;if (f->credit <= 0) {f->credit += q->quantum;head->first = f->next;fq_flow_add_tail(&q->old_flows, f);goto begin;}

对于当前处理的流结构,如果其credit有值,但是报文的下一次发送时间还没有到,将此流结构由链表(new或者old链表)中移除,并将此流结构设置为节流状态(throttled)。链表(new或者old)的头部指向下一个流结构。

    skb = f->head;if (skb) {u64 time_next_packet = max_t(u64, ktime_to_ns(skb->tstamp),f->time_next_packet);if (now < time_next_packet) {head->first = f->next;f->time_next_packet = time_next_packet;fq_flow_set_throttled(q, f);goto begin;}

所有throttled状态的流结构链接在delayed表示的红黑树中,以下一个报文发送时间作为键值。由于流结构的next指针还是指向new_flow或者old_flow链表中的元素,这里将next执行全局静态变量throttled,用于表示此流结构的throttled状态,函数fq_flow_is_throttled即通过判断流结构的next决定其是否处于throttled状态。

变量time_next_delayed_flow保存了整个delayed红黑树中,最早要发送的报文的发送时间。

static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f)
{struct rb_node **p = &q->delayed.rb_node, *parent = NULL;while (*p) {struct fq_flow *aux;parent = *p;aux = rb_entry(parent, struct fq_flow, rate_node);if (f->time_next_packet >= aux->time_next_packet)p = &parent->rb_right;elsep = &parent->rb_left;}rb_link_node(&f->rate_node, parent, p);rb_insert_color(&f->rate_node, &q->delayed);q->throttled_flows++;q->stat_throttled++;f->next = &throttled;if (q->time_next_delayed_flow > f->time_next_packet)q->time_next_delayed_flow = f->time_next_packet;
}

内核版本 5.0

FQ队列throttled流管理相关推荐

  1. FQ队列detached流管理

    对于FQ中的流结构,如果其没有任何要发送的报文,即其为空,将其设置为detached状态,这样的流结构即不在new_flow链表,也不在old_flow链表.在detach设置函数中,不仅将其next ...

  2. 《深入浅出DPDK》读书笔记(九):流分类与多队列、流过滤、虚拟化流分类方式、流分类技术的使用

    Table of Contents 94.Linux内核对多队列的支持 95.DPDK与多队列 98.流分类 99.RSS 100.Flow Director 101.服务质量 102.虚拟化流分类方 ...

  3. Linux FQ 队列实现原理浅析

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

  4. suricata 流管理

    flow相关文件及作用 flow.h flow.c:flow-worker.h flow-worker.c:flow-hash.h flow-hash.c:flow-manager.h flow-ma ...

  5. 基于EasyDSS流媒体服务器实现的直播流管理与鉴权的后台方案

    本文转自EasyDSS团队Marvin的博客:http://blog.csdn.net/marvin1311/article/details/73548929 最新版本的EasyDSS流媒体解决方案, ...

  6. Spring Web Flow 2中的流管理持久性

    Spring Web Flow是一个创新的Java™Web框架,它扩展了Spring MVC技术. 使用Spring Web Flow进行应用程序开发是围绕用例定义的,这些用例被定义为Web流. 根据 ...

  7. 基于VSM价值流管理提升BizDevOps落地成效

    软件作为新一代信息技术的灵魂,已经成为驱动产业和技术创新.引领经济和社会转型发展的核心力量.与此同时,软件价值从"以产品为中心"演进为"以产品+服务为中心",软 ...

  8. asp.net1036-物流管理信息系统#毕业设计

    项目编号:asp.net1036-物流管理信息系统#毕业设计 运行环境:VS+SQL 开发工具:VS2010及以上版本 数据库:SQL2008及以上版本 使用技术:HTML+JS+HTML 开发语言: ...

  9. 魔坊APP项目-26-直播、docker安装OSSRS流媒体直播服务器、基于APICloud的acLive直播推流模块实现RTMP直播推流、直播流管理

    一.docker安装OSSRS流媒体直播服务器 在外界开发中, 如果要实现直播功能.常用的方式有: 1. 通过第三方接口来实现.可以申请阿里云,腾讯云,网易云,七牛云的直播接口,根据文档,下载集成SD ...

最新文章

  1. 实验七 访问列表配置
  2. 必须为元素类型 association 声明属性 oftype。_CSS相关的选择器和属性介绍
  3. 第三次组队赛 (DFSBFS)
  4. (电影播放器)MPMoviePlayerController
  5. 优秀大数据GitHub项目一览
  6. concurrenthashmap在1.8和1.7里面有什么区别
  7. 程序员面试100题之十三:求二叉查找树的镜像
  8. hbuilderx 小程序分包_基于uniapp的微信小程序之分包
  9. 两大图灵奖得主点赞中国用AI检测新冠,AI还能做什么?
  10. html文件打开多出很多数字,【求助】页面上显示几个数字,打开html的时候希望能滚动起来...
  11. 斐波那契回调线怎么画_外汇MT4平台上的斐波那契回调线怎么使用
  12. 【恋上数据结构】希尔排序
  13. python装饰器 廖雪峰_python装饰器的一个妙用
  14. opengl 矩阵投影代码 shade_LookAt、Viewport、Perspective矩阵
  15. 【OpenCV学习笔记】【函数学习】三(cvGetCaptureProperty函数)
  16. qq微信趣味测试小程序源码
  17. 多尺度卷积稀疏编码的无监督迁移学习
  18. 【第38题】2019年OCP认证12C题库062考试最新考试原题
  19. 【基础理论】Jenkins CI/DI持续集成部署
  20. 新生儿的一类(免费)疫苗(截止2019年)

热门文章

  1. 算法基础-加密与解密-程序设计
  2. 解析learn the python3 the hard way里的ex43
  3. 世界睁大眼睛关注中国春节
  4. 【软件质量保证与测试】实验一、基于Selenium+Python的自动化测试
  5. 面试|C# .net 面试题
  6. 使用哈希表统计数组中数字出现的次数
  7. 【Spring】mybatis-spring
  8. 单片机c 语言0-99,单片机“0~99”加法计数器程序的设计51单片机原理及应用.doc...
  9. ADO 与ADO.NET
  10. 成功需要“十商”(网络转载)