|
@@ -4,6 +4,7 @@ import (
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"fmt"
|
|
"fmt"
|
|
"net"
|
|
"net"
|
|
|
|
+ "os"
|
|
"sync"
|
|
"sync"
|
|
"syscall"
|
|
"syscall"
|
|
|
|
|
|
@@ -12,11 +13,17 @@ import (
|
|
"github.com/docker/libnetwork/driverapi"
|
|
"github.com/docker/libnetwork/driverapi"
|
|
"github.com/docker/libnetwork/netutils"
|
|
"github.com/docker/libnetwork/netutils"
|
|
"github.com/docker/libnetwork/osl"
|
|
"github.com/docker/libnetwork/osl"
|
|
|
|
+ "github.com/docker/libnetwork/resolvconf"
|
|
"github.com/docker/libnetwork/types"
|
|
"github.com/docker/libnetwork/types"
|
|
"github.com/vishvananda/netlink"
|
|
"github.com/vishvananda/netlink"
|
|
"github.com/vishvananda/netlink/nl"
|
|
"github.com/vishvananda/netlink/nl"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+var (
|
|
|
|
+ hostMode bool
|
|
|
|
+ hostModeOnce sync.Once
|
|
|
|
+)
|
|
|
|
+
|
|
type networkTable map[string]*network
|
|
type networkTable map[string]*network
|
|
|
|
|
|
type subnet struct {
|
|
type subnet struct {
|
|
@@ -87,22 +94,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-/* func (d *driver) createNetworkfromStore(nid string) (*network, error) {
|
|
|
|
- n := &network{
|
|
|
|
- id: nid,
|
|
|
|
- driver: d,
|
|
|
|
- endpoints: endpointTable{},
|
|
|
|
- once: &sync.Once{},
|
|
|
|
- subnets: []*subnet{},
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- err := d.store.GetObject(datastore.Key(n.Key()...), n)
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, fmt.Errorf("unable to get network %q from data store, %v", nid, err)
|
|
|
|
- }
|
|
|
|
- return n, nil
|
|
|
|
-}*/
|
|
|
|
-
|
|
|
|
func (d *driver) DeleteNetwork(nid string) error {
|
|
func (d *driver) DeleteNetwork(nid string) error {
|
|
if nid == "" {
|
|
if nid == "" {
|
|
return fmt.Errorf("invalid network id")
|
|
return fmt.Errorf("invalid network id")
|
|
@@ -171,24 +162,110 @@ func (n *network) destroySandbox() {
|
|
}
|
|
}
|
|
|
|
|
|
for _, s := range n.subnets {
|
|
for _, s := range n.subnets {
|
|
|
|
+ if hostMode {
|
|
|
|
+ if err := removeFilters(n.id[:12], s.brName); err != nil {
|
|
|
|
+ logrus.Warnf("Could not remove overlay filters: %v", err)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if s.vxlanName != "" {
|
|
if s.vxlanName != "" {
|
|
- err := deleteVxlan(s.vxlanName)
|
|
|
|
|
|
+ err := deleteInterface(s.vxlanName)
|
|
if err != nil {
|
|
if err != nil {
|
|
logrus.Warnf("could not cleanup sandbox properly: %v", err)
|
|
logrus.Warnf("could not cleanup sandbox properly: %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if hostMode {
|
|
|
|
+ if err := removeNetworkChain(n.id[:12]); err != nil {
|
|
|
|
+ logrus.Warnf("could not remove network chain: %v", err)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
sbox.Destroy()
|
|
sbox.Destroy()
|
|
n.setSandbox(nil)
|
|
n.setSandbox(nil)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func (n *network) initSubnetSandbox(s *subnet) error {
|
|
|
|
- // create a bridge and vxlan device for this subnet and move it to the sandbox
|
|
|
|
- brName, err := netutils.GenerateIfaceName("bridge", 7)
|
|
|
|
|
|
+func setHostMode() {
|
|
|
|
+ if os.Getenv("_OVERLAY_HOST_MODE") != "" {
|
|
|
|
+ hostMode = true
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ err := createVxlan("testvxlan", 1)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return err
|
|
|
|
|
|
+ logrus.Errorf("Failed to create testvxlan interface: %v", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ defer deleteInterface("testvxlan")
|
|
|
|
+
|
|
|
|
+ path := "/proc/self/ns/net"
|
|
|
|
+ f, err := os.OpenFile(path, os.O_RDONLY, 0)
|
|
|
|
+ if err != nil {
|
|
|
|
+ logrus.Errorf("Failed to open path %s for network namespace for setting host mode: %v", path, err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ defer f.Close()
|
|
|
|
+
|
|
|
|
+ nsFD := f.Fd()
|
|
|
|
+
|
|
|
|
+ iface, err := netlink.LinkByName("testvxlan")
|
|
|
|
+ if err != nil {
|
|
|
|
+ logrus.Errorf("Failed to get link testvxlan: %v", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If we are not able to move the vxlan interface to a namespace
|
|
|
|
+ // then fallback to host mode
|
|
|
|
+ if err := netlink.LinkSetNsFd(iface, int(nsFD)); err != nil {
|
|
|
|
+ hostMode = true
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (n *network) generateVxlanName(s *subnet) string {
|
|
|
|
+ return "vx-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + n.id[:5]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (n *network) generateBridgeName(s *subnet) string {
|
|
|
|
+ return "ov-" + fmt.Sprintf("%06x", n.vxlanID(s)) + "-" + n.id[:5]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func isOverlap(nw *net.IPNet) bool {
|
|
|
|
+ var nameservers []string
|
|
|
|
+
|
|
|
|
+ if rc, err := resolvconf.Get(); err == nil {
|
|
|
|
+ nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if err := netutils.CheckNameserverOverlaps(nameservers, nw); err != nil {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if err := netutils.CheckRouteOverlaps(nw); err != nil {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (n *network) initSubnetSandbox(s *subnet) error {
|
|
|
|
+ brName := n.generateBridgeName(s)
|
|
|
|
+ vxlanName := n.generateVxlanName(s)
|
|
|
|
+
|
|
|
|
+ if hostMode {
|
|
|
|
+ // Try to delete stale bridge interface if it exists
|
|
|
|
+ deleteInterface(brName)
|
|
|
|
+ // Try to delete the vxlan interface by vni if already present
|
|
|
|
+ deleteVxlanByVNI(n.vxlanID(s))
|
|
|
|
+
|
|
|
|
+ if isOverlap(s.subnetIP) {
|
|
|
|
+ return fmt.Errorf("overlay subnet %s has conflicts in the host while running in host mode", s.subnetIP.String())
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // create a bridge and vxlan device for this subnet and move it to the sandbox
|
|
sbox := n.sandbox()
|
|
sbox := n.sandbox()
|
|
|
|
|
|
if err := sbox.AddInterface(brName, "br",
|
|
if err := sbox.AddInterface(brName, "br",
|
|
@@ -197,7 +274,7 @@ func (n *network) initSubnetSandbox(s *subnet) error {
|
|
return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err)
|
|
return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err)
|
|
}
|
|
}
|
|
|
|
|
|
- vxlanName, err := createVxlan(n.vxlanID(s))
|
|
|
|
|
|
+ err := createVxlan(vxlanName, n.vxlanID(s))
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
@@ -207,6 +284,12 @@ func (n *network) initSubnetSandbox(s *subnet) error {
|
|
return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.String(), err)
|
|
return fmt.Errorf("vxlan interface creation failed for subnet %q: %v", s.subnetIP.String(), err)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if hostMode {
|
|
|
|
+ if err := addFilters(n.id[:12], brName); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
n.Lock()
|
|
n.Lock()
|
|
s.vxlanName = vxlanName
|
|
s.vxlanName = vxlanName
|
|
s.brName = brName
|
|
s.brName = brName
|
|
@@ -220,8 +303,16 @@ func (n *network) initSandbox() error {
|
|
n.initEpoch++
|
|
n.initEpoch++
|
|
n.Unlock()
|
|
n.Unlock()
|
|
|
|
|
|
|
|
+ hostModeOnce.Do(setHostMode)
|
|
|
|
+
|
|
|
|
+ if hostMode {
|
|
|
|
+ if err := addNetworkChain(n.id[:12]); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
sbox, err := osl.NewSandbox(
|
|
sbox, err := osl.NewSandbox(
|
|
- osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), true)
|
|
|
|
|
|
+ osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), !hostMode)
|
|
if err != nil {
|
|
if err != nil {
|
|
return fmt.Errorf("could not create network sandbox: %v", err)
|
|
return fmt.Errorf("could not create network sandbox: %v", err)
|
|
}
|
|
}
|