Chinaunix首页 | 论坛 | 博客
  • 博客访问: 434477
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2014-02-14 09:27:06

// pfifo_fast 这个discipiline里面有skb队列数组,优先级从大到小,队列下标分别是0,1,2
// enqueue 根据skb的priority, 使用prio2band数组找出skb对应的队列
// dequeue 优先选择下标为0的skb队列,0队列变空后选择1队列,1队列变空后选择2队列

// 同样优先级的skb,实现fifo策略, 入队时插入队列尾部,出队时从头部出队

static const u8 prio2band[TC_PRIO_MAX + 1] = { //skb优先级与队列下标的关系
 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1
};

/* 3-band FIFO queue: old style, but should be a bit faster than
   generic prio+fifo combination.
 */

#define PFIFO_FAST_BANDS 3

/*
 * Private data for a pfifo_fast scheduler containing:
 *  - queues for the three band
 *  - bitmap indicating which of the bands contain skbs
 */
struct pfifo_fast_priv {
 u32 bitmap;
 struct sk_buff_head q[PFIFO_FAST_BANDS];
};

/*
 * Convert a bitmap to the first band number where an skb is queued, where:
 *  bitmap=0 means there are no skbs on any band.
 *  bitmap=1 means there is an skb on band 0.
 * bitmap=7 means there are skbs on all 3 bands, etc.
 */
static const int bitmap2band[] = {-1, 0, 1, 0, 2, 0, 1, 0};   // bitmap与当前有skb的最高优先级队列下标之间的关系

static inline struct sk_buff_head *band2list(struct pfifo_fast_priv *priv,
          int band)
{
 return priv->q + band;
}

static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc)
{
 if (skb_queue_len(&qdisc->q) < qdisc_dev(qdisc)->tx_queue_len) { //队列不超限
  int band = prio2band[skb->priority & TC_PRIO_MAX];  //根据优先级确定放入3个q中的哪一个
  struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
  struct sk_buff_head *list = band2list(priv, band);

  priv->bitmap |= (1 << band);  // 更新bitmap
  qdisc->q.qlen++;
  return __qdisc_enqueue_tail(skb, qdisc, list);   // 插入目标队列尾部
 }

 return qdisc_drop(skb, qdisc);
}

static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
{
 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
 int band = bitmap2band[priv->bitmap];

 if (likely(band >= 0)) {
  struct sk_buff_head *list = band2list(priv, band);   // 根据bitmap当前的状况,确定从哪个队列头部取skb
  struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list);

  qdisc->q.qlen--;
  if (skb_queue_empty(list))
   priv->bitmap &= ~(1 << band);  // 更新bitmap

  return skb;
 }

 return NULL;
}

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;   // 设置BYPASS标志,__dev_queue_xmit里面发现有这个标志,会尝试直接发送,而不入队
 return 0;
}

struct Qdisc_ops pfifo_fast_ops __read_mostly = {
 .id  = "pfifo_fast",
 .priv_size = sizeof(struct pfifo_fast_priv),
 .enqueue = pfifo_fast_enqueue,
 .dequeue = pfifo_fast_dequeue,
 .peek  = pfifo_fast_peek,
 .init  = pfifo_fast_init,
 .reset  = pfifo_fast_reset,
 .dump  = pfifo_fast_dump,
 .owner  = THIS_MODULE,
};
EXPORT_SYMBOL(pfifo_fast_ops);

阅读(2030) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~