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:
parent
438314977f
commit
6cff09f710
3 changed files with 38 additions and 22 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue