qdisc.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package netlink
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. const (
  7. HANDLE_NONE = 0
  8. HANDLE_INGRESS = 0xFFFFFFF1
  9. HANDLE_CLSACT = HANDLE_INGRESS
  10. HANDLE_ROOT = 0xFFFFFFFF
  11. PRIORITY_MAP_LEN = 16
  12. )
  13. const (
  14. HANDLE_MIN_INGRESS = 0xFFFFFFF2
  15. HANDLE_MIN_EGRESS = 0xFFFFFFF3
  16. )
  17. type Qdisc interface {
  18. Attrs() *QdiscAttrs
  19. Type() string
  20. }
  21. // QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link,
  22. // has a handle, a parent and a refcnt. The root qdisc of a device should
  23. // have parent == HANDLE_ROOT.
  24. type QdiscAttrs struct {
  25. LinkIndex int
  26. Handle uint32
  27. Parent uint32
  28. Refcnt uint32 // read only
  29. }
  30. func (q QdiscAttrs) String() string {
  31. return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt)
  32. }
  33. func MakeHandle(major, minor uint16) uint32 {
  34. return (uint32(major) << 16) | uint32(minor)
  35. }
  36. func MajorMinor(handle uint32) (uint16, uint16) {
  37. return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF)
  38. }
  39. func HandleStr(handle uint32) string {
  40. switch handle {
  41. case HANDLE_NONE:
  42. return "none"
  43. case HANDLE_INGRESS:
  44. return "ingress"
  45. case HANDLE_ROOT:
  46. return "root"
  47. default:
  48. major, minor := MajorMinor(handle)
  49. return fmt.Sprintf("%x:%x", major, minor)
  50. }
  51. }
  52. func Percentage2u32(percentage float32) uint32 {
  53. // FIXME this is most likely not the best way to convert from % to uint32
  54. if percentage == 100 {
  55. return math.MaxUint32
  56. }
  57. return uint32(math.MaxUint32 * (percentage / 100))
  58. }
  59. // PfifoFast is the default qdisc created by the kernel if one has not
  60. // been defined for the interface
  61. type PfifoFast struct {
  62. QdiscAttrs
  63. Bands uint8
  64. PriorityMap [PRIORITY_MAP_LEN]uint8
  65. }
  66. func (qdisc *PfifoFast) Attrs() *QdiscAttrs {
  67. return &qdisc.QdiscAttrs
  68. }
  69. func (qdisc *PfifoFast) Type() string {
  70. return "pfifo_fast"
  71. }
  72. // Prio is a basic qdisc that works just like PfifoFast
  73. type Prio struct {
  74. QdiscAttrs
  75. Bands uint8
  76. PriorityMap [PRIORITY_MAP_LEN]uint8
  77. }
  78. func NewPrio(attrs QdiscAttrs) *Prio {
  79. return &Prio{
  80. QdiscAttrs: attrs,
  81. Bands: 3,
  82. PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
  83. }
  84. }
  85. func (qdisc *Prio) Attrs() *QdiscAttrs {
  86. return &qdisc.QdiscAttrs
  87. }
  88. func (qdisc *Prio) Type() string {
  89. return "prio"
  90. }
  91. // Htb is a classful qdisc that rate limits based on tokens
  92. type Htb struct {
  93. QdiscAttrs
  94. Version uint32
  95. Rate2Quantum uint32
  96. Defcls uint32
  97. Debug uint32
  98. DirectPkts uint32
  99. }
  100. func NewHtb(attrs QdiscAttrs) *Htb {
  101. return &Htb{
  102. QdiscAttrs: attrs,
  103. Version: 3,
  104. Defcls: 0,
  105. Rate2Quantum: 10,
  106. Debug: 0,
  107. DirectPkts: 0,
  108. }
  109. }
  110. func (qdisc *Htb) Attrs() *QdiscAttrs {
  111. return &qdisc.QdiscAttrs
  112. }
  113. func (qdisc *Htb) Type() string {
  114. return "htb"
  115. }
  116. // Netem is a classless qdisc that rate limits based on tokens
  117. type NetemQdiscAttrs struct {
  118. Latency uint32 // in us
  119. DelayCorr float32 // in %
  120. Limit uint32
  121. Loss float32 // in %
  122. LossCorr float32 // in %
  123. Gap uint32
  124. Duplicate float32 // in %
  125. DuplicateCorr float32 // in %
  126. Jitter uint32 // in us
  127. ReorderProb float32 // in %
  128. ReorderCorr float32 // in %
  129. CorruptProb float32 // in %
  130. CorruptCorr float32 // in %
  131. }
  132. func (q NetemQdiscAttrs) String() string {
  133. return fmt.Sprintf(
  134. "{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}",
  135. q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter,
  136. )
  137. }
  138. type Netem struct {
  139. QdiscAttrs
  140. Latency uint32
  141. DelayCorr uint32
  142. Limit uint32
  143. Loss uint32
  144. LossCorr uint32
  145. Gap uint32
  146. Duplicate uint32
  147. DuplicateCorr uint32
  148. Jitter uint32
  149. ReorderProb uint32
  150. ReorderCorr uint32
  151. CorruptProb uint32
  152. CorruptCorr uint32
  153. }
  154. func (qdisc *Netem) Attrs() *QdiscAttrs {
  155. return &qdisc.QdiscAttrs
  156. }
  157. func (qdisc *Netem) Type() string {
  158. return "netem"
  159. }
  160. // Tbf is a classless qdisc that rate limits based on tokens
  161. type Tbf struct {
  162. QdiscAttrs
  163. Rate uint64
  164. Limit uint32
  165. Buffer uint32
  166. Peakrate uint64
  167. Minburst uint32
  168. // TODO: handle other settings
  169. }
  170. func (qdisc *Tbf) Attrs() *QdiscAttrs {
  171. return &qdisc.QdiscAttrs
  172. }
  173. func (qdisc *Tbf) Type() string {
  174. return "tbf"
  175. }
  176. // Ingress is a qdisc for adding ingress filters
  177. type Ingress struct {
  178. QdiscAttrs
  179. }
  180. func (qdisc *Ingress) Attrs() *QdiscAttrs {
  181. return &qdisc.QdiscAttrs
  182. }
  183. func (qdisc *Ingress) Type() string {
  184. return "ingress"
  185. }
  186. // GenericQdisc qdiscs represent types that are not currently understood
  187. // by this netlink library.
  188. type GenericQdisc struct {
  189. QdiscAttrs
  190. QdiscType string
  191. }
  192. func (qdisc *GenericQdisc) Attrs() *QdiscAttrs {
  193. return &qdisc.QdiscAttrs
  194. }
  195. func (qdisc *GenericQdisc) Type() string {
  196. return qdisc.QdiscType
  197. }