ncsid: Import from gBMC
This is the initial code drop from gBMC.
Google-Bug-Id: 179618516
Upstream: 1e71af914bc8c54d8b91d0a1cf377e2696713c2f
Change-Id: Ic653e8271dacd205e04f2bc713071ef2ec5936a4
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/ncsid/src/ncsi_state_machine.h b/ncsid/src/ncsi_state_machine.h
new file mode 100644
index 0000000..d55bba7
--- /dev/null
+++ b/ncsid/src/ncsi_state_machine.h
@@ -0,0 +1,112 @@
+#pragma once
+#include "ncsi_sockio.h"
+#include "net_config.h"
+#include "net_iface.h"
+#include "platforms/nemora/portable/ncsi_client.h"
+#include "platforms/nemora/portable/ncsi_fsm.h"
+#include "platforms/nemora/portable/net_types.h"
+
+#include <optional>
+
+namespace ncsi
+{
+
+typedef ncsi_response_type_t (*ncsi_simple_poll_f)(ncsi_state_t*,
+ network_debug_t*,
+ ncsi_buf_t*, mac_addr_t*,
+ uint32_t, uint16_t);
+
+// This class encapsulates three state machines:
+// * L2 -- performs basic NC-SI setup, reads NIC MAC addr
+// * L3/4 -- once network is configured on the interface,
+// sets up NC-SI filter in the NIC.
+// * Test -- runs several basic NC-SI link tests, like
+// ECHO Request/Reply, checks filter setup etc.
+// Also, reads hostless/host-based flag from the NIC, see
+// ncsi_fsm.c:is_nic_hostless() for details.
+class StateMachine
+{
+ public:
+ StateMachine();
+
+ void set_sockio(net::SockIO* sock_io);
+
+ void set_net_config(net::ConfigBase* net_config);
+
+ // NC-SI State Machine's main function.
+ // max_rounds = 0 means run forever.
+ void run(int max_rounds = 0);
+
+ // How often Test FSM re-runs, in seconds.
+ void set_retest_delay(unsigned int delay);
+
+ private:
+ // Reset the state machine
+ void reset();
+
+ // Poll L2 state machine. Each call advances it by one step.
+ // Its implementation is taken directly from EC.
+ size_t poll_l2_config();
+
+ // This function is used to poll both L3/4 and Test state machine,
+ // depending on the function passed in as an argument.
+ size_t poll_simple(ncsi_simple_poll_f poll_func);
+
+ // Helper function for printing NC-SI error to stdout.
+ void report_ncsi_error(ncsi_response_type_t response_type);
+
+ int receive_ncsi();
+
+ // Helper function for advancing the test FSM.
+ void run_test_fsm(size_t* tx_len);
+
+ // Clear the state and reset all state machines.
+ void clear_state();
+
+ // In current implementation this is the same as clear state,
+ // except that it also increments the failure counter.
+ void fail();
+
+ // Return true if the test state machine finished successfully.
+ bool is_test_done() const
+ {
+ return ncsi_state_.test_state == NCSI_STATE_TEST_END;
+ }
+
+ // Max number of times a state machine is going to retry a command.
+ static constexpr auto MAX_TRIES = 5;
+
+ // How long (in seconds) to wait before re-running NC-SI test state
+ // machine.
+ unsigned int retest_delay_s_ = 1;
+
+ // The last known state of the link on the NIC
+ std::optional<bool> link_up_;
+
+ // The last known hostless mode of the NIC
+ std::optional<bool> hostless_;
+
+ // net_config_ is used to query and set network configuration.
+ // The StateMachine does not own the pointer and it is the
+ // responsibility of the client to make sure that it outlives the
+ // StateMachine.
+ net::ConfigBase* net_config_ = nullptr;
+
+ // sock_io_ is used to read and write NC-SI packets.
+ // The StateMachine does not own the pointer. It is the responsibility
+ // of the client to make sure that sock_io_ outlives the StateMachine.
+ net::SockIO* sock_io_ = nullptr;
+
+ // Both ncsi_state_ and network_debug_ parameters represent the state of
+ // the NC-SI state machine. The names and definitions are taken directly
+ // from EC.
+ ncsi_state_t ncsi_state_;
+ network_debug_t network_debug_;
+
+ // Depending on the state ncsi_buf_ represents either the NC-SI packet
+ // received from the NIC or NC-SI packet that was (or about to be)
+ // sent to the NIC.
+ ncsi_buf_t ncsi_buf_;
+};
+
+} // namespace ncsi