tc

package module
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2021 License: MIT Imports: 14 Imported by: 0

README

tc PkgGoDev Go Report Card GitHub Actions Coverage Status

This is a work in progress version of tc. It provides a C-binding free API to the netlink based traffic control system of rtnetlink.

Example

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)
		}
	}()

    // get all the qdiscs from all interfaces
	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)
	}
}

Requirements

Privileges

This package processes information directly from the kernel and therefore it requires special privileges. You can provide this privileges by adjusting the CAP_NET_ADMIN capabilities.

	setcap 'cap_net_admin=+ep' /your/executable

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

Examples

Constants

View Source
const (
	EmatchLayerLink      = EmatchLayer(0)
	EmatchLayerNetwork   = EmatchLayer(1)
	EmatchLayerTransport = EmatchLayer(2)
)
View Source
const (
	EmatchOpndEq = EmatchOpnd(0)
	EmatchOpndGt = EmatchOpnd(1)
	EmatchOpndLt = EmatchOpnd(2)
)
View Source
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

View Source
const (
	CmpMatchU8  = CmpMatchAlign(1)
	CmpMatchU16 = CmpMatchAlign(2)
	CmpMatchU32 = CmpMatchAlign(4)
)
View Source
const (
	ActBind      = 1
	ActNoBind    = 0
	ActUnbind    = 1
	ActNoUnbind  = 0
	ActReplace   = 1
	ActNoReplace = 0
)
View Source
const (
	ActOk         = 0
	ActReclassify = 1
	ActShot       = 2
	ActPipe       = 3
	ActStolen     = 4
	ActQueued     = 5
	ActRepeat     = 6
	ActRedirect   = 7
	ActTrap       = 8
)
View Source
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

View Source
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

View Source
const (
	BpfActDirect = 1
)

Flags defined by the kernel for the BPF filter

View Source
const (
	CmpMatchTrans = CmpMatchFlag(1)
)

Variables

View Source
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

type ActBpfParms struct {
	Index   uint32
	Capab   uint32
	Action  uint32
	Refcnt  uint32
	Bindcnt uint32
}

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
	Gate      *Gate
	Ife       *Ife
	Ipt       *Ipt
	Mirred    *Mirred
	Nat       *Nat
	Sample    *Sample
	VLan      *VLan
	Police    *Police
	TunnelKey *TunnelKey
	Gact      *Gact
}

Action represents action attributes of various filters and classes

type Atm

type Atm struct {
	FD     *uint32
	Excess *uint32
	Addr   *AtmPvc
	State  *uint32
}

Atm contains attributes of the atm discipline

type AtmPvc

type AtmPvc struct {
	SapFamily byte
	Itf       byte
	Vpi       byte
	Vci       byte
}

AtmPvc from include/uapi/linux/atm.h

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
	Red     *Red
	MqPrio  *MqPrio
	Pfifo   *FifoOpt
	Bfifo   *FifoOpt
	Choke   *Choke
	Netem   *Netem

	// Classful qdiscs
	Htb      *Htb
	Hfsc     *Hfsc
	HfscQOpt *HfscQOpt
	Dsmark   *Dsmark
	Drr      *Drr
	Cbq      *Cbq
	Atm      *Atm
	Qfq      *Qfq
}

Attribute contains various elements for traffic control

type Basic

type Basic struct {
	ClassID *uint32
	Police  *Police
	Ematch  *Ematch
}

Basic contains attributes of the basic discipline

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 CbqFOpt

type CbqFOpt struct {
	Split     uint32
	Defmap    uint32
	Defchange uint32
}

CbqFOpt from include/uapi/linux/pkt_sched.h

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 CbqOvl

type CbqOvl struct {
	Strategy  byte
	Priority2 byte
	Pad       uint16
	Penalty   uint32
}

CbqOvl from include/uapi/linux/pkt_sched.h

type CbqPolice

type CbqPolice struct {
	Police byte
	Res1   byte
	Res2   uint16
}

CbqPolice 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 CbqXStats

type CbqXStats struct {
	Borrows     uint32
	Overactions uint32
	AvgIdle     int32
	Undertime   int32
}

CbqXStats from include/uapi/linux/pkt_sched.h

type Cgroup

type Cgroup struct {
	Action *Action
	Ematch *Ematch
}

Cgroup contains attributes of the cgroup discipline

type Chain

type Chain struct {
	Tc
}

Chain represents a collection of filter

func (*Chain) Add

func (c *Chain) Add(info *Object) error

Add creates a new chain

func (*Chain) Delete

func (c *Chain) Delete(info *Object) error

Delete removes a chain

func (*Chain) Get

func (c *Chain) Get(i *Msg) ([]Object, error)

Get fetches chains

type Choke

type Choke struct {
	Parms *RedQOpt
	MaxP  *uint32
}

Choke contains attributes of the choke discipline

type ChokeXStats

type ChokeXStats struct {
	Early   uint32
	PDrop   uint32
	Other   uint32
	Marked  uint32
	Matched uint32
}

ChokeXStats from include/uapi/linux/pkt_sched.h

type Class

type Class struct {
	Tc
}

Class represents the class part of rtnetlink

func (*Class) Add

func (c *Class) Add(info *Object) error

Add creats a new class

func (*Class) Delete

func (c *Class) Delete(info *Object) error

Delete removes a class

func (*Class) Get

func (c *Class) Get(i *Msg) ([]Object, error)

Get fetches all classes

func (*Class) Replace

func (c *Class) Replace(info *Object) error

Replace add/remove a class. If the node does not exist yet it is created

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 Codel

type Codel struct {
	Target      *uint32
	Limit       *uint32
	Interval    *uint32
	ECN         *uint32
	CEThreshold *uint32
}

Codel contains attributes of the codel discipline

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 Csum

type Csum struct {
	Parms *CsumParms
	Tm    *Tcft
}

Csum contains attributes of the csum discipline

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

type DefactParms struct {
	Index   uint32
	Capab   uint32
	Action  uint32
	RefCnt  uint32
	BindCnt uint32
}

DefactParms from include/uapi/linux/tc_act/tc_defact.h

type Drr

type Drr struct {
	Quantum *uint32
}

Drr contains attributes of the drr discipline

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
}

type EmatchOpnd

type EmatchOpnd uint8

type EmatchTreeHdr

type EmatchTreeHdr struct {
	NMatches uint16
	ProgID   uint16
}

tcf_ematch_tree_hdr from include/uapi/linux/pkt_cls.h

type Ets

type Ets struct {
	NBands  *uint8
	NStrict *uint8
	Quanta  *[]uint32
	PrioMap *[]uint8
}

Ets represents a struct for Enhanced Transmission Selection, a 802.1Qaz-based Qdisc. More info at https://lwn.net/Articles/805229/

type FifoOpt

type FifoOpt struct {
	Limit uint32
}

FifoOpt from include/uapi/linux/pkt_sched.h

type Filter

type Filter struct {
	Tc
}

Filter represents the filtering part of rtnetlink

func (*Filter) Add

func (f *Filter) Add(info *Object) error

Add create a new filter

func (*Filter) Delete

func (f *Filter) Delete(info *Object) error

Delete removes a filter

func (*Filter) Get

func (f *Filter) Get(i *Msg) ([]Object, error)

Get fetches all filters

func (*Filter) Replace

func (f *Filter) Replace(info *Object) error

Replace add/remove a filter. If the node does not exist yet it is created

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.IPMask
	KeyIPv4Dst           *net.IP
	KeyIPv4DstMask       *net.IPMask
	KeyTCPSrc            *uint16
	KeyTCPDst            *uint16
	KeyUDPSrc            *uint16
	KeyUDPDst            *uint16
	Flags                *uint32
	KeyVlanID            *uint16
	KeyVlanPrio          *uint8
	KeyVlanEthType       *uint16
	KeyEncKeyID          *uint32
	KeyEncIPv4Src        *net.IP
	KeyEncIPv4SrcMask    *net.IPMask
	KeyEncIPv4Dst        *net.IP
	KeyEncIPv4DstMask    *net.IPMask
	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

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 Fw

type Fw struct {
	ClassID *uint32
	Police  *Police
	InDev   *string
	Mask    *uint32
}

Fw contains attributes of the fw discipline

type Gact

type Gact struct {
	Parms *GactParms
	Tm    *Tcft
	Prob  *GactProb
}

Gact contains attribute of the Gact discipline

type GactParms

type GactParms struct {
	Index   uint32
	Capab   uint32
	Action  uint32
	RefCnt  uint32
	BindCnt uint32
}

GactParms include attributes from include/uapi/linux/tc_act/tc_gact.h

type GactProb

type GactProb struct {
	Ptype   uint16
	Pval    uint16
	Paction uint64
}

GactProb defines the type of generic action that will be taken

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 GateParms

type GateParms struct {
	Index   uint32
	Capab   uint32
	Action  uint32
	RefCnt  uint32
	BindCnt uint32
}

GateParms from include/uapi/linux/tc_act/tc_gate.h

type GenBasic

type GenBasic struct {
	Bytes   uint64
	Packets uint32
}

GenBasic from include/uapi/linux/gen_stats.h

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

type GenRateEst struct {
	BytePerSecond   uint32
	PacketPerSecond uint32
}

GenRateEst from include/uapi/linux/gen_stats.h

type GenRateEst64

type GenRateEst64 struct {
	BytePerSecond   uint64
	PacketPerSecond uint64
}

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/dennisafa/go-tc"
	"github.com/dennisafa/go-tc/core"
	"github.com/jsimonetti/rtnetlink"
	"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

type HfscXStats struct {
	Work   uint64
	RtWork uint64
	Period uint32
	Level  uint32
}

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

type HookFunc func(action uint16, m Object) int

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 HtbXStats

type HtbXStats struct {
	Lends   uint32
	Borrows uint32
	Giants  uint32
	Tokens  uint32
	CTokens uint32
}

HtbXStats from include/uapi/linux/pkt_sched.h

type Ife

type Ife struct {
	Parms *IfeParms
	SMac  *[]byte
	DMac  *[]byte
	Type  *uint16
	Tm    *Tcft
}

Ife contains attribute of the ife discipline

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 Ipt

type Ipt struct {
	Table *string
	Hook  *uint32
	Index *uint32
	Cnt   *IptCnt
	Tm    *Tcft
}

Ipt contains attribute of the ipt discipline

type IptCnt

type IptCnt struct {
	RefCnt  uint32
	BindCnt uint32
}

IptCnt as tc_cnt from include/uapi/linux/pkt_cls.h

type Matchall

type Matchall struct {
	ClassID *uint32
	Actions *[]*Action
	Flags   *uint32
}

Matchall contains attributes of the matchall discipline

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 {
	Mode      *uint16
	Shaper    *uint16
	MinRate64 *uint64
	MaxRate64 *uint64
}

MqPrio contains attributes of the mqprio discipline

type Msg

type Msg struct {
	Family  uint32
	Ifindex uint32
	Handle  uint32
	Parent  uint32
	Info    uint32
}

Msg represents a Traffic Control Message

type Nat

type Nat struct {
	Parms *NatParms
	Tm    *Tcft
}

Nat contains attribute of the nat discipline

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 NetemCorr

type NetemCorr struct {
	Delay uint32
	Loss  uint32
	Dup   uint32
}

NetemCorr from include/uapi/linux/pkt_sched.h

type NetemCorrupt

type NetemCorrupt struct {
	Probability uint32
	Correlation uint32
}

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 NetemRate

type NetemRate struct {
	Rate           uint32
	PacketOverhead int32
	CellSize       int32
	CellOverhead   int32
}

NetemRate from include/uapi/linux/pkt_sched.h

type NetemReorder

type NetemReorder struct {
	Probability uint32
	Correlation uint32
}

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 Object

type Object struct {
	Msg
	Attribute
}

Object represents a generic traffic control object

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 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) Add

func (qd *Qdisc) Add(info *Object) error

Add creates a new queueing discipline

func (*Qdisc) Change

func (qd *Qdisc) Change(info *Object) error

Change modifies a queueing discipline 'in place'

func (*Qdisc) Delete

func (qd *Qdisc) Delete(info *Object) error

Delete removes a queueing discipline

func (*Qdisc) Get

func (qd *Qdisc) Get() ([]Object, error)

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:

func (qd *Qdisc) Link(info *Object) error

Link performs a replace on an existing queueing discipline

func (*Qdisc) Replace

func (qd *Qdisc) Replace(info *Object) error

Replace add/remove a queueing discipline. If the node does not exist yet it is created

type Qfq

type Qfq struct {
	Weight *uint32
	Lmax   *uint32
}

Qfq contains attributes of the qfq discipline

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 Red

type Red struct {
	Parms *RedQOpt
	MaxP  *uint32
}

Red contains attributes of the red discipline

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 RedXStats

type RedXStats struct {
	Early  uint32
	PDrop  uint32
	Other  uint32
	Marked uint32
}

RedXStats from include/uapi/linux/pkt_sched.h

type Route4

type Route4 struct {
	ClassID *uint32
	To      *uint32
	From    *uint32
	IIf     *uint32
}

Route4 contains attributes of the route discipline

type Rsvp

type Rsvp struct {
	ClassID *uint32
	Dst     *[]byte
	Src     *[]byte
	PInfo   *RsvpPInfo
	Police  *Police
}

Rsvp contains attributes of the rsvp discipline

type RsvpGpi

type RsvpGpi struct {
	Key    uint32
	Mask   uint32
	Offset uint32
}

RsvpGpi 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

type SampleParms struct {
	Index   uint32
	Capab   uint32
	Action  uint32
	RefCnt  uint32
	BindCnt uint32
}

SampleParms from from include/uapi/linux/tc_act/tc_sample.h

type ServiceCurve

type ServiceCurve struct {
	M1 uint32
	D  uint32
	M2 uint32
}

ServiceCurve from include/uapi/linux/pkt_sched.h

type Sfb

type Sfb struct {
	Parms *SfbQopt
}

Sfb contains attributes of the SBF discipline

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 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

type Stab struct {
	Base *SizeSpec
	Data *[]byte
}

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

type Tbf struct {
	Parms  *TbfQopt
	Burst  *uint32
	Pburst *uint32
}

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 TbfQopt

type TbfQopt struct {
	Rate     RateSpec
	PeakRate RateSpec
	Limit    uint32
	Buffer   uint32
	Mtu      uint32
}

TbfQopt from include/uapi/linux/pkt_sched.h

type Tc

type Tc struct {
	// contains filtered or unexported fields
}

Tc represents a RTNETLINK wrapper

func Open

func Open(config *Config) (*Tc, error)

Open establishes a RTNETLINK socket for traffic control

func (*Tc) Chain

func (tc *Tc) Chain() *Chain

Chain allows to read and alter chains

func (*Tc) Class

func (tc *Tc) Class() *Class

Class allows to read and alter classes

func (*Tc) Close

func (tc *Tc) Close() error

Close the connection

func (*Tc) Filter

func (tc *Tc) Filter() *Filter

Filter allows to read and alter filters

func (*Tc) Monitor

func (tc *Tc) Monitor(ctx context.Context, deadline time.Duration, fn HookFunc) error

Monitor NETLINK_ROUTE messages

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:

func (*Tc) Qdisc

func (tc *Tc) Qdisc() *Qdisc

Qdisc allows to read and alter queues

type TcIndex

type TcIndex struct {
	Hash        *uint32
	Mask        *uint16
	Shift       *uint32
	FallThrough *uint32
	ClassID     *uint32
}

TcIndex contains attributes of the tcIndex discipline

type Tcft

type Tcft struct {
	Install  uint64
	LastUse  uint64
	Expires  uint64
	FirstUse uint64
}

Tcft from include/uapi/linux/pkt_sched.h

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 U32Key

type U32Key struct {
	Mask    uint32
	Val     uint32
	Off     uint32
	OffMask uint32
}

U32Key from include/uapi/linux/pkt_sched.h

type U32Mark

type U32Mark struct {
	Val     uint32
	Mask    uint32
	Success uint32
}

U32Mark from include/uapi/linux/pkt_sched.h

type U32Match

type U32Match struct {
	Mask    uint32 // big endian
	Value   uint32 // big endian
	Off     int32
	OffMask int32
}

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

Directories

Path Synopsis
Package core contains some generic helper functions for the package github.com/dennisafa/go-tc.
Package core contains some generic helper functions for the package github.com/dennisafa/go-tc.
internal
unix
Package unix contains some constants, that are needed to use github.com/dennisafa/go-tc.
Package unix contains some constants, that are needed to use github.com/dennisafa/go-tc.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL