diff --git a/libnetwork/Godeps/Godeps.json b/libnetwork/Godeps/Godeps.json index 8d234c12976d3c7f513d60d3cd07569611809511..1aceae3d71f1d64fedf78aaad667b5b3e4b3bb87 100644 --- a/libnetwork/Godeps/Godeps.json +++ b/libnetwork/Godeps/Godeps.json @@ -398,11 +398,11 @@ }, { "ImportPath": "github.com/vishvananda/netlink", - "Rev": "7995ff5647a22cbf0dc41bf5c0e977bdb0d5c6b7" + "Rev": "734d02c3e202f682c74b71314b2c61eec0170fd4" }, { "ImportPath": "github.com/vishvananda/netlink/nl", - "Rev": "7995ff5647a22cbf0dc41bf5c0e977bdb0d5c6b7" + "Rev": "734d02c3e202f682c74b71314b2c61eec0170fd4" }, { "ImportPath": "github.com/vishvananda/netns", diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md index 8cd50a93b6db14decc6ec4c08847aab99a17e27c..2367fae097bf7675f7f71fe3dc48a6465012c62e 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md @@ -8,7 +8,7 @@ the kernel. It can be used to add and remove interfaces, set ip addresses and routes, and configure ipsec. Netlink communication requires elevated privileges, so in most cases this code needs to be run as root. Since low-level netlink messages are inscrutable at best, the library attempts -to provide an api that is loosely modeled on the CLI provied by iproute2. +to provide an api that is loosely modeled on the CLI provided by iproute2. Actions like `ip link add` will be accomplished via a similarly named function like AddLink(). This library began its life as a fork of the netlink functionality in diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go index 457730410007e591163bbd51049dff5c2ee105a8..8ee13af48eb9871a07e920df999ccbc10a2ba4e6 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class.go @@ -50,39 +50,6 @@ type HtbClass struct { Prio uint32 } -func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { - mtu := 1600 - rate := cattrs.Rate / 8 - ceil := cattrs.Ceil / 8 - buffer := cattrs.Buffer - cbuffer := cattrs.Cbuffer - - if ceil == 0 { - ceil = rate - } - - if buffer == 0 { - buffer = uint32(float64(rate)/Hz() + float64(mtu)) - } - buffer = uint32(Xmittime(rate, buffer)) - - if cbuffer == 0 { - cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) - } - cbuffer = uint32(Xmittime(ceil, cbuffer)) - - return &HtbClass{ - ClassAttrs: attrs, - Rate: rate, - Ceil: ceil, - Buffer: buffer, - Cbuffer: cbuffer, - Quantum: 10, - Level: 0, - Prio: 0, - } -} - func (q HtbClass) String() string { return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) } diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go index be62abd9cb9af731f46d0ac61a8909873d4a0d84..91cd3883de90838fbf68abfaae98fbfbcc305475 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/class_linux.go @@ -7,6 +7,40 @@ import ( "github.com/vishvananda/netlink/nl" ) +// NOTE: function is in here because it uses other linux functions +func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { + mtu := 1600 + rate := cattrs.Rate / 8 + ceil := cattrs.Ceil / 8 + buffer := cattrs.Buffer + cbuffer := cattrs.Cbuffer + + if ceil == 0 { + ceil = rate + } + + if buffer == 0 { + buffer = uint32(float64(rate)/Hz() + float64(mtu)) + } + buffer = uint32(Xmittime(rate, buffer)) + + if cbuffer == 0 { + cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) + } + cbuffer = uint32(Xmittime(ceil, cbuffer)) + + return &HtbClass{ + ClassAttrs: attrs, + Rate: rate, + Ceil: ceil, + Buffer: buffer, + Cbuffer: cbuffer, + Quantum: 10, + Level: 0, + Prio: 0, + } +} + // ClassDel will delete a class from the system. // Equivalent to: `tc class del $class` func ClassDel(class Class) error { diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go index 7e178ee00addbf35a682c13d70ab600e6d74cbf3..116aeba06ef4e9fc0deb04cb81dd957bc4c8db71 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter.go @@ -1,11 +1,6 @@ package netlink -import ( - "errors" - "fmt" - - "github.com/vishvananda/netlink/nl" -) +import "fmt" type Filter interface { Attrs() *FilterAttrs @@ -217,74 +212,6 @@ type FilterFwAttrs struct { LinkLayer int } -// Fw filter filters on firewall marks -type Fw struct { - FilterAttrs - ClassId uint32 - // TODO remove nl type from interface - Police nl.TcPolice - InDev string - // TODO Action - Mask uint32 - AvRate uint32 - Rtab [256]uint32 - Ptab [256]uint32 -} - -func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { - var rtab [256]uint32 - var ptab [256]uint32 - rcellLog := -1 - pcellLog := -1 - avrate := fattrs.AvRate / 8 - police := nl.TcPolice{} - police.Rate.Rate = fattrs.Rate / 8 - police.PeakRate.Rate = fattrs.PeakRate / 8 - buffer := fattrs.Buffer - linklayer := nl.LINKLAYER_ETHERNET - - if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { - linklayer = fattrs.LinkLayer - } - - police.Action = int32(fattrs.Action) - if police.Rate.Rate != 0 { - police.Rate.Mpu = fattrs.Mpu - police.Rate.Overhead = fattrs.Overhead - if CalcRtable(&police.Rate, rtab, rcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("TBF: failed to calculate rate table") - } - police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) - } - police.Mtu = fattrs.Mtu - if police.PeakRate.Rate != 0 { - police.PeakRate.Mpu = fattrs.Mpu - police.PeakRate.Overhead = fattrs.Overhead - if CalcRtable(&police.PeakRate, ptab, pcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("POLICE: failed to calculate peak rate table") - } - } - - return &Fw{ - FilterAttrs: attrs, - ClassId: fattrs.ClassId, - InDev: fattrs.InDev, - Mask: fattrs.Mask, - Police: police, - AvRate: avrate, - Rtab: rtab, - Ptab: ptab, - }, nil -} - -func (filter *Fw) Attrs() *FilterAttrs { - return &filter.FilterAttrs -} - -func (filter *Fw) Type() string { - return "fw" -} - type BpfFilter struct { FilterAttrs ClassId uint32 diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go index 2a8cf89022b98321409ec624ce742f04959fa5c6..b403dad2f82f240f6708835ba5ff02325f5e9561 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/filter_linux.go @@ -3,12 +3,83 @@ package netlink import ( "bytes" "encoding/binary" + "errors" "fmt" "syscall" "github.com/vishvananda/netlink/nl" ) +// Fw filter filters on firewall marks +// NOTE: this is in filter_linux because it refers to nl.TcPolice which +// is defined in nl/tc_linux.go +type Fw struct { + FilterAttrs + ClassId uint32 + // TODO remove nl type from interface + Police nl.TcPolice + InDev string + // TODO Action + Mask uint32 + AvRate uint32 + Rtab [256]uint32 + Ptab [256]uint32 +} + +func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { + var rtab [256]uint32 + var ptab [256]uint32 + rcellLog := -1 + pcellLog := -1 + avrate := fattrs.AvRate / 8 + police := nl.TcPolice{} + police.Rate.Rate = fattrs.Rate / 8 + police.PeakRate.Rate = fattrs.PeakRate / 8 + buffer := fattrs.Buffer + linklayer := nl.LINKLAYER_ETHERNET + + if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { + linklayer = fattrs.LinkLayer + } + + police.Action = int32(fattrs.Action) + if police.Rate.Rate != 0 { + police.Rate.Mpu = fattrs.Mpu + police.Rate.Overhead = fattrs.Overhead + if CalcRtable(&police.Rate, rtab, rcellLog, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("TBF: failed to calculate rate table") + } + police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) + } + police.Mtu = fattrs.Mtu + if police.PeakRate.Rate != 0 { + police.PeakRate.Mpu = fattrs.Mpu + police.PeakRate.Overhead = fattrs.Overhead + if CalcRtable(&police.PeakRate, ptab, pcellLog, fattrs.Mtu, linklayer) < 0 { + return nil, errors.New("POLICE: failed to calculate peak rate table") + } + } + + return &Fw{ + FilterAttrs: attrs, + ClassId: fattrs.ClassId, + InDev: fattrs.InDev, + Mask: fattrs.Mask, + Police: police, + AvRate: avrate, + Rtab: rtab, + Ptab: ptab, + }, nil +} + +func (filter *Fw) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *Fw) Type() string { + return "fw" +} + // FilterDel will delete a filter from the system. // Equivalent to: `tc filter del $filter` func FilterDel(filter Filter) error { @@ -126,14 +197,14 @@ func (h *Handle) FilterAdd(filter Filter) error { // FilterList gets a list of filters in the system. // Equivalent to: `tc filter show`. -// Generally retunrs nothing if link and parent are not specified. +// Generally returns nothing if link and parent are not specified. func FilterList(link Link, parent uint32) ([]Filter, error) { return pkgHandle.FilterList(link, parent) } // FilterList gets a list of filters in the system. // Equivalent to: `tc filter show`. -// Generally retunrs nothing if link and parent are not specified. +// Generally returns nothing if link and parent are not specified. func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { req := h.newNetlinkRequest(syscall.RTM_GETTFILTER, syscall.NLM_F_DUMP) msg := &nl.TcMsg{ diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle.go deleted file mode 100644 index a96d2397f46ba74cdd54e6607c7f8d357cf3ef8b..0000000000000000000000000000000000000000 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle.go +++ /dev/null @@ -1,86 +0,0 @@ -package netlink - -import ( - "sync/atomic" - "syscall" - - "github.com/vishvananda/netlink/nl" - "github.com/vishvananda/netns" -) - -// Empty handle used by the netlink package methods -var pkgHandle = &Handle{} - -// Handle is an handle for the netlink requests -// on a specific network namespace. All the requests -// share the same netlink socket, which gets released -// when the handle is deleted. -type Handle struct { - seq uint32 - routeSocket *nl.NetlinkSocket - xfrmSocket *nl.NetlinkSocket - lookupByDump bool -} - -// NewHandle returns a netlink handle on the current network namespace. -func NewHandle() (*Handle, error) { - return newHandle(netns.None(), netns.None()) -} - -// NewHandle returns a netlink handle on the network namespace -// specified by ns. If ns=netns.None(), current network namespace -// will be assumed -func NewHandleAt(ns netns.NsHandle) (*Handle, error) { - return newHandle(ns, netns.None()) -} - -// NewHandleAtFrom works as NewHandle but allows client to specify the -// new and the origin netns Handle. -func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { - return newHandle(newNs, curNs) -} - -func newHandle(newNs, curNs netns.NsHandle) (*Handle, error) { - var ( - err error - rSocket *nl.NetlinkSocket - xSocket *nl.NetlinkSocket - ) - rSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_ROUTE) - if err != nil { - return nil, err - } - xSocket, err = nl.GetNetlinkSocketAt(newNs, curNs, syscall.NETLINK_XFRM) - if err != nil { - return nil, err - } - return &Handle{routeSocket: rSocket, xfrmSocket: xSocket}, nil -} - -// Delete releases the resources allocated to this handle -func (h *Handle) Delete() { - if h.routeSocket != nil { - h.routeSocket.Close() - } - if h.xfrmSocket != nil { - h.xfrmSocket.Close() - } - h.routeSocket, h.xfrmSocket = nil, nil -} - -func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest { - // Do this so that package API still use nl package variable nextSeqNr - if h.routeSocket == nil { - return nl.NewNetlinkRequest(proto, flags) - } - return &nl.NetlinkRequest{ - NlMsghdr: syscall.NlMsghdr{ - Len: uint32(syscall.SizeofNlMsghdr), - Type: uint16(proto), - Flags: syscall.NLM_F_REQUEST | uint16(flags), - Seq: atomic.AddUint32(&h.seq, 1), - }, - RouteSocket: h.routeSocket, - XfmrSocket: h.xfrmSocket, - } -} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle_linux.go new file mode 100644 index 0000000000000000000000000000000000000000..5377988752be271e1b0dcbb883b9a086d9b68e97 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/handle_linux.go @@ -0,0 +1,86 @@ +package netlink + +import ( + "syscall" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" +) + +// Empty handle used by the netlink package methods +var pkgHandle = &Handle{} + +// Handle is an handle for the netlink requests on a +// specific network namespace. All the requests on the +// same netlink family share the same netlink socket, +// which gets released when the handle is deleted. +type Handle struct { + sockets map[int]*nl.SocketHandle + 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. +// Caller may specify the netlink families the handle should support. +// 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 +// specified by ns. If ns=netns.None(), current network namespace +// will be assumed +func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { + return newHandle(ns, netns.None(), nlFamilies...) +} + +// NewHandleAtFrom works as NewHandle but allows client to specify the +// new and the origin netns Handle. +func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { + return newHandle(newNs, curNs) +} + +func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) { + h := &Handle{sockets: map[int]*nl.SocketHandle{}} + fams := nl.SupportedNlFamilies + if len(nlFamilies) != 0 { + fams = nlFamilies + } + for _, f := range fams { + s, err := nl.GetNetlinkSocketAt(newNs, curNs, f) + if err != nil { + return nil, err + } + h.sockets[f] = &nl.SocketHandle{Socket: s} + } + return h, nil +} + +// Delete releases the resources allocated to this handle +func (h *Handle) Delete() { + for _, sh := range h.sockets { + sh.Close() + } + h.sockets = nil +} + +func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest { + // Do this so that package API still use nl package variable nextSeqNr + if h.sockets == nil { + return nl.NewNetlinkRequest(proto, flags) + } + return &nl.NetlinkRequest{ + NlMsghdr: syscall.NlMsghdr{ + Len: uint32(syscall.SizeofNlMsghdr), + Type: uint16(proto), + Flags: syscall.NLM_F_REQUEST | uint16(flags), + }, + Sockets: h.sockets, + } +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go index 4efd32cbf2ef9798703ddc62e4b4d8a5ff206aba..9dbc221506f1b9e2775e502a0bbfc33f758da61b 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go @@ -3,7 +3,6 @@ package netlink import ( "fmt" "net" - "syscall" ) // Link represents a link device from netlink. Shared link attributes @@ -173,11 +172,6 @@ func (macvtap Macvtap) Type() string { type TuntapMode uint16 -const ( - TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN - TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP -) - // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink type Tuntap struct { LinkAttrs diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go index 0ed307dd2532ff8568c40d751fc4f5e4f22efdfa..08a93843d6aef8c84d949ee8f15f19f4e8c582f4 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go @@ -14,6 +14,11 @@ import ( const SizeofLinkStats = 0x5c +const ( + TUNTAP_MODE_TUN TuntapMode = syscall.IFF_TUN + TUNTAP_MODE_TAP TuntapMode = syscall.IFF_TAP +) + var native = nl.NativeEndian() var lookupByDump = false @@ -675,6 +680,11 @@ func (h *Handle) LinkAdd(link Link) error { data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode])) } + } else if macv, ok := link.(*Macvtap); ok { + if macv.Mode != MACVLAN_MODE_DEFAULT { + data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil) + nl.NewRtAttrChild(data, nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macv.Mode])) + } } else if gretap, ok := link.(*Gretap); ok { addGretapAttrs(gretap, linkInfo) } diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go index deafb6cfa7e8a689dff4c5e8354e37d423acdc9d..d8e02f479f2c0cb63e4b67f14fa3255e57842c84 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go @@ -8,18 +8,7 @@ // interface that is loosly modeled on the iproute2 cli. package netlink -import ( - "net" - - "github.com/vishvananda/netlink/nl" -) - -// Family type definitions -const ( - FAMILY_ALL = nl.FAMILY_ALL - FAMILY_V4 = nl.FAMILY_V4 - FAMILY_V6 = nl.FAMILY_V6 -) +import "net" // ParseIPNet parses a string in ip/net format and returns a net.IPNet. // This is valuable because addresses in netlink are often IPNets and diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_linux.go new file mode 100644 index 0000000000000000000000000000000000000000..32d8537ef43fe869ba344719899a5f5357d97237 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_linux.go @@ -0,0 +1,10 @@ +package netlink + +import "github.com/vishvananda/netlink/nl" + +// Family type definitions +const ( + FAMILY_ALL = nl.FAMILY_ALL + FAMILY_V4 = nl.FAMILY_V4 + FAMILY_V6 = nl.FAMILY_V6 +) diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go index 10c49c1bfce8fa9cc88c1ce1bfcde65e17cdae52..9ad7a62875060968b843ecd63e3463794257b605 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go @@ -138,6 +138,6 @@ func NeighList(linkIndex, family int) ([]Neigh, error) { return nil, ErrNotImplemented } -func NeighDeserialize(m []byte) (*Ndmsg, *Neigh, error) { - return nil, nil, ErrNotImplemented +func NeighDeserialize(m []byte) (*Neigh, error) { + return nil, ErrNotImplemented } diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go index f41821dd7200b557ab6a4f10be2ef08b07fe87d4..fd5550a3062c208fdde89857b25b5327fb4a051b 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go @@ -22,6 +22,9 @@ const ( 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 // GetIPFamily returns the family type of a net.IP. @@ -175,9 +178,8 @@ func (a *RtAttr) Serialize() []byte { type NetlinkRequest struct { syscall.NlMsghdr - Data []NetlinkRequestData - RouteSocket *NetlinkSocket - XfmrSocket *NetlinkSocket + Data []NetlinkRequestData + Sockets map[int]*SocketHandle } // Serialize the Netlink Request into a byte array @@ -209,7 +211,7 @@ func (req *NetlinkRequest) AddData(data NetlinkRequestData) { } // Execute the request against a the given sockType. -// Returns a list of netlink messages in seriaized format, optionally filtered +// Returns a list of netlink messages in serialized format, optionally filtered // by resType. func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { var ( @@ -217,15 +219,12 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro err error ) - switch sockType { - case syscall.NETLINK_XFRM: - s = req.XfmrSocket - case syscall.NETLINK_ROUTE: - s = req.RouteSocket - default: - return nil, fmt.Errorf("Socket type %d is not handled", sockType) + if req.Sockets != nil { + if sh, ok := req.Sockets[sockType]; ok { + s = sh.Socket + req.Seq = atomic.AddUint32(&sh.Seq, 1) + } } - sharedSocket := 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 } + +// 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() + } +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go index 447e83e5ae5e46649d175642b54a979df8c15cd6..f7db88dfeedeebb1f6ff8e2772999f9a8ca4a67c 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go @@ -40,3 +40,15 @@ func DeserializeRtMsg(b []byte) *RtMsg { func (msg *RtMsg) Serialize() []byte { return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:] } + +type RtNexthop struct { + syscall.RtNexthop +} + +func DeserializeRtNexthop(b []byte) *RtNexthop { + return (*RtNexthop)(unsafe.Pointer(&b[0:syscall.SizeofRtNexthop][0])) +} + +func (msg *RtNexthop) Serialize() []byte { + return (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go index 3fb2bbae24ce2e7949e673ba3949d2408001ba54..28f65f38948431acec2f71d443a0316a25813258 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc.go @@ -176,70 +176,6 @@ type Netem struct { CorruptCorr uint32 } -func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { - var limit uint32 = 1000 - var lossCorr, delayCorr, duplicateCorr uint32 - var reorderProb, reorderCorr uint32 - var corruptProb, corruptCorr uint32 - - latency := nattrs.Latency - loss := Percentage2u32(nattrs.Loss) - gap := nattrs.Gap - duplicate := Percentage2u32(nattrs.Duplicate) - jitter := nattrs.Jitter - - // Correlation - if latency > 0 && jitter > 0 { - delayCorr = Percentage2u32(nattrs.DelayCorr) - } - if loss > 0 { - lossCorr = Percentage2u32(nattrs.LossCorr) - } - if duplicate > 0 { - duplicateCorr = Percentage2u32(nattrs.DuplicateCorr) - } - // FIXME should validate values(like loss/duplicate are percentages...) - latency = time2Tick(latency) - - if nattrs.Limit != 0 { - limit = nattrs.Limit - } - // Jitter is only value if latency is > 0 - if latency > 0 { - jitter = time2Tick(jitter) - } - - reorderProb = Percentage2u32(nattrs.ReorderProb) - reorderCorr = Percentage2u32(nattrs.ReorderCorr) - - if reorderProb > 0 { - // ERROR if lantency == 0 - if gap == 0 { - gap = 1 - } - } - - corruptProb = Percentage2u32(nattrs.CorruptProb) - corruptCorr = Percentage2u32(nattrs.CorruptCorr) - - return &Netem{ - QdiscAttrs: attrs, - Latency: latency, - DelayCorr: delayCorr, - Limit: limit, - Loss: loss, - LossCorr: lossCorr, - Gap: gap, - Duplicate: duplicate, - DuplicateCorr: duplicateCorr, - Jitter: jitter, - ReorderProb: reorderProb, - ReorderCorr: reorderCorr, - CorruptProb: corruptProb, - CorruptCorr: corruptCorr, - } -} - func (qdisc *Netem) Attrs() *QdiscAttrs { return &qdisc.QdiscAttrs } diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go index 62ac9d3dd8f73810c7d10225ea355fbfe867d1e6..1bb485646bf67ece40299ec2c338b98cc6004f13 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/qdisc_linux.go @@ -10,6 +10,71 @@ import ( "github.com/vishvananda/netlink/nl" ) +// NOTE function is here because it uses other linux functions +func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { + var limit uint32 = 1000 + var lossCorr, delayCorr, duplicateCorr uint32 + var reorderProb, reorderCorr uint32 + var corruptProb, corruptCorr uint32 + + latency := nattrs.Latency + loss := Percentage2u32(nattrs.Loss) + gap := nattrs.Gap + duplicate := Percentage2u32(nattrs.Duplicate) + jitter := nattrs.Jitter + + // Correlation + if latency > 0 && jitter > 0 { + delayCorr = Percentage2u32(nattrs.DelayCorr) + } + if loss > 0 { + lossCorr = Percentage2u32(nattrs.LossCorr) + } + if duplicate > 0 { + duplicateCorr = Percentage2u32(nattrs.DuplicateCorr) + } + // FIXME should validate values(like loss/duplicate are percentages...) + latency = time2Tick(latency) + + if nattrs.Limit != 0 { + limit = nattrs.Limit + } + // Jitter is only value if latency is > 0 + if latency > 0 { + jitter = time2Tick(jitter) + } + + reorderProb = Percentage2u32(nattrs.ReorderProb) + reorderCorr = Percentage2u32(nattrs.ReorderCorr) + + if reorderProb > 0 { + // ERROR if lantency == 0 + if gap == 0 { + gap = 1 + } + } + + corruptProb = Percentage2u32(nattrs.CorruptProb) + corruptCorr = Percentage2u32(nattrs.CorruptCorr) + + return &Netem{ + QdiscAttrs: attrs, + Latency: latency, + DelayCorr: delayCorr, + Limit: limit, + Loss: loss, + LossCorr: lossCorr, + Gap: gap, + Duplicate: duplicate, + DuplicateCorr: duplicateCorr, + Jitter: jitter, + ReorderProb: reorderProb, + ReorderCorr: reorderCorr, + CorruptProb: corruptProb, + CorruptCorr: corruptCorr, + } +} + // QdiscDel will delete a qdisc from the system. // Equivalent to: `tc qdisc del $qdisc` func QdiscDel(qdisc Qdisc) error { diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go index aa869ea93cf73819956e9a7d77978036c43607c0..61cf5ec5e11c3dd8de782c0f61758ad234999534 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route.go @@ -3,27 +3,13 @@ package netlink import ( "fmt" "net" - "syscall" ) // Scope is an enum representing a route scope. type Scope uint8 -const ( - SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE - SCOPE_SITE Scope = syscall.RT_SCOPE_SITE - SCOPE_LINK Scope = syscall.RT_SCOPE_LINK - SCOPE_HOST Scope = syscall.RT_SCOPE_HOST - SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE -) - type NextHopFlag int -const ( - FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK - FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE -) - // Route represents a netlink route. type Route struct { LinkIndex int @@ -32,6 +18,7 @@ type Route struct { Dst *net.IPNet Src net.IP Gw net.IP + MultiPath []*NexthopInfo Protocol int Priority int Table int @@ -41,6 +28,10 @@ type Route struct { } func (r Route) String() string { + if len(r.MultiPath) > 0 { + return fmt.Sprintf("{Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.Dst, + r.Src, r.MultiPath, r.ListFlags(), r.Table) + } return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.LinkIndex, r.Dst, r.Src, r.Gw, r.ListFlags(), r.Table) } @@ -58,23 +49,18 @@ type flagString struct { s string } -var testFlags = []flagString{ - {f: FLAG_ONLINK, s: "onlink"}, - {f: FLAG_PERVASIVE, s: "pervasive"}, -} - -func (r *Route) ListFlags() []string { - var flags []string - for _, tf := range testFlags { - if r.Flags&int(tf.f) != 0 { - flags = append(flags, tf.s) - } - } - return flags -} - // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE type RouteUpdate struct { Type uint16 Route } + +type NexthopInfo struct { + LinkIndex int + Hops int + Gw net.IP +} + +func (n *NexthopInfo) String() string { + return fmt.Sprintf("{Ifindex: %d Weight: %d, Gw: %s}", n.LinkIndex, n.Hops+1, n.Gw) +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go index db952512e938f0634b4658647687cc3b76c46c18..5d684ad795d04385e1b48e38c7db0be29d965aba 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_linux.go @@ -10,6 +10,14 @@ import ( // RtAttr is shared so it is in netlink_linux.go +const ( + SCOPE_UNIVERSE Scope = syscall.RT_SCOPE_UNIVERSE + SCOPE_SITE Scope = syscall.RT_SCOPE_SITE + SCOPE_LINK Scope = syscall.RT_SCOPE_LINK + SCOPE_HOST Scope = syscall.RT_SCOPE_HOST + SCOPE_NOWHERE Scope = syscall.RT_SCOPE_NOWHERE +) + const ( RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) RT_FILTER_SCOPE @@ -23,6 +31,26 @@ const ( RT_FILTER_TABLE ) +const ( + FLAG_ONLINK NextHopFlag = syscall.RTNH_F_ONLINK + FLAG_PERVASIVE NextHopFlag = syscall.RTNH_F_PERVASIVE +) + +var testFlags = []flagString{ + {f: FLAG_ONLINK, s: "onlink"}, + {f: FLAG_PERVASIVE, s: "pervasive"}, +} + +func (r *Route) ListFlags() []string { + var flags []string + for _, tf := range testFlags { + if r.Flags&int(tf.f) != 0 { + flags = append(flags, tf.s) + } + } + return flags +} + // RouteAdd will add a route to the system. // Equivalent to: `ip route add $route` func RouteAdd(route *Route) error { @@ -102,6 +130,37 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData)) } + if len(route.MultiPath) > 0 { + buf := []byte{} + for _, nh := range route.MultiPath { + rtnh := &nl.RtNexthop{ + RtNexthop: syscall.RtNexthop{ + Hops: uint8(nh.Hops), + Ifindex: int32(nh.LinkIndex), + Len: uint16(syscall.SizeofRtNexthop), + }, + } + var gwData []byte + if nh.Gw != nil { + gwFamily := nl.GetIPFamily(nh.Gw) + if family != -1 && family != gwFamily { + return fmt.Errorf("gateway, source, and destination ip are not the same IP family") + } + var gw *nl.RtAttr + if gwFamily == FAMILY_V4 { + gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To4())) + } else { + gw = nl.NewRtAttr(syscall.RTA_GATEWAY, []byte(nh.Gw.To16())) + } + gwData := gw.Serialize() + rtnh.Len += uint16(len(gwData)) + } + buf = append(buf, rtnh.Serialize()...) + buf = append(buf, gwData...) + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_MULTIPATH, buf)) + } + if route.Table > 0 { if route.Table >= 256 { msg.Table = syscall.RT_TABLE_UNSPEC @@ -275,6 +334,40 @@ func deserializeRoute(m []byte) (Route, error) { route.Priority = int(native.Uint32(attr.Value[0:4])) case syscall.RTA_TABLE: route.Table = int(native.Uint32(attr.Value[0:4])) + case syscall.RTA_MULTIPATH: + parseRtNexthop := func(value []byte) (*NexthopInfo, []byte, error) { + if len(value) < syscall.SizeofRtNexthop { + return nil, nil, fmt.Errorf("Lack of bytes") + } + nh := nl.DeserializeRtNexthop(value) + if len(value) < int(nh.RtNexthop.Len) { + return nil, nil, fmt.Errorf("Lack of bytes") + } + info := &NexthopInfo{ + LinkIndex: int(nh.RtNexthop.Ifindex), + Hops: int(nh.RtNexthop.Hops), + } + attrs, err := nl.ParseRouteAttr(value[syscall.SizeofRtNexthop:int(nh.RtNexthop.Len)]) + if err != nil { + return nil, nil, err + } + for _, attr := range attrs { + switch attr.Attr.Type { + case syscall.RTA_GATEWAY: + info.Gw = net.IP(attr.Value) + } + } + return info, value[int(nh.RtNexthop.Len):], nil + } + rest := attr.Value + for len(rest) > 0 { + info, buf, err := parseRtNexthop(rest) + if err != nil { + return route, err + } + route.MultiPath = append(route.MultiPath, info) + rest = buf + } } } return route, nil diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_unspecified.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_unspecified.go new file mode 100644 index 0000000000000000000000000000000000000000..1b2053064610350116b46f3d88f3dfcb7bd55995 --- /dev/null +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/route_unspecified.go @@ -0,0 +1,7 @@ +// +build !linux + +package netlink + +func (r *Route) ListFlags() []string { + return []string{} +} diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go index bd699a7e124b2fffcc9d58179434e81094ce5a2f..f0243defd7d04486f1a8fe53bcd78710372f344e 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule.go @@ -3,13 +3,10 @@ package netlink import ( "fmt" "net" - - "github.com/vishvananda/netlink/nl" ) // Rule represents a netlink rule. type Rule struct { - *nl.RtMsg Priority int Table int Mark int diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go index 8bce6666c99c977874b9d9f338aefb1b499097ef..58fac557c0130d3bb6ab76c511c30131a7079cff 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/rule_linux.go @@ -165,7 +165,6 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { } rule := NewRule() - rule.RtMsg = msg for j := range attrs { switch attrs[j].Attr.Type { diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm.go index 6ec40acac96d47ef0bfdcfba8897581cdb70c27a..9962dcf7006dff2bcdd6d2400458d72f4f3a1f72 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm.go @@ -13,7 +13,7 @@ const ( XFRM_PROTO_ESP Proto = syscall.IPPROTO_ESP XFRM_PROTO_AH Proto = syscall.IPPROTO_AH XFRM_PROTO_HAO Proto = syscall.IPPROTO_DSTOPTS - XFRM_PROTO_COMP Proto = syscall.IPPROTO_COMP + XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin XFRM_PROTO_IPSEC_ANY Proto = syscall.IPPROTO_RAW ) diff --git a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state.go b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state.go index 7f38bfa2267efefc5b499c2057ea0fbe79b2e86f..6ffbcdb476154a7ab1f0afabd43a047a6d345d27 100644 --- a/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state.go +++ b/libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/xfrm_state.go @@ -3,8 +3,6 @@ package netlink import ( "fmt" "net" - - "github.com/vishvananda/netlink/nl" ) // XfrmStateAlgo represents the algorithm to use for the ipsec encryption. @@ -93,7 +91,7 @@ func (sa XfrmState) Print(stats bool) string { } func printLimit(lmt uint64) string { - if lmt == nl.XFRM_INF { + if lmt == ^uint64(0) { return "(INF)" } return fmt.Sprintf("%d", lmt) diff --git a/libnetwork/drivers/overlay/joinleave.go b/libnetwork/drivers/overlay/joinleave.go index 8cdf3194de734e0ab121b17a4510c517b7146ef9..1f21ee9b0d1508509a2bde51bab549b1f6420248 100644 --- a/libnetwork/drivers/overlay/joinleave.go +++ b/libnetwork/drivers/overlay/joinleave.go @@ -3,6 +3,7 @@ package overlay import ( "fmt" "net" + "syscall" log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/driverapi" @@ -31,6 +32,12 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("cannot join secure network: encryption keys not present") } + nlh := ns.NlHandle() + + if n.secure && !nlh.SupportsNetlinkFamily(syscall.NETLINK_XFRM) { + return fmt.Errorf("cannot join secure network: required modules to install IPSEC rules are missing on host") + } + s := n.getSubnetforIP(ep.addr) if s == nil { return fmt.Errorf("could not find subnet for endpoint %s", eid) @@ -65,8 +72,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err) } - nlh := ns.NlHandle() - // Set the container interface and its peer MTU to 1450 to allow // for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) + // outer UDP(8) + vxlan header(8)) diff --git a/libnetwork/drivers/overlay/ov_network.go b/libnetwork/drivers/overlay/ov_network.go index 7edb5077c5e101634d9dfaaaba988f100475cee2..cc2f0879a0fe09672f2be2f099e45055b5bf0c4a 100644 --- a/libnetwork/drivers/overlay/ov_network.go +++ b/libnetwork/drivers/overlay/ov_network.go @@ -284,7 +284,7 @@ func populateVNITbl() { } defer ns.Close() - nlh, err := netlink.NewHandleAt(ns) + nlh, err := netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE) if err != nil { logrus.Errorf("Could not open netlink handle during vni population for ns %s: %v", path, err) return nil diff --git a/libnetwork/drivers/overlay/ov_utils.go b/libnetwork/drivers/overlay/ov_utils.go index f9f32dec48ce0767a8d3049ef91befebb713d6ec..f49c5d4e5fc1f0c351e41c28587ed29a567a20df 100644 --- a/libnetwork/drivers/overlay/ov_utils.go +++ b/libnetwork/drivers/overlay/ov_utils.go @@ -3,6 +3,7 @@ package overlay import ( "fmt" "strings" + "syscall" "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/netutils" @@ -128,7 +129,7 @@ func deleteVxlanByVNI(path string, vni uint32) error { } defer ns.Close() - nlh, err = netlink.NewHandleAt(ns) + nlh, err = netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE) if err != nil { return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err) } diff --git a/libnetwork/ns/init_linux.go b/libnetwork/ns/init_linux.go index ea0cfc059351322735bbc13873b2366615eb94f0..78529c7fbe6869d3e32f71fd44266744fb361d34 100644 --- a/libnetwork/ns/init_linux.go +++ b/libnetwork/ns/init_linux.go @@ -3,6 +3,8 @@ package ns import ( "fmt" "os" + "os/exec" + "strings" "sync" "syscall" @@ -24,7 +26,7 @@ func Init() { if err != nil { log.Errorf("could not get initial namespace: %v", err) } - initNl, err = netlink.NewHandle() + initNl, err = netlink.NewHandle(getSupportedNlFamilies()...) if err != nil { log.Errorf("could not create netlink handle on initial namespace: %v", err) } @@ -32,6 +34,7 @@ func Init() { // SetNamespace sets the initial namespace handler func SetNamespace() error { + initOnce.Do(Init) if err := netns.Set(initNs); err != nil { linkInfo, linkErr := getLink() if linkErr != nil { @@ -62,3 +65,22 @@ func NlHandle() *netlink.Handle { initOnce.Do(Init) return initNl } + +func getSupportedNlFamilies() []int { + fams := []int{syscall.NETLINK_ROUTE} + if err := loadXfrmModules(); err != nil { + log.Warnf("Could not load necessary modules for IPSEC rules: %v", err) + return fams + } + return append(fams, syscall.NETLINK_XFRM) +} + +func loadXfrmModules() error { + if out, err := exec.Command("modprobe", "-va", "xfrm_user").CombinedOutput(); err != nil { + return fmt.Errorf("Running modprobe xfrm_user failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) + } + if out, err := exec.Command("modprobe", "-va", "xfrm_algo").CombinedOutput(); err != nil { + return fmt.Errorf("Running modprobe xfrm_algo failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err) + } + return nil +} diff --git a/libnetwork/osl/namespace_linux.go b/libnetwork/osl/namespace_linux.go index b9a0201e16aa8ffdf8d8b0d03fe44bf7efad4eec..3dad60472a28668606ed6d0e473dc8e389aac19e 100644 --- a/libnetwork/osl/namespace_linux.go +++ b/libnetwork/osl/namespace_linux.go @@ -30,7 +30,6 @@ var ( gpmWg sync.WaitGroup gpmCleanupPeriod = 60 * time.Second gpmChan = make(chan chan struct{}) - nsOnce sync.Once ) // The networkNamespace type is the linux implementation of the Sandbox @@ -196,7 +195,7 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) { } defer sboxNs.Close() - n.nlHandle, err = netlink.NewHandleAt(sboxNs) + n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } @@ -238,7 +237,7 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) { } defer sboxNs.Close() - n.nlHandle, err = netlink.NewHandleAt(sboxNs) + n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } @@ -326,7 +325,6 @@ func (n *networkNamespace) InvokeFunc(f func()) error { // InitOSContext initializes OS context while configuring network resources func InitOSContext() func() { - nsOnce.Do(ns.Init) runtime.LockOSThread() if err := ns.SetNamespace(); err != nil { log.Error(err) diff --git a/libnetwork/osl/sandbox_linux_test.go b/libnetwork/osl/sandbox_linux_test.go index 1c5373e134aa9ac35eb50efdce210f94efdf6578..b76377806ef9d0f386deefa83731016d49eff781 100644 --- a/libnetwork/osl/sandbox_linux_test.go +++ b/libnetwork/osl/sandbox_linux_test.go @@ -197,7 +197,7 @@ func TestDisableIPv6DAD(t *testing.T) { LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, PeerName: "sideB", } - nlh, err := netlink.NewHandle() + nlh, err := netlink.NewHandle(syscall.NETLINK_ROUTE) if err != nil { t.Fatal(err) }