github.com/vishvananda/netlink@v1.3.0/qdisc.go (about) 1 package netlink 2 3 import ( 4 "fmt" 5 "math" 6 ) 7 8 const ( 9 HANDLE_NONE = 0 10 HANDLE_INGRESS = 0xFFFFFFF1 11 HANDLE_CLSACT = HANDLE_INGRESS 12 HANDLE_ROOT = 0xFFFFFFFF 13 PRIORITY_MAP_LEN = 16 14 ) 15 const ( 16 HANDLE_MIN_INGRESS = 0xFFFFFFF2 17 HANDLE_MIN_EGRESS = 0xFFFFFFF3 18 ) 19 20 const ( 21 HORIZON_DROP_POLICY_CAP = 0 22 HORIZON_DROP_POLICY_DROP = 1 23 HORIZON_DROP_POLICY_DEFAULT = 255 24 ) 25 26 type Qdisc interface { 27 Attrs() *QdiscAttrs 28 Type() string 29 } 30 31 type QdiscStatistics ClassStatistics 32 33 // QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, 34 // has a handle, a parent and a refcnt. The root qdisc of a device should 35 // have parent == HANDLE_ROOT. 36 type QdiscAttrs struct { 37 LinkIndex int 38 Handle uint32 39 Parent uint32 40 Refcnt uint32 // read only 41 IngressBlock *uint32 42 Statistics *QdiscStatistics 43 } 44 45 func (q QdiscAttrs) String() string { 46 return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) 47 } 48 49 func MakeHandle(major, minor uint16) uint32 { 50 return (uint32(major) << 16) | uint32(minor) 51 } 52 53 func MajorMinor(handle uint32) (uint16, uint16) { 54 return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) 55 } 56 57 func HandleStr(handle uint32) string { 58 switch handle { 59 case HANDLE_NONE: 60 return "none" 61 case HANDLE_INGRESS: 62 return "ingress" 63 case HANDLE_ROOT: 64 return "root" 65 default: 66 major, minor := MajorMinor(handle) 67 return fmt.Sprintf("%x:%x", major, minor) 68 } 69 } 70 71 func Percentage2u32(percentage float32) uint32 { 72 // FIXME this is most likely not the best way to convert from % to uint32 73 if percentage == 100 { 74 return math.MaxUint32 75 } 76 return uint32(math.MaxUint32 * (percentage / 100)) 77 } 78 79 // PfifoFast is the default qdisc created by the kernel if one has not 80 // been defined for the interface 81 type PfifoFast struct { 82 QdiscAttrs 83 Bands uint8 84 PriorityMap [PRIORITY_MAP_LEN]uint8 85 } 86 87 func (qdisc *PfifoFast) Attrs() *QdiscAttrs { 88 return &qdisc.QdiscAttrs 89 } 90 91 func (qdisc *PfifoFast) Type() string { 92 return "pfifo_fast" 93 } 94 95 // Prio is a basic qdisc that works just like PfifoFast 96 type Prio struct { 97 QdiscAttrs 98 Bands uint8 99 PriorityMap [PRIORITY_MAP_LEN]uint8 100 } 101 102 func NewPrio(attrs QdiscAttrs) *Prio { 103 return &Prio{ 104 QdiscAttrs: attrs, 105 Bands: 3, 106 PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 107 } 108 } 109 110 func (qdisc *Prio) Attrs() *QdiscAttrs { 111 return &qdisc.QdiscAttrs 112 } 113 114 func (qdisc *Prio) Type() string { 115 return "prio" 116 } 117 118 // Htb is a classful qdisc that rate limits based on tokens 119 type Htb struct { 120 QdiscAttrs 121 Version uint32 122 Rate2Quantum uint32 123 Defcls uint32 124 Debug uint32 125 DirectPkts uint32 126 DirectQlen *uint32 127 } 128 129 func NewHtb(attrs QdiscAttrs) *Htb { 130 return &Htb{ 131 QdiscAttrs: attrs, 132 Version: 3, 133 Defcls: 0, 134 Rate2Quantum: 10, 135 Debug: 0, 136 DirectPkts: 0, 137 DirectQlen: nil, 138 } 139 } 140 141 func (qdisc *Htb) Attrs() *QdiscAttrs { 142 return &qdisc.QdiscAttrs 143 } 144 145 func (qdisc *Htb) Type() string { 146 return "htb" 147 } 148 149 // Netem is a classless qdisc that rate limits based on tokens 150 151 type NetemQdiscAttrs struct { 152 Latency uint32 // in us 153 DelayCorr float32 // in % 154 Limit uint32 155 Loss float32 // in % 156 LossCorr float32 // in % 157 Gap uint32 158 Duplicate float32 // in % 159 DuplicateCorr float32 // in % 160 Jitter uint32 // in us 161 ReorderProb float32 // in % 162 ReorderCorr float32 // in % 163 CorruptProb float32 // in % 164 CorruptCorr float32 // in % 165 Rate64 uint64 166 } 167 168 func (q NetemQdiscAttrs) String() string { 169 return fmt.Sprintf( 170 "{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}", 171 q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter, 172 ) 173 } 174 175 type Netem struct { 176 QdiscAttrs 177 Latency uint32 178 DelayCorr uint32 179 Limit uint32 180 Loss uint32 181 LossCorr uint32 182 Gap uint32 183 Duplicate uint32 184 DuplicateCorr uint32 185 Jitter uint32 186 ReorderProb uint32 187 ReorderCorr uint32 188 CorruptProb uint32 189 CorruptCorr uint32 190 Rate64 uint64 191 } 192 193 func (netem *Netem) String() string { 194 return fmt.Sprintf( 195 "{Latency: %v, Limit: %v, Loss: %v, Gap: %v, Duplicate: %v, Jitter: %v}", 196 netem.Latency, netem.Limit, netem.Loss, netem.Gap, netem.Duplicate, netem.Jitter, 197 ) 198 } 199 200 func (qdisc *Netem) Attrs() *QdiscAttrs { 201 return &qdisc.QdiscAttrs 202 } 203 204 func (qdisc *Netem) Type() string { 205 return "netem" 206 } 207 208 // Tbf is a classless qdisc that rate limits based on tokens 209 type Tbf struct { 210 QdiscAttrs 211 Rate uint64 212 Limit uint32 213 Buffer uint32 214 Peakrate uint64 215 Minburst uint32 216 // TODO: handle other settings 217 } 218 219 func (qdisc *Tbf) Attrs() *QdiscAttrs { 220 return &qdisc.QdiscAttrs 221 } 222 223 func (qdisc *Tbf) Type() string { 224 return "tbf" 225 } 226 227 // Clsact is a qdisc for adding filters 228 type Clsact struct { 229 QdiscAttrs 230 } 231 232 func (qdisc *Clsact) Attrs() *QdiscAttrs { 233 return &qdisc.QdiscAttrs 234 } 235 236 func (qdisc *Clsact) Type() string { 237 return "clsact" 238 } 239 240 // Ingress is a qdisc for adding ingress filters 241 type Ingress struct { 242 QdiscAttrs 243 } 244 245 func (qdisc *Ingress) Attrs() *QdiscAttrs { 246 return &qdisc.QdiscAttrs 247 } 248 249 func (qdisc *Ingress) Type() string { 250 return "ingress" 251 } 252 253 // GenericQdisc qdiscs represent types that are not currently understood 254 // by this netlink library. 255 type GenericQdisc struct { 256 QdiscAttrs 257 QdiscType string 258 } 259 260 func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { 261 return &qdisc.QdiscAttrs 262 } 263 264 func (qdisc *GenericQdisc) Type() string { 265 return qdisc.QdiscType 266 } 267 268 type Hfsc struct { 269 QdiscAttrs 270 Defcls uint16 271 } 272 273 func NewHfsc(attrs QdiscAttrs) *Hfsc { 274 return &Hfsc{ 275 QdiscAttrs: attrs, 276 Defcls: 1, 277 } 278 } 279 280 func (hfsc *Hfsc) Attrs() *QdiscAttrs { 281 return &hfsc.QdiscAttrs 282 } 283 284 func (hfsc *Hfsc) Type() string { 285 return "hfsc" 286 } 287 288 func (hfsc *Hfsc) String() string { 289 return fmt.Sprintf( 290 "{%v -- default: %d}", 291 hfsc.Attrs(), hfsc.Defcls, 292 ) 293 } 294 295 // Fq is a classless packet scheduler meant to be mostly used for locally generated traffic. 296 type Fq struct { 297 QdiscAttrs 298 PacketLimit uint32 299 FlowPacketLimit uint32 300 // In bytes 301 Quantum uint32 302 InitialQuantum uint32 303 // called RateEnable under the hood 304 Pacing uint32 305 FlowDefaultRate uint32 306 FlowMaxRate uint32 307 // called BucketsLog under the hood 308 Buckets uint32 309 FlowRefillDelay uint32 310 LowRateThreshold uint32 311 Horizon uint32 312 HorizonDropPolicy uint8 313 } 314 315 func (fq *Fq) String() string { 316 return fmt.Sprintf( 317 "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v, Horizon: %v, HorizonDropPolicy: %v}", 318 fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, fq.Horizon, fq.HorizonDropPolicy, 319 ) 320 } 321 322 func NewFq(attrs QdiscAttrs) *Fq { 323 return &Fq{ 324 QdiscAttrs: attrs, 325 Pacing: 1, 326 HorizonDropPolicy: HORIZON_DROP_POLICY_DEFAULT, 327 } 328 } 329 330 func (qdisc *Fq) Attrs() *QdiscAttrs { 331 return &qdisc.QdiscAttrs 332 } 333 334 func (qdisc *Fq) Type() string { 335 return "fq" 336 } 337 338 // FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme. 339 type FqCodel struct { 340 QdiscAttrs 341 Target uint32 342 Limit uint32 343 Interval uint32 344 ECN uint32 345 Flows uint32 346 Quantum uint32 347 CEThreshold uint32 348 DropBatchSize uint32 349 MemoryLimit uint32 350 } 351 352 func (fqcodel *FqCodel) String() string { 353 return fmt.Sprintf( 354 "{%v -- Target: %v, Limit: %v, Interval: %v, ECM: %v, Flows: %v, Quantum: %v}", 355 fqcodel.Attrs(), fqcodel.Target, fqcodel.Limit, fqcodel.Interval, fqcodel.ECN, fqcodel.Flows, fqcodel.Quantum, 356 ) 357 } 358 359 func NewFqCodel(attrs QdiscAttrs) *FqCodel { 360 return &FqCodel{ 361 QdiscAttrs: attrs, 362 ECN: 1, 363 } 364 } 365 366 func (qdisc *FqCodel) Attrs() *QdiscAttrs { 367 return &qdisc.QdiscAttrs 368 } 369 370 func (qdisc *FqCodel) Type() string { 371 return "fq_codel" 372 } 373 374 type Sfq struct { 375 QdiscAttrs 376 // TODO: Only the simplified options for SFQ are handled here. Support for the extended one can be added later. 377 Quantum uint8 378 Perturb uint8 379 Limit uint32 380 Divisor uint8 381 } 382 383 func (sfq *Sfq) String() string { 384 return fmt.Sprintf( 385 "{%v -- Quantum: %v, Perturb: %v, Limit: %v, Divisor: %v}", 386 sfq.Attrs(), sfq.Quantum, sfq.Perturb, sfq.Limit, sfq.Divisor, 387 ) 388 } 389 390 func (qdisc *Sfq) Attrs() *QdiscAttrs { 391 return &qdisc.QdiscAttrs 392 } 393 394 func (qdisc *Sfq) Type() string { 395 return "sfq" 396 }