• tc:逼良为娼


    tc的学习原来是想着直接从用户态学习的,但是万万没想到哇,qdisc class两个概念直接把我给搞晕了,直接看代码吧

    调用:tc qdisc add dev tap0 root handle 1: htb default 2

    %stc 0xffffffff81744fe0 : qdisc_create+0x0/0x410 [kernel]
     0xffffffff81745597 : tc_modify_qdisc+0x1a7/0x5b0 [kernel]
     0xffffffff8172b336 : rtnetlink_rcv_msg+0xe6/0x230 [kernel]
     0xffffffff8174ee24 : netlink_rcv_skb+0xa4/0xc0 [kernel]
     0xffffffff8172b248 : rtnetlink_rcv+0x28/0x30 [kernel]
     0xffffffff8174e5da : netlink_unicast+0x12a/0x1b0 [kernel]
     0xffffffff8174eb01 : netlink_sendmsg+0x4a1/0x5f0 [kernel]
     0xffffffff816fe098 : sock_sendmsg+0x38/0x50 [kernel]
     0xffffffff816feb41 : ___sys_sendmsg+0x281/0x290 [kernel]
     0xffffffff816ff491 : __sys_sendmsg+0x51/0x90 [kernel]
     0xffffffff816ff4e2 : sys_sendmsg+0x12/0x20 [kernel]
     0xffffffff818244f2 : entry_SYSCALL_64_fastpath+0x16/0x71 [kernel]
    

    在增加tc class的时候的调用栈是:

    tc
     0xffffffff81741950 : qdisc_create_dflt+0x0/0x80 [kernel]
     0xffffffffc0a87abf [sch_htb]
     0xffffffff81744d85 : tc_ctl_tclass+0x3b5/0x400 [kernel] (inexact)
     0xffffffff8172b336 : rtnetlink_rcv_msg+0xe6/0x230 [kernel] (inexact)
     0xffffffff81706bd7 : __alloc_skb+0x87/0x1f0 [kernel] (inexact)
     0xffffffff8172b250 : rtnetlink_rcv_msg+0x0/0x230 [kernel] (inexact)
     0xffffffff8174ee24 : netlink_rcv_skb+0xa4/0xc0 [kernel] (inexact)
     0xffffffff8172b248 : rtnetlink_rcv+0x28/0x30 [kernel] (inexact)
     0xffffffff8174e5da : netlink_unicast+0x12a/0x1b0 [kernel] (inexact)
     0xffffffff8174eb01 : netlink_sendmsg+0x4a1/0x5f0 [kernel] (inexact)
     0xffffffff813912f1 : aa_sock_msg_perm+0x61/0x150 [kernel] (inexact)
     0xffffffff816fe098 : sock_sendmsg+0x38/0x50 [kernel] (inexact)
     0xffffffff816feb41 : ___sys_sendmsg+0x281/0x290 [kernel] (inexact)
     0xffffffff8120018b : mem_cgroup_try_charge+0x6b/0x1b0 [kernel] (inexact)
     0xffffffff8119dfd7 : lru_cache_add_active_or_unevictable+0x27/0xa0 [kernel] (inexact)
     0xffffffff811bf87a : handle_mm_fault+0xcaa/0x1820 [kernel] (inexact)
     0xffffffff816ff491 : __sys_sendmsg+0x51/0x90 [kernel] (inexact)
     0xffffffff816ff4e2 : sys_sendmsg+0x12/0x20 [kernel] (inexact)
     0xffffffff818244f2 : entry_SYSCALL_64_fastpath+0x16/0x71 [kernel] (inexact)
    

    在qdisc中打点,发现每创建一个分类都会导致创建一个新的qdisc,然后这个qdisc会放到哪里?

     rt_netlink

    4068 static int __net_init rtnetlink_net_init(struct net *net)
    4069 {
    4070     struct sock *sk;
    4071     struct netlink_kernel_cfg cfg = {
    4072         .groups     = RTNLGRP_MAX,
    4073         .input      = rtnetlink_rcv,
    4074         .cb_mutex   = &rtnl_mutex,
    4075         .flags      = NL_CFG_F_NONROOT_RECV,
    4076     };
    4077 
    4078     sk = netlink_kernel_create(net, NETLINK_ROUTE, &cfg);
    4079     if (!sk)
    4080         return -ENOMEM;
    4081     net->rtnl = sk;
    4082     return 0;
    4083 }
    

     注册了这样的一种网络的协议,然后这种协议专门处理网络收发包的策略

    htb_qdisc_ops函数的原型如下:

    1582 static const struct Qdisc_class_ops htb_class_ops = {
    1583     .graft      =   htb_graft,
    1584     .leaf       =   htb_leaf,
    1585     .qlen_notify    =   htb_qlen_notify,
    1586     .get        =   htb_get,
    1587     .put        =   htb_put,
    1588     .change     =   htb_change_class,
    1589     .delete     =   htb_delete,
    1590     .walk       =   htb_walk,
    1591     .tcf_chain  =   htb_find_tcf,
    1592     .bind_tcf   =   htb_bind_filter,
    1593     .unbind_tcf =   htb_unbind_filter,
    1594     .dump       =   htb_dump_class,
    1595     .dump_stats =   htb_dump_class_stats,
    1596 };
    1597
    1598 static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
    1599     .cl_ops     =   &htb_class_ops,
    1600     .id     =   "htb",
    1601     .priv_size  =   sizeof(struct htb_sched),
    1602     .enqueue    =   htb_enqueue,
    1603     .dequeue    =   htb_dequeue,
    1604     .peek       =   qdisc_peek_dequeued,
    1605     .init       =   htb_init,
    1606     .reset      =   htb_reset,
    1607     .destroy    =   htb_destroy,
    1608     .dump       =   htb_dump,
    1609     .owner      =   THIS_MODULE,
    1610 };

     tc_ctl_tclass就是对class的处理!!!!!

    子队列是怎么关联到父队列中去的?对于htb算法来说,到底是怎么管理的这棵树的?

     207 static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
    如何htb_classify,把数据包放到对应的队列中去。

    所以我们再整理一下看一下htb里面是怎么把数据包放到,首先会根据数据包skb->priority字段去找到这个数据包属于的class编号,确定了class之后,【这里有个疑问】为什么不是先做filter呢?

    先找到这个priority对应的class,class上依附着这个class所有的filter,路由!

    所以现在基本明白了qdisc/class/filter之间的关系,一个qdisc下有一个class,然后这个class中依附着一个路由表,这个表中指向的是多个新的qdisc。下面这些叶子qdisc中又有自己的class了,这个class了,这个class规定了自己的一些特性呢!所以一个qdisc一定关联着一个class,这个class定义着这个qdisc的发送的速率等参数。

    所以clas这个结构体是一定要存在的!看下,像htb这样的tc算法,如果filter直接放在qdisc上面的话,那么子class流量共享与不共享就只能选择其中一个了,但是如果此时创建了一个class

    那么其实还有个问题,在skb中标志了这个major:minor号码,那么为什么不直接找到这个号码呢?看下tc filter是怎么操作的!是怎么把这个priory放到了skb->priority域中的?!tc filter add dev

    __ip_make_skb<--ip_make_skb

    https://blog.csdn.net/eydwyz/article/details/53320910

    所以在htb_enqueue时设置了优先级的概念priority:

    skb->priority:

    19 #define TC_PRIO_BESTEFFORT      0
     20 #define TC_PRIO_FILLER          1
     21 #define TC_PRIO_BULK            2
     22 #define TC_PRIO_INTERACTIVE_BULK    4
     23 #define TC_PRIO_INTERACTIVE     6
     24 #define TC_PRIO_CONTROL         7
    这个就是skb->priority中设置的数据包

    有一个例子:

    #tc qdisc add dev eth0 root handle 1: htb default 21

    #tc class add dev eth0 partent 1: classid 1:1 htb rate 20mbit ceil 20mbit

    #tc class add dev eth0 parent 1: classid 1:2 htb rate 80mbit ceil 80mbit

    #tc class add dev eth0 parent 1: classid 1:21 htb rate 40mbit ceil 20mbit

    #tc class add dev eth0 parent 1:2 classid 1:22 htb rate 40mbit ceil 80mbit

    #tc filter add dev eth0 protocol parent 10 prio 1 u32 match ip dport 80 0xffff flowid 1:21

    #tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:22

    #tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 23 0xffff flowid 1:1

    数据包中根本就没有代表,但是tc也是肯能打标的

    那么就再看htb_enqueue

  • 相关阅读:
    智能合约初体验
    安装solidity遇见的问题——unused variable 'returned'
    Clojure学习笔记(二)——函数式编程
    《Java虚拟机并发编程》学习笔记
    Clojure学习笔记(一)——介绍、安装和语法
    Ubuntu配置pyethapp
    no leveldbjni64-1.8 in java.library.path
    Merkle Patricia Tree (MPT) 树详解
    Ubuntu下配置和编译cpp-ethereum客户端
    conda安装python库出现ssl error
  • 原文地址:https://www.cnblogs.com/honpey/p/9822961.html
Copyright © 2020-2023  润新知