diff --git a/ipvs/ipvs.go b/ipvs/ipvs.go index 9b44159d..266cc24d 100644 --- a/ipvs/ipvs.go +++ b/ipvs/ipvs.go @@ -42,6 +42,7 @@ type Destination struct { // Handle provides a namespace specific ipvs handle to program ipvs // rules. type Handle struct { + seq uint32 sock *nl.NetlinkSocket } @@ -82,6 +83,11 @@ func (i *Handle) NewService(s *Service) error { return i.doCmd(s, nil, ipvsCmdNewService) } +// IsServicePresent queries for the ipvs service in the passed handle. +func (i *Handle) IsServicePresent(s *Service) bool { + return nil == i.doCmd(s, nil, ipvsCmdGetService) +} + // UpdateService updates an already existing service in the passed // handle. func (i *Handle) UpdateService(s *Service) error { diff --git a/ipvs/netlink.go b/ipvs/netlink.go index 26ce6cc4..a0e99ac0 100644 --- a/ipvs/netlink.go +++ b/ipvs/netlink.go @@ -10,6 +10,7 @@ import ( "os/exec" "strings" "sync" + "sync/atomic" "syscall" "unsafe" @@ -118,6 +119,7 @@ func fillDestinaton(d *Destination) nl.NetlinkRequestData { func (i *Handle) doCmd(s *Service, d *Destination, cmd uint8) error { req := newIPVSRequest(cmd) + req.Seq = atomic.AddUint32(&i.seq, 1) req.AddData(fillService(s)) if d != nil { @@ -206,7 +208,7 @@ done: } for _, m := range msgs { if m.Header.Seq != req.Seq { - return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) + continue } if m.Header.Pid != pid { return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid) diff --git a/service_common.go b/service_common.go index b43c6403..04f807ae 100644 --- a/service_common.go +++ b/service_common.go @@ -61,11 +61,6 @@ func (c *controller) cleanupServiceBindings(cleanupNID string) { } func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error { - var ( - s *service - addService bool - ) - n, err := c.NetworkByID(nid) if err != nil { return err @@ -123,11 +118,6 @@ func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, i fwMarkCtrMu.Unlock() s.loadBalancers[nid] = lb - - // Since we just created this load balancer make sure - // we add a new service service in IPVS rules. - addService = true - } lb.backEnds[eid] = ip @@ -135,7 +125,7 @@ func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, i // Add loadbalancer service and backend in all sandboxes in // the network only if vip is valid. if len(vip) != 0 { - n.(*network).addLBBackend(ip, vip, lb.fwMark, ingressPorts, addService) + n.(*network).addLBBackend(ip, vip, lb.fwMark, ingressPorts) } return nil diff --git a/service_linux.go b/service_linux.go index 3087639f..b095d2b7 100644 --- a/service_linux.go +++ b/service_linux.go @@ -97,20 +97,16 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) { } lb.service.Lock() - addService := true for _, ip := range lb.backEnds { - sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, - eIP, gwIP, addService, n.ingress) - addService = false + sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, gwIP, n.ingress) } lb.service.Unlock() } } // Add loadbalancer backend to all sandboxes which has a connection to -// this network. If needed add the service as well, as specified by -// the addService bool. -func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, addService bool) { +// this network. If needed add the service as well. +func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig) { n.WalkEndpoints(func(e Endpoint) bool { ep := e.(*endpoint) if sb, ok := ep.getSandbox(); ok { @@ -123,7 +119,7 @@ func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po gwIP = ep.Iface().Address().IP } - sb.addLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, addService, n.ingress) + sb.addLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, n.ingress) } return false @@ -154,7 +150,7 @@ func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Por } // Add loadbalancer backend into one connected sandbox. -func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, gwIP net.IP, addService bool, isIngressNetwork bool) { +func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, gwIP net.IP, isIngressNetwork bool) { if sb.osSbox == nil { return } @@ -176,7 +172,7 @@ func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*P SchedName: ipvs.RoundRobin, } - if addService { + if !i.IsServicePresent(s) { var filteredPorts []*PortConfig if sb.ingress { filteredPorts = filterPortConfigs(ingressPorts, false) diff --git a/service_windows.go b/service_windows.go index 8d79b2d8..6fe521ef 100644 --- a/service_windows.go +++ b/service_windows.go @@ -2,7 +2,7 @@ package libnetwork import "net" -func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, addService bool) { +func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig) { } func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, rmService bool) {