123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- package netlink
- import (
- "fmt"
- "syscall"
- "time"
- "github.com/vishvananda/netlink/nl"
- "github.com/vishvananda/netns"
- )
- // Empty handle used by the netlink package methods
- var pkgHandle = &Handle{}
- // Handle is an handle for the netlink requests on a
- // specific network namespace. All the requests on the
- // same netlink family share the same netlink socket,
- // which gets released when the handle is deleted.
- type Handle struct {
- sockets map[int]*nl.SocketHandle
- lookupByDump bool
- }
- // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
- func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
- _, ok := h.sockets[nlFamily]
- return ok
- }
- // NewHandle returns a netlink handle on the current network namespace.
- // Caller may specify the netlink families the handle should support.
- // If no families are specified, all the families the netlink package
- // supports will be automatically added.
- func NewHandle(nlFamilies ...int) (*Handle, error) {
- return newHandle(netns.None(), netns.None(), nlFamilies...)
- }
- // SetSocketTimeout sets the send and receive timeout for each socket in the
- // netlink handle. Although the socket timeout has granularity of one
- // microsecond, the effective granularity is floored by the kernel timer tick,
- // which default value is four milliseconds.
- func (h *Handle) SetSocketTimeout(to time.Duration) error {
- if to < time.Microsecond {
- return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
- }
- tv := syscall.NsecToTimeval(to.Nanoseconds())
- for _, sh := range h.sockets {
- fd := sh.Socket.GetFd()
- err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
- if err != nil {
- return err
- }
- err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
- if err != nil {
- return err
- }
- }
- return nil
- }
- // NewHandle returns a netlink handle on the network namespace
- // specified by ns. If ns=netns.None(), current network namespace
- // will be assumed
- func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
- return newHandle(ns, netns.None(), nlFamilies...)
- }
- // NewHandleAtFrom works as NewHandle but allows client to specify the
- // new and the origin netns Handle.
- func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
- return newHandle(newNs, curNs)
- }
- func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
- h := &Handle{sockets: map[int]*nl.SocketHandle{}}
- fams := nl.SupportedNlFamilies
- if len(nlFamilies) != 0 {
- fams = nlFamilies
- }
- for _, f := range fams {
- s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
- if err != nil {
- return nil, err
- }
- h.sockets[f] = &nl.SocketHandle{Socket: s}
- }
- return h, nil
- }
- // Delete releases the resources allocated to this handle
- func (h *Handle) Delete() {
- for _, sh := range h.sockets {
- sh.Close()
- }
- h.sockets = nil
- }
- func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
- // Do this so that package API still use nl package variable nextSeqNr
- if h.sockets == nil {
- return nl.NewNetlinkRequest(proto, flags)
- }
- return &nl.NetlinkRequest{
- NlMsghdr: syscall.NlMsghdr{
- Len: uint32(syscall.SizeofNlMsghdr),
- Type: uint16(proto),
- Flags: syscall.NLM_F_REQUEST | uint16(flags),
- },
- Sockets: h.sockets,
- }
- }
|