Linux kernel traffic control (15)

2011-01-10  来源:本站原创  分类:Internet  人气:150 

Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited.
msn: [email protected]
Source: http://yfydz.cublog.cn

5.15. Qdisc  The netlink control  

  The card's user-level operation control Qdisc by  rtnetlink  Interface between user and kernel space communication  : rtnetlink_link, rtnetlink  Specifically for the netlink interface to the routing control  .
/* include/linux/rtnetlink.h */
struct rtnetlink_link
{
//   The two member functions, operations, and output
 int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr);
 int (*dumpit)(struct sk_buff *, struct netlink_callback *cb);
};

//   Global array, specifically in the   net/core/rtnetlink.c  Defined
extern struct rtnetlink_link * rtnetlink_links[NPROTO];

  Two members of which are defined as follows  :
/* net/core/rtnetlink.c */

void __init rtnetlink_init(void)
{
......
 rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table;
 rtnetlink_links[PF_PACKET] = link_rtnetlink_table;
......
}

  One is an array link_rtnetlink_table  ,   Defined as  :
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
{
//   The basic elements of the array to handle routing  ,   ARP neighbors and other related information  ,   These are not paper focuses  ,
//   Only Qdisc related operations are also defined in this array
 [RTM_GETLINK     - RTM_BASE] = { .doit   = rtnl_getlink,
      .dumpit = rtnl_dump_ifinfo  },
 [RTM_SETLINK     - RTM_BASE] = { .doit   = rtnl_setlink   },
 [RTM_GETADDR     - RTM_BASE] = { .dumpit = rtnl_dump_all  },
 [RTM_GETROUTE    - RTM_BASE] = { .dumpit = rtnl_dump_all  },
 [RTM_NEWNEIGH    - RTM_BASE] = { .doit   = neigh_add   },
 [RTM_DELNEIGH    - RTM_BASE] = { .doit   = neigh_delete   },
 [RTM_GETNEIGH    - RTM_BASE] = { .dumpit = neigh_dump_info  },
#ifdef CONFIG_FIB_RULES
 [RTM_NEWRULE     - RTM_BASE] = { .doit   = fib_nl_newrule  },
 [RTM_DELRULE     - RTM_BASE] = { .doit   = fib_nl_delrule  },
#endif
 [RTM_GETRULE     - RTM_BASE] = { .dumpit = rtnl_dump_all  },
 [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info  },
 [RTM_SETNEIGHTBL - RTM_BASE] = { .doit   = neightbl_set   },
};

5.15.1   Initialization  

  Initialization process is to define the corresponding tc  qdisc  And the class action command handler  :
/* net/sched/sch_api.c */
static int __init pktsched_init(void)
{
 struct rtnetlink_link *link_p;
//   The clock scheduling flow control initialization
#ifdef CONFIG_NET_SCH_CLK_CPU
 if (psched_calibrate_clock() < 0)
  return -1;
#elif defined(CONFIG_NET_SCH_CLK_JIFFIES)
 psched_tick_per_us = HZ<<PSCHED_JSCALE;
 psched_us_per_tick = 1000000;
#endif
//   Use  PF_UNSPEC(0)  No. rtnetlink_links element is used as a  QDISC  Interface operation
 link_p = rtnetlink_links[PF_UNSPEC];
 /* Setup rtnetlink links. It is made here to avoid
    exporting large number of public symbols.
  */
// link_p  The array will point to link_rtnetlink_table
 if (link_p) {
//   Related elements of the array assignment mid-stream control
// Qdisc  Operation, that is, the corresponding  tc qdisc add/modify  And other operations
  link_p[RTM_NEWQDISC-RTM_BASE].doit = tc_modify_qdisc;
//   Remove / extract  Qdisc  Operation
  link_p[RTM_DELQDISC-RTM_BASE].doit = tc_get_qdisc;
  link_p[RTM_GETQDISC-RTM_BASE].doit = tc_get_qdisc;
//   Get Qdisc information  ,   Is the corresponding  tc qdisc show
  link_p[RTM_GETQDISC-RTM_BASE].dumpit = tc_dump_qdisc;
// class  Operation, that is, the corresponding  tc class add/delete/modify/get  And other operations, in the subsequent analysis of the article
  link_p[RTM_NEWTCLASS-RTM_BASE].doit = tc_ctl_tclass;
  link_p[RTM_DELTCLASS-RTM_BASE].doit = tc_ctl_tclass;
  link_p[RTM_GETTCLASS-RTM_BASE].doit = tc_ctl_tclass;
  link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_tclass;
 }
//   Registration FIFO flow control handle  ,   This is the basic flow control methods LAN equipment, there must be the default
 register_qdisc(&pfifo_qdisc_ops);
 register_qdisc(&bfifo_qdisc_ops);
 proc_net_fops_create("psched", 0, &psched_fops);
 return 0;
}

5.15.2   Related operations  

 Qdisc used in the following function operating functions can be seen first in this series  ,   Section 4  

5.15.2.1   Create / Modify  qdisc

/*
   Create/change qdisc.
 */
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
 struct tcmsg *tcm;
 struct rtattr **tca;
 struct net_device *dev;
 u32 clid;
 struct Qdisc *q, *p;
 int err;
replay:
 /* Reinit, just in case something touches this. */
// tc  Pointers to messages
 tcm = NLMSG_DATA(n);
 tca = arg;
// class id
 clid = tcm->tcm_parent;
 q = p = NULL;
//   The tc command for the NIC
 if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
  return -ENODEV;
 if (clid) {
//   ID specifies the type of situation
  if (clid != TC_H_ROOT) {
//   If not the root node
   if (clid != TC_H_INGRESS) {
//   Non-ingress nodes  ,   According to the high class ID  16  Find Qdisc bit node
    if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
     return -ENOENT;
//   Leaf node for node p  ,   Calls  p->ops->cl_ops->leaf()  Function
    q = qdisc_leaf(p, clid);
   } else { /*ingress */
//   Ingress flow control equipment used
    q = dev->qdisc_ingress;
   }
  } else {
//   Dirty root situation is used to control equipment  qdisc_sleeping
   q = dev->qdisc_sleeping;
  }
  /* It may be default qdisc, ignore it */
//   If you find a handle for the Qdisc  0,   Give up  q
  if (q && q->handle == 0)
   q = NULL;
  if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) {
//   Node not found Qdisc  ,   Or not specified in the message handle value tc  ,   Or find Qdisc handle and  tc  Message
//   Handle different
   if (tcm->tcm_handle) {
// TC  Handle is specified
//   If there is, but not the update command Qdisc  ,   Returns an error object
    if (q && !(n->nlmsg_flags&NLM_F_REPLACE))
     return -EEXIST;
// TC  Can not handle 16-bit low-  0
    if (TC_H_MIN(tcm->tcm_handle))
     return -EINVAL;
//   According to TC to find the device handle  Qdisc,   Can not find the words to jump to action to create a new node
    if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
     goto create_n_graft;
//   Find the exclusion of signs, but set NLM_F_EXCL  ,   Returns an error object
    if (n->nlmsg_flags&NLM_F_EXCL)
     return -EEXIST;
//   Comparison of algorithm TC command name and  Qdisc  Name of the same algorithm
    if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
     return -EINVAL;
//   Checking algorithm loop condition occurs, p is  clid  Found  Qdisc
    if (q == p ||
        (p && check_loop(q, p, 0)))
     return -ELOOP;
//   Qdisc found an effective new  ,   Go to grafting
    atomic_inc(&q->refcnt);
    goto graft;
   } else {
//   TC did not specify the handle  ,   If you do not find Qdisc, jump to create a new node
    if (q == NULL)
     goto create_n_graft;
    /* This magic test requires explanation.
     *
     *   We know, that some child q is already
     *   attached to this parent and have choice:
     *   either to change it or to create/graft new one.
     *
     *   1. We are allowed to create/graft only
     *   if CREATE and REPLACE flags are set.
     *
     *   2. If EXCL is set, requestor wanted to say,
     *   that qdisc tcm_handle is not expected
     *   to exist, so that we choose create/graft too.
     *
     *   3. The last case is when no flags are set.
     *   Alas, it is sort of hole in API, we
     *   cannot decide what to do unambiguously.
     *   For now we select create/graft, if
     *   user gave KIND, which does not match existing.
     */
//   Check whether the signs of conflict, Qdisc name is correct
    if ((n->nlmsg_flags&NLM_F_CREATE) &&
        (n->nlmsg_flags&NLM_F_REPLACE) &&
        ((n->nlmsg_flags&NLM_F_EXCL) ||
         (tca[TCA_KIND-1] &&
          rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))))
     goto create_n_graft;
   }
  }
 } else {
//   If you do not specify the type of ID, from the  tc  Message to find the handle  Qdisc
  if (!tcm->tcm_handle)
   return -EINVAL;
  q = qdisc_lookup(dev, tcm->tcm_handle);
 }
//   Here are Qdisc modify operation
 /* Change qdisc parameters */
//   Node not found Qdisc  ,   Return error
 if (q == NULL)
  return -ENOENT;
//   Node to find Qdisc  ,   But the set  NLM_F_EXCL(  Exclusion  )  Sign and return an error object
 if (n->nlmsg_flags&NLM_F_EXCL)
  return -EEXIST;
//   Check the name of the node found Qdisc and  tc  Match specified
 if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
  return -EINVAL;
//   Modify Qdisc parameters
 err = qdisc_change(q, tca);
 if (err == 0)
  qdisc_notify(skb, n, clid, NULL, q);
 return err;
create_n_graft:
//   Create a new node Qdisc
//   If the command does not create a logo TC  ,   Return error
 if (!(n->nlmsg_flags&NLM_F_CREATE))
  return -ENOENT;
//   Create a new node Qdisc
 if (clid == TC_H_INGRESS)
  q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
        else
  q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
 if (q == NULL) {
//   Creation failed, if not  EAGAIN(  Come again  ),   Return failure
  if (err == -EAGAIN)
   goto replay;
  return err;
 }
graft:
//   Grafting
 if (1) {
  struct Qdisc *old_q = NULL;
//   The grafting operation, returns the old node
  err = qdisc_graft(dev, p, clid, q, &old_q);
  if (err) {
//   Failure, the release of the newly created  Qdisc
   if (q) {
    spin_lock_bh(&dev->queue_lock);
    qdisc_destroy(q);
    spin_unlock_bh(&dev->queue_lock);
   }
   return err;
  }
// Qdisc  Notice
  qdisc_notify(skb, n, clid, old_q, q);
  if (old_q) {
//   If there are nodes in the old Qdisc  ,   Release of
   spin_lock_bh(&dev->queue_lock);
   qdisc_destroy(old_q);
   spin_unlock_bh(&dev->queue_lock);
  }
 }
 return 0;
}

5.15.2.2   Get / Delete  qdisc
/*
 * Delete/get qdisc.
 */
static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
 struct tcmsg *tcm = NLMSG_DATA(n);
 struct rtattr **tca = arg;
 struct net_device *dev;
// class id
 u32 clid = tcm->tcm_parent;
 struct Qdisc *q = NULL;
 struct Qdisc *p = NULL;
 int err;
//   TC parameter based on index card to find network card device
 if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
  return -ENODEV;
//   ID or by category  TC  Handle search Qdisc, similar to the above functions
 if (clid) {
  if (clid != TC_H_ROOT) {
   if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
    if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
     return -ENOENT;
    q = qdisc_leaf(p, clid);
   } else { /* ingress */
    q = dev->qdisc_ingress;
                        }
  } else {
   q = dev->qdisc_sleeping;
  }
  if (!q)
   return -ENOENT;
  if (tcm->tcm_handle && q->handle != tcm->tcm_handle)
   return -EINVAL;
 } else {
  if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
   return -ENOENT;
 }
//   Check the name and found Qdisc  TC  Whether specified in the command line
 if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], q->ops->id))
  return -EINVAL;
//   Remove Qdisc operation
 if (n->nlmsg_type == RTM_DELQDISC) {
//   Must specify the type of  ID
  if (!clid)
   return -EINVAL;
//   If you find the handle for the Qdisc  0,   Return error
  if (q->handle == 0)
   return -ENOENT;
//   The Qdisc grafting  ,   New node is NULL, will replace the leaf node  NULL,   The original leaf node is removed
//   Return to the original leaf node  q
  if ((err = qdisc_graft(dev, p, clid, NULL, &q)) != 0)
   return err;
  if (q) {
//   The release of the original leaf node
   qdisc_notify(skb, n, clid, q, NULL);
   spin_lock_bh(&dev->queue_lock);
   qdisc_destroy(q);
   spin_unlock_bh(&dev->queue_lock);
  }
 } else {
//   Non-deletion, notices about  , q  Parameters as the return obtained Qdisc
  qdisc_notify(skb, n, clid, NULL, q);
 }
 return 0;
}

//   Notification messages sent Qdisc  , new  After dealing with the new node information Qdisc  , old  Node information before dealing with the old
static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,
   u32 clid, struct Qdisc *old, struct Qdisc *new)
{
 struct sk_buff *skb;
 u32 pid = oskb ? NETLINK_CB(oskb).pid : 0;
//   Netlink packet distribution
 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 if (!skb)
  return -ENOBUFS;
 if (old && old->handle) {
//   Fill the information the old Qdisc
  if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0)
   goto err_out;
 }
 if (new) {
//   Fill the new information Qdisc
  if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
   goto err_out;
 }
//   Send packets
 if (skb->len)
  return rtnetlink_send(skb, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
err_out:
//   Error handling, the release of data packets
 kfree_skb(skb);
 return -EINVAL;
}

5.15.2.3   Output card qdisc parameters  

static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
{
 int idx, q_idx;
 int s_idx, s_q_idx;
 struct net_device *dev;
 struct Qdisc *q;
//   Start index cards
 s_idx = cb->args[0];
//   Start Qdisc index
 s_q_idx = q_idx = cb->args[1];
 read_lock(&dev_base_lock);
//   Through all cards
 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
//   Provided the index value is less than the initial index value, skip
//   This index and the index card should have nothing to
  if (idx < s_idx)
   continue;
//   The index value is greater than the initial index value provided will be starting  Qdisc  Clear Index
  if (idx > s_idx)
   s_q_idx = 0;
  read_lock(&qdisc_tree_lock);
// q_idx  Cleared, so there was no need in front of the assignment in the initialization
  q_idx = 0;
//   Traverse all the LAN equipment  Qdisc
  list_for_each_entry(q, &dev->qdisc_list, list) {
//   The current index is less than the starting Qdisc  Qdisc  Index, skip
//   So when  idx > s_idx  When, s_q_idx = 0, only with the first  Qdisc
//   The time when the idx == s_idx  ,   Processing from the beginning of all s_q_idx  Qdisc
   if (q_idx < s_q_idx) {
    q_idx++;
    continue;
   }
//   Packet of information to fill Qdisc
   if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
       cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
    read_unlock(&qdisc_tree_lock);
    goto done;
   }
   q_idx++;
  }
  read_unlock(&qdisc_tree_lock);
 }
done:
 read_unlock(&dev_base_lock);
//   Returns the number of processing all card numbers and Qdisc
 cb->args[0] = idx;
 cb->args[1] = q_idx;
 return skb->len;
}

//   Information to fill Qdisc  skb  Packet
static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
    u32 pid, u32 seq, u16 flags, int event)
{
 struct tcmsg *tcm;
 struct nlmsghdr  *nlh;
 unsigned char  *b = skb->tail;
 struct gnet_dump d;
// skb  Netlink header in the position of
 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
// TC  Head position information data
 tcm = NLMSG_DATA(nlh);
//   Fill the information parameters TC
 tcm->tcm_family = AF_UNSPEC;
 tcm->tcm__pad1 = 0;
 tcm->tcm__pad2 = 0;
 tcm->tcm_ifindex = q->dev->ifindex;
 tcm->tcm_parent = clid;
 tcm->tcm_handle = q->handle;
 tcm->tcm_info = atomic_read(&q->refcnt);
 RTA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
// Qdisc  The output function
 if (q->ops->dump && q->ops->dump(q, skb) < 0)
  goto rtattr_failure;
 q->qstats.qlen = q->q.qlen;
//   Ready to begin copying statistics
 if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
   TCA_XSTATS, q->stats_lock, &d) < 0)
  goto rtattr_failure;
//   Output Statistics
 if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
  goto rtattr_failure;
//   Copy of the basic statistical information, statistical information flow control rate  ,   Queue Statistics
 if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
#ifdef CONFIG_NET_ESTIMATOR
     gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
#endif
     gnet_stats_copy_queue(&d, &q->qstats) < 0)
  goto rtattr_failure;
//   End of the sealing operation
 if (gnet_stats_finish_copy(&d) < 0)
  goto rtattr_failure;

 nlh->nlmsg_len = skb->tail - b;
 return skb->len;
nlmsg_failure:
rtattr_failure:
 skb_trim(skb, b - skb->data);
 return -1;
}

5.16 Qdisc  Summary 

  About flow control  (Qdisc)  Analysis of this come to an end, the back will continue to analyze classification  (class),   Filter  (filter)  And action  (action)  The process  .

......   Continued   ......
相关文章
  • Linux kernel traffic control (15) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.15. Qdis

  • Linux kernel traffic control (18) 2011-01-10

    Linux kernel traffic control (18) Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source:

  • Linux kernel traffic control (1) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 1. Pr

  • Linux kernel traffic control (24) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 8.10 mirre

  • Linux kernel traffic control (16) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 6. Class a

  • Linux kernel traffic control (2) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5. Co

  • Linux kernel traffic control (3) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.2 F

  • Linux kernel traffic control (4) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.4 P

  • Linux kernel traffic control (11) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected]ail.com Source: http://yfydz.cublog.cn 5.11

  • Linux kernel traffic control (6) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.6 DSMARK

  • Linux kernel traffic control (7) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.7 RED(Ra

  • Linux kernel traffic control (9) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.9 ingres

  • Linux kernel traffic control (12) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.11.

  • Linux kernel traffic control (13) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.11.9 Enq

  • Linux kernel traffic control (14) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.14 CBQ(C

  • Linux kernel traffic control (17) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 7.6 tcf_pr

  • Linux kernel traffic control (22) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 8. action

  • Linux kernel traffic control (23) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 8.7 ipt Op

  • Linux kernel traffic control (5) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.5 S

  • Linux kernel traffic control (8) 2011-01-10

    Copyleft this document owned by yfydz all, the use of GPL, free to copy, reprint, reproduced keep the documents for completeness, Used for any commercial purposes is strictly prohibited. msn: [email protected] Source: http://yfydz.cublog.cn 5.8 G