From b6540296b0769cafb5f587e56ccea40cf065059b Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Sat, 19 Nov 2016 08:18:19 -0800 Subject: [PATCH 1/2] Revert "Enable ping for service vip address" This reverts commit ddc74ffcedbdf927a6855db611360f9c06658be8. Signed-off-by: Madhu Venugopal --- libnetwork/endpoint.go | 17 ------------- libnetwork/osl/interface_linux.go | 41 ++++++++++++++----------------- libnetwork/osl/options_linux.go | 6 +++++ libnetwork/osl/sandbox.go | 10 +++++--- libnetwork/sandbox.go | 8 ++++++ libnetwork/service_linux.go | 28 ++------------------- 6 files changed, 41 insertions(+), 69 deletions(-) diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index df79477dbb..f47ea4e18f 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -1148,20 +1148,3 @@ 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 65ad2ea144..2be99d72ea 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -26,6 +26,7 @@ type nwIface struct { mac net.HardwareAddr address *net.IPNet addressIPv6 *net.IPNet + ipAliases []*net.IPNet llAddrs []*net.IPNet routes []*net.IPNet bridge bool @@ -96,6 +97,13 @@ 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() @@ -122,28 +130,6 @@ 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 @@ -347,6 +333,7 @@ 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 { @@ -405,6 +392,16 @@ 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 818669647f..64309d0506 100644 --- a/libnetwork/osl/options_linux.go +++ b/libnetwork/osl/options_linux.go @@ -66,6 +66,12 @@ 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 051a7facc2..18085c9082 100644 --- a/libnetwork/osl/sandbox.go +++ b/libnetwork/osl/sandbox.go @@ -91,6 +91,9 @@ 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. @@ -147,6 +150,9 @@ 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 @@ -160,10 +166,6 @@ 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 5512e2a57b..1fd585cd28 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -761,6 +761,10 @@ 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 { @@ -814,6 +818,10 @@ 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 8d382d5540..9edbadefe8 100644 --- a/libnetwork/service_linux.go +++ b/libnetwork/service_linux.go @@ -101,14 +101,6 @@ 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() @@ -132,16 +124,8 @@ 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 }) } @@ -163,16 +147,8 @@ 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 }) } From 684ea925156f4c0abefb97007834fb65a9917e54 Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Sun, 20 Nov 2016 16:54:32 -0800 Subject: [PATCH 2/2] Add a ICMP reply rule for service VIP Ping on VIP has been behaving inconsistently depending on if a task for a service is local or remote. With this fix, the ICMP echo-request packets to service VIP are replied to by the NAT rule to self Signed-off-by: Madhu Venugopal --- libnetwork/service_linux.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libnetwork/service_linux.go b/libnetwork/service_linux.go index 9edbadefe8..be8dc84d3e 100644 --- a/libnetwork/service_linux.go +++ b/libnetwork/service_linux.go @@ -654,6 +654,9 @@ func fwMarker() { rule := strings.Fields(fmt.Sprintf("-t mangle %s OUTPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark)) rules = append(rules, rule) + rule = strings.Fields(fmt.Sprintf("-t nat %s OUTPUT -p icmp --icmp echo-request -d %s -j DNAT --to 127.0.0.1", addDelOpt, vip)) + rules = append(rules, rule) + for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err)