8 "github.com/vishvananda/netlink/nl"
9 "github.com/vishvananda/netns"
12 // Empty handle used by the netlink package methods
13 var pkgHandle = &Handle{}
15 // Handle is an handle for the netlink requests on a
16 // specific network namespace. All the requests on the
17 // same netlink family share the same netlink socket,
18 // which gets released when the handle is deleted.
20 sockets map[int]*nl.SocketHandle
24 // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
25 func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
26 _, ok := h.sockets[nlFamily]
30 // NewHandle returns a netlink handle on the current network namespace.
31 // Caller may specify the netlink families the handle should support.
32 // If no families are specified, all the families the netlink package
33 // supports will be automatically added.
34 func NewHandle(nlFamilies ...int) (*Handle, error) {
35 return newHandle(netns.None(), netns.None(), nlFamilies...)
38 // SetSocketTimeout sets the send and receive timeout for each socket in the
39 // netlink handle. Although the socket timeout has granularity of one
40 // microsecond, the effective granularity is floored by the kernel timer tick,
41 // which default value is four milliseconds.
42 func (h *Handle) SetSocketTimeout(to time.Duration) error {
43 if to < time.Microsecond {
44 return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
46 tv := syscall.NsecToTimeval(to.Nanoseconds())
47 for _, sh := range h.sockets {
48 fd := sh.Socket.GetFd()
49 err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
53 err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
61 // NewHandle returns a netlink handle on the network namespace
62 // specified by ns. If ns=netns.None(), current network namespace
64 func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
65 return newHandle(ns, netns.None(), nlFamilies...)
68 // NewHandleAtFrom works as NewHandle but allows client to specify the
69 // new and the origin netns Handle.
70 func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
71 return newHandle(newNs, curNs)
74 func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
75 h := &Handle{sockets: map[int]*nl.SocketHandle{}}
76 fams := nl.SupportedNlFamilies
77 if len(nlFamilies) != 0 {
80 for _, f := range fams {
81 s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
85 h.sockets[f] = &nl.SocketHandle{Socket: s}
90 // Delete releases the resources allocated to this handle
91 func (h *Handle) Delete() {
92 for _, sh := range h.sockets {
98 func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
99 // Do this so that package API still use nl package variable nextSeqNr
100 if h.sockets == nil {
101 return nl.NewNetlinkRequest(proto, flags)
103 return &nl.NetlinkRequest{
104 NlMsghdr: syscall.NlMsghdr{
105 Len: uint32(syscall.SizeofNlMsghdr),
107 Flags: syscall.NLM_F_REQUEST | uint16(flags),