This commit is contained in:
Onur Filiz 2017-02-28 01:27:20 -08:00
Родитель db1901b6c6
Коммит 903ff36e69
4 изменённых файлов: 139 добавлений и 47 удалений

Просмотреть файл

@ -10,9 +10,70 @@ import (
"golang.org/x/sys/unix"
)
// Link types.
const (
LINK_TYPE_BRIDGE = "bridge"
LINK_TYPE_VETH = "veth"
LINK_TYPE_IPVLAN = "ipvlan"
LINK_TYPE_DUMMY = "dummy"
)
// IPVLAN link attributes.
type IPVlanMode uint16
const (
IPVLAN_MODE_L2 IPVlanMode = iota
IPVLAN_MODE_L3
IPVLAN_MODE_L3S
IPVLAN_MODE_MAX
)
// Link represents a network interface.
type Link interface {
Info() *LinkInfo
}
// LinkInfo respresents the common properties of all network interfaces.
type LinkInfo struct {
Type string
Name string
MTU uint
TxQLen uint
ParentIndex int
}
func (linkInfo *LinkInfo) Info() *LinkInfo {
return linkInfo
}
// BridgeLink represents an ethernet bridge.
type BridgeLink struct {
LinkInfo
}
// VEthLink represents a virtual ethernet network interface.
type VEthLink struct {
LinkInfo
PeerName string
}
// IPVlanLink represents an IPVlan network interface.
type IPVlanLink struct {
LinkInfo
Mode IPVlanMode
}
// DummyLink represents a dummy network interface.
type DummyLink struct {
LinkInfo
}
// AddLink adds a new network interface of a specified type.
func AddLink(name string, linkType string) error {
if name == "" || linkType == "" {
func AddLink(link Link) error {
var info *LinkInfo
info = link.Info()
if info.Name == "" || info.Type == "" {
return fmt.Errorf("Invalid link name or type")
}
@ -26,13 +87,51 @@ func AddLink(name string, linkType string) error {
ifInfo := newIfInfoMsg()
req.addPayload(ifInfo)
attrLinkInfo := newAttribute(unix.IFLA_LINKINFO, nil)
attrLinkInfo.addNested(newAttributeString(IFLA_INFO_KIND, linkType))
req.addPayload(attrLinkInfo)
attrIfName := newAttributeStringZ(unix.IFLA_IFNAME, name)
// Set interface name.
attrIfName := newAttributeStringZ(unix.IFLA_IFNAME, info.Name)
req.addPayload(attrIfName)
// Set MTU.
if info.MTU > 0 {
req.addPayload(newAttributeUint32(unix.IFLA_MTU, uint32(info.MTU)))
}
// Set transmission queue length.
if info.TxQLen > 0 {
req.addPayload(newAttributeUint32(unix.IFLA_TXQLEN, uint32(info.TxQLen)))
}
// Set parent interface index.
if info.ParentIndex != 0 {
req.addPayload(newAttributeUint32(unix.IFLA_LINK, uint32(info.ParentIndex)))
}
// Set link info.
attrLinkInfo := newAttribute(unix.IFLA_LINKINFO, nil)
attrLinkInfo.addNested(newAttributeString(IFLA_INFO_KIND, info.Type))
// Set link type-specific attributes.
if veth, ok := link.(*VEthLink); ok {
// Set VEth attributes.
attrData := newAttribute(IFLA_INFO_DATA, nil)
attrPeer := newAttribute(VETH_INFO_PEER, nil)
attrPeer.addNested(newIfInfoMsg())
attrPeer.addNested(newAttributeStringZ(unix.IFLA_IFNAME, veth.PeerName))
attrData.addNested(attrPeer)
attrLinkInfo.addNested(attrData)
} else if ipvlan, ok := link.(*IPVlanLink); ok {
// Set IPVlan attributes.
attrData := newAttribute(IFLA_INFO_DATA, nil)
attrData.addNested(newAttributeUint16(IFLA_IPVLAN_MODE, uint16(ipvlan.Mode)))
attrLinkInfo.addNested(attrData)
}
req.addPayload(attrLinkInfo)
return s.sendAndWaitForAck(req)
}
@ -207,35 +306,3 @@ func SetLinkAddress(ifName string, hwAddress net.HardwareAddr) error {
return s.sendAndWaitForAck(req)
}
// AddVethPair adds a new veth pair.
func AddVethPair(name1 string, name2 string) error {
s, err := getSocket()
if err != nil {
return err
}
req := newRequest(unix.RTM_NEWLINK, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
ifInfo := newIfInfoMsg()
req.addPayload(ifInfo)
attrIfName := newAttributeStringZ(unix.IFLA_IFNAME, name1)
req.addPayload(attrIfName)
attrLinkInfo := newAttribute(unix.IFLA_LINKINFO, nil)
attrLinkInfo.addNested(newAttributeStringZ(IFLA_INFO_KIND, "veth"))
attrData := newAttribute(IFLA_INFO_DATA, nil)
attrPeer := newAttribute(VETH_INFO_PEER, nil)
attrPeer.addNested(newIfInfoMsg())
attrPeer.addNested(newAttributeStringZ(unix.IFLA_IFNAME, name2))
attrLinkInfo.addNested(attrData)
attrData.addNested(attrPeer)
req.addPayload(attrLinkInfo)
return s.sendAndWaitForAck(req)
}

Просмотреть файл

@ -13,11 +13,12 @@ import (
// Netlink protocol constants that are not already defined in unix package.
const (
IFLA_INFO_KIND = 1
IFLA_INFO_DATA = 2
IFLA_NET_NS_FD = 28
VETH_INFO_PEER = 1
DEFAULT_CHANGE = 0xFFFFFFFF
IFLA_INFO_KIND = 1
IFLA_INFO_DATA = 2
IFLA_NET_NS_FD = 28
IFLA_IPVLAN_MODE = 1
VETH_INFO_PEER = 1
DEFAULT_CHANGE = 0xFFFFFFFF
)
// Serializable types are used to construct netlink messages.
@ -159,6 +160,13 @@ func newAttributeUint32(attrType int, value uint32) *attribute {
return newAttribute(attrType, buf)
}
// Creates a new attribute with a uint16 value.
func newAttributeUint16(attrType int, value uint16) *attribute {
buf := make([]byte, 2)
encoder.PutUint16(buf, value)
return newAttribute(attrType, buf)
}
// Creates a new attribute with a net.IP value.
func newAttributeIpAddress(attrType int, value net.IP) *attribute {
addr := value.To4()

Просмотреть файл

@ -34,7 +34,16 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
contIfName := fmt.Sprintf("%s%s-2", hostInterfacePrefix, epInfo.Id[:7])
log.Printf("[net] Creating veth pair %v %v.", hostIfName, contIfName)
err = netlink.AddVethPair(contIfName, hostIfName)
link := netlink.VEthLink{
LinkInfo: netlink.LinkInfo{
Type: netlink.LINK_TYPE_VETH,
Name: contIfName,
},
PeerName: hostIfName,
}
err = netlink.AddLink(&link)
if err != nil {
log.Printf("[net] Failed to create veth pair, err:%v.", err)
return nil, err

Просмотреть файл

@ -46,7 +46,7 @@ func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInt
// DeleteNetworkImpl deletes an existing container network.
func (nm *networkManager) deleteNetworkImpl(nw *network) error {
// Disconnect the interface if this was the last network using it.
if len(nw.extIf.Networks) == 0 {
if len(nw.extIf.Networks) == 1 {
nm.disconnectExternalInterface(nw.extIf)
}
@ -76,7 +76,15 @@ func (nm *networkManager) connectExternalInterface(extIf *externalInterface, bri
if err != nil {
// Create the bridge.
log.Printf("[net] Creating bridge %v.", bridgeName)
err = netlink.AddLink(bridgeName, "bridge")
link := netlink.BridgeLink{
LinkInfo: netlink.LinkInfo{
Type: netlink.LINK_TYPE_BRIDGE,
Name: bridgeName,
},
}
err = netlink.AddLink(&link)
if err != nil {
return err
}