Signed-off-by: Alessandro Boch <aboch@docker.com>
| ... | ... |
@@ -23,7 +23,7 @@ github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e |
| 23 | 23 |
github.com/imdario/mergo 0.2.1 |
| 24 | 24 |
|
| 25 | 25 |
#get libnetwork packages |
| 26 |
-github.com/docker/libnetwork f36e733a08cd8239a2db296994cb6613fef1cece |
|
| 26 |
+github.com/docker/libnetwork dd0ddde6749fdffe310087e1c3616142d8c3ef9e |
|
| 27 | 27 |
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 28 | 28 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 29 | 29 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -123,7 +123,7 @@ func (sb *sandbox) needDefaultGW() bool {
|
| 123 | 123 |
return false |
| 124 | 124 |
} |
| 125 | 125 |
for _, r := range ep.StaticRoutes() {
|
| 126 |
- if r.Destination.String() == "0.0.0.0/0" {
|
|
| 126 |
+ if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" {
|
|
| 127 | 127 |
return false |
| 128 | 128 |
} |
| 129 | 129 |
} |
| ... | ... |
@@ -1148,20 +1148,3 @@ func (c *controller) cleanupLocalEndpoints() {
|
| 1148 | 1148 |
} |
| 1149 | 1149 |
} |
| 1150 | 1150 |
} |
| 1151 |
- |
|
| 1152 |
-func (ep *endpoint) setAliasIP(sb *sandbox, ip net.IP, add bool) error {
|
|
| 1153 |
- sb.Lock() |
|
| 1154 |
- sbox := sb.osSbox |
|
| 1155 |
- sb.Unlock() |
|
| 1156 |
- |
|
| 1157 |
- for _, i := range sbox.Info().Interfaces() {
|
|
| 1158 |
- if ep.hasInterface(i.SrcName()) {
|
|
| 1159 |
- ipNet := &net.IPNet{IP: ip, Mask: []byte{255, 255, 255, 255}}
|
|
| 1160 |
- if err := i.SetAliasIP(ipNet, add); err != nil {
|
|
| 1161 |
- return err |
|
| 1162 |
- } |
|
| 1163 |
- break |
|
| 1164 |
- } |
|
| 1165 |
- } |
|
| 1166 |
- return nil |
|
| 1167 |
-} |
| ... | ... |
@@ -114,12 +114,12 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
|
| 114 | 114 |
} |
| 115 | 115 |
} |
| 116 | 116 |
if v, ok := epMap["llAddrs"]; ok {
|
| 117 |
- list := v.([]string) |
|
| 117 |
+ list := v.([]interface{})
|
|
| 118 | 118 |
epi.llAddrs = make([]*net.IPNet, 0, len(list)) |
| 119 | 119 |
for _, llS := range list {
|
| 120 |
- ll, err := types.ParseCIDR(llS) |
|
| 120 |
+ ll, err := types.ParseCIDR(llS.(string)) |
|
| 121 | 121 |
if err != nil {
|
| 122 |
- return types.InternalErrorf("failed to decode endpoint interface link-local address (%s) after json unmarshal: %v", llS, err)
|
|
| 122 |
+ return types.InternalErrorf("failed to decode endpoint interface link-local address (%v) after json unmarshal: %v", llS, err)
|
|
| 123 | 123 |
} |
| 124 | 124 |
epi.llAddrs = append(epi.llAddrs, ll) |
| 125 | 125 |
} |
| ... | ... |
@@ -26,6 +26,7 @@ type nwIface struct {
|
| 26 | 26 |
mac net.HardwareAddr |
| 27 | 27 |
address *net.IPNet |
| 28 | 28 |
addressIPv6 *net.IPNet |
| 29 |
+ ipAliases []*net.IPNet |
|
| 29 | 30 |
llAddrs []*net.IPNet |
| 30 | 31 |
routes []*net.IPNet |
| 31 | 32 |
bridge bool |
| ... | ... |
@@ -96,6 +97,13 @@ func (i *nwIface) LinkLocalAddresses() []*net.IPNet {
|
| 96 | 96 |
return i.llAddrs |
| 97 | 97 |
} |
| 98 | 98 |
|
| 99 |
+func (i *nwIface) IPAliases() []*net.IPNet {
|
|
| 100 |
+ i.Lock() |
|
| 101 |
+ defer i.Unlock() |
|
| 102 |
+ |
|
| 103 |
+ return i.ipAliases |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 99 | 106 |
func (i *nwIface) Routes() []*net.IPNet {
|
| 100 | 107 |
i.Lock() |
| 101 | 108 |
defer i.Unlock() |
| ... | ... |
@@ -122,28 +130,6 @@ func (n *networkNamespace) Interfaces() []Interface {
|
| 122 | 122 |
return ifaces |
| 123 | 123 |
} |
| 124 | 124 |
|
| 125 |
-func (i *nwIface) SetAliasIP(ip *net.IPNet, add bool) error {
|
|
| 126 |
- i.Lock() |
|
| 127 |
- n := i.ns |
|
| 128 |
- i.Unlock() |
|
| 129 |
- |
|
| 130 |
- n.Lock() |
|
| 131 |
- nlh := n.nlHandle |
|
| 132 |
- n.Unlock() |
|
| 133 |
- |
|
| 134 |
- // Find the network interface identified by the DstName attribute. |
|
| 135 |
- iface, err := nlh.LinkByName(i.DstName()) |
|
| 136 |
- if err != nil {
|
|
| 137 |
- return err |
|
| 138 |
- } |
|
| 139 |
- |
|
| 140 |
- ipAddr := &netlink.Addr{IPNet: ip, Label: ""}
|
|
| 141 |
- if add {
|
|
| 142 |
- return nlh.AddrAdd(iface, ipAddr) |
|
| 143 |
- } |
|
| 144 |
- return nlh.AddrDel(iface, ipAddr) |
|
| 145 |
-} |
|
| 146 |
- |
|
| 147 | 125 |
func (i *nwIface) Remove() error {
|
| 148 | 126 |
i.Lock() |
| 149 | 127 |
n := i.ns |
| ... | ... |
@@ -347,6 +333,7 @@ func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *nwIface) err |
| 347 | 347 |
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
|
| 348 | 348 |
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
| 349 | 349 |
{setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())},
|
| 350 |
+ {setInterfaceIPAliases, fmt.Sprintf("error setting interface %q IP Aliases to %v", ifaceName, i.IPAliases())},
|
|
| 350 | 351 |
} |
| 351 | 352 |
|
| 352 | 353 |
for _, config := range ifaceConfigurators {
|
| ... | ... |
@@ -405,6 +392,16 @@ func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *nwIfac |
| 405 | 405 |
return nil |
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 |
+func setInterfaceIPAliases(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
|
|
| 409 |
+ for _, si := range i.IPAliases() {
|
|
| 410 |
+ ipAddr := &netlink.Addr{IPNet: si}
|
|
| 411 |
+ if err := nlh.AddrAdd(iface, ipAddr); err != nil {
|
|
| 412 |
+ return err |
|
| 413 |
+ } |
|
| 414 |
+ } |
|
| 415 |
+ return nil |
|
| 416 |
+} |
|
| 417 |
+ |
|
| 408 | 418 |
func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
|
| 409 | 419 |
return nlh.LinkSetName(iface, i.DstName()) |
| 410 | 420 |
} |
| ... | ... |
@@ -66,6 +66,12 @@ func (n *networkNamespace) LinkLocalAddresses(list []*net.IPNet) IfaceOption {
|
| 66 | 66 |
} |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 |
+func (n *networkNamespace) IPAliases(list []*net.IPNet) IfaceOption {
|
|
| 70 |
+ return func(i *nwIface) {
|
|
| 71 |
+ i.ipAliases = list |
|
| 72 |
+ } |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 69 | 75 |
func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption {
|
| 70 | 76 |
return func(i *nwIface) {
|
| 71 | 77 |
i.routes = routes |
| ... | ... |
@@ -91,6 +91,9 @@ type IfaceOptionSetter interface {
|
| 91 | 91 |
// LinkLocalAddresses returns an option setter to set the link-local IP addresses. |
| 92 | 92 |
LinkLocalAddresses([]*net.IPNet) IfaceOption |
| 93 | 93 |
|
| 94 |
+ // IPAliases returns an option setter to set IP address Aliases |
|
| 95 |
+ IPAliases([]*net.IPNet) IfaceOption |
|
| 96 |
+ |
|
| 94 | 97 |
// Master returns an option setter to set the master interface if any for this |
| 95 | 98 |
// interface. The master interface name should refer to the srcname of a |
| 96 | 99 |
// previously added interface of type bridge. |
| ... | ... |
@@ -147,6 +150,9 @@ type Interface interface {
|
| 147 | 147 |
// LinkLocalAddresses returns the link-local IP addresses assigned to the interface. |
| 148 | 148 |
LinkLocalAddresses() []*net.IPNet |
| 149 | 149 |
|
| 150 |
+ // IPAliases returns the IP address aliases assigned to the interface. |
|
| 151 |
+ IPAliases() []*net.IPNet |
|
| 152 |
+ |
|
| 150 | 153 |
// IP routes for the interface. |
| 151 | 154 |
Routes() []*net.IPNet |
| 152 | 155 |
|
| ... | ... |
@@ -160,10 +166,6 @@ type Interface interface {
|
| 160 | 160 |
// and moving it out of the sandbox. |
| 161 | 161 |
Remove() error |
| 162 | 162 |
|
| 163 |
- // SetAliasIP adds or deletes the passed IP as an alias on the interface. |
|
| 164 |
- // ex: set the vip of services in the same network as secondary IP. |
|
| 165 |
- SetAliasIP(ip *net.IPNet, add bool) error |
|
| 166 |
- |
|
| 167 | 163 |
// Statistics returns the statistics for this interface |
| 168 | 164 |
Statistics() (*types.InterfaceStatistics, error) |
| 169 | 165 |
} |
| ... | ... |
@@ -87,6 +87,7 @@ type resolver struct {
|
| 87 | 87 |
listenAddress string |
| 88 | 88 |
proxyDNS bool |
| 89 | 89 |
resolverKey string |
| 90 |
+ startCh chan struct{}
|
|
| 90 | 91 |
} |
| 91 | 92 |
|
| 92 | 93 |
func init() {
|
| ... | ... |
@@ -101,6 +102,7 @@ func NewResolver(address string, proxyDNS bool, resolverKey string, backend DNSB |
| 101 | 101 |
listenAddress: address, |
| 102 | 102 |
resolverKey: resolverKey, |
| 103 | 103 |
err: fmt.Errorf("setup not done yet"),
|
| 104 |
+ startCh: make(chan struct{}, 1),
|
|
| 104 | 105 |
} |
| 105 | 106 |
} |
| 106 | 107 |
|
| ... | ... |
@@ -136,6 +138,9 @@ func (r *resolver) SetupFunc(port int) func() {
|
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 | 138 |
func (r *resolver) Start() error {
|
| 139 |
+ r.startCh <- struct{}{}
|
|
| 140 |
+ defer func() { <-r.startCh }()
|
|
| 141 |
+ |
|
| 139 | 142 |
// make sure the resolver has been setup before starting |
| 140 | 143 |
if r.err != nil {
|
| 141 | 144 |
return r.err |
| ... | ... |
@@ -160,6 +165,9 @@ func (r *resolver) Start() error {
|
| 160 | 160 |
} |
| 161 | 161 |
|
| 162 | 162 |
func (r *resolver) Stop() {
|
| 163 |
+ r.startCh <- struct{}{}
|
|
| 164 |
+ defer func() { <-r.startCh }()
|
|
| 165 |
+ |
|
| 163 | 166 |
if r.server != nil {
|
| 164 | 167 |
r.server.Shutdown() |
| 165 | 168 |
} |
| ... | ... |
@@ -761,6 +761,10 @@ func (sb *sandbox) restoreOslSandbox() error {
|
| 761 | 761 |
if len(i.llAddrs) != 0 {
|
| 762 | 762 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) |
| 763 | 763 |
} |
| 764 |
+ if len(ep.virtualIP) != 0 {
|
|
| 765 |
+ vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
|
|
| 766 |
+ ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
|
|
| 767 |
+ } |
|
| 764 | 768 |
Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions
|
| 765 | 769 |
if joinInfo != nil {
|
| 766 | 770 |
for _, r := range joinInfo.StaticRoutes {
|
| ... | ... |
@@ -814,6 +818,10 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
| 814 | 814 |
if len(i.llAddrs) != 0 {
|
| 815 | 815 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) |
| 816 | 816 |
} |
| 817 |
+ if len(ep.virtualIP) != 0 {
|
|
| 818 |
+ vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
|
|
| 819 |
+ ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
|
|
| 820 |
+ } |
|
| 817 | 821 |
if i.mac != nil {
|
| 818 | 822 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac)) |
| 819 | 823 |
} |
| ... | ... |
@@ -101,14 +101,6 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
|
| 101 | 101 |
for _, ip := range lb.backEnds {
|
| 102 | 102 |
sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, |
| 103 | 103 |
eIP, gwIP, addService, n.ingress) |
| 104 |
- // For a new service program the vip as an alias on the task's sandbox interface |
|
| 105 |
- // connected to this network. |
|
| 106 |
- if !addService {
|
|
| 107 |
- continue |
|
| 108 |
- } |
|
| 109 |
- if err := ep.setAliasIP(sb, lb.vip, true); err != nil {
|
|
| 110 |
- logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", lb.vip, ep.ID(), ep.Name(), err)
|
|
| 111 |
- } |
|
| 112 | 104 |
addService = false |
| 113 | 105 |
} |
| 114 | 106 |
lb.service.Unlock() |
| ... | ... |
@@ -132,16 +124,8 @@ func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po |
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 | 134 |
sb.addLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, addService, n.ingress) |
| 135 |
- |
|
| 136 |
- // For a new service program the vip as an alias on the task's sandbox interface |
|
| 137 |
- // connected to this network. |
|
| 138 |
- if !addService {
|
|
| 139 |
- return false |
|
| 140 |
- } |
|
| 141 |
- if err := ep.setAliasIP(sb, vip, true); err != nil {
|
|
| 142 |
- logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err)
|
|
| 143 |
- } |
|
| 144 | 135 |
} |
| 136 |
+ |
|
| 145 | 137 |
return false |
| 146 | 138 |
}) |
| 147 | 139 |
} |
| ... | ... |
@@ -163,16 +147,8 @@ func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Por |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 | 165 |
sb.rmLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, rmService, n.ingress) |
| 166 |
- |
|
| 167 |
- // If the service is being remove its vip alias on on the task's sandbox interface |
|
| 168 |
- // has to be removed as well. |
|
| 169 |
- if !rmService {
|
|
| 170 |
- return false |
|
| 171 |
- } |
|
| 172 |
- if err := ep.setAliasIP(sb, vip, false); err != nil {
|
|
| 173 |
- logrus.Errorf("Removing Service VIP %v from ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err)
|
|
| 174 |
- } |
|
| 175 | 166 |
} |
| 167 |
+ |
|
| 176 | 168 |
return false |
| 177 | 169 |
}) |
| 178 | 170 |
} |
| ... | ... |
@@ -678,6 +654,9 @@ func fwMarker() {
|
| 678 | 678 |
rule := strings.Fields(fmt.Sprintf("-t mangle %s OUTPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark))
|
| 679 | 679 |
rules = append(rules, rule) |
| 680 | 680 |
|
| 681 |
+ 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))
|
|
| 682 |
+ rules = append(rules, rule) |
|
| 683 |
+ |
|
| 681 | 684 |
for _, rule := range rules {
|
| 682 | 685 |
if err := iptables.RawCombinedOutputNative(rule...); err != nil {
|
| 683 | 686 |
logrus.Errorf("setting up rule failed, %v: %v", rule, err)
|