async fn network_layer_state(
    name: &str,
    interface_id: u64,
    routes: &[fnet_stack::ForwardingEntry],
    p: &dyn Ping,
    internet_ping_address: std::net::IpAddr,
) -> State {
    use std::convert::TryInto as _;

    let mut relevant_routes = routes
        .into_iter()
        .filter(|fnet_stack::ForwardingEntry { subnet: _, device_id, next_hop: _, metric: _ }| {
            *device_id == interface_id
        })
        .peekable();

    if relevant_routes.peek() == None {
        return State::Up;
    }

    // TODO(https://fxbug.dev/36242) Check neighbor reachability and upgrade state to Local.

    let gateway_reachable = relevant_routes
        .filter_map(
            move |fnet_stack::ForwardingEntry { subnet: _, device_id, next_hop, metric: _ }| {
                // TODO(https://fxbug.dev/91821): only consider default routes.
                next_hop.as_ref().and_then(|next_hop| {
                    let fnet_ext::IpAddress(next_hop) = (**next_hop).into();
                    match next_hop {
                        std::net::IpAddr::V4(v4) => {
                            Some(std::net::SocketAddr::V4(std::net::SocketAddrV4::new(v4, 0)))
                        }
                        std::net::IpAddr::V6(v6) => match (*device_id).try_into() {
                            Err(std::num::TryFromIntError { .. }) => {
                                log::error!("device id {} doesn't fit in u32", device_id);
                                None
                            }
                            Ok(device_id) => {
                                if device_id == 0
                                    && net_types::ip::Ipv6Addr::from_bytes(v6.octets()).scope()
                                        != net_types::ip::Ipv6Scope::Global
                                {
                                    None
                                } else {
                                    Some(std::net::SocketAddr::V6(std::net::SocketAddrV6::new(
                                        v6, 0, 0, device_id,
                                    )))
                                }
                            }
                        },
                    }
                })
            },
        )
        .map(|next_hop| p.ping(name, next_hop))
        .collect::<futures::stream::FuturesUnordered<_>>()
        .filter(|ok| futures::future::ready(*ok))
        .next()
        .await
        .is_some();
    if !gateway_reachable {
        return State::Local;
    };

    if !p.ping(name, std::net::SocketAddr::new(internet_ping_address, 0)).await {
        return State::Gateway;
    }
    return State::Internet;
}
// `network_layer_state` determines the L3 reachability state.
`network_layer_state` determines the L3 reachability state.
` network_layer_state ` determines the L3 reachability state .
async fn network_layer_state(
    name: &str,
    interface_id: u64,
    routes: &[fnet_stack::ForwardingEntry],
    p: &dyn Ping,
    internet_ping_address: std::net::IpAddr,
) -> State {
    use std::convert::TryInto as _;
    let mut relevant_routes = routes
        .into_iter()
        .filter(|fnet_stack::ForwardingEntry { subnet: _, device_id, next_hop: _, metric: _ }| {
            *device_id == interface_id
        })
        .peekable();
    if relevant_routes.peek() == None {
        return State::Up;
    }
    // TODO(https://fxbug.dev/36242) Check neighbor reachability and upgrade state to Local.
    let gateway_reachable = relevant_routes
        .filter_map(
            move |fnet_stack::ForwardingEntry { subnet: _, device_id, next_hop, metric: _ }| {
                // TODO(https://fxbug.dev/91821): only consider default routes.
                next_hop.as_ref().and_then(|next_hop| {
                    let fnet_ext::IpAddress(next_hop) = (**next_hop).into();
                    match next_hop {
                        std::net::IpAddr::V4(v4) => {
                            Some(std::net::SocketAddr::V4(std::net::SocketAddrV4::new(v4, 0)))
                        }
                        std::net::IpAddr::V6(v6) => match (*device_id).try_into() {
                            Err(std::num::TryFromIntError { .. }) => {
                                log::error!("device id {} doesn't fit in u32", device_id);
                                None
                            }
                            Ok(device_id) => {
                                if device_id == 0
                                    && net_types::ip::Ipv6Addr::from_bytes(v6.octets()).scope()
                                        != net_types::ip::Ipv6Scope::Global
                                {
                                    None
                                } else {
                                    Some(std::net::SocketAddr::V6(std::net::SocketAddrV6::new(
                                        v6, 0, 0, device_id,
                                    )))
                                }
                            }
                        },
                    }
                })
            },
        )
        .map(|next_hop| p.ping(name, next_hop))
        .collect::<futures::stream::FuturesUnordered<_>>()
        .filter(|ok| futures::future::ready(*ok))
        .next()
        .await
        .is_some();
    if !gateway_reachable {
        return State::Local;
    };
    if !p.ping(name, std::net::SocketAddr::new(internet_ping_address, 0)).await {
        return State::Gateway;
    }
    return State::Internet;
}
async fn network_layer_state ( name : & str , interface_id : u64 , routes : & [ fnet_stack :: ForwardingEntry ] , p : & dyn Ping , internet_ping_address : std :: net :: IpAddr , ) -> State { use std :: convert :: TryInto as _ ; let mut relevant_routes = routes . into_iter ( ) . filter ( | fnet_stack :: ForwardingEntry { subnet : _ , device_id , next_hop : _ , metric : _ } | { * device_id == interface_id } ) . peekable ( ) ; if relevant_routes . peek ( ) == None { return State :: Up ; } // TODO(https://fxbug.dev/36242) Check neighbor reachability and upgrade state to Local. let gateway_reachable = relevant_routes . filter_map ( move | fnet_stack :: ForwardingEntry { subnet : _ , device_id , next_hop , metric : _ } | { // TODO(https://fxbug.dev/91821): only consider default routes. next_hop . as_ref ( ) . and_then ( | next_hop | { let fnet_ext :: IpAddress ( next_hop ) = ( * * next_hop ) . into ( ) ; match next_hop { std :: net :: IpAddr :: V4 ( v4 ) => { Some ( std :: net :: SocketAddr :: V4 ( std :: net :: SocketAddrV4 :: new ( v4 , 0 ) ) ) } std :: net :: IpAddr :: V6 ( v6 ) => match ( * device_id ) . try_into ( ) { Err ( std :: num :: TryFromIntError { .. } ) => { log :: error ! ( " " device_id ) ; None } Ok ( device_id ) => { if device_id == 0 && net_types :: ip :: Ipv6Addr :: from_bytes ( v6 . octets ( ) ) . scope ( ) != net_types :: ip :: Ipv6Scope :: Global { None } else { Some ( std :: net :: SocketAddr :: V6 ( std :: net :: SocketAddrV6 :: new ( v6 , 0 , 0 , device_id , ) ) ) } } } , } } ) } , ) . map ( | next_hop | p . ping ( name , next_hop ) ) . collect :: < futures :: stream :: FuturesUnordered < _ > > ( ) . filter ( | ok | futures :: future :: ready ( * ok ) ) . next ( ) . await . is_some ( ) ; if ! gateway_reachable { return State :: Local ; } ; if ! p . ping ( name , std :: net :: SocketAddr :: new ( internet_ping_address , 0 ) ) . await { return State :: Gateway ; } return State :: Internet ; }
`network_layer_state` determines the L3 reachability state.
` network_layer_state ` determines the L3 reachability state .
name
&str
interface_id
u64
routes
&[fnet_stack::ForwardingEntry]
p
&dyn Ping
internet_ping_address
std::net::IpAddr
name
&str
interface_id
u64
routes
&[fnet_stack::ForwardingEntry]
p
&dyn Ping
internet_ping_address
std::net::IpAddr