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 }
Output:
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 }
Output:
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) }
Output:
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) }
Output:
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) }
Output:
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 }
Output:
func (*Qdisc) Get ¶
Get fetches all queueing disciplines
Example ¶
This example demonstrate how Get() can get used to read information
// 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) }
Output:
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
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 }
Output:
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. |