Bläddra i källkod

Check existence of network chain before creating

We check for existence of all filter rules in
overlay driver before creating it. We should
also do this for chain creation, because even though
we cleanup network chains when the last container
stops, there is a possibility of a stale network
chain in case of ungraceful restart.

Also cleaned up stale bridges if any exist due to
ungraceful shutdown of daemon.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 9 år sedan
förälder
incheckning
6cff09f710

+ 21 - 9
libnetwork/drivers/overlay/filter.go

@@ -22,15 +22,21 @@ func rawIPTables(args ...string) error {
 	return nil
 	return nil
 }
 }
 
 
+func chainExists(cname string) bool {
+	if err := rawIPTables("-L", cname); err != nil {
+		return false
+	}
+
+	return true
+}
+
 func setupGlobalChain() {
 func setupGlobalChain() {
 	if err := rawIPTables("-N", globalChain); err != nil {
 	if err := rawIPTables("-N", globalChain); err != nil {
-		logrus.Errorf("could not create global overlay chain: %v", err)
-		return
+		logrus.Debugf("could not create global overlay chain: %v", err)
 	}
 	}
 
 
 	if err := rawIPTables("-A", globalChain, "-j", "RETURN"); err != nil {
 	if err := rawIPTables("-A", globalChain, "-j", "RETURN"); err != nil {
-		logrus.Errorf("could not install default return chain in the overlay global chain: %v", err)
-		return
+		logrus.Debugf("could not install default return chain in the overlay global chain: %v", err)
 	}
 	}
 }
 }
 
 
@@ -38,22 +44,28 @@ func setNetworkChain(cname string, remove bool) error {
 	// Initialize the onetime global overlay chain
 	// Initialize the onetime global overlay chain
 	filterOnce.Do(setupGlobalChain)
 	filterOnce.Do(setupGlobalChain)
 
 
+	exists := chainExists(cname)
+
 	opt := "-N"
 	opt := "-N"
 	// In case of remove, make sure to flush the rules in the chain
 	// In case of remove, make sure to flush the rules in the chain
-	if remove {
+	if remove && exists {
 		if err := rawIPTables("-F", cname); err != nil {
 		if err := rawIPTables("-F", cname); err != nil {
 			return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
 			return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
 		}
 		}
 		opt = "-X"
 		opt = "-X"
 	}
 	}
 
 
-	if err := rawIPTables(opt, cname); err != nil {
-		return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
+	if (!remove && !exists) || (remove && exists) {
+		if err := rawIPTables(opt, cname); err != nil {
+			return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
+		}
 	}
 	}
 
 
 	if !remove {
 	if !remove {
-		if err := rawIPTables("-A", cname, "-j", "DROP"); err != nil {
-			return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
+		if !iptables.Exists(iptables.Filter, cname, "-j", "DROP") {
+			if err := rawIPTables("-A", cname, "-j", "DROP"); err != nil {
+				return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
+			}
 		}
 		}
 	}
 	}
 
 

+ 14 - 10
libnetwork/drivers/overlay/ov_network.go

@@ -169,7 +169,7 @@ func (n *network) destroySandbox() {
 			}
 			}
 
 
 			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)
 				}
 				}
@@ -199,7 +199,7 @@ func setHostMode() {
 		return
 		return
 	}
 	}
 
 
-	defer deleteVxlan("testvxlan")
+	defer deleteInterface("testvxlan")
 
 
 	path := "/proc/self/ns/net"
 	path := "/proc/self/ns/net"
 	f, err := os.OpenFile(path, os.O_RDONLY, 0)
 	f, err := os.OpenFile(path, os.O_RDONLY, 0)
@@ -251,12 +251,21 @@ func isOverlap(nw *net.IPNet) bool {
 }
 }
 
 
 func (n *network) initSubnetSandbox(s *subnet) error {
 func (n *network) initSubnetSandbox(s *subnet) error {
-	if hostMode && isOverlap(s.subnetIP) {
-		return fmt.Errorf("overlay subnet %s has conflicts in the host while running in host mode", s.subnetIP.String())
+	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
 	// create a bridge and vxlan device for this subnet and move it to the sandbox
-	brName := n.generateBridgeName(s)
 	sbox := n.sandbox()
 	sbox := n.sandbox()
 
 
 	if err := sbox.AddInterface(brName, "br",
 	if err := sbox.AddInterface(brName, "br",
@@ -265,11 +274,6 @@ 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 := n.generateVxlanName(s)
-
-	// Try to delete the vxlan interface by vni if already present
-	deleteVxlanByVNI(n.vxlanID(s))
-
 	err := createVxlan(vxlanName, n.vxlanID(s))
 	err := createVxlan(vxlanName, n.vxlanID(s))
 	if err != nil {
 	if err != nil {
 		return err
 		return err

+ 3 - 3
libnetwork/drivers/overlay/ov_utils.go

@@ -67,16 +67,16 @@ func createVxlan(name string, vni uint32) error {
 	return nil
 	return nil
 }
 }
 
 
-func deleteVxlan(name string) error {
+func deleteInterface(name string) error {
 	defer osl.InitOSContext()()
 	defer osl.InitOSContext()()
 
 
 	link, err := netlink.LinkByName(name)
 	link, err := netlink.LinkByName(name)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("failed to find vxlan interface with name %s: %v", name, err)
+		return fmt.Errorf("failed to find interface with name %s: %v", name, err)
 	}
 	}
 
 
 	if err := netlink.LinkDel(link); err != nil {
 	if err := netlink.LinkDel(link); err != nil {
-		return fmt.Errorf("error deleting vxlan interface: %v", err)
+		return fmt.Errorf("error deleting interface with name %s: %v", name, err)
 	}
 	}
 
 
 	return nil
 	return nil