in dp_check/dp_check.go [298:336]
func checkLocalIPv6Routes(localAddress *net.IP, backendAddress string) error {
destIPStr, destPort, err := net.SplitHostPort(backendAddress)
if err != nil {
return fmt.Errorf("failed to split backend address: %v into host and port components", backendAddress)
}
destIP := net.ParseIP(destIPStr)
if destIP == nil {
return fmt.Errorf("failed to parse IP component of backend address: %v", backendAddress)
}
if destIP.To4() != nil {
return fmt.Errorf("backend address %v is not an IPv6 address", backendAddress)
}
sourceStr := net.JoinHostPort(localAddress.String(), "0")
infoLog.Printf("Check kernel routability of DirectPath/IPv6 by opening a UDP socket, binding it to %v and calling connect for %v", sourceStr, backendAddress)
// Also see https://github.com/golang/go/issues/10552#issuecomment-115540597 for this strategy.
fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
if err != nil {
return fmt.Errorf("error creating IPv6/UDP socket: %v", err)
}
source := &syscall.SockaddrInet6{Port: 0}
for i := 0; i < 16; i++ {
source.Addr[i] = (*localAddress)[i]
}
if err := syscall.Bind(fd, source); err != nil {
return fmt.Errorf("error binding UDP/IPV6 socket to %v: %v", sourceStr, err)
}
port, err := strconv.Atoi(destPort)
if err != nil {
return fmt.Errorf("failed to convert port %v to int: %v", destPort, err)
}
dest := &syscall.SockaddrInet6{Port: port}
for i := 0; i < 16; i++ {
dest.Addr[i] = destIP[i]
}
if err := syscall.Connect(fd, dest); err != nil {
return fmt.Errorf("failed to connect UDP socket (source: %v) to dest: %v, err: %v. This indicates the DirectPath/IPv6 backends aren't routable from this VM", sourceStr, backendAddress, err)
}
return nil
}