diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 236a189e84..0cda83017c 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -1131,3 +1131,20 @@ func (c *controller) cleanupLocalEndpoints() { } } } + +func (ep *endpoint) setAliasIP(sb *sandbox, ip net.IP, add bool) error { + sb.Lock() + sbox := sb.osSbox + sb.Unlock() + + for _, i := range sbox.Info().Interfaces() { + if ep.hasInterface(i.SrcName()) { + ipNet := &net.IPNet{IP: ip, Mask: []byte{255, 255, 255, 255}} + if err := i.SetAliasIP(ipNet, add); err != nil { + return err + } + break + } + } + return nil +} diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 72b1b13b6a..643939322e 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -26,7 +26,6 @@ type nwIface struct { mac net.HardwareAddr address *net.IPNet addressIPv6 *net.IPNet - ipAliases []*net.IPNet llAddrs []*net.IPNet routes []*net.IPNet bridge bool @@ -97,13 +96,6 @@ func (i *nwIface) LinkLocalAddresses() []*net.IPNet { return i.llAddrs } -func (i *nwIface) IPAliases() []*net.IPNet { - i.Lock() - defer i.Unlock() - - return i.ipAliases -} - func (i *nwIface) Routes() []*net.IPNet { i.Lock() defer i.Unlock() @@ -130,6 +122,28 @@ func (n *networkNamespace) Interfaces() []Interface { return ifaces } +func (i *nwIface) SetAliasIP(ip *net.IPNet, add bool) error { + i.Lock() + n := i.ns + i.Unlock() + + n.Lock() + nlh := n.nlHandle + n.Unlock() + + // Find the network interface identified by the DstName attribute. + iface, err := nlh.LinkByName(i.DstName()) + if err != nil { + return err + } + + ipAddr := &netlink.Addr{IPNet: ip, Label: ""} + if add { + return nlh.AddrAdd(iface, ipAddr) + } + return nlh.AddrDel(iface, ipAddr) +} + func (i *nwIface) Remove() error { i.Lock() n := i.ns @@ -333,7 +347,6 @@ func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *nwIface) err {setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())}, {setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())}, {setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())}, - {setInterfaceIPAliases, fmt.Sprintf("error setting interface %q IP Aliases to %v", ifaceName, i.IPAliases())}, } for _, config := range ifaceConfigurators { @@ -387,16 +400,6 @@ func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *nwIfac return nil } -func setInterfaceIPAliases(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { - for _, si := range i.IPAliases() { - ipAddr := &netlink.Addr{IPNet: si} - if err := nlh.AddrAdd(iface, ipAddr); err != nil { - return err - } - } - return nil -} - func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { return nlh.LinkSetName(iface, i.DstName()) } diff --git a/libnetwork/osl/options_linux.go b/libnetwork/osl/options_linux.go index 64309d0506..818669647f 100644 --- a/libnetwork/osl/options_linux.go +++ b/libnetwork/osl/options_linux.go @@ -66,12 +66,6 @@ func (n *networkNamespace) LinkLocalAddresses(list []*net.IPNet) IfaceOption { } } -func (n *networkNamespace) IPAliases(list []*net.IPNet) IfaceOption { - return func(i *nwIface) { - i.ipAliases = list - } -} - func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption { return func(i *nwIface) { i.routes = routes diff --git a/libnetwork/osl/sandbox.go b/libnetwork/osl/sandbox.go index 18085c9082..051a7facc2 100644 --- a/libnetwork/osl/sandbox.go +++ b/libnetwork/osl/sandbox.go @@ -91,9 +91,6 @@ type IfaceOptionSetter interface { // LinkLocalAddresses returns an option setter to set the link-local IP addresses. LinkLocalAddresses([]*net.IPNet) IfaceOption - // IPAliases returns an option setter to set IP address Aliases - IPAliases([]*net.IPNet) IfaceOption - // Master returns an option setter to set the master interface if any for this // interface. The master interface name should refer to the srcname of a // previously added interface of type bridge. @@ -150,9 +147,6 @@ type Interface interface { // LinkLocalAddresses returns the link-local IP addresses assigned to the interface. LinkLocalAddresses() []*net.IPNet - // IPAliases returns the IP address aliases assigned to the interface. - IPAliases() []*net.IPNet - // IP routes for the interface. Routes() []*net.IPNet @@ -166,6 +160,10 @@ type Interface interface { // and moving it out of the sandbox. Remove() error + // SetAliasIP adds or deletes the passed IP as an alias on the interface. + // ex: set the vip of services in the same network as secondary IP. + SetAliasIP(ip *net.IPNet, add bool) error + // Statistics returns the statistics for this interface Statistics() (*types.InterfaceStatistics, error) } diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index 7d1eef5b73..f4dbfd392a 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -725,10 +725,6 @@ func (sb *sandbox) restoreOslSandbox() error { if len(i.llAddrs) != 0 { ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) } - if len(ep.virtualIP) != 0 { - vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)} - ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias})) - } Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions if joinInfo != nil { for _, r := range joinInfo.StaticRoutes { @@ -782,10 +778,6 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error { if len(i.llAddrs) != 0 { ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) } - if len(ep.virtualIP) != 0 { - vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)} - ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias})) - } if i.mac != nil { ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac)) } diff --git a/libnetwork/service_linux.go b/libnetwork/service_linux.go index a3f49c28f8..669eda9fb3 100644 --- a/libnetwork/service_linux.go +++ b/libnetwork/service_linux.go @@ -317,6 +317,14 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) { for _, ip := range lb.backEnds { sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, gwIP, addService, n.ingress) + // For a new service program the vip as an alias on the task's sandbox interface + // connected to this network. + if !addService { + continue + } + if err := ep.setAliasIP(sb, lb.vip, true); err != nil { + logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", lb.vip, ep.ID(), ep.Name(), err) + } addService = false } lb.service.Unlock() @@ -340,8 +348,16 @@ func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po } sb.addLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, addService, n.ingress) - } + // For a new service program the vip as an alias on the task's sandbox interface + // connected to this network. + if !addService { + return false + } + if err := ep.setAliasIP(sb, vip, true); err != nil { + logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err) + } + } return false }) } @@ -363,8 +379,16 @@ func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Por } sb.rmLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, rmService, n.ingress) - } + // If the service is being remove its vip alias on on the task's sandbox interface + // has to be removed as well. + if !rmService { + return false + } + if err := ep.setAliasIP(sb, vip, false); err != nil { + logrus.Errorf("Removing Service VIP %v from ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err) + } + } return false }) }