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>
This commit is contained in:
Jana Radhakrishnan 2015-12-22 10:12:23 -08:00
parent 438314977f
commit 6cff09f710
3 changed files with 38 additions and 22 deletions

View file

@ -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)
}
}
}

View file

@ -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

View file

@ -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