From 6cff09f710e64fec53ced2b289864bf89bc5ac9c Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Tue, 22 Dec 2015 10:12:23 -0800 Subject: [PATCH] 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 --- libnetwork/drivers/overlay/filter.go | 30 +++++++++++++++++------- libnetwork/drivers/overlay/ov_network.go | 24 +++++++++++-------- libnetwork/drivers/overlay/ov_utils.go | 6 ++--- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/libnetwork/drivers/overlay/filter.go b/libnetwork/drivers/overlay/filter.go index 01b4d5b01b..33178ade37 100644 --- a/libnetwork/drivers/overlay/filter.go +++ b/libnetwork/drivers/overlay/filter.go @@ -22,15 +22,21 @@ func rawIPTables(args ...string) error { return nil } +func chainExists(cname string) bool { + if err := rawIPTables("-L", cname); err != nil { + return false + } + + return true +} + func setupGlobalChain() { 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 { - 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 filterOnce.Do(setupGlobalChain) + exists := chainExists(cname) + opt := "-N" // 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 { return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err) } 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 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) + } } } diff --git a/libnetwork/drivers/overlay/ov_network.go b/libnetwork/drivers/overlay/ov_network.go index 6e558c9a3c..0a891c0e5e 100644 --- a/libnetwork/drivers/overlay/ov_network.go +++ b/libnetwork/drivers/overlay/ov_network.go @@ -169,7 +169,7 @@ func (n *network) destroySandbox() { } if s.vxlanName != "" { - err := deleteVxlan(s.vxlanName) + err := deleteInterface(s.vxlanName) if err != nil { logrus.Warnf("could not cleanup sandbox properly: %v", err) } @@ -199,7 +199,7 @@ func setHostMode() { return } - defer deleteVxlan("testvxlan") + defer deleteInterface("testvxlan") path := "/proc/self/ns/net" 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 { - 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 - brName := n.generateBridgeName(s) sbox := n.sandbox() 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) } - 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)) if err != nil { return err diff --git a/libnetwork/drivers/overlay/ov_utils.go b/libnetwork/drivers/overlay/ov_utils.go index 211879c447..42c44b9675 100644 --- a/libnetwork/drivers/overlay/ov_utils.go +++ b/libnetwork/drivers/overlay/ov_utils.go @@ -67,16 +67,16 @@ func createVxlan(name string, vni uint32) error { return nil } -func deleteVxlan(name string) error { +func deleteInterface(name string) error { defer osl.InitOSContext()() link, err := netlink.LinkByName(name) 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 { - return fmt.Errorf("error deleting vxlan interface: %v", err) + return fmt.Errorf("error deleting interface with name %s: %v", name, err) } return nil