Linux 网络流量控制

1流量控制

  • UP状态时, 会调用dev_activate设置设备流量控制函数

void dev_activate(struct net_device *dev)

{

if (dev->qdisc == &noop_qdisc)

 /*为每个发送队列设置默认的流量控制接口 */

  •  
  • 激活每个队列流量控制 */

netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog);

if (dev_ingress_queue(dev))

           transition_one_qdisc(dev, dev_ingress_queue(dev), NULL);

  •  

 

1.1流量控制初始化

static void attach_default_qdiscs(struct net_device *dev)

  •  

  /*单队列流量控制 */

  if (!netif_is_multiqueue(dev) || dev->tx_queue_len == 0) {

            netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);

            dev->qdisc = txq->qdisc_sleeping;

            atomic_inc(&dev->qdisc->refcnt);

  } else {

    多队列流量控制,root discs设置为mq_qdisc_ops */

            qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);

            if (qdisc) {

                     qdisc->ops->attach(qdisc);

                     dev->qdisc = qdisc;

            }

  }

  •  

truct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,

                              struct Qdisc_ops *ops, unsigned int parentid)

  •  

  struct Qdisc *sch;

       表示一个流量控制规则 */

  sch = qdisc_alloc(dev_queue, ops);

  if (IS_ERR(sch))

            goto errout;

  sch->parent = parentid;

  /*初始化流量控制规则 */

  if (!ops->init || ops->init(sch, NULL) == 0)

            return sch;

  qdisc_destroy(sch);

  •  

  return NULL;

  •  

 

1.2 mq_init 函数

sstatic int mq_init(struct Qdisc *sch, struct nlattr *opt)

  •  

  struct net_device *dev = qdisc_dev(sch);

  struct mq_sched *priv = qdisc_priv(sch);

  struct netdev_queue *dev_queue;

  struct Qdisc *qdisc;

  unsigned int ntx;

  为根流量控制初始化函数 */

  if (sch->parent != TC_H_ROOT)

            return -EOPNOTSUPP;

  /*一定是多队列 */

  if (!netif_is_multiqueue(dev))

            return -EOPNOTSUPP;

  为每个队列分配流量控制 */

  /* pre-allocate qdiscs, attachment can't fail */

  priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),

                            GFP_KERNEL);

  if (priv->qdiscs == NULL)

            return -ENOMEM;

  /*依次设置流量控制规则为pfifo_fast_ops */

  for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {

            dev_queue = netdev_get_tx_queue(dev, ntx);

            /*这里递归调用qdisc_create_dflt函数 */

            qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops,

                                          TC_H_MAKE(TC_H_MAJ(sch->handle),

                                                     TC_H_MIN(ntx + 1)));

            if (qdisc == NULL)

                     goto err;

            priv->qdiscs[ntx] = qdisc;

            qdisc->flags |= TCQ_F_ONETXQUEUE;

  }

  sch->flags |= TCQ_F_MQROOT;

  return 0;

 

  •  

  mq_destroy(sch);

  return -ENOMEM;

  •  

 

1.3 pfifo_fast_init函数

static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)

  •  

  int prio;

  struct pfifo_fast_priv *priv = qdisc_priv(qdisc);

  • 每个发送队列到流量控制又维护三个链表,根据优先级映射到对应链表 */

  for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)

            skb_queue_head_init(band2list(priv, prio));

  /* Can by-pass the queue discipline */

  qdisc->flags |= TCQ_F_CAN_BYPASS;

  return 0;

  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值