forked from florianl/go-tc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
m_skbedit.go
127 lines (119 loc) · 3.61 KB
/
m_skbedit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package tc
import (
"fmt"
"github.com/mdlayher/netlink"
)
const (
tcaSkbEditUnspec = iota
tcaSkbEditTm
tcaSkbEditParms
tcaSkbEditPriority
tcaSkbEditQueueMapping
tcaSkbEditMark
tcaSkbEditPad
tcaSkbEditPtype
tcaSkbEditMask
tcaSkbEditFlags
tcaSkbEditQueueMappingMax
)
// SkbEdit contains attribute of the SkbEdit discipline
type SkbEdit struct {
Tm *Tcft
Parms *SkbEditParms
Priority *uint32
QueueMapping *uint16
Mark *uint32
Ptype *uint16
Mask *uint32
Flags *uint64
QueueMappingMax *uint16
}
// SkbEditParms from include/uapi/linux/tc_act/tc_skbedit.h
type SkbEditParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
}
// unmarshalSkbEdit parses the skbedit-encoded data and stores the result in the value pointed to by info.
func unmarshalSkbEdit(data []byte, info *SkbEdit) error {
ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
return err
}
var multiError error
for ad.Next() {
switch ad.Type() {
case tcaSkbEditTm:
tcft := &Tcft{}
err = unmarshalStruct(ad.Bytes(), tcft)
multiError = concatError(multiError, err)
info.Tm = tcft
case tcaSkbEditParms:
parms := &SkbEditParms{}
err = unmarshalStruct(ad.Bytes(), parms)
multiError = concatError(multiError, err)
info.Parms = parms
case tcaSkbEditPriority:
info.Priority = uint32Ptr(ad.Uint32())
case tcaSkbEditQueueMapping:
info.QueueMapping = uint16Ptr(ad.Uint16())
case tcaSkbEditMark:
info.Mark = uint32Ptr(ad.Uint32())
case tcaSkbEditPtype:
info.Ptype = uint16Ptr(ad.Uint16())
case tcaSkbEditMask:
info.Mask = uint32Ptr(ad.Uint32())
case tcaSkbEditFlags:
info.Flags = uint64Ptr(ad.Uint64())
case tcaSkbEditQueueMappingMax:
info.QueueMappingMax = uint16Ptr(ad.Uint16())
case tcaSkbEditPad:
// padding does not contain data, we just skip it
default:
return fmt.Errorf("UnmarshalSkbEdit()\t%d\n\t%v", ad.Type(), ad.Bytes())
}
}
return concatError(multiError, ad.Err())
}
// marshalSkbEdit returns the binary encoding of SkbEdit
func marshalSkbEdit(info *SkbEdit) ([]byte, error) {
options := []tcOption{}
if info == nil {
return []byte{}, fmt.Errorf("SkbEdit: %w", ErrNoArg)
}
// TODO: improve logic and check combinations
if info.Tm != nil {
return []byte{}, ErrNoArgAlter
}
if info.Parms != nil {
data, err := marshalStruct(info.Parms)
if err != nil {
return []byte{}, err
}
options = append(options, tcOption{Interpretation: vtBytes, Type: tcaSkbEditParms, Data: data})
}
if info.Priority != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaSkbEditPriority, Data: uint32Value(info.Priority)})
}
if info.QueueMapping != nil {
options = append(options, tcOption{Interpretation: vtUint16, Type: tcaSkbEditQueueMapping, Data: uint16Value(info.QueueMapping)})
}
if info.Mark != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaSkbEditMark, Data: uint32Value(info.Mark)})
}
if info.Ptype != nil {
options = append(options, tcOption{Interpretation: vtUint16, Type: tcaSkbEditPtype, Data: uint16Value(info.Ptype)})
}
if info.Mask != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaSkbEditMask, Data: uint32Value(info.Mask)})
}
if info.Flags != nil {
options = append(options, tcOption{Interpretation: vtUint64, Type: tcaSkbEditFlags, Data: uint64Value(info.Flags)})
}
if info.QueueMappingMax != nil {
options = append(options, tcOption{Interpretation: vtUint16, Type: tcaSkbEditQueueMappingMax, Data: uint16Value(info.QueueMappingMax)})
}
return marshalAttributes(options)
}