diff --git a/veilid-core/src/network_manager/native/network_class_discovery.rs b/veilid-core/src/network_manager/native/network_class_discovery.rs index 3de494e1..3ddccde1 100644 --- a/veilid-core/src/network_manager/native/network_class_discovery.rs +++ b/veilid-core/src/network_manager/native/network_class_discovery.rs @@ -622,37 +622,58 @@ impl Network { context: &DiscoveryContext, protocol_type: ProtocolType, ) -> EyreResult<()> { + let mut retry_count = { + let c = self.config.get(); + c.network.restricted_nat_retries + }; + // Start doing ipv6 protocol context.protocol_begin(protocol_type, AddressType::IPV6); - log_net!(debug "=== update_ipv6_protocol_dialinfo {:?} ===", protocol_type); - - // Get our external address from some fast node, call it node 1 - if !context.protocol_get_external_address_1().await { - // If we couldn't get an external address, then we should just try the whole network class detection again later - return Ok(()); - } - - // If our local interface list doesn't contain external_1 then there is an Ipv6 NAT in place - { - let inner = context.inner.lock(); - if !inner - .intf_addrs - .as_ref() - .unwrap() - .contains(inner.external_1_address.as_ref().unwrap()) - { - // IPv6 NAT is not supported today - log_net!(warn - "IPv6 NAT is not supported for external address: {}", - inner.external_1_address.unwrap() - ); + // Loop for restricted NAT retries + loop { + log_net!(debug + "=== update_ipv6_protocol_dialinfo {:?} tries_left={} ===", + protocol_type, + retry_count + ); + // Get our external address from some fast node, call it node 1 + if !context.protocol_get_external_address_1().await { + // If we couldn't get an external address, then we should just try the whole network class detection again later return Ok(()); } - } - // No NAT - context.protocol_process_no_nat().await?; + // If our local interface list contains external_1 then there is no NAT in place + { + let res = { + let inner = context.inner.lock(); + inner + .intf_addrs + .as_ref() + .unwrap() + .contains(inner.external_1_address.as_ref().unwrap()) + }; + if res { + // No NAT + context.protocol_process_no_nat().await?; + + // No more retries + break; + } + } + + // There is -some NAT- + if context.protocol_process_nat().await? { + // We either got dial info or a network class without one + break; + } + + // If we tried everything, break anyway after N attempts + if retry_count == 0 { + break; + } + retry_count -= 1; + } Ok(()) } diff --git a/veilid-core/src/network_manager/types/address.rs b/veilid-core/src/network_manager/types/address.rs index 45ec1c98..0dbb0e95 100644 --- a/veilid-core/src/network_manager/types/address.rs +++ b/veilid-core/src/network_manager/types/address.rs @@ -1,5 +1,7 @@ use super::*; +// Ordering here matters, IPV6 is preferred to IPV4 in dial info sorts +// See issue #236 for eventual resolution of this unfortunate implementation #[derive( Copy, Clone, @@ -17,8 +19,8 @@ use super::*; )] #[archive_attr(repr(u8), derive(CheckBytes))] pub enum Address { - IPV4(Ipv4Addr), IPV6(Ipv6Addr), + IPV4(Ipv4Addr), } impl Default for Address {