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