我自己分析内核tc的一点心得(4)
关于sch_ingress.c
http://bbs.chinaunix.net/viewthr ... p;highlight=qtdszws
使用ingress的内核处理流程
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: pref 10 protocol ip u32
1.init_module->nf_register_hook
注册ingress的钩子到
static struct nf_hook_ops ing_ops =
{
{ NULL, NULL},
ing_hook,
PF_INET,// 2
NF_IP_PRE_ROUTING,//注册到PRE_ROUTING
NF_IP_PRI_FILTER + 1
};
2.网卡接收到一个ip数据包后调用ip_input.c中的ip_rcv
NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,ip_rcv_finish)
NF_HOOK定义如下
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
(list_empty(&nf_hooks[(pf)][(hook)]) \
? (okfn)(skb) \
: nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn)))
因此将调用nf_hook_slow,在core/netfilter.c中
nf_hook_slow->nf_iterate-> hook-> ing_hook(ingress的钩子函数)-> ingress_enqueue(入队)-> tc_classify(分类)
3.根据分类结果决定继续处理该包,还是丢弃(例如被管制器管制)
sch_teql.c
teql原理
1.在Linux的路由和流量控制HOWTO.pdf有一些说明,可以参照
2.teql实现了一个简单的多网卡负载均衡.简单,是因为它不考虑实际的硬件情况,只是在关联的实际设备之间轮转转发包,即使是一个千兆网卡和MODEM被关联在一起.可以称做发包数负载均衡吧.
3.insmod sch_teql.o时, init_module会注册一个名为teql0的虚网络接口和一个名为teql0的队列规程,他们被集成在struct teql_master结构中,彼此分不开.
可以使用一下命令绑定实设备到队列规程teql0
tc qdisc add dev eth0 root teql0
tc qdisc add dev eth1 root teql0
然后用命令ip link set dev teql0 up激活虚设备teql0
这样一个teql设备就配置完成了
接下来可以再配置另一个teql设备
insmod –o sch_teql1 sch_teql.o
我这是RED HAT 7.2,由于已经加载了sch_teql.o模块,只能重命名加载了.
新版本内核已经实现一次insmod就可指定若干个teql
tc qdisc add dev eth2 root teql1
tc qdisc add dev eth3 root teql1
ip link set dev teql1 up
4.当有数据包到达teql0时先进入自己的队列,缺省为pfifo_fast,然后内核就调用teql_master_xmit来在从设备中循环轮转选择一个设备eth*发包.如果teql*是该实设备的根队列规程,就直接调用eth*的hard_start_xmit函数发包.如果不是就选择下一个设备,只至成功或失败.而配置在该设备上的teql*规程,它的行为就类似于pfifo规程.这是给那些直接通过该设备发送的包准备的规程.
sch_red.c random early detection
随机早期探测
说明
1.qlen 为当前队列长度
2.qave 平均队列长度,它的计算公式是qave=qave*(1-W)+qlen*W,W为权重,W一般选得很小 ,这可以使突发包对qave不会产生太大波动
3.qmin,qmax 当qmin<=qave<=qmax时,开始随机标记/丢包,标记/丢包的概率为
max_P * (qave- qmin)/(qmax-qmin),,随着qave增长,概率逼近max_P
标记包是希望客户端知道目前网络已经开始拥挤,放慢发包速度吧
如果qave>=qmax,标记/丢弃所有的包
4.如果网络空闲了一段时间,就应该相应地减少qave的大小,qave=qave*(1-W)^m,m为空闲时间段长度
路由分类器cls_route.c
路由分类器的原理很简单,就是在路由的时候由路由规则对数据包打标记.路由分类器就用这个标记来对数据包分类.
路由规则语法如下
ip route add Host/Network via Gateway dev Device realm RealmNumber
例
ip route add 192.168.10.0/24 via 192.168.10.1 dev eth1 realm 10
至于如何打标记,我现在还不了解
在设置了路由规则以后,就可以使用路由分类器分类数据了
tc filter add dev eth0 protocol ip prio 100 route to 10 classid :2
tc filter add dev eth0 protocol ip prio 100 route from 10 classid :1
路由分类器参考的参数有fromdev/from,to,fromdev和from互斥,只能使用其中一个,由他们在分类器的二层hash表中索引和查找.
资源预留协议分类器cls_rsvp.h
资源预留协议分类器的原理也很简单,就是用ip协议(也支持ipv6,此处不涉及)的目的地址,可能的目的端口,源地址,可能的源端口来索引和查找一个二层hash表.
"可能的"意思是不一定使用,由用户决定.也就是它是基于session(会话)的.
tc filter add dev eth0 pref 10 protocol ip rsvp ipproto tcp session 10.1.1.1/80 classid :1
这条规则的意思就是,到10.1.1.1:80的数据流分类到:1的队列
还可以加入sender,指定发送者,或者不指定端口,而指定一个GPI,也就是在offset处的值&mask==key方式更加灵活地指定一个匹配.
文章来源CU社区:我自己分析内核tc的一点心得
相关文章