mirror of
https://github.com/vishvananda/netlink
synced 2025-02-16 12:06:49 +00:00
Allow to specify netlink families for Handle (#143)
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
293adec041
commit
734d02c3e2
@ -1,7 +1,6 @@
|
|||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync/atomic"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink/nl"
|
"github.com/vishvananda/netlink/nl"
|
||||||
@ -11,27 +10,34 @@ import (
|
|||||||
// Empty handle used by the netlink package methods
|
// Empty handle used by the netlink package methods
|
||||||
var pkgHandle = &Handle{}
|
var pkgHandle = &Handle{}
|
||||||
|
|
||||||
// Handle is an handle for the netlink requests
|
// Handle is an handle for the netlink requests on a
|
||||||
// on a specific network namespace. All the requests
|
// specific network namespace. All the requests on the
|
||||||
// share the same netlink socket, which gets released
|
// same netlink family share the same netlink socket,
|
||||||
// when the handle is deleted.
|
// which gets released when the handle is deleted.
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
seq uint32
|
sockets map[int]*nl.SocketHandle
|
||||||
routeSocket *nl.NetlinkSocket
|
|
||||||
xfrmSocket *nl.NetlinkSocket
|
|
||||||
lookupByDump bool
|
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.
|
// NewHandle returns a netlink handle on the current network namespace.
|
||||||
func NewHandle() (*Handle, error) {
|
// Caller may specify the netlink families the handle should support.
|
||||||
return newHandle(netns.None(), netns.None())
|
// 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...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandle returns a netlink handle on the network namespace
|
// NewHandle returns a netlink handle on the network namespace
|
||||||
// specified by ns. If ns=netns.None(), current network namespace
|
// specified by ns. If ns=netns.None(), current network namespace
|
||||||
// will be assumed
|
// will be assumed
|
||||||
func NewHandleAt(ns netns.NsHandle) (*Handle, error) {
|
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
|
||||||
return newHandle(ns, netns.None())
|
return newHandle(ns, netns.None(), nlFamilies...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandleAtFrom works as NewHandle but allows client to specify the
|
// NewHandleAtFrom works as NewHandle but allows client to specify the
|
||||||
@ -40,37 +46,33 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
|
|||||||
return newHandle(newNs, curNs)
|
return newHandle(newNs, curNs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHandle(newNs, curNs netns.NsHandle) (*Handle, error) {
|
func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) {
|
||||||
var (
|
h := &Handle{sockets: map[int]*nl.SocketHandle{}}
|
||||||
err error
|
fams := nl.SupportedNlFamilies
|
||||||
rSocket *nl.NetlinkSocket
|
if len(nlFamilies) != 0 {
|
||||||
xSocket *nl.NetlinkSocket
|
fams = nlFamilies
|
||||||
)
|
|
||||||
rSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_ROUTE)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
xSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_XFRM)
|
for _, f := range fams {
|
||||||
if err != nil {
|
s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h.sockets[f] = &nl.SocketHandle{Socket: s}
|
||||||
}
|
}
|
||||||
return &Handle{routeSocket: rSocket, xfrmSocket: xSocket}, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete releases the resources allocated to this handle
|
// Delete releases the resources allocated to this handle
|
||||||
func (h *Handle) Delete() {
|
func (h *Handle) Delete() {
|
||||||
if h.routeSocket != nil {
|
for _, sh := range h.sockets {
|
||||||
h.routeSocket.Close()
|
sh.Close()
|
||||||
}
|
}
|
||||||
if h.xfrmSocket != nil {
|
h.sockets = nil
|
||||||
h.xfrmSocket.Close()
|
|
||||||
}
|
|
||||||
h.routeSocket, h.xfrmSocket = nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
||||||
// Do this so that package API still use nl package variable nextSeqNr
|
// Do this so that package API still use nl package variable nextSeqNr
|
||||||
if h.routeSocket == nil {
|
if h.sockets == nil {
|
||||||
return nl.NewNetlinkRequest(proto, flags)
|
return nl.NewNetlinkRequest(proto, flags)
|
||||||
}
|
}
|
||||||
return &nl.NetlinkRequest{
|
return &nl.NetlinkRequest{
|
||||||
@ -78,9 +80,7 @@ func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
|
|||||||
Len: uint32(syscall.SizeofNlMsghdr),
|
Len: uint32(syscall.SizeofNlMsghdr),
|
||||||
Type: uint16(proto),
|
Type: uint16(proto),
|
||||||
Flags: syscall.NLM_F_REQUEST | uint16(flags),
|
Flags: syscall.NLM_F_REQUEST | uint16(flags),
|
||||||
Seq: atomic.AddUint32(&h.seq, 1),
|
|
||||||
},
|
},
|
||||||
RouteSocket: h.routeSocket,
|
Sockets: h.sockets,
|
||||||
XfmrSocket: h.xfrmSocket,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink/nl"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,12 +19,18 @@ func TestHandleCreateDelete(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if h.routeSocket == nil || h.xfrmSocket == nil {
|
for _, f := range nl.SupportedNlFamilies {
|
||||||
t.Fatalf("Handle socket(s) were not created")
|
sh, ok := h.sockets[f]
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Handle socket(s) for family %d was not created", f)
|
||||||
|
}
|
||||||
|
if sh.Socket == nil {
|
||||||
|
t.Fatalf("Socket for family %d was not created", f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Delete()
|
h.Delete()
|
||||||
if h.routeSocket != nil || h.xfrmSocket != nil {
|
if h.sockets != nil {
|
||||||
t.Fatalf("Handle socket(s) were not destroyed")
|
t.Fatalf("Handle socket(s) were not destroyed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@ const (
|
|||||||
FAMILY_V6 = syscall.AF_INET6
|
FAMILY_V6 = syscall.AF_INET6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SupportedNlFamilies contains the list of netlink families this netlink package supports
|
||||||
|
var SupportedNlFamilies = []int{syscall.NETLINK_ROUTE, syscall.NETLINK_XFRM}
|
||||||
|
|
||||||
var nextSeqNr uint32
|
var nextSeqNr uint32
|
||||||
|
|
||||||
// GetIPFamily returns the family type of a net.IP.
|
// GetIPFamily returns the family type of a net.IP.
|
||||||
@ -175,9 +178,8 @@ func (a *RtAttr) Serialize() []byte {
|
|||||||
|
|
||||||
type NetlinkRequest struct {
|
type NetlinkRequest struct {
|
||||||
syscall.NlMsghdr
|
syscall.NlMsghdr
|
||||||
Data []NetlinkRequestData
|
Data []NetlinkRequestData
|
||||||
RouteSocket *NetlinkSocket
|
Sockets map[int]*SocketHandle
|
||||||
XfmrSocket *NetlinkSocket
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the Netlink Request into a byte array
|
// Serialize the Netlink Request into a byte array
|
||||||
@ -217,15 +219,12 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
switch sockType {
|
if req.Sockets != nil {
|
||||||
case syscall.NETLINK_XFRM:
|
if sh, ok := req.Sockets[sockType]; ok {
|
||||||
s = req.XfmrSocket
|
s = sh.Socket
|
||||||
case syscall.NETLINK_ROUTE:
|
req.Seq = atomic.AddUint32(&sh.Seq, 1)
|
||||||
s = req.RouteSocket
|
}
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("Socket type %d is not handled", sockType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedSocket := s != nil
|
sharedSocket := s != nil
|
||||||
|
|
||||||
if s == nil {
|
if s == nil {
|
||||||
@ -486,3 +485,17 @@ func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
|
|||||||
}
|
}
|
||||||
return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
|
return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SocketHandle contains the netlink socket and the associated
|
||||||
|
// sequence counter for a specific netlink family
|
||||||
|
type SocketHandle struct {
|
||||||
|
Seq uint32
|
||||||
|
Socket *NetlinkSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the netlink socket
|
||||||
|
func (sh *SocketHandle) Close() {
|
||||||
|
if sh.Socket != nil {
|
||||||
|
sh.Socket.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user