Background
Sometimes we need to dial inside another net namespace and switch back. On linux, namespace is thread-level, so a thread lock is needed.
With "github.com/vishvananda/netns" for example:
func connect(target string, network, addr string) net.Conn {
dialer := &net.Dialer{}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
origNS, _ := netns.Get()
targetNS, _ := netns.GetFromName(target)
netns.Set(targetNS)
defer netns.Set(origNS)
conn, _ := dialer.Dial(network, addr)
return conn
}
However, this blocks the current thread until Dial() returns. A workaround may be moving the unlocking stuff into dialer.Control:
dialer.Control = func(network, address string, c syscall.RawConn) error {
netns.Set(origNS)
runtime.UnlockOSThread()
return nil
}
This doesn't work well because dialParallel() dials in new goroutines which are out of control.
Proposal
Add callback before and after the connection (socket) is created in net.Dialer:
type Dialer struct {
PreControl func(network, address string) error
PostControl func(network, address string) error
}
The call of PreControl - PostControl pair should be in the same goroutine and surround the socket syscall. PostControl should be called regardless of whether the conn is successfully created.
Similar thing can be done with net.ListenConfig.
Background
Sometimes we need to dial inside another net namespace and switch back. On linux, namespace is thread-level, so a thread lock is needed.
With
"github.com/vishvananda/netns"for example:However, this blocks the current thread until
Dial()returns. A workaround may be moving the unlocking stuff intodialer.Control:This doesn't work well because
dialParallel()dials in new goroutines which are out of control.Proposal
Add callback before and after the connection (socket) is created in
net.Dialer:The call of
PreControl - PostControlpair should be in the same goroutine and surround the socket syscall.PostControlshould be called regardless of whether the conn is successfully created.Similar thing can be done with
net.ListenConfig.