免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3818 | 回复: 3
打印 上一主题 下一主题

[网络子系统] skb中的priority怎么用的? [复制链接]

求职 : 通讯/电信开
论坛徽章:
2
2015亚冠之鹿岛鹿角
日期:2015-07-08 11:58:2615-16赛季CBA联赛之佛山
日期:2015-12-21 17:28:04
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-11-02 20:18 |只看该作者 |倒序浏览
请教各位前辈,这是我刚才看到的ip包的tos字段与skb的priority之间的关系,我的问题是系统后面是怎么用这个字段完成什么功能的,具体代码在哪儿。如蒙回复不甚感激。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
2 [报告]
发表于 2015-11-03 12:24 |只看该作者
tx路径上qdisc根据skb优先级enque/deque的时候使用。
最简单的可以参考net/sched/sch_prio.c的实现。

求职 : 通讯/电信开
论坛徽章:
2
2015亚冠之鹿岛鹿角
日期:2015-07-08 11:58:2615-16赛季CBA联赛之佛山
日期:2015-12-21 17:28:04
3 [报告]
发表于 2015-11-03 15:09 |只看该作者
非常感谢您的回复,我这就来看看,不甚感激啊回复 2# nswcfd


   

求职 : 通讯/电信开
论坛徽章:
2
2015亚冠之鹿岛鹿角
日期:2015-07-08 11:58:2615-16赛季CBA联赛之佛山
日期:2015-12-21 17:28:04
4 [报告]
发表于 2015-11-03 15:58 |只看该作者
各位兄弟姐妹,经过上面的兄弟的提醒,我找到了PFIFO_FAST流控算法,目前是默认的流控算法,用到了skb->priority字段,给大家一个参考,共同进步。感谢Chinaunix
  1. 5. 流控算法的具体实现

  2. 5.1 PFIFO_FAST

  3. PFIFO_FAST是缺省的流控算法,网卡初始化时就是设置该算法为网卡的流控算法,算法比较简单,就
  4. 在net/sched/sch_generic.c中定义了,没在单独文件中定义。

  5. 5.1.1 操作结构定义
  6. #define PFIFO_FAST_BANDS 3
  7. static struct Qdisc_ops pfifo_fast_ops = {
  8. .id  = "pfifo_fast",
  9. // 私有数据是3个skb数据包链表头
  10. .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
  11. .enqueue = pfifo_fast_enqueue,
  12. .dequeue = pfifo_fast_dequeue,
  13. .requeue = pfifo_fast_requeue,
  14. .init  = pfifo_fast_init,
  15. .reset  = pfifo_fast_reset,
  16. .dump  = pfifo_fast_dump,
  17. .owner  = THIS_MODULE,
  18. };

  19. 该算法中, 数据队列是3个, 流控算法就是将数据包输入特定的队列, 从特定队列中取数据包。

  20. 5.1.2 初始化

  21. static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
  22. {
  23. int prio;
  24. // qdisc私有数据指针, 数据包链表头
  25. struct sk_buff_head *list = qdisc_priv(qdisc);
  26. // 初始化3个链表头
  27. for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
  28.   skb_queue_head_init(list + prio);
  29. return 0;
  30. }
  31. 5.1.3 入队

  32. static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
  33. {
  34. // 根据数据包的优先级参数挑一个队列头准备将数据包插入该队列
  35. struct sk_buff_head *list = prio2list(skb, qdisc);
  36. // 如果当前队列中的数据包数量小于网卡设备允许的输出队列的数量
  37. // 则将该数据包插入该队列
  38. if (skb_queue_len(list) < qdisc->dev->tx_queue_len) {
  39.   qdisc->q.qlen++;
  40.   return __qdisc_enqueue_tail(skb, qdisc, list);
  41. }
  42. // 否则的话丢弃该数据包
  43. return qdisc_drop(skb, qdisc);
  44. }
  45. // 选队列处理
  46. static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
  47.           struct Qdisc *qdisc)
  48. {
  49. // qdisc私有数据指针, 数据包链表头
  50. struct sk_buff_head *list = qdisc_priv(qdisc);
  51. // 根据数据包的优先权值确定队列头偏移值
  52. // skb->priority是个32位整数, 只使用最后4位
  53. return list + prio2band[skb->priority & TC_PRIO_MAX];
  54. }
  55. // 优先权值到队列号的变换数组, 该数组体现算法内容, 通过修改该数组可以调整算法效果
  56. // 该数组定义中, 优先值(低4位)为1,2,3,5时使用2号队列, 优先值(低4位)为6,7时使用0号
  57. // 队列, 其他值为1号队列
  58. // 在普通情况下skb->priority都是0, 所有应该只使用了1号队列
  59. // 这个数组实际是根据RFC1349中定义的TOS类型值定义的, 在该RFC中TOS就是只有4位有效
  60. static const u8 prio2band[TC_PRIO_MAX+1] =
  61. { 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };

  62. 5.1.4 出队

  63. static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
  64. {
  65. int prio;
  66. struct sk_buff_head *list = qdisc_priv(qdisc);
  67. // 循环3个队列
  68. for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
  69. // 如果队列非空, 返回队列头的那个数据包
  70.   if (!skb_queue_empty(list + prio)) {
  71.    qdisc->q.qlen--;
  72.    return __qdisc_dequeue_head(qdisc, list + prio);
  73.   }
  74. }
  75. return NULL;
  76. }

  77. 由此可见, 0号队列有最高优先级, 2号队列优先级最低, 只有高优先级队列中的数据都发送完后才发
  78. 送低优先级队列中的数据。

  79. 5.1.5 重入队

  80. static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
  81. {
  82. // 队列长度递增
  83. qdisc->q.qlen++;
  84. // 使用标准重入队函数将数据插回队列链表
  85. return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
  86. }

  87. 5.1.6 复位
  88. static void pfifo_fast_reset(struct Qdisc* qdisc)
  89. {
  90. int prio;
  91. struct sk_buff_head *list = qdisc_priv(qdisc);
  92. // 释放三个队列链表中的所有数据包
  93. for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
  94.   __qdisc_reset_queue(qdisc, list + prio);
  95. // 计数清零
  96. qdisc->qstats.backlog = 0;
  97. qdisc->q.qlen = 0;
  98. }

  99. 5.1.7 输出

  100. 输出当前算法的内容信息, 由于PFIFO_FAST算法核心就是prio2band数组, 因此就是将该数组内容输
  101. 出到数据包供用户空间获取。
  102. static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
  103. {
  104. // TC优先权数组结构
  105. struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
  106. // 将当前prio2band数组内容拷贝到选项数据中
  107. memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
  108. // 将结构作为路由属性复制到数据包中供返回
  109. RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
  110. return skb->len;
  111. rtattr_failure:
  112. return -1;
  113. }

  114. ...... 待续 ......

  115. 发表于: 2007-07-28,修改于: 2007-07-29 15:30,已浏览3052次,有评论2条 推荐 投诉
  116.         网友: burning423         时间:2007-09-21 08:53:33 IP地址:218.108.51.★
  117.        

  118. 5.1.2 初始化



  119. static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)

  120. {

  121. int prio;

  122. // qdisc私有数据指针, 数据包链表头

  123. struct sk_buff_head *list = qdisc_priv(qdisc);

  124. ........................................



  125. struct sk_buff_head *list = qdisc_priv(qdisc);这语句是怎样得到qdisc的私有数据的?我看了qdisc_priv(qdisc)函数的定义,可还是不是很明白.你能否给我解释一下?谢谢了..刚开始看内核的东西....


  126.         网友: yfydz         时间:2007-09-22 21:44:39 IP地址:123.116.100.★
  127.        

  128. 每种qdisc定义都包括基本的Qdisc结构和后面一些参数, 大小由prive_size指定, 那些参数就是该qdisc的私有数据, 获取私有数据的指针就是从Qdisc起始位置移动标准Qdisc大小就是了
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP