Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions handle_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,15 @@ type HandleOptions struct {
// [ErrDumpInterrupted].
RetryInterrupted bool

// NetNS specifies the network namespace to operate on. If not set, the
// current network namespace will be used.
// NetNS specifies the network namespace in which the Handle's persistent
// netlink sockets are created. A persistent socket remains bound to its
// creation namespace even if the calling OS thread later changes namespaces.
//
// When NetNS is non-nil, persistent sockets are created in that namespace.
// When NetNS is nil, persistent sockets are created in the calling OS thread's
// current namespace when the Handle is created. A socketless Handle instead
// creates a temporary socket for each operation in the calling OS thread's
// current namespace when the operation is executed.
NetNS *netns.NsHandle
}

Expand Down Expand Up @@ -199,7 +206,13 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
}

// NewHandleWithOptions returns a Handle created using the specified options.
// If DisableVFInfoCollection is the only option set and no netlink families are
// specified, the returned Handle creates a socket for each request in the
// caller's current network namespace instead of keeping persistent sockets.
func NewHandleWithOptions(opts HandleOptions, nlFamilies ...int) (*Handle, error) {
if opts.DisableVFInfoCollection && !opts.RetryInterrupted && opts.NetNS == nil && len(nlFamilies) == 0 {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how widely is NewHandleWithOptions() used now, so just want to open a small window to allow disabling VFInfoCollection without init Handle.sockets.

return &Handle{options: opts}, nil
}
return newHandle(netns.None(), opts, nlFamilies...)
}

Expand Down
61 changes: 61 additions & 0 deletions handle_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"time"

"github.com/stretchr/testify/assert"
"github.com/vishvananda/netns"
"golang.org/x/sys/unix"
)

func TestSetGetSocketTimeout(t *testing.T) {
Expand Down Expand Up @@ -34,3 +36,62 @@ func TestConfigureHandle(t *testing.T) {
assert.NoError(t, pkgHandle.Close())
assert.Error(t, ConfigureHandle(HandleOptions{}))
}

func TestNewHandleWithOptions(t *testing.T) {
none := netns.None()
tests := []struct {
name string
opts HandleOptions
nlFamilies []int
wantSocketless bool
}{
{
name: "disable VF only",
opts: HandleOptions{DisableVFInfoCollection: true},
wantSocketless: true,
},
{
name: "retry interrupted",
opts: HandleOptions{
DisableVFInfoCollection: true,
RetryInterrupted: true,
},
},
{
name: "explicit namespace",
opts: HandleOptions{
DisableVFInfoCollection: true,
NetNS: &none,
},
},
{
name: "explicit netlink family",
opts: HandleOptions{DisableVFInfoCollection: true},
nlFamilies: []int{unix.NETLINK_ROUTE},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h, err := NewHandleWithOptions(tt.opts, tt.nlFamilies...)
if !assert.NoError(t, err) {
return
}
t.Cleanup(func() { assert.NoError(t, h.Close()) })

assert.True(t, h.options.DisableVFInfoCollection)
if tt.wantSocketless {
assert.Nil(t, h.sockets)
} else {
assert.NotNil(t, h.sockets)
}

req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
if tt.wantSocketless {
assert.Nil(t, req.Sockets)
} else {
assert.NotNil(t, req.Sockets)
}
})
}
}
Loading