-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathm_ctinfo.go
128 lines (119 loc) · 3.81 KB
/
m_ctinfo.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
128
package tc
import (
"fmt"
"github.com/mdlayher/netlink"
)
const (
tcaCtInfoUnspec = iota
tcaCtInfoPad
tcaCtInfoTm
tcaCtInfoAct
tcaCtInfoZone
tcaCtInfoParmsDscpMask
tcaCtInfoParmsDscpStateMask
tcaCtInfoParmsCpMarkMask
tcaCtInfoStatsDscpSet
tcaCtInfoStatsDscpError
tcaCtInfoStatsCpMarkSet
)
// CtInfo contains attributes of the ctinfo discipline
type CtInfo struct {
Tm *Tcft
Act *CtInfoAct
Zone *uint16
ParmsDscpMask *uint32
ParmsDscpStateMask *uint32
ParmsCpMarkMask *uint32
StatsDscpSet *uint64
StatsDscpError *uint64
StatsCpMarkSet *uint64
}
// CtInfoAct as tc_ctinfo from include/uapi/linux/tc_act/tc_ctinfo.h
type CtInfoAct struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
}
// unmarshalCtInfo parses the ctinfo-encoded data and stores the result in the value pointed to by info.
func unmarshalCtInfo(data []byte, info *CtInfo) error {
ad, err := netlink.NewAttributeDecoder(data)
if err != nil {
return err
}
var multiError error
for ad.Next() {
switch ad.Type() {
case tcaCtInfoTm:
tcft := &Tcft{}
err = unmarshalStruct(ad.Bytes(), tcft)
multiError = concatError(multiError, err)
info.Tm = tcft
case tcaCtInfoAct:
parms := &CtInfoAct{}
err = unmarshalStruct(ad.Bytes(), parms)
multiError = concatError(multiError, err)
info.Act = parms
case tcaCtInfoZone:
info.Zone = uint16Ptr(ad.Uint16())
case tcaCtInfoParmsDscpMask:
info.ParmsDscpMask = uint32Ptr(ad.Uint32())
case tcaCtInfoParmsDscpStateMask:
info.ParmsDscpStateMask = uint32Ptr(ad.Uint32())
case tcaCtInfoParmsCpMarkMask:
info.ParmsCpMarkMask = uint32Ptr(ad.Uint32())
case tcaCtInfoStatsDscpSet:
info.StatsDscpSet = uint64Ptr(ad.Uint64())
case tcaCtInfoStatsDscpError:
info.StatsDscpError = uint64Ptr(ad.Uint64())
case tcaCtInfoStatsCpMarkSet:
info.StatsCpMarkSet = uint64Ptr(ad.Uint64())
case tcaCtInfoPad:
// padding does not contain data, we just skip it
default:
return fmt.Errorf("UnmarshalCtInfo()\t%d\n\t%v", ad.Type(), ad.Bytes())
}
}
return concatError(multiError, ad.Err())
}
// marshalCtInfo returns the binary encoding of CtInfo
func marshalCtInfo(info *CtInfo) ([]byte, error) {
options := []tcOption{}
if info == nil {
return []byte{}, fmt.Errorf("CtInfo: %w", ErrNoArg)
}
// TODO: improve logic and check combinations
if info.Tm != nil {
return []byte{}, ErrNoArgAlter
}
if info.Act != nil {
data, err := marshalStruct(info.Act)
if err != nil {
return []byte{}, nil
}
options = append(options, tcOption{Interpretation: vtBytes, Type: tcaCtInfoAct, Data: data})
}
if info.Zone != nil {
options = append(options, tcOption{Interpretation: vtUint16, Type: tcaCtInfoZone, Data: uint16Value(info.Zone)})
}
if info.ParmsDscpMask != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaCtInfoParmsDscpMask, Data: uint32Value(info.ParmsDscpMask)})
}
if info.ParmsDscpStateMask != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaCtInfoParmsDscpStateMask, Data: uint32Value(info.ParmsDscpStateMask)})
}
if info.ParmsCpMarkMask != nil {
options = append(options, tcOption{Interpretation: vtUint32, Type: tcaCtInfoParmsCpMarkMask, Data: uint32Value(info.ParmsCpMarkMask)})
}
if info.StatsDscpSet != nil {
options = append(options, tcOption{Interpretation: vtUint64, Type: tcaCtInfoStatsDscpSet, Data: uint64Value(info.StatsDscpSet)})
}
if info.StatsDscpError != nil {
options = append(options, tcOption{Interpretation: vtUint64, Type: tcaCtInfoStatsDscpError, Data: uint64Value(info.StatsDscpError)})
}
if info.StatsCpMarkSet != nil {
options = append(options, tcOption{Interpretation: vtUint64, Type: tcaCtInfoStatsCpMarkSet, Data: uint64Value(info.StatsCpMarkSet)})
}
return marshalAttributes(options)
}