Documentation
¶
Overview ¶
Package tc allows to show and alter traffic control settings in the Linux kernel.
Traffic control is composed of the elements shaping, scheduling, policing and dropping. This processing is controlled by qdiscs, classes and filters.
For a more detailed introduction of these elements, please have a look at http://man7.org/linux/man-pages/man8/tc.8.html.
Example (CBPF) ¶
This example demonstrate the use with classic BPF
tcIface := "ExampleClassicBPF"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(tc.HandleIngress, 0x0000),
Parent: tc.HandleIngress,
Info: 0,
},
tc.Attribute{
Kind: "clsact",
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign clsact to lo: %v\n", err)
return
}
// when deleting the qdisc, the applied filter will also be gone
defer tcnl.Qdisc().Delete(&qdisc)
ops := []byte{0x6, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff}
opsLen := uint16(1)
classID := uint32(0x1001)
flags := uint32(0x1)
filter := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: 0,
Parent: tc.HandleIngress,
Info: 0x300,
},
tc.Attribute{
Kind: "bpf",
BPF: &tc.Bpf{
Ops: &ops,
OpsLen: &opsLen,
ClassID: &classID,
Flags: &flags,
},
},
}
if err := tcnl.Filter().Add(&filter); err != nil {
fmt.Fprintf(os.Stderr, "could not assign cBPF: %v\n", err)
return
}
Index ¶
- Constants
- Variables
- type ActBpf
- type ActBpfParms
- type Action
- type Atm
- type AtmPvc
- type Attribute
- type Basic
- type Bpf
- type Cake
- type Cbq
- type CbqFOpt
- type CbqLssOpt
- type CbqOvl
- type CbqPolice
- type CbqWrrOpt
- type CbqXStats
- type Cgroup
- type Chain
- type Choke
- type ChokeXStats
- type Class
- type CmpMatch
- type CmpMatchAlign
- type CmpMatchFlag
- type Codel
- type CodelXStats
- type Config
- type Connmark
- type ConnmarkParam
- type Csum
- type CsumParms
- type Defact
- type DefactParms
- type Drr
- type Dsmark
- type Ematch
- type EmatchHdr
- type EmatchKind
- type EmatchLayer
- type EmatchMatch
- type EmatchOpnd
- type EmatchTreeHdr
- type ErrorFunc
- type Ets
- type FifoOpt
- type Filter
- type Flow
- type Flower
- type Fq
- type FqCodel
- type FqCodelClStats
- type FqCodelQdStats
- type FqCodelXStats
- type Fw
- type Gact
- type GactParms
- type GactProb
- type Gate
- type GateParms
- type GenBasic
- type GenQueue
- type GenRateEst
- type GenRateEst64
- type GenStats
- type Hfsc
- type HfscQOpt
- type HfscXStats
- type Hhf
- type HhfXStats
- type HookFunc
- type Htb
- type HtbGlob
- type HtbOpt
- type HtbXStats
- type IPSetDir
- type IPSetMatch
- type Ife
- type IfeParms
- type Ipt
- type IptCnt
- type Matchall
- type Mirred
- type MirredParam
- type MqPrio
- type MqPrioQopt
- type Msg
- type Nat
- type NatParms
- type Netem
- type NetemCorr
- type NetemCorrupt
- type NetemQopt
- type NetemRate
- type NetemReorder
- type NetemSlot
- type Object
- type Pie
- type PieXStats
- type Plug
- type PlugAction
- type Police
- type Policy
- type PolicyAction
- type Prio
- type Qdisc
- type Qfq
- type RateSpec
- type Red
- type RedQOpt
- type RedXStats
- type Route4
- type Rsvp
- type RsvpGpi
- type RsvpPInfo
- type Sample
- type SampleParms
- type ServiceCurve
- type Sfb
- type SfbQopt
- type SfbXStats
- type Sfq
- type SfqQopt
- type SfqXStats
- type SizeSpec
- type Stab
- type Stats
- type Stats2
- type Tbf
- type TbfQopt
- type Tc
- func (tc *Tc) Chain() *Chain
- func (tc *Tc) Class() *Class
- func (tc *Tc) Close() error
- func (tc *Tc) Filter() *Filter
- func (tc *Tc) Monitor(ctx context.Context, deadline time.Duration, fn HookFunc) errordeprecated
- func (tc *Tc) MonitorWithErrorFunc(ctx context.Context, deadline time.Duration, fn HookFunc, errfn ErrorFunc) error
- func (tc *Tc) Qdisc() *Qdisc
- type TcIndex
- type Tcft
- type TunnelKey
- type TunnelParms
- type U32
- type U32Key
- type U32Mark
- type U32Match
- type U32Sel
- type VLan
- type VLanParms
- type XStats
Examples ¶
Constants ¶
const ( EmatchLayerLink = EmatchLayer(0) EmatchLayerNetwork = EmatchLayer(1) EmatchLayerTransport = EmatchLayer(2) )
const ( EmatchOpndEq = EmatchOpnd(0) EmatchOpndGt = EmatchOpnd(1) EmatchOpndLt = EmatchOpnd(2) )
const ( EmatchContainer = EmatchKind(0) EmatchCmp = EmatchKind(1) EmatchNByte = EmatchKind(2) EmatchU32 = EmatchKind(3) EmatchMeta = EmatchKind(4) EmatchText = EmatchKind(5) EmatchVLan = EmatchKind(6) EmatchCanID = EmatchKind(7) EmatchIPSet = EmatchKind(8) EmatchIPT = EmatchKind(9) )
Various Ematch kinds
const ( CmpMatchU8 = CmpMatchAlign(1) CmpMatchU16 = CmpMatchAlign(2) CmpMatchU32 = CmpMatchAlign(4) )
const ( IPSetSrc = IPSetDir(1) IPSetDst = IPSetDir(2) )
const ( ActBind = 1 ActNoBind = 0 ActUnbind = 1 ActNoUnbind = 0 ActReplace = 1 ActNoReplace = 0 )
const ( ActOk = 0 ActReclassify = 1 ActShot = 2 ActPipe = 3 ActStolen = 4 ActQueued = 5 ActRepeat = 6 ActRedirect = 7 ActTrap = 8 )
const ( HandleRoot uint32 = 0xFFFFFFFF HandleIngress uint32 = 0xFFFFFFF1 HandleMinPriority uint32 = 0xFFE0 HandleMinIngress uint32 = 0xFFF2 HandleMinEgress uint32 = 0xFFF3 // To alter filter in shared blocks, set Msg.Ifindex to MagicBlock MagicBlock = 0xFFFFFFFF )
Constants to define the direction
const ( // don't offload filter to HW SkipHw uint32 = 1 << iota // don't use filter in SW SkipSw // filter is offloaded to HW InHw // filter isn't offloaded to HW NotInHw // verbose logging Verbose )
Common flags from include/uapi/linux/pkt_cls.h
const (
BpfActDirect = 1
)
Flags defined by the kernel for the BPF filter
const (
CmpMatchTrans = CmpMatchFlag(1)
)
Variables ¶
var ( ErrNoArgAlter = errors.New("argument cannot be altered") ErrInvalidDev = errors.New("invalid device ID") // ErrNotImplemented is returned for not yet implemented parts. ErrNotImplemented = errors.New("functionality not yet implemented") // ErrNoArg is returned for missing arguments. ErrNoArg = errors.New("missing argument") // ErrInvalidArg is returned on invalid given arguments. ErrInvalidArg = errors.New("invalid argument") // ErrUnknownKind is returned for unknown qdisc, filter or class types. ErrUnknownKind = errors.New("unknown kind") )
Various errors
Functions ¶
This section is empty.
Types ¶
type ActBpf ¶
type ActBpf struct {
Tm *Tcft
Parms *ActBpfParms
Ops *[]byte
OpsLen *uint16
FD *uint32
Name *string
Tag *[]byte
ID *uint32
}
ActBpf represents policing attributes of various filters and classes
type ActBpfParms ¶
ActBpfParms from include/uapi/linux/tc_act/tc_bpf.h
type Action ¶
type Action struct {
Kind string
Index uint32
Stats *GenStats
Cookie *[]byte
Bpf *ActBpf
ConnMark *Connmark
CSum *Csum
Defact *Defact
Gact *Gact
Gate *Gate
Ife *Ife
Ipt *Ipt
Mirred *Mirred
Nat *Nat
Sample *Sample
VLan *VLan
Police *Police
TunnelKey *TunnelKey
}
Action represents action attributes of various filters and classes
type Attribute ¶
type Attribute struct {
Kind string
EgressBlock *uint32
IngressBlock *uint32
HwOffload *uint8
Chain *uint32
Stats *Stats
XStats *XStats
Stats2 *Stats2
Stab *Stab
// Filters
Basic *Basic
BPF *Bpf
Cgroup *Cgroup
U32 *U32
Rsvp *Rsvp
Route4 *Route4
Fw *Fw
Flow *Flow
Flower *Flower
Matchall *Matchall
// Classless qdiscs
Cake *Cake
FqCodel *FqCodel
Codel *Codel
Fq *Fq
Pie *Pie
Hhf *Hhf
Tbf *Tbf
Sfb *Sfb
Sfq *Sfq
Red *Red
MqPrio *MqPrio
Pfifo *FifoOpt
Bfifo *FifoOpt
Choke *Choke
Netem *Netem
Plug *Plug
// Classful qdiscs
Htb *Htb
Hfsc *Hfsc
HfscQOpt *HfscQOpt
Dsmark *Dsmark
Drr *Drr
Cbq *Cbq
Atm *Atm
Qfq *Qfq
Prio *Prio
}
Attribute contains various elements for traffic control
type Bpf ¶
type Bpf struct {
Action *Action
Police *Police
ClassID *uint32
OpsLen *uint16
Ops *[]byte
FD *uint32
Name *string
Flags *uint32
FlagsGen *uint32
Tag *[]byte
ID *uint32
}
Bpf contains attributes of the bpf discipline
type Cake ¶
type Cake struct {
BaseRate *uint64
DiffServMode *uint32
Atm *uint32
FlowMode *uint32
Overhead *uint32
Rtt *uint32
Target *uint32
Autorate *uint32
Memory *uint32
Nat *uint32
Raw *uint32
Wash *uint32
Mpu *uint32
Ingress *uint32
AckFilter *uint32
SplitGso *uint32
FwMark *uint32
}
Cake contains attributes of the cake discipline. http://man7.org/linux/man-pages/man8/tc-cake.8.html
type Cbq ¶
type Cbq struct {
LssOpt *CbqLssOpt
WrrOpt *CbqWrrOpt
FOpt *CbqFOpt
OVLStrategy *CbqOvl
Rate *RateSpec
RTab []byte
Police *CbqPolice
}
Cbq contains attributes of the cbq discipline
type CbqLssOpt ¶
type CbqLssOpt struct {
Change byte
Flags byte
EwmaLog byte
Level byte
Maxidle uint32
Minidle uint32
OffTime uint32
Avpkt uint32
}
CbqLssOpt from include/uapi/linux/pkt_sched.h
type CbqWrrOpt ¶
type CbqWrrOpt struct {
Flags byte
Priority byte
CPriority byte
Reserved byte
Allot uint32
Weight uint32
}
CbqWrrOpt from include/uapi/linux/pkt_sched.h
type ChokeXStats ¶
ChokeXStats from include/uapi/linux/pkt_sched.h
type CmpMatch ¶
type CmpMatch struct {
Val uint32
Mask uint32
Off uint16
Align CmpMatchAlign
Flags CmpMatchFlag
Layer EmatchLayer
Opnd EmatchOpnd
}
type CmpMatchAlign ¶
type CmpMatchAlign uint8
type CmpMatchFlag ¶
type CmpMatchFlag uint8
type CodelXStats ¶
type CodelXStats struct {
MaxPacket uint32
Count uint32
LastCount uint32
LDelay uint32
DropNext int32
DropOverlimit uint32
EcnMark uint32
Dropping uint32
CeMark uint32
}
CodelXStats from include/uapi/linux/pkt_sched.h
type Config ¶
type Config struct {
// NetNS defines the network namespace
NetNS int
// Interface to log internals
Logger *log.Logger
}
Config contains options for RTNETLINK
type Connmark ¶
type Connmark struct {
Parms *ConnmarkParam
Tm *Tcft
}
Connmark represents policing attributes of various filters and classes
type ConnmarkParam ¶
type ConnmarkParam struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
Zone uint16
}
ConnmarkParam from include/uapi/linux/tc_act/tc_connmark.h
type CsumParms ¶
type CsumParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
UpdateFlags uint32
}
CsumParms from include/uapi/linux/tc_act/tc_csum.h
type Defact ¶
type Defact struct {
Parms *DefactParms
Tm *Tcft
Data *string
}
Defact contains attributes of the defact discipline
type DefactParms ¶
DefactParms from include/uapi/linux/tc_act/tc_defact.h
type Dsmark ¶
type Dsmark struct {
Indices *uint16
DefaultIndex *uint16
SetTCIndex *bool
Mask *uint8
Value *uint8
}
Dsmark contains attributes of the dsmark discipline
type Ematch ¶
type Ematch struct {
Hdr *EmatchTreeHdr
Matches *[]EmatchMatch
}
Ematch contains attributes of the ematch discipline https://man7.org/linux/man-pages/man8/tc-ematch.8.html
type EmatchHdr ¶
type EmatchHdr struct {
MatchID uint16
Kind EmatchKind
Flags uint16
Pad uint16
}
tcf_ematch_hdr from include/uapi/linux/pkt_cls.h
type EmatchKind ¶
type EmatchKind uint16
type EmatchLayer ¶
type EmatchLayer uint8
type EmatchMatch ¶
type EmatchMatch struct {
Hdr EmatchHdr
U32Match *U32Match
CmpMatch *CmpMatch
IPSetMatch *IPSetMatch
}
type EmatchOpnd ¶
type EmatchOpnd uint8
type EmatchTreeHdr ¶
tcf_ematch_tree_hdr from include/uapi/linux/pkt_cls.h
type ErrorFunc ¶
ErrorFunc is a function that receives all errors that happen while reading from a Netlinkgroup. To stop receiving messages return something different than 0.
type Ets ¶
Ets represents a struct for Enhanced Transmission Selection, a 802.1Qaz-based Qdisc. More info at https://lwn.net/Articles/805229/
type Flow ¶
type Flow struct {
Keys *uint32
Mode *uint32
BaseClass *uint32
RShift *uint32
Addend *uint32
Mask *uint32
XOR *uint32
Divisor *uint32
PerTurb *uint32
Ematch *Ematch
}
Flow contains attributes of the flow discipline
type Flower ¶
type Flower struct {
ClassID *uint32
Indev *string
Actions *[]*Action
KeyEthDst *net.HardwareAddr
KeyEthDstMask *net.HardwareAddr
KeyEthSrc *net.HardwareAddr
KeyEthSrcMask *net.HardwareAddr
KeyEthType *uint16
KeyIPProto *uint8
KeyIPv4Src *net.IP
KeyIPv4SrcMask *net.IP
KeyIPv4Dst *net.IP
KeyIPv4DstMask *net.IP
KeyTCPSrc *uint16
KeyTCPDst *uint16
KeyUDPSrc *uint16
KeyUDPDst *uint16
Flags *uint32
KeyVlanID *uint16
KeyVlanPrio *uint8
KeyVlanEthType *uint16
KeyEncKeyID *uint32
KeyEncIPv4Src *net.IP
KeyEncIPv4SrcMask *net.IP
KeyEncIPv4Dst *net.IP
KeyEncIPv4DstMask *net.IP
KeyTCPSrcMask *uint16
KeyTCPDstMask *uint16
KeyUDPSrcMask *uint16
KeyUDPDstMask *uint16
KeySctpSrc *uint16
KeySctpDst *uint16
KeyEncUDPSrcPort *uint16
KeyEncUDPSrcPortMask *uint16
KeyEncUDPDstPort *uint16
KeyEncUDPDstPortMask *uint16
KeyFlags *uint32
KeyFlagsMask *uint32
KeyIcmpv4Code *uint8
KeyIcmpv4CodeMask *uint8
KeyIcmpv4Type *uint8
KeyIcmpv4TypeMask *uint8
KeyIcmpv6Code *uint8
KeyIcmpv6CodeMask *uint8
KeyArpSIP *uint32
KeyArpSIPMask *uint32
KeyArpTIP *uint32
KeyArpTIPMask *uint32
KeyArpOp *uint8
KeyArpOpMask *uint8
KeyMplsTTL *uint8
KeyMplsBos *uint8
KeyMplsTc *uint8
KeyMplsLabel *uint32
KeyTCPFlags *uint16
KeyTCPFlagsMask *uint16
KeyIPTOS *uint8
KeyIPTOSMask *uint8
KeyIPTTL *uint8
KeyIPTTLMask *uint8
KeyCVlanID *uint16
KeyCVlanPrio *uint8
KeyCVlanEthType *uint16
KeyEncIPTOS *uint8
KeyEncIPTOSMask *uint8
KeyEncIPTTL *uint8
KeyEncIPTTLMask *uint8
InHwCount *uint32
}
Flower contains attrobutes of the flower discipline
Example ¶
tcIface := "ExampleFlower"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(tc.HandleRoot, 0),
Parent: tc.HandleIngress,
Info: 0,
},
tc.Attribute{
Kind: "clsact",
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign clsact to lo: %v\n", err)
return
}
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete qdisc from iface (%d): %v\n", devID.Index, err)
return
}
}()
srcMac, _ := net.ParseMAC("00:00:5e:00:53:01")
actions := []*tc.Action{
{
Kind: "gact",
Gact: &tc.Gact{
Parms: &tc.GactParms{
Action: 2, // action drop
},
},
},
}
filter := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: 0,
Parent: tc.HandleIngress + 1,
Info: 768,
},
tc.Attribute{
Kind: "flower",
Flower: &tc.Flower{
KeyEthSrc: &srcMac,
Actions: &actions,
},
},
}
// tc filter add dev ExampleFlower ingress protocol all prio 1 \
// flower src_mac 00:00:5e:00:53:01 \
// action gact drop
if err := tcnl.Filter().Add(&filter); err != nil {
fmt.Fprintf(os.Stderr, "could not assign flower filter to iface (%d): %v\n", devID.Index, err)
return
}
type Fq ¶
type Fq struct {
PLimit *uint32
FlowPLimit *uint32
Quantum *uint32
InitQuantum *uint32
RateEnable *uint32
FlowDefaultRate *uint32
FlowMaxRate *uint32
BucketsLog *uint32
FlowRefillDelay *uint32
OrphanMask *uint32
LowRateThreshold *uint32
CEThreshold *uint32
}
Fq contains attributes of the fq discipline
type FqCodel ¶
type FqCodel struct {
Target *uint32
Limit *uint32
Interval *uint32
ECN *uint32
Flows *uint32
Quantum *uint32
CEThreshold *uint32
DropBatchSize *uint32
MemoryLimit *uint32
}
FqCodel contains attributes of the fq_codel discipline
Example ¶
tcIface := "ExampleFQCodel"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
target := uint32(0xbb8)
limit := uint32(0x7d0)
interval := uint32(0x9c40)
ecn := uint32(0x0)
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(0x1, 0x0),
Parent: tc.HandleRoot,
Info: 0,
},
tc.Attribute{
Kind: "fq_codel",
// http://man7.org/linux/man-pages/man8/tc-fq_codel.8.html
// fq_codel limit 2000 target 3ms interval 40ms noecn
FqCodel: &tc.FqCodel{
Target: &target,
Limit: &limit,
Interval: &interval,
ECN: &ecn,
},
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign htb to lo: %v\n", err)
return
}
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete htb qdisc of lo: %v\n", err)
return
}
}()
qdiscs, err := tcnl.Qdisc().Get()
if err != nil {
fmt.Fprintf(os.Stderr, "could not get all qdiscs: %v\n", err)
}
for _, qdisc := range qdiscs {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%s\n", iface.Name, qdisc.Kind)
}
type FqCodelClStats ¶
type FqCodelClStats struct {
Deficit int32
LDelay uint32
Count uint32
LastCount uint32
Dropping uint32
DropNext int32
}
FqCodelClStats from include/uapi/linux/pkt_sched.h
type FqCodelQdStats ¶
type FqCodelQdStats struct {
MaxPacket uint32
DropOverlimit uint32
EcnMark uint32
NewFlowCount uint32
NewFlowsLen uint32
OldFlowsLen uint32
CeMark uint32
MemoryUsage uint32
DropOvermemory uint32
}
FqCodelQdStats from include/uapi/linux/pkt_sched.h
type FqCodelXStats ¶
type FqCodelXStats struct {
Type uint32
Qd *FqCodelQdStats
Cl *FqCodelClStats
}
FqCodelXStats from include/uapi/linux/pkt_sched.h
type Gate ¶
type Gate struct {
Tm *Tcft
Parms *GateParms
Priority *int32
BaseTime *uint64
CycleTime *uint64
CycleTimeExt *uint64
Flags *uint32
ClockID *int32
}
Gate contains attributes of the gate discipline https://man7.org/linux/man-pages/man8/tc-gate.8.html
type GenQueue ¶
type GenQueue struct {
QueueLen uint32
Backlog uint32
Drops uint32
Requeues uint32
Overlimits uint32
}
GenQueue from include/uapi/linux/gen_stats.h
type GenRateEst ¶
GenRateEst from include/uapi/linux/gen_stats.h
type GenRateEst64 ¶
GenRateEst64 from include/uapi/linux/gen_stats.h
type GenStats ¶
type GenStats struct {
Basic *GenBasic
RateEst *GenRateEst
Queue *GenQueue
RateEst64 *GenRateEst64
BasicHw *GenBasic
}
GenStats from include/uapi/linux/gen_stats.h
type Hfsc ¶
type Hfsc struct {
Rsc *ServiceCurve
Fsc *ServiceCurve
Usc *ServiceCurve
}
Hfsc contains attributes of the hfsc class
Example ¶
//go:build linux
// +build linux
package main
import (
"fmt"
"net"
"os"
"github.com/jsimonetti/rtnetlink"
"github.com/xcxinng/go-tc"
"github.com/xcxinng/go-tc/core"
"golang.org/x/sys/unix"
)
// setupDummyInterface installs a temporary dummy interface
func setupDummyInterface(iface string) (*rtnetlink.Conn, error) {
con, err := rtnetlink.Dial(nil)
if err != nil {
return &rtnetlink.Conn{}, err
}
if err := con.Link.New(&rtnetlink.LinkMessage{
Family: unix.AF_UNSPEC,
Type: unix.ARPHRD_NETROM,
Index: 0,
Flags: unix.IFF_UP,
Change: unix.IFF_UP,
Attributes: &rtnetlink.LinkAttributes{
Name: iface,
Info: &rtnetlink.LinkInfo{Kind: "dummy"},
},
}); err != nil {
return con, err
}
return con, err
}
func addHfscClass(class *tc.Class, devID, maj, min uint32, serviceCurve *tc.ServiceCurve) (*tc.Object, error) {
hfsc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: devID,
Handle: core.BuildHandle(maj, min),
Parent: 0x10000,
Info: 0,
},
tc.Attribute{
Kind: "hfsc",
Hfsc: &tc.Hfsc{
Rsc: serviceCurve,
Fsc: serviceCurve,
Usc: serviceCurve,
},
},
}
if err := class.Add(&hfsc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign hfsc class: %v\n", err)
return nil, err
}
return &hfsc, nil
}
func main() {
var rtnl *rtnetlink.Conn
var err error
tcIface := "tcDev"
if rtnl, err = setupDummyInterface(tcIface); err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: 0x10000,
Parent: tc.HandleRoot,
Info: 0,
},
// tc qdisc add dev tcDev stab linklayer ethernet mtu 1500 root handle 1: hfsc default 3
// http://man7.org/linux/man-pages/man8/tc-stab.8.html
tc.Attribute{
Kind: "hfsc",
HfscQOpt: &tc.HfscQOpt{
DefCls: 3,
},
Stab: &tc.Stab{
Base: &tc.SizeSpec{
CellLog: 0,
SizeLog: 0,
CellAlign: 0,
Overhead: 0,
LinkLayer: 1,
MPU: 0,
MTU: 1500,
TSize: 0,
},
},
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign hfsc to %s: %v\n", tcIface, err)
return
}
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete htb qdisc of %s: %v\n", tcIface, err)
return
}
}()
class1, err := addHfscClass(tcnl.Class(), uint32(devID.Index), 0x10000, 0x1, &tc.ServiceCurve{M2: 0x1e848})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to add hfsc: %v\n", err)
return
}
defer func() {
if err := tcnl.Class().Delete(class1); err != nil {
fmt.Fprintf(os.Stderr, "could not delete hfsc class of %s: %v\n", tcIface, err)
return
}
}()
class2, err := addHfscClass(tcnl.Class(), uint32(devID.Index), 0x10000, 0x2, &tc.ServiceCurve{M2: 0x1e848})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to add hfsc: %v\n", err)
return
}
defer func() {
if err := tcnl.Class().Delete(class2); err != nil {
fmt.Fprintf(os.Stderr, "could not delete hfsc class of %s: %v\n", tcIface, err)
return
}
}()
class3, err := addHfscClass(tcnl.Class(), uint32(devID.Index), 0x10000, 0x3, &tc.ServiceCurve{M2: 0x1e848})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to add hfsc: %v\n", err)
return
}
defer func() {
if err := tcnl.Class().Delete(class3); err != nil {
fmt.Fprintf(os.Stderr, "could not delete hfsc class of %s: %v\n", tcIface, err)
return
}
}()
classes, err := tcnl.Class().Get(&tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index)})
if err != nil {
fmt.Fprintf(os.Stderr, "could not get all classes: %v\n", err)
}
for _, class := range classes {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%s\n", iface.Name, class.Kind)
}
}
Output:
type HfscQOpt ¶
type HfscQOpt struct {
DefCls uint16
}
HfscQOpt contains attributes of the hfsc qdisc
type HfscXStats ¶
HfscXStats from include/uapi/linux/pkt_sched.h
type Hhf ¶
type Hhf struct {
BacklogLimit *uint32
Quantum *uint32
HHFlowsLimit *uint32
ResetTimeout *uint32
AdmitBytes *uint32
EVICTTimeout *uint32
NonHHWeight *uint32
}
Hhf contains attributes of the hhf discipline
type HhfXStats ¶
type HhfXStats struct {
DropOverlimit uint32
HhOverlimit uint32
HhTotCount uint32
HhCurCount uint32
}
HhfXStats from include/uapi/linux/pkt_sched.h
type HookFunc ¶
HookFunc is a function, which is called for each altered RTNETLINK Object. Return something different than 0, to stop receiving messages. action will have the value of unix.RTM_[NEW|GET|DEL][QDISC|TCLASS|FILTER].
type Htb ¶
type Htb struct {
Parms *HtbOpt
Init *HtbGlob
Ctab *[]byte
Rtab *[]byte
DirectQlen *uint32
Rate64 *uint64
Ceil64 *uint64
}
Htb contains attributes of the HTB discipline
Example ¶
tcIface := "ExampleHtb"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(0x1, 0x0),
Parent: tc.HandleRoot,
Info: 0,
},
// configure a very basic hierarchy token bucket (htb) qdisc
tc.Attribute{
Kind: "htb",
Htb: &tc.Htb{
Init: &tc.HtbGlob{
Version: 0x3,
Rate2Quantum: 0xa,
},
},
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign htb to lo: %v\n", err)
return
}
// delete the qdisc, if this program terminates
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete htb qdisc of lo: %v\n", err)
return
}
}()
qdiscs, err := tcnl.Qdisc().Get()
if err != nil {
fmt.Fprintf(os.Stderr, "could not get all qdiscs: %v\n", err)
}
for _, qdisc := range qdiscs {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%s\n", iface.Name, qdisc.Kind)
}
type HtbGlob ¶
type HtbGlob struct {
Version uint32
Rate2Quantum uint32
Defcls uint32
Debug uint32
DirectPkts uint32
}
HtbGlob from include/uapi/linux/pkt_sched.h
type HtbOpt ¶
type HtbOpt struct {
Rate RateSpec
Ceil RateSpec
Buffer uint32
Cbuffer uint32
Quantum uint32
Level uint32
Prio uint32
}
HtbOpt from include/uapi/linux/pkt_sched.h
type IPSetMatch ¶
type IfeParms ¶
type IfeParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
Flags uint16
}
IfeParms from from include/uapi/linux/tc_act/tc_ife.h
type Mirred ¶
type Mirred struct {
Parms *MirredParam
Tm *Tcft
}
Mirred represents policing attributes of various filters and classes
type MirredParam ¶
type MirredParam struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
Eaction uint32
IfIndex uint32
}
MirredParam from include/uapi/linux/tc_act/tc_mirred.h
type MqPrio ¶
type MqPrio struct {
Opt *MqPrioQopt
Mode *uint16
Shaper *uint16
MinRate64 *uint64
MaxRate64 *uint64
}
MqPrio contains attributes of the mqprio discipline
type MqPrioQopt ¶
type MqPrioQopt struct {
NumTc uint8
PrioTcMap [16]uint8 // TC_QOPT_BITMASK + 1 = 16
Hw uint8
Count [16]uint16 // TC_QOPT_MAX_QUEUE = 16
Offset [16]uint16 // TC_QOPT_MAX_QUEUE = 16
}
MqPrioQopt according to tc_mqprio_qopt in /include/uapi/linux/pkt_sched.h
type NatParms ¶
type NatParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
OldAddr uint32
NewAddr uint32
Mask uint32
Flags uint32
}
NatParms from from include/uapi/linux/tc_act/tc_nat.h
type Netem ¶
type Netem struct {
Qopt NetemQopt
Corr *NetemCorr
Reorder *NetemReorder
Corrupt *NetemCorrupt
Rate *NetemRate
Ecn *uint32
Rate64 *uint64
Latency64 *int64
Jitter64 *int64
Slot *NetemSlot
}
Netem contains attributes of the netem discipline
Example ¶
tcIface := "ExampleNetem"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
var ecn uint32 = 1
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(0x1, 0x0),
Parent: tc.HandleRoot,
Info: 0,
},
tc.Attribute{
Kind: "netem",
// tc qdisc replace dev tcDev root netem loss 1% ecn
Netem: &tc.Netem{
Qopt: tc.NetemQopt{
Limit: 1000,
Loss: 42949673},
Ecn: &ecn,
},
},
}
if err := tcnl.Qdisc().Replace(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign qdisc netem to lo: %v\n", err)
return
}
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete netem qdisc of lo: %v\n", err)
return
}
}()
qdiscs, err := tcnl.Qdisc().Get()
if err != nil {
fmt.Fprintf(os.Stderr, "could not get all qdiscs: %v\n", err)
}
for _, qdisc := range qdiscs {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%s\n", iface.Name, qdisc.Kind)
}
type NetemCorrupt ¶
NetemCorrupt from include/uapi/linux/pkt_sched.h
type NetemQopt ¶
type NetemQopt struct {
Latency uint32
Limit uint32
Loss uint32
Gap uint32
Duplicate uint32
Jitter uint32
}
NetemQopt from include/uapi/linux/pkt_sched.h
type NetemReorder ¶
NetemReorder from include/uapi/linux/pkt_sched.h
type NetemSlot ¶
type NetemSlot struct {
MinDelay int64
MaxDelay int64
MaxPackets int32
MaxBytes int32
DistDelay int64
DistJitter int64
}
NetemSlot from include/uapi/linux/pkt_sched.h
type Pie ¶
type Pie struct {
Target *uint32
Limit *uint32
TUpdate *uint32
Alpha *uint32
Beta *uint32
ECN *uint32
Bytemode *uint32
}
Pie contains attributes of the pie discipline
type PieXStats ¶
type PieXStats struct {
Prob uint64
Delay uint32
AvgDqRate uint32
PacketsIn uint32
Dropped uint32
Overlimit uint32
Maxq uint32
EcnMark uint32
}
PieXStats from include/uapi/linux/pkt_sched.h
type Plug ¶
type Plug struct {
Action PlugAction
Limit uint32
}
type PlugAction ¶
type PlugAction int32
const ( PlugBuffer PlugAction = iota PlugReleaseOne PlugReleaseIndefinite PlugLimit )
type Police ¶
type Police struct {
Tbf *Policy
Rate *RateSpec
PeakRate *RateSpec
AvRate *uint32
Result *uint32
Tm *Tcft
Rate64 *uint64
PeakRate64 *uint64
}
Police represents policing attributes of various filters and classes
type Policy ¶
type Policy struct {
Index uint32
Action PolicyAction
Limit uint32
Burst uint32
Mtu uint32
Rate RateSpec
PeakRate RateSpec
RefCnt uint32
BindCnt uint32
Capab uint32
}
Policy from include/uapi/linux/pkt_sched.h
type PolicyAction ¶
type PolicyAction uint32
PolicyAction defines the action that is applied by Policy.
const ( PolicyOk PolicyAction = iota PolicyReclassify PolicyShot PolicyPipe )
Default Policy actions. PolicyUnspec - skipped as it is -1
type Qdisc ¶
type Qdisc struct {
Tc
}
Qdisc represents the queueing discipline part of traffic control
Example ¶
This example demonstraces how to add a qdisc to an interface and delete it again
tcIface := "ExampleQdisc"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
// open a rtnetlink socket
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := rtnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(0xFFFF, 0x0000),
Parent: 0xFFFFFFF1,
Info: 0,
},
tc.Attribute{
Kind: "clsact",
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign clsact to lo: %v\n", err)
return
}
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete clsact qdisc from lo: %v\n", err)
return
}
func (*Qdisc) Get ¶
Get fetches all queueing disciplines
Example ¶
This example demonstrate how Get() can get used to read information
package main
import (
"fmt"
"net"
"os"
"github.com/xcxinng/go-tc"
)
func main() {
// open a rtnetlink socket
rtnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := rtnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdiscs, err := rtnl.Qdisc().Get()
if err != nil {
fmt.Fprintf(os.Stderr, "could not get qdiscs: %v\n", err)
return
}
for _, qdisc := range qdiscs {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%s\n", iface.Name, qdisc.Kind)
}
}
Output:
type RateSpec ¶
type RateSpec struct {
CellLog uint8
Linklayer uint8
Overhead uint16
CellAlign uint16
Mpu uint16
Rate uint32
}
RateSpec from include/uapi/linux/pkt_sched.h
type RedQOpt ¶
type RedQOpt struct {
Limit uint32
QthMin uint32
QthMax uint32
Wlog byte
Plog byte
ScellLog byte
Flags byte
}
RedQOpt from include/uapi/linux/pkt_sched.h
type RsvpPInfo ¶
type RsvpPInfo struct {
Dpi RsvpGpi
Spi RsvpGpi
Protocol uint8
TunnelID uint8
TunnelHdr uint8
Pad uint8
}
RsvpPInfo from include/uapi/linux/pkt_sched.h
type Sample ¶
type Sample struct {
Parms *SampleParms
Tm *Tcft
Rate *uint32
TruncSize *uint32
SampleGroup *uint32
}
Sample contains attribute of the Sample discipline
type SampleParms ¶
SampleParms from from include/uapi/linux/tc_act/tc_sample.h
type ServiceCurve ¶
ServiceCurve from include/uapi/linux/pkt_sched.h
type SfbQopt ¶
type SfbQopt struct {
RehashInterval uint32 // in ms
WarmupTime uint32 // in ms
Max uint32
BinSize uint32
Increment uint32
Decrement uint32
Limit uint32
PenaltyRate uint32
PenaltyBurst uint32
}
SfbQopt from include/uapi/linux/pkt_sched.h
type SfbXStats ¶
type SfbXStats struct {
EarlyDrop uint32
PenaltyDrop uint32
BucketDrop uint32
QueueDrop uint32
ChildDrop uint32
Marked uint32
MaxQlen uint32
MaxProb uint32
AvgProb uint32
}
SfbXStats from include/uapi/linux/pkt_sched.h
type Sfq ¶
type Sfq struct {
V0 SfqQopt
Depth uint32 /* max number of packets per flow */
Headdrop uint32
/* SFQRED parameters */
Limit uint32 /* HARD maximal flow queue length (bytes) */
QthMin uint32 /* Min average length threshold (bytes) */
QthMax uint32 /* Max average length threshold (bytes) */
Wlog uint8 /* log(W) */
Plog uint8 /* log(P_max/(qth_max-qth_min)) */
ScellLog uint8 /* cell size for idle damping */
Flags uint8
MaxP uint32 /* probability, high resolution */
}
type SfqXStats ¶
type SfqXStats struct {
Allot int32
}
SfqXStats from include/uapi/linux/pkt_sched.h
type SizeSpec ¶
type SizeSpec struct {
CellLog uint8
SizeLog uint8
CellAlign int16
Overhead int32
LinkLayer uint32
MPU uint32
MTU uint32
TSize uint32
}
SizeSpec implements tc_sizespec
type Stab ¶
Stab contains attributes of a stab http://man7.org/linux/man-pages/man8/tc-stab.8.html
type Stats ¶
type Stats struct {
Bytes uint64 /* Number of enqueued bytes */
Packets uint32 /* Number of enqueued packets */
Drops uint32 /* Packets dropped because of lack of resources */
Overlimits uint32 /* Number of throttle events when this
* flow goes out of allocated bandwidth */
Bps uint32 /* Current flow byte rate */
Pps uint32 /* Current flow packet rate */
Qlen uint32
Backlog uint32
}
Stats from include/uapi/linux/pkt_sched.h
type Stats2 ¶
type Stats2 struct {
// gnet_stats_basic
Bytes uint64
Packets uint32
//gnet_stats_queue
Qlen uint32
Backlog uint32
Drops uint32
Requeues uint32
Overlimits uint32
}
Stats2 from include/uapi/linux/pkt_sched.h
type Tbf ¶
Tbf contains attributes of the TBF discipline
Example ¶
tcIface := "tcExampleTbf"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
linklayerEthernet := uint8(1)
burst := uint32(0x500000)
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: core.BuildHandle(tc.HandleRoot, 0x0),
Parent: tc.HandleRoot,
Info: 0,
},
tc.Attribute{
Kind: "tbf",
Tbf: &tc.Tbf{
Parms: &tc.TbfQopt{
Mtu: 1514,
Limit: 0x5000,
Rate: tc.RateSpec{
Rate: 0x7d00,
Linklayer: linklayerEthernet,
CellLog: 0x3,
},
},
Burst: &burst,
},
},
}
// tc qdisc add dev tcExampleTbf root tbf burst 20480 limit 20480 mtu 1514 rate 32000bps
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign tbf to %s: %v\n", tcIface, err)
return
}
defer func() {
if err := tcnl.Qdisc().Delete(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not delete tbf qdisc of %s: %v\n", tcIface, err)
return
}
}()
qdiscs, err := tcnl.Qdisc().Get()
if err != nil {
fmt.Fprintf(os.Stderr, "could not get all qdiscs: %v\n", err)
//return
}
fmt.Println("## qdiscs:")
for _, qdisc := range qdiscs {
iface, err := net.InterfaceByIndex(int(qdisc.Ifindex))
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface from id %d: %v", qdisc.Ifindex, err)
return
}
fmt.Printf("%20s\t%-11s\n", iface.Name, qdisc.Kind)
}
type Tc ¶
type Tc struct {
// contains filtered or unexported fields
}
Tc represents a RTNETLINK wrapper
func (*Tc) Monitor
deprecated
Monitor NETLINK_ROUTE messages
Deprecated: Use MonitorWithErrorFunc() instead.
Example ¶
This example demonstrates how Monitor() can be used
package main
import (
"context"
"fmt"
"time"
"github.com/xcxinng/go-tc"
)
func main() {
tcSocket, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Printf("could not open socket for TC: %v", err)
return
}
defer func() {
if err := tcSocket.Close(); err != nil {
fmt.Printf("coult not close TC socket: %v", err)
return
}
}()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Hook function mon, which is called every time,
// something is received by the kernel on this socket
mon := func(action uint16, m tc.Object) int {
fmt.Printf("Action:\t%d\nObject: \t%#v\n", action, m)
return 0
}
tcSocket.Monitor(ctx, 10*time.Millisecond, mon)
<-ctx.Done()
}
Output:
type TunnelKey ¶
type TunnelKey struct {
Parms *TunnelParms
Tm *Tcft
KeyEncSrc *net.IP
KeyEncDst *net.IP
KeyEncKeyID *uint32
KeyEncDstPort *uint16
KeyNoCSUM *uint8
KeyEncTOS *uint8
KeyEncTTL *uint8
}
TunnelKey contains attribute of the TunnelKey discipline
type TunnelParms ¶
type TunnelParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
TunnelKeyAction uint32
}
TunnelParms from from include/uapi/linux/tc_act/tc_tunnel_key.h
type U32 ¶
type U32 struct {
ClassID *uint32
Hash *uint32
Link *uint32
Divisor *uint32
Sel *U32Sel
InDev *string
Pcnt *uint64
Mark *U32Mark
Flags *uint32
Police *Police
Actions *[]*Action
}
U32 contains attributes of the u32 discipline
Example ¶
// example from http://man7.org/linux/man-pages/man8/tc-police.8.html
tcIface := "ExampleU32"
rtnl, err := setupDummyInterface(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not setup dummy interface: %v\n", err)
return
}
defer rtnl.Close()
devID, err := net.InterfaceByName(tcIface)
if err != nil {
fmt.Fprintf(os.Stderr, "could not get interface ID: %v\n", err)
return
}
defer func(devID uint32, rtnl *rtnetlink.Conn) {
if err := rtnl.Link.Delete(devID); err != nil {
fmt.Fprintf(os.Stderr, "could not delete interface: %v\n", err)
}
}(uint32(devID.Index), rtnl)
tcnl, err := tc.Open(&tc.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
return
}
defer func() {
if err := tcnl.Close(); err != nil {
fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
}
}()
qdisc := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: 0,
Parent: 0xFFFF0000,
Info: 768,
},
tc.Attribute{
Kind: "u32",
U32: &tc.U32{
Sel: &tc.U32Sel{
Flags: 0x1,
NKeys: 0x3,
Keys: []tc.U32Key{
// match ip protocol 6 0xff
{Mask: 0xff0000, Val: 0x60000, Off: 0x800, OffMask: 0x0},
{Mask: 0xff000f00, Val: 0x5c0, Off: 0x0, OffMask: 0x0},
{Mask: 0xff0000, Val: 0x100000, Off: 0x2000, OffMask: 0x0},
},
},
Police: &tc.Police{
Tbf: &tc.Policy{
Action: 0x1,
Burst: 0xc35000,
Rate: tc.RateSpec{
CellLog: 0x3,
Linklayer: 0x1,
CellAlign: 0xffff,
Rate: 0x1e848,
},
},
},
},
},
}
if err := tcnl.Qdisc().Add(&qdisc); err != nil {
fmt.Fprintf(os.Stderr, "could not assign clsact to lo: %v\n", err)
return
}
// when deleting the qdisc, the applied filter will also be gone
defer tcnl.Qdisc().Delete(&qdisc)
ops := []byte{0x6, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff}
opsLen := uint16(1)
classID := uint32(0x1001)
flags := uint32(0x1)
filter := tc.Object{
tc.Msg{
Family: unix.AF_UNSPEC,
Ifindex: uint32(devID.Index),
Handle: 0,
Parent: tc.HandleIngress,
Info: 0x300,
},
tc.Attribute{
Kind: "bpf",
BPF: &tc.Bpf{
Ops: &ops,
OpsLen: &opsLen,
ClassID: &classID,
Flags: &flags,
},
},
}
if err := tcnl.Filter().Add(&filter); err != nil {
fmt.Fprintf(os.Stderr, "could not assign cBPF: %v\n", err)
return
}
type U32Sel ¶
type U32Sel struct {
Flags uint8
Offshift uint8
NKeys uint8
OffMask uint16
Off uint16
Offoff uint16
Hoff uint16
Hmask uint32
Keys []U32Key
}
U32Sel from include/uapi/linux/pkt_sched.h
type VLan ¶
type VLan struct {
Parms *VLanParms
Tm *Tcft
PushID *uint16
PushProtocol *uint16
PushPriority *uint32
}
VLan contains attribute of the VLan discipline
type VLanParms ¶
type VLanParms struct {
Index uint32
Capab uint32
Action uint32
RefCnt uint32
BindCnt uint32
VLanAction uint32
}
VLanParms from from include/uapi/linux/tc_act/tc_vlan.h
type XStats ¶
type XStats struct {
Sfb *SfbXStats
Sfq *SfqXStats
Red *RedXStats
Choke *ChokeXStats
Htb *HtbXStats
Cbq *CbqXStats
Codel *CodelXStats
Hhf *HhfXStats
Pie *PieXStats
FqCodel *FqCodelXStats
Hfsc *HfscXStats
}
XStats contains further statistics to the TCA_KIND
Source Files
¶
- attributeTcMsg.go
- chain.go
- class.go
- converter.go
- doc.go
- ematch.go
- ematch_cmp.go
- ematch_ipset.go
- ematch_u32.go
- errors.go
- f_basic.go
- f_bpf.go
- f_cgroup.go
- f_flow.go
- f_flower.go
- f_fw.go
- f_matchall.go
- f_route4.go
- f_rsvp.go
- f_tcindex.go
- f_u32.go
- filter.go
- helper.go
- m_action.go
- m_bpf.go
- m_connmark.go
- m_csum.go
- m_defact.go
- m_gact.go
- m_gate.go
- m_ife.go
- m_ipt.go
- m_mirred.go
- m_nat.go
- m_police.go
- m_sample.go
- m_tunnel_key.go
- m_vlan.go
- nest.go
- q_atm.go
- q_cake.go
- q_cbq.go
- q_choke.go
- q_codel.go
- q_drr.go
- q_dsmark.go
- q_ets.go
- q_fq.go
- q_fqCodel.go
- q_hfsc.go
- q_hhf.go
- q_htb.go
- q_mqPrio.go
- q_netem.go
- q_pie.go
- q_plug.go
- q_prio.go
- q_qfq.go
- q_red.go
- q_sfb.go
- q_sfq.go
- q_tbf.go
- qdisc.go
- ratetable.go
- stab.go
- stats.go
- structs.go
- tc.go
- tc_gteq_1.16.go
- types.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package core contains some generic helper functions for the package github.com/florianl/go-tc.
|
Package core contains some generic helper functions for the package github.com/florianl/go-tc. |
|
internal
|
|
|
unix
Package unix contains some constants, that are needed to use github.com/florianl/go-tc.
|
Package unix contains some constants, that are needed to use github.com/florianl/go-tc. |