uint64_t ProbeTxControlProcessProbeState()

in src/cdi/adapter_efa_probe_tx.c [341:465]


uint64_t ProbeTxControlProcessProbeState(ProbeEndpointState* probe_ptr)
{
    uint64_t wait_timeout_ms = DEFAULT_TIMEOUT_MSEC;
    CdiEndpointHandle cdi_endpoint_handle = probe_ptr->app_adapter_endpoint_handle->cdi_endpoint_handle;
    const char* remote_ip_str = EndpointManagerEndpointRemoteIpGet(cdi_endpoint_handle);
    int remote_dest_port = EndpointManagerEndpointRemotePortGet(cdi_endpoint_handle);

    // Don't log the kProbeStateEfaConnected state. It is used for ping (generates too many log messages).
    if (kProbeStateEfaConnected != probe_ptr->tx_probe_state.tx_state &&
        kProbeStateEfaConnectedPing != probe_ptr->tx_probe_state.tx_state) {
        CDI_LOG_THREAD_COMPONENT(kLogDebug, kLogComponentProbe, "Probe Tx remote IP[%s:%d] state[%s]",
                                 remote_ip_str, remote_dest_port,
                                 InternalUtilityKeyEnumToString(kKeyProbeState, probe_ptr->tx_probe_state.tx_state));
        if (kProbeStateSendReset == probe_ptr->tx_probe_state.tx_state ||
            kProbeStateWaitForStart == probe_ptr->tx_probe_state.tx_state) {
            CDI_LOG_THREAD(kLogInfo, "No reply to connection response received.");
        }
    }

    switch (probe_ptr->tx_probe_state.tx_state) {
        case kProbeStateResetting:
        case kProbeStateWaitForStart:
            // Got timeout before these commands completed. Go to connection reset state.
            ProbeControlSendCommand(probe_ptr, kProbeCommandReset, true);
            wait_timeout_ms = SEND_RESET_COMMAND_FREQUENCY_MSEC;
            break;
        case kProbeStateEfaReset:
            // Notify the application that we are disconnected and send a request to reset the connection to the
            // Endpoint Manager.
            ProbeControlEfaConnectionQueueReset(probe_ptr, NULL);
            ProbeControlSendCommand(probe_ptr, kProbeCommandReset, true);
            probe_ptr->tx_probe_state.tx_state = kProbeStateResetting; // Advance to resetting state.
            wait_timeout_ms = ENDPOINT_MANAGER_COMPLETION_TIMEOUT_MSEC;
            break;
        case kProbeStateResetDone:
            // If the reset was triggered by the remote connection, respond with an ACK command.
            if (probe_ptr->send_ack_command_valid) {
                ProbeControlSendAck(probe_ptr, probe_ptr->send_ack_command, probe_ptr->send_ack_control_packet_num);
                probe_ptr->send_ack_command_valid = false;
            }
            probe_ptr->tx_probe_state.tx_state = kProbeStateWaitForStart; // Advance to wait for start state.
            wait_timeout_ms = ENDPOINT_MANAGER_COMPLETION_TIMEOUT_MSEC;
            break;
        case kProbeStateIdle:
        case kProbeStateSendReset:
            // Notify application that we are disconnected.
            EndpointManagerConnectionStateChange(cdi_endpoint_handle, kCdiConnectionStatusDisconnected, NULL);
            // Send command to reset the remote Rx (server) connection. Will expect an ACK back from the remote.
            ProbeControlSendCommand(probe_ptr, kProbeCommandReset, true);
            probe_ptr->tx_probe_state.tx_state = kProbeStateSendReset; // Ensure we are in send reset state.
            wait_timeout_ms = SEND_RESET_COMMAND_FREQUENCY_MSEC;
            break;
        case kProbeStateSendProtocolVersion:
            // Either first time here and need to send the protocol version command or did not get an ACK back from it
            // within the timeout period.
            wait_timeout_ms = ProcessSendCommandRetry(probe_ptr, remote_ip_str, remote_dest_port,
                                                      kProbeCommandProtocolVersion);
            break;
        case kProbeStateEfaStart:
            // Enable the EFA connection for probe state. Use the EFA interface to send probe packets before allowing
            // application to use the connection. Once all the probe packets have been acknowledged as being received by
            // the remote, it will send a kProbeCommandConnected command back. Start this process here.
            CDI_LOG_THREAD_COMPONENT(kLogDebug, kLogComponentProbe,
                                     "Probe Tx remote IP[%s:%d] starting the SRD probe process",
                                     remote_ip_str, remote_dest_port);
            ProbeControlEfaConnectionStart(probe_ptr);
            EfaEnqueueSendProbePackets(probe_ptr);
            probe_ptr->tx_probe_state.tx_state = kProbeStateEfaProbe;
            // If the EFA probe does not complete by this timeout, we return back to connection reset state.
            wait_timeout_ms = EFA_PROBE_MONITOR_TIMEOUT_MSEC;
            break;
        case kProbeStateEfaProbe:
            // Got timeout before EFA probe completed. Go to connection reset state.
            probe_ptr->tx_probe_state.tx_state = kProbeStateEfaReset; // Advance to resetting state.
            wait_timeout_ms = 0; // Do immediately.
            CDI_LOG_THREAD(kLogError, "Control handshake was successful. However, an insufficient number of probe "
                                      "packets were received. Verify the security group settings are correctly "
                                      "configured. See the CDI SDK Install and Setup Guide for proper security group "
                                      "configuration.");

            break;
        case kProbeStateEfaTxProbeAcks:
            if (probe_ptr->tx_probe_state.packets_acked_count >= EFA_PROBE_PACKET_COUNT) {
                // Received all ACKs from probe packets, so advance to the EFA connected state.
                ProbeControlEfaConnectionEnableApplication(probe_ptr);
                // Advance to the connected state, which will start the ping process. Setup wait period for next ping
                // based on ping frequency.
                probe_ptr->tx_probe_state.tx_state = kProbeStateEfaConnected;
                wait_timeout_ms = SEND_PING_COMMAND_FREQUENCY_MSEC;
            } else {
                if (++probe_ptr->tx_probe_state.packets_ack_wait_count < EFA_TX_PROBE_ACK_MAX_RETRIES) {
                    // Wait a little while and retry if we have not received all the ACKs yet.
                    wait_timeout_ms = EFA_TX_PROBE_ACK_TIMEOUT;
                } else {
                    CDI_LOG_THREAD(kLogError, "Did not get all ACKs from probe packets. Resetting connection.");
                    probe_ptr->tx_probe_state.tx_state = kProbeStateEfaReset; // Advance to resetting state.
                    wait_timeout_ms = 0; // Do immediately.
                }
            }
            break;
        case kProbeStateEfaConnected:
#ifdef DISABLE_PROBE_MONITORING
            wait_timeout_ms = CDI_INFINITE;
#else
            // Notify application that we are connected.
            EndpointManagerConnectionStateChange(cdi_endpoint_handle, kCdiConnectionStatusConnected, NULL);

            // Advance state to send ping to the remote Rx (server) connection. Will expect an ACK back from the remote.
            probe_ptr->tx_probe_state.tx_state = kProbeStateEfaConnectedPing;
            probe_ptr->tx_probe_state.send_command_retry_count = 0; // Reset command retry counter.
            wait_timeout_ms = 0; // Do immediately.
#endif
            break;
        case kProbeStateEfaConnectedPing:
            // Either first time here and need to send the ping command or did not get an ACK back from it within the
            // timeout period.
            wait_timeout_ms = ProcessSendCommandRetry(probe_ptr, remote_ip_str, remote_dest_port, kProbeCommandPing);
            break;
        case kProbeStateDestroy:
            // Nothing special needed.
            break;
    }

    return wait_timeout_ms;
}