Added IPVLAN link support
This commit is contained in:
Родитель
db1901b6c6
Коммит
903ff36e69
145
netlink/link.go
145
netlink/link.go
|
@ -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
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче