1package netlink
2
3import (
4	"fmt"
5)
6
7const (
8	HANDLE_NONE      = 0
9	HANDLE_INGRESS   = 0xFFFFFFF1
10	HANDLE_ROOT      = 0xFFFFFFFF
11	PRIORITY_MAP_LEN = 16
12)
13
14type Qdisc interface {
15	Attrs() *QdiscAttrs
16	Type() string
17}
18
19// Qdisc represents a netlink qdisc. A qdisc is associated with a link,
20// has a handle, a parent and a refcnt. The root qdisc of a device should
21// have parent == HANDLE_ROOT.
22type QdiscAttrs struct {
23	LinkIndex int
24	Handle    uint32
25	Parent    uint32
26	Refcnt    uint32 // read only
27}
28
29func (q QdiscAttrs) String() string {
30	return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %s}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt)
31}
32
33func MakeHandle(major, minor uint16) uint32 {
34	return (uint32(major) << 16) | uint32(minor)
35}
36
37func MajorMinor(handle uint32) (uint16, uint16) {
38	return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF)
39}
40
41func HandleStr(handle uint32) string {
42	switch handle {
43	case HANDLE_NONE:
44		return "none"
45	case HANDLE_INGRESS:
46		return "ingress"
47	case HANDLE_ROOT:
48		return "root"
49	default:
50		major, minor := MajorMinor(handle)
51		return fmt.Sprintf("%x:%x", major, minor)
52	}
53}
54
55// PfifoFast is the default qdisc created by the kernel if one has not
56// been defined for the interface
57type PfifoFast struct {
58	QdiscAttrs
59	Bands       uint8
60	PriorityMap [PRIORITY_MAP_LEN]uint8
61}
62
63func (qdisc *PfifoFast) Attrs() *QdiscAttrs {
64	return &qdisc.QdiscAttrs
65}
66
67func (qdisc *PfifoFast) Type() string {
68	return "pfifo_fast"
69}
70
71// Prio is a basic qdisc that works just like PfifoFast
72type Prio struct {
73	QdiscAttrs
74	Bands       uint8
75	PriorityMap [PRIORITY_MAP_LEN]uint8
76}
77
78func 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
86func (qdisc *Prio) Attrs() *QdiscAttrs {
87	return &qdisc.QdiscAttrs
88}
89
90func (qdisc *Prio) Type() string {
91	return "prio"
92}
93
94// Tbf is a classful qdisc that rate limits based on tokens
95type Tbf struct {
96	QdiscAttrs
97	// TODO: handle 64bit rate properly
98	Rate   uint64
99	Limit  uint32
100	Buffer uint32
101	// TODO: handle other settings
102}
103
104func (qdisc *Tbf) Attrs() *QdiscAttrs {
105	return &qdisc.QdiscAttrs
106}
107
108func (qdisc *Tbf) Type() string {
109	return "tbf"
110}
111
112// Ingress is a qdisc for adding ingress filters
113type Ingress struct {
114	QdiscAttrs
115}
116
117func (qdisc *Ingress) Attrs() *QdiscAttrs {
118	return &qdisc.QdiscAttrs
119}
120
121func (qdisc *Ingress) Type() string {
122	return "ingress"
123}
124
125// GenericQdisc qdiscs represent types that are not currently understood
126// by this netlink library.
127type GenericQdisc struct {
128	QdiscAttrs
129	QdiscType string
130}
131
132func (qdisc *GenericQdisc) Attrs() *QdiscAttrs {
133	return &qdisc.QdiscAttrs
134}
135
136func (qdisc *GenericQdisc) Type() string {
137	return qdisc.QdiscType
138}
139