@@ -3,7 +3,9 @@ package common
33import (
44 "fmt"
55 "net"
6+ "os"
67 "sync"
8+ "syscall"
79 "time"
810
911 "github.com/golang/glog"
@@ -468,11 +470,12 @@ func (eit *EgressIPTracker) lookupNodeIP(ip string) string {
468470 return ip
469471}
470472
471- // Ping a node and return whether or not it is online. We do this by trying to open a TCP
472- // connection to the "discard" service (port 9); if the node is offline, the attempt will
473- // time out with no response (and we will return false). If the node is online then we
474- // presumably will get a "connection refused" error; the code below assumes that anything
475- // other than timing out indicates that the node is online.
473+ // Ping a node and return whether or not we think it is online. We do this by trying to
474+ // open a TCP connection to the "discard" service (port 9); if the node is offline, the
475+ // attempt will either time out with no response, or else return "no route to host" (and
476+ // we will return false). If the node is online then we presumably will get a "connection
477+ // refused" error; but the code below assumes that anything other than timeout or "no
478+ // route" indicates that the node is online.
476479func (eit * EgressIPTracker ) Ping (ip string , timeout time.Duration ) bool {
477480 // If the caller used a public node IP, replace it with the SDN IP
478481 ip = eit .lookupNodeIP (ip )
@@ -481,11 +484,15 @@ func (eit *EgressIPTracker) Ping(ip string, timeout time.Duration) bool {
481484 if conn != nil {
482485 conn .Close ()
483486 }
484- if opErr , ok := err .(* net.OpError ); ok && opErr .Timeout () {
485- return false
486- } else {
487- return true
487+ if opErr , ok := err .(* net.OpError ); ok {
488+ if opErr .Timeout () {
489+ return false
490+ }
491+ if sysErr , ok := opErr .Err .(* os.SyscallError ); ok && sysErr .Err == syscall .EHOSTUNREACH {
492+ return false
493+ }
488494 }
495+ return true
489496}
490497
491498// Finds the best node to allocate the egress IP to, given the existing allocation. The
@@ -517,7 +524,19 @@ func (eit *EgressIPTracker) findEgressIPAllocation(ip net.IP, allocation map[str
517524}
518525
519526func (eit * EgressIPTracker ) makeEmptyAllocation () (map [string ][]string , map [string ]bool ) {
520- return make (map [string ][]string ), make (map [string ]bool )
527+ allocation := make (map [string ][]string )
528+ alreadyAllocated := make (map [string ]bool )
529+
530+ // We don't want to auto-allocate/reallocate IPs for NetNamespaces using
531+ // multiple-egress-IP HA, so those should be considered "already allocated"
532+ // even before we start.
533+ for egressIP , eip := range eit .egressIPs {
534+ if eip .assignedNodeIP != "" && len (eip .namespaces [0 ].requestedIPs ) > 1 {
535+ alreadyAllocated [egressIP ] = true
536+ }
537+ }
538+
539+ return allocation , alreadyAllocated
521540}
522541
523542func (eit * EgressIPTracker ) allocateExistingEgressIPs (allocation map [string ][]string , alreadyAllocated map [string ]bool ) bool {
0 commit comments