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  }