From fedca67af7cab79a8ce3f8472186bce0bed39af2 Mon Sep 17 00:00:00 2001 From: Manohar Castelino Date: Wed, 22 Mar 2017 00:08:08 +0000 Subject: [PATCH] drivers/macvlan: Add support for optional runtime hint docker supports alternate OCI runtimes including virtual machine based runtimes. In certian cases network plugins can optionally choose to support creation of virtual machine friendly interfaces using optional network options. This is illustrated here with the hint being used by the macvlan driver to create a macvtap interface vs a macvlan interface when the runtime is known to be a VM based runtime. docker run --runtime=cor -it --net=pub_net --network "name=pub_net,runtime=namespace" alpine sh This is currently based off of https://github.com/docker/docker/pull/27638 However this will be implemented as per the proposal https://github.com/docker/docker/issues/31964 Signed-off-by: Manohar Castelino --- drivers/macvlan/macvlan.go | 1 + drivers/macvlan/macvlan_endpoint.go | 13 ++++++++ drivers/macvlan/macvlan_joinleave.go | 2 +- drivers/macvlan/macvlan_setup.go | 50 +++++++++++++++++++--------- drivers/macvlan/macvlan_store.go | 2 ++ 5 files changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/macvlan/macvlan.go b/drivers/macvlan/macvlan.go index 49b9fbae00..70bec82024 100644 --- a/drivers/macvlan/macvlan.go +++ b/drivers/macvlan/macvlan.go @@ -46,6 +46,7 @@ type endpoint struct { srcName string dbIndex uint64 dbExists bool + runtime string } type network struct { diff --git a/drivers/macvlan/macvlan_endpoint.go b/drivers/macvlan/macvlan_endpoint.go index 3e5ccb29f8..a55fe31bdb 100644 --- a/drivers/macvlan/macvlan_endpoint.go +++ b/drivers/macvlan/macvlan_endpoint.go @@ -40,6 +40,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, return err } } + // disallow portmapping -p if opt, ok := epOptions[netlabel.PortMap]; ok { if _, ok := opt.([]types.PortBinding); ok { @@ -57,6 +58,18 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, } } + // Setup the runtime to default to namespace, override if specified + ep.runtime = "namespace" + if opt, ok := epOptions["runtime"]; ok { + if runtime, ok := opt.(string); ok { + if runtime != "namespace" && runtime != "vm" { + logrus.Warnf("driver does not support [%s] runtime", runtime) + } else { + ep.runtime = runtime + } + } + } + if err := d.storeUpdate(ep); err != nil { return fmt.Errorf("failed to save macvlan endpoint %s to store: %v", ep.id[0:7], err) } diff --git a/drivers/macvlan/macvlan_joinleave.go b/drivers/macvlan/macvlan_joinleave.go index cf5c2a4bf9..bdd80b8995 100644 --- a/drivers/macvlan/macvlan_joinleave.go +++ b/drivers/macvlan/macvlan_joinleave.go @@ -28,7 +28,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, return fmt.Errorf("error generating an interface name: %s", err) } // create the netlink macvlan interface - vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode) + vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode, endpoint.runtime) if err != nil { return err } diff --git a/drivers/macvlan/macvlan_setup.go b/drivers/macvlan/macvlan_setup.go index b5b4be3499..88322531ca 100644 --- a/drivers/macvlan/macvlan_setup.go +++ b/drivers/macvlan/macvlan_setup.go @@ -16,8 +16,8 @@ const ( macvlanMajorVer = 9 // minimum macvlan major kernel support ) -// Create the macvlan slave specifying the source name -func createMacVlan(containerIfName, parent, macvlanMode string) (string, error) { +// Create the macvlan slave specifying the source name and the runtime type +func createMacVlan(containerIfName, parent, macvlanMode, runtime string) (string, error) { // Set the macvlan mode. Default is bridge mode mode, err := setMacVlanMode(macvlanMode) if err != nil { @@ -32,20 +32,40 @@ func createMacVlan(containerIfName, parent, macvlanMode string) (string, error) if err != nil { return "", fmt.Errorf("error occoured looking up the %s parent iface %s error: %s", macvlanType, parent, err) } - // Create a macvlan link - macvlan := &netlink.Macvlan{ - LinkAttrs: netlink.LinkAttrs{ - Name: containerIfName, - ParentIndex: parentLink.Attrs().Index, - }, - Mode: mode, - } - if err := ns.NlHandle().LinkAdd(macvlan); err != nil { - // If a user creates a macvlan and ipvlan on same parent, only one slave iface can be active at a time. - return "", fmt.Errorf("failed to create the %s port: %v", macvlanType, err) - } - return macvlan.Attrs().Name, nil + if runtime == "vm" { + // Create a macvtap link + macvtap := &netlink.Macvtap{ + Macvlan: netlink.Macvlan{ + LinkAttrs: netlink.LinkAttrs{ + Name: containerIfName, + ParentIndex: parentLink.Attrs().Index, + }, + Mode: mode, + }, + } + + if err := ns.NlHandle().LinkAdd(macvtap); err != nil { + return "", fmt.Errorf("failed to create the %s port: %v", macvlanType, err) + } + + return macvtap.Attrs().Name, nil + } else { + // Create a macvlan link + macvlan := &netlink.Macvlan{ + LinkAttrs: netlink.LinkAttrs{ + Name: containerIfName, + ParentIndex: parentLink.Attrs().Index, + }, + Mode: mode, + } + if err := ns.NlHandle().LinkAdd(macvlan); err != nil { + // If a user creates a macvlan and ipvlan on same parent, only one slave iface can be active at a time. + return "", fmt.Errorf("failed to create the %s port: %v", macvlanType, err) + } + + return macvlan.Attrs().Name, nil + } } // setMacVlanMode setter for one of the four macvlan port types diff --git a/drivers/macvlan/macvlan_store.go b/drivers/macvlan/macvlan_store.go index 3fd92786bf..1d23bb89de 100644 --- a/drivers/macvlan/macvlan_store.go +++ b/drivers/macvlan/macvlan_store.go @@ -255,6 +255,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) { epMap["id"] = ep.id epMap["nid"] = ep.nid epMap["SrcName"] = ep.srcName + epMap["runtime"] = ep.runtime if len(ep.mac) != 0 { epMap["MacAddress"] = ep.mac.String() } @@ -295,6 +296,7 @@ func (ep *endpoint) UnmarshalJSON(b []byte) error { ep.id = epMap["id"].(string) ep.nid = epMap["nid"].(string) ep.srcName = epMap["SrcName"].(string) + ep.runtime = epMap["runtime"].(string) return nil }