florianl / go-tc

traffic control in pure go - it allows to read and alter queues, filters and classes
MIT License
439 stars 48 forks source link
bpf class ebpf filter go linux network qdisc qos rtnetlink traffic-control

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

package main

import (
    "fmt"
    "net"
    "os"

    "github.com/mdlayher/netlink"

    "github.com/florianl/go-tc"
)

func main() {
    // open a rtnetlink socket
    rtnl, err := tc.Open(&tc.Config{})
    if err != nil {
        fmt.Fprintf(os.Stderr, "could not open rtnetlink socket: %v\n", err)
        return
    }
    defer func() {
        if err := rtnl.Close(); err != nil {
            fmt.Fprintf(os.Stderr, "could not close rtnetlink socket: %v\n", err)
        }
    }()

    // For enhanced error messages from the kernel, it is recommended to set
    // option `NETLINK_EXT_ACK`, which is supported since 4.12 kernel.
    //
    // If not supported, `unix.ENOPROTOOPT` is returned.

    err = rtnl.SetOption(netlink.ExtendedAcknowledge, true)
    if err != nil {
        fmt.Fprintf(os.Stderr, "could not set option ExtendedAcknowledge: %v\n", err)
        return
    }

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