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/doc/ncsid_arch.dot b/ncsid/doc/ncsid_arch.dot
new file mode 100644
index 0000000..7edc8a3
--- /dev/null
+++ b/ncsid/doc/ncsid_arch.dot
@@ -0,0 +1,60 @@
+digraph {
+	node [shape="box"];
+	subgraph {
+		node [shape=plaintext];
+
+		ncsid [label=<
+			<table>
+				<tr>
+					<td bgcolor="lightblue" colspan="2" port="config">net::ConfigBase</td>
+					<td port="sockio" bgcolor="lightblue">net::SockIO</td>
+				</tr>
+				<tr><td bgcolor="lightblue" colspan="3">ncsi::StateMachine</td></tr>
+				<tr>
+					<td bgcolor="black"><font color="white">L2 FSM</font></td>
+					<td bgcolor="black"><font color="white">L3/4 FSM</font></td>
+					<td bgcolor="black"><font color="white">Test FSM</font></td>
+				</tr>
+			</table>
+		>];
+	}
+
+	subgraph notes {
+		node [shape="note" style="filled"];
+		core [label="NC-SId Core" fillcolor="lightblue"];
+		hardware [label="Hardware" fillcolor="limegreen"];
+		external [label="External Components" color="magenta" fillcolor="white"];
+		ec [label="EC" fillcolor="black" fontcolor="white"];
+	} -> NIC [style="invis"];
+
+	subgraph external {
+		node [color="magenta"];
+		p_networkd [label="phosphord-networkd"];
+		systemd;
+		d_bus [shape="doublecircle" label="DBus"];
+	}
+
+	subgraph core_comps {
+		node [fillcolor="lightblue" style="filled"];
+		p_config [label="net::PhosphorConfig"];
+		ncsi_sockio [label="ncsi::SockIO"];
+		net_ifacebase [label="net::IFaceBase"];
+		net_iface [label="net::IFace"];
+
+		net_iface -> net_ifacebase [arrowhead="diamond"];
+		ncsi_sockio -> net_iface [label="bind"];
+		ncsid;
+	}
+
+	NIC [shape="tab" fillcolor="limegreen" style="filled"];
+
+	ncsi_sockio -> ncsid:sockio [arrowhead="diamond"];
+	NIC -> ncsi_sockio [dir="both" label="NC-SI Cable" color="limegreen"];
+
+	p_config -> ncsid:config [arrowhead="diamond"];
+	p_config -> p_networkd [style="dashed"];
+	p_config -> d_bus;
+	p_networkd -> d_bus [dir="both"];
+	d_bus -> systemd;
+	p_networkd -> systemd [style="dashed"];
+}
diff --git a/ncsid/doc/ncsid_arch.png b/ncsid/doc/ncsid_arch.png
new file mode 100644
index 0000000..1e26622
--- /dev/null
+++ b/ncsid/doc/ncsid_arch.png
Binary files differ
diff --git a/ncsid/doc/ncsid_internals.md b/ncsid/doc/ncsid_internals.md
new file mode 100644
index 0000000..a85e6f6
--- /dev/null
+++ b/ncsid/doc/ncsid_internals.md
@@ -0,0 +1,106 @@
+# NC-SId Internals
+
+__NOTE__: This documents describes the internal architecture of NC-SId daemon.
+However, it is meant to be used as a guide for understanding the code, not on
+its own. Some details are intentionally omitted.
+
+![Internals Diagram](ncsid_arch.png)
+
+In the diagram above the components are split into four groups:
+
+* __NC-SId Core__. These are new components implemented in NC-SId.
+
+* __Hardware__. External hardware components, in this case, the NIC.
+
+* __EC__. This is the code borrowed from EC. The three state machines are
+  pretty much copied from EC code.
+
+* __External Components__. These are external services/daemons NC-SIs interacts
+  with.
+
+Let's look into their details.
+
+## NIC
+
+In the NIC — NC-SId interactions, NIC acts as a server, replying to NC-SId
+requests and NC-SId itself acts as a client, sending those requests.  Thus,
+there is no state in NIC (server), but there is a state in NC-SId (client).
+
+## EC State Machines
+
+NC-SId reuses the state machines from EC. They are treated like black boxes.
+They are C functions with simple interface: the state machine is given incoming
+NC-SI command buffer (reply from the NIC) and returns the buffer that needs to
+be sent to the NIC (the next command).
+
+### L2 FSM
+
+This state machine performs basic configuration of the NC-SI comm channel and
+also reads the MAC Address of the NIC.
+
+### L3/4 FSM
+
+Once BMC's network is configured, this state machine sets up filters in the NIC.
+
+### Test FSM
+
+This state machine periodically tests NC-SI connection with the NIC, verifies
+filters and queries the NIC state (hostless or host-based). If it ever fails,
+all state machines restart, which means that NC-SI in the NIC is also reset and
+reconfigured.
+
+---
+
+In addition to the buffer there are parameters that provide information which is
+not a part of EC state machines' state:
+
+* State Parameters. These structures are allocated outside of EC State Machines,
+  but their content is fully managed by EC State Machines.
+* MAC Address. For L2 FSM this parameter is _OUT_.
+* IP Address (only for L3/4 FSM and Test FSM) for setting up and verifying
+  filteres. If set to zero, the NIC filter won't check for IP address.
+* TCP Port (only for L3/4 FSM and Test FSM) for setting up and verifying
+  filters.
+
+In the initial state the command buffer (reply from the NIC) is empty. When
+there is nothing more to send to the NIC, i.e. that particular state machine is
+done, it returns empty buffer.
+
+## External Components
+
+NC-SId uses `phosphord-networkd` to configure the BMC's network (MAC Address).
+In turn, `phosphord-networkd` uses `systemd`. Their interactions go through
+`DBus`.
+
+## NC-SId Core
+
+### ncsi::StateMachine
+
+This component coordinates the interaction between EC State Machines and is also
+heavily based on EC code. It uses `net::SockIO` interface to interact with the
+NIC and `net::ConfigBase` interface to set/query MAC Address.
+
+### net::PhosphorConfig
+
+Implements `net::ConfigBase` and makes calls to `phosphord-networkd` via `DBus`
+to get/set MAC Address.
+
+### ncsi::SockIO
+
+Implements `net::SockIO` and sends NC-SI commands to the NIC through raw Unix
+socket. That socket is configured using `net::IFace` component, which represents
+the network interface (think ethX). To simplify testing, the abstract
+`net::IFaceBase` interface is introduced.
+
+---
+
+## Unit Testing
+
+![Test infrastructure](ncsid_test_arch.png)
+
+To allow some fairly sophisticated unit-tests, EC State Machines as well as
+`ncsi::StateMachine` component only interact with the outside world using
+`net::SockIO` and `net::ConfigBase` interfaces. This makes it easy to mock them.
+
+The most complicated part of these tests is `mock::NIC`, which acts as a NC-SI
+server, replying to NC-SI requests coming from NC-SI State Machines.
diff --git a/ncsid/doc/ncsid_test_arch.dot b/ncsid/doc/ncsid_test_arch.dot
new file mode 100644
index 0000000..081d5d6
--- /dev/null
+++ b/ncsid/doc/ncsid_test_arch.dot
@@ -0,0 +1,38 @@
+digraph {
+	node [shape="box"];
+	subgraph {
+		node [shape=plaintext];
+
+		ncsid [label=<
+			<table>
+				<tr><td port="sockio" bgcolor="lightblue">net::SockIO</td><td bgcolor="lightblue" colspan="2" port="config">net::ConfigBase</td></tr>
+				<tr><td bgcolor="lightblue" colspan="3">ncsi::StateMachine</td></tr>
+				<tr>
+					<td bgcolor="black"><font color="white">L2 FSM</font></td>
+					<td bgcolor="black"><font color="white">L3/4 FSM</font></td>
+					<td bgcolor="black"><font color="white">Test FSM</font></td>
+				</tr>
+			</table>
+		>];
+	}
+
+	subgraph notes {
+		node [shape="note" style="filled"];
+		core [label="NC-SId Core" fillcolor="lightblue"];
+		ec [label="EC" fillcolor="black" fontcolor="white"];
+		mock [label="Mocks" fillcolor="beige"];
+	}
+
+	p_config [label="MockConfig" style="filled" fillcolor="beige"];
+
+	ncsi_sockio [style="filled" fillcolor="beige" label=<
+		<table border="0">
+			<tr><td align="left">NICConnection</td></tr>
+			<tr><td border="1">mock::NIC</td></tr>
+		</table>
+	>];
+
+	ncsi_sockio -> ncsid:sockio [arrowhead="diamond"];
+
+	p_config -> ncsid:config [arrowhead="diamond"];
+}
diff --git a/ncsid/doc/ncsid_test_arch.png b/ncsid/doc/ncsid_test_arch.png
new file mode 100644
index 0000000..6c3ee64
--- /dev/null
+++ b/ncsid/doc/ncsid_test_arch.png
Binary files differ