func checkLocalIPv6Routes()

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
}