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;
}