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-server
obmc-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-client
As 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}.conf
socket-id
systemctl enable obmc-console-ssh@${PORT}
systemctl start obmc-console-ssh@${PORT}