mirror of https://github.com/vishvananda/netlink
Allow setting socket timeout on Handle
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
ffec63e1f1
commit
17ea11b5a1
|
@ -1,7 +1,9 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"github.com/vishvananda/netns"
|
||||
|
@ -33,6 +35,29 @@ 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
|
||||
|
|
|
@ -8,7 +8,10 @@ import (
|
|||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"github.com/vishvananda/netns"
|
||||
|
@ -107,6 +110,48 @@ func TestHandleCreateNetns(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestHandleTimeout(t *testing.T) {
|
||||
h, err := NewHandle()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer h.Delete()
|
||||
|
||||
for _, sh := range h.sockets {
|
||||
verifySockTimeVal(t, sh.Socket.GetFd(), syscall.Timeval{Sec: 0, Usec: 0})
|
||||
}
|
||||
|
||||
h.SetSocketTimeout(2*time.Second + 8*time.Millisecond)
|
||||
|
||||
for _, sh := range h.sockets {
|
||||
verifySockTimeVal(t, sh.Socket.GetFd(), syscall.Timeval{Sec: 2, Usec: 8000})
|
||||
}
|
||||
}
|
||||
|
||||
func verifySockTimeVal(t *testing.T, fd int, tv syscall.Timeval) {
|
||||
var (
|
||||
tr syscall.Timeval
|
||||
v = uint32(0x10)
|
||||
)
|
||||
_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, uintptr(unsafe.Pointer(&tr)), uintptr(unsafe.Pointer(&v)), 0)
|
||||
if errno != 0 {
|
||||
t.Fatal(errno)
|
||||
}
|
||||
|
||||
if tr.Sec != tv.Sec || tr.Usec != tv.Usec {
|
||||
t.Fatalf("Unexpected timeout value read: %v. Expected: %v", tr, tv)
|
||||
}
|
||||
|
||||
_, _, errno = syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, uintptr(unsafe.Pointer(&tr)), uintptr(unsafe.Pointer(&v)), 0)
|
||||
if errno != 0 {
|
||||
t.Fatal(errno)
|
||||
}
|
||||
|
||||
if tr.Sec != tv.Sec || tr.Usec != tv.Usec {
|
||||
t.Fatalf("Unexpected timeout value read: %v. Expected: %v", tr, tv)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
iter = 10
|
||||
numThread = uint32(4)
|
||||
|
|
Loading…
Reference in New Issue