原文:http://www.xuebuyuan.com/2961303.html

首先贴上Linux内核的ifb.c的文件头注释:

    The purpose of this driver is to provide a device that allows
    for sharing of resources:

1) qdiscs/policies that are per device as opposed to system wide.
    ifb allows for a device which can be redirected to thus providing
    an impression of sharing.

2) Allows for queueing incoming traffic for shaping instead of
    dropping.

The original concept is based on what is known as the IMQ
    driver initially written by Martin Devera, later rewritten
    by Patrick McHardy and then maintained by Andre Correa.

You need the tc action  mirror or redirect to feed this device
           packets.

This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version
    2 of the License, or (at your option) any later version.

      Authors:    Jamal Hadi Salim (2005)

和tun一样,ifb也是一个虚拟网卡,和tun一样,ifb也是在数据包来自的地方和去往的地方做文章。对于tun而言,数据包在xmit中发往字符设备,而从字符设备写下来的数据包则在tun网卡上模拟一个rx操作,对于ifb而言,情况和这类似。
       ifb驱动太简单,以至于很短的话就可以将其说清,然后上一幅全景图,最后留下一点如何使用它的技巧,本文就完了。

ifb驱动模拟一块虚拟网卡,它可以被看作是一个只有TC过滤功能的虚拟网卡,说它只有过滤功能,是因为它并不改变数据包的方向,即对于往外发的数据包被重定向到ifb之后,经过ifb的TC过滤之后,依然是通过重定向之前的网卡发出去,对于一个网卡接收的数据包,被重定向到ifb之后,经过ifb的TC过滤之后,依然被重定向之前的网卡继续进行接收处理,不管是从一块网卡发送数据包还是从一块网卡接收数据包,重定向到ifb之后,都要经过一个经由ifb虚拟网卡的dev_queue_xmit操作。说了这么多,看个图就明白了:

ingress队列

Linux TC是一个控发不控收的框架,然而这是对于TC所置于的位置而言的,而不是TC本身的限制,事实上,你完全可以自己在ingress点上实现一个队列机制,说TC控发不控收只是因为Linux TC目前的实现没有实现ingress队列而已。
       Linux的协议栈上有诸多的钩子点,Netfilter当然是最显然的了,它不但可以实现防火墙和NAT,也可以将一个数据包在PREROUTING钩子点上queue到一个队列,然后再将此队列的数据包发往一个虚拟网卡,虚拟网卡的xmit回调函数将数据包重新放回Netfilter将数据包STOLEN走的点上,在发往虚拟网卡的时候做发送流控从而变相地实现ingress队列,这就是IMQ的原理,它工作地不错,但是需要在skb中增加字段,使用起来也要牵扯到Netfilter的配置,不是那么纯粹,于是在这个思想的基础上实现了ifb驱动,这个驱动直接挂在TC本身的ingress钩子上,并不和Netfilter发生关系,但是由于TC的钩子机制并没有将一个数据包偷走再放回的机制,于是只有在做完ifb的流控后在ifb网卡的xmit函数中重新调用实际网卡的rx一次,这个实现和Linux Bridge的实现中完成local deliver的实现如出一辙。

Qdisc的多网卡共享

除了ingress队列之外,在多个网卡之间共享一个根Qdisc是ifb实现的另一个初衷,可以从文件头的注释中看出来。如果你有10块网卡,想在这10块网卡上实现相同的流控策略,你需要配置10遍吗?将相同的东西抽出来,实现一个ifb虚拟网卡,然后将这10块网卡的流量全部重定向到这个ifb虚拟网卡上,此时只需要在这个虚拟网卡上配置一个Qdisc就可以了。

性能问题

也许你觉得,将多块网卡的流量重定向到一块ifb网卡,这岂不是要将所有的本属于不同的网卡队列被不同CPU处理的数据包排队到ifb虚拟网卡的一个队列被一个CPU处理吗?事实上,这种担心是多余的。
       是的,ifb虚拟网卡只有一个网卡接收队列和发送队列,但是这个队列并非被一个CPU处理的,而是被原来处理该数据包的CPU(只是尽量,但不能保证就是原来处理该数据包的那个CPU)继续处理,怎么做到的呢?事实上ifb采用了tasklet来对待数据包的发送和接收,在数据包进入fib的xmit函数之后,将数据包排入队列,然后在本CPU上,注意这个CPU就是原来处理数据包的那个CPU,在本CPU上调度一个tasklet,当tasklet被执行的时候,会取出队列中的数据包进行处理,如果是egress上被重定向到了ifb,就调用原始网卡的xmit,如果是ingress上被重定向到了ifb,就调用原始网卡的rx。当然,tasklet中只是在队列中取出第一个数据包,这个数据包不一定就是在这个CPU上被排入的,这也许会损失一点cache的高利用率带来的性能提升,但不管怎样,如果是多CPU系统,那么显然tasklet不会只在一个CPU上被调度执行。另外,开销还是有一点的,那就是操作单一队列时的自旋锁开销。
       优化方式是显然的,那就是将队列实现成“每CPU”的,这样不但可以保证cache的高利用率,也免去了操作单一队列的锁开销。

Linux TC的ifb原理以及ingress流控-转的更多相关文章

  1. Linux下使用虚拟网卡的ingress流控(入口流控)

    Linux内核实现了数据包的队列机制,配合多种不同的排队策略,可以实现完美的流量控制和流量整形(以下统称流控).流控可以在两个地方实现,分别为egress和ingress,egress是在数据包发出前 ...

  2. Linux数据包路由原理、Iptables/netfilter入门学习

    相关学习资料 https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html http://zh.wik ...

  3. Linux TC(Traffic Control)框架原理解析

    近日的工作多多少少和Linux的流控有点关系.自打几年前知道有TC这么一个玩意儿而且多多少少理解了它的原理之后,我就没有再动过它,由于我不喜欢TC命令行,实在是太繁琐了.iptables命令行也比較繁 ...

  4. Linux TC 流量控制介绍

    前段时间在做一些测试的时候接触到了Linux tc,因为需要对数据包添加延迟,用到了tc中的netem.添加简单的延迟非常简单,像这样一条命令就搞定了:$ tc qdisc add dev eth0 ...

  5. Linux串口设备树硬件、软件流控设置

    /********************************************************************** * Linux串口设备树硬件.软件流控设置 * 说明: ...

  6. 动态替换Linux核心函数的原理和实现

    转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实 ...

  7. sentinel 集群流控原理

    为什么需要集群流控呢?假设需要将某个API的总qps限制在100,机器数可能为50,这时很自然的想到使用一个专门的server来统计总的调用量,其他实例与该server通信来判断是否可以调用,这就是基 ...

  8. Linux系统的启动原理

    Linux系统的启动原理 RHEL的启动原理BIOS自检-MBR-启动GRUB-加载内核-systemd的init进程 systemd的初始化进程加载需要的服务,挂载文件系统/etc/fstabsys ...

  9. linux seccomp使用和原理

    linux seccomp使用和原理 概要 linux的沙箱机制,可以限制进程对系统调用的访问,从系统调用号,到系统调用的参数,都可以检查和限制 有两种模式 SECCOMP_MODE_STRICT, ...

随机推荐

  1. Django之13种必会查询

    1.常见的13中查询方式(必须记住) <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> g ...

  2. Linux 容器 vs 虚拟机——谁更胜一筹

    自从Linux上的容器变得流行以来,了解Linux容器和虚拟机之间的区别变得更加棘手.本文将向您提供详细信息,以了解Linux容器和虚拟机之间的差异. Linux容器vs虚拟机 - 应用程序与操作系统 ...

  3. 笔记:Python操作sql

    python操作mysql步骤: 创建connect连接 conn = connect(host='127.0.0.1', port=3306, user='root', password='1234 ...

  4. (转)Windows中杀死占用某个端口的进程

    启动tomcat时候,控制台报错,发现是端口占用,于是寻找方法关闭对应的程序. 从网上找了好久,尝试之后,发现不行.开始自己尝试,终于,成功的将占用端口的进程杀掉.在此记录下过程(以8081端口为例) ...

  5. thinkphp 统计查询

    在应用中我们经常会用到一些统计数据,例如当前所有(或者满足某些条件)的用户数.所有用户的最大积分.用户的平均成绩等等,ThinkPHP为这些统计操作提供了一系列的内置方法,包括: 大理石平台检定规程 ...

  6. 「题解」:windy数

    问题: windy数 时间限制: 1 Sec  内存限制: 512 MB 题面 题目描述 Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为 的正整数被称为 Windy 数. ...

  7. LUOGU P1313 计算系数 (组合数学)

    解题思路 比较简单的题,用二项式定理即可. #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  8. IOS6 新特性之UIActivityViewController详解

    新的IOS6增加了一些新特性.因为应用需要,所以在国庆的几天里.研究了一下IOS6的说明文档,然后大概地总结了一下UIActivityViewController的用法与大家分享. 首先 从实际效果入 ...

  9. 服务器重启,自动重启httpd

    1. 手动重启 cd http ll cd /etc/httpd/   ll service httpd restart 2. 查看服务器内存使用情况 df -h 3. 自动重启 cat /etc/i ...

  10. Android之GridLayout网格布局

    1.相关属性 GridLayout网格布局是4.0之后引入的布局方式! android:columnCount="4" //设置列数(4列) android:rowCount=&q ...