Software development notes
by Andrew
obmc-console provides the plumbing to expose one or more host
consoles onto BMC’s network interfaces. It comes in two parts:
TTY devices do not have sensible semantics when opened across multiple
processes. obmc-console-server is a system daemon that acts as a
client multiplexer - it is the single process that opens an upstream TTY along
with a listening AF_UNIX socket on which other applications can connect. Data
is shuffled bi-directionally between the upstream TTY and the connections
accepted on the AF_UNIX socket.
obmc-console-client is the typical process that connects to the AF_UNIX
socket exposed by obmc-console-server. We pair obmc-console-client with
dropbear to expose the upstream TTY on the BMC’s network.
obmc-console-serverobmc-console ships systemd service units that cater
to systems with multiple upstream TTYs. Instantiation of the
obmc-console-server daemons is done in two parts:
systemd service unit to start the
daemon, andudev rules to trigger the service unitThe udev rules and the templated systemd service
unit work in concert to determine what TTYs should have
an obmc-console-server instance started. Whether or not an instance is started
depends on:
udev
rules, andobmc-console-server configuration file for the TTYAs a concrete example of the udev rules involved, the following triggers the
instantiation of the obmc-console-server process for /dev/ttyVUART0, so long
as both conditions listed above hold:
SUBSYSTEM=="tty", ATTRS{iomem_base}=="0x1E787000", ENV{SYSTEMD_WANTS}="obmc-console@ttyVUART0" SYMLINK+="ttyVUART0", TAG+="systemd"
We can see here that the template parameter for the service unit is the name of
the TTY device of interest - the ttyVUART0 in
ENV{SYSTEMD_WANTS}="obmc-console@ttyVUART0".
The gate on the existence of the configuration file is implemented in the
obmc-console@.service unit as follows:
ConditionPathExists=/etc/obmc-console/server.%i.conf
Where ConditionPathExists is documented
as:
ConditionPathExists=Check for the existence of a file. If the specified absolute path name does not exist, the condition will fail. If the absolute path name passed to ConditionPathExists= is prefixed with an exclamation mark (“!”), the test is negated, and the unit is only started if the path does not exist.
Again, the systemd unit documentation specifies the behaviour of conditions as:
Before the unit is started, systemd will verify that the specified conditions and asserts are true. If not, the starting of the unit will be (mostly silently) skipped (in case of conditions), or aborted with an error message (in case of asserts). Failing conditions or asserts will not result in the unit being moved into the “failed” state.
By the documentation for template unit
specifiers, the path specified in the template
service unit’s condition is transformed by substition of %i to:
ConditionPathExists=/etc/obmc-console/server.ttyVUART0.conf
Finally, the ExecStart= line then passes the configuration file path as a
command-line argument to obmc-console-server, allowing us to provide
configurations that are specific to the instance for the TTY:
ExecStart=/usr/sbin/obmc-console-server --config /etc/obmc-console/server.%i.conf %i
Reified with our example unit template parameter ttyVUART0, this becomes:
ExecStart=/usr/sbin/obmc-console-server --config /etc/obmc-console/server.ttyVUART0.conf ttyVUART0
obmc-console-clientAs mentioned in the Overview, obmc-console-client is paired with
dropbear to expose console data to the network. Wrapping
obmc-console-client up in dropbear gives us authentication, authorisation
and encryption for data in motion all in one fell swoop, and keeps the details
out of the implementation of obmc-console-client itself. This separation of
concerns allows us to invoke obmc-console-client directly from a shell prompt
on the BMC if we wish!
By the obmc-console-ssh@.service template
unit, we invoke obmc-console-client from
dropbear by configuring dropbear to force obmc-console-client as the
session’s command:
ExecStart=/usr/sbin/dropbear -K 5 -r ${DROPBEAR_RSAKEY_DIR}/dropbear_rsa_host_key -c "/usr/bin/obmc-console-client -c /etc/obmc-console/client.%i.conf" -p %i -F $DROPBEAR_EXTRA_ARGS
From this we see we also configure the port on which a dropbear instance
listens using the template parameter for the unit (-p %i). Essentially, this
allows us configure new network console servers by running e.g.
DESIRED_PORT=2210; systemctl enable obmc-console-ssh@${DESIRED_PORT}.service
Again by the “force command” (-c) option to dropbear in the ExecStart
line, we find that obmc-console-client is configured to look for its
configuration file at /etc/obmc-console/client.%i.conf, subject to template
substitution. Reified with our example unit template parameter, this becomes
/etc/obmc-console/client.2210.conf
Above we’ve explored how each of the clients and servers are instantiated, but
the missing piece is how an obmc-console-client knows the
obmc-console-server to which it should connect. This comes down to a
correlation key, known currently as socket-id, which is specfied in both the
client and server configuration files:
2 16:34:33 andrew@fedora:~/src/openbmc/openbmc ((e6970b4909a2...)) $ \
> git grep socket-id meta-ibm/ | grep p10bmc
meta-ibm/recipes-phosphor/console/obmc-console/p10bmc/client.2201.conf:socket-id = hypervisor
meta-ibm/recipes-phosphor/console/obmc-console/p10bmc/server.ttyVUART1.conf:socket-id = hypervisor
In terms of the current implementation, the value of socket-id is used to
construct the abstract socket name published by the server and
connected to by the client in the common code between the client and the
server.
Combined, the template service units for obmc-console-server and
obmc-console-client allow us to expose multiple upstream TTYs to the network
in an arbitrary arrangement. All that is required to do so is to:
/etc/obmc-console/server.${TTY}.conf/etc/obmc-console/client.${PORT}.confsocket-idsystemctl enable obmc-console-ssh@${PORT}systemctl start obmc-console-ssh@${PORT}