In Shill, a network interface is represented by a Device
instance. Among other
things, the Device
class provides basic functionality to configure its
interface through /proc/sys/net
parameters, to acquire and use IP
configuration parameters, and to drive Service
state. Device
is
the base class for a hierarchy of Device
children that perform
technology-specific behavior and that actually trigger base Device
functionality:
Most Device
instances are created by the DeviceInfo
class. DeviceInfo
listens to device and address-configuration events using RTNL
. On
startup, it also requests a dump of existing device and address-configuration
information in order to be in sync with the current system state. When
DeviceInfo
has enough information about an interface, it will create a
Device
child instance of the proper type. DeviceInfo
will also update
existing Device
instances with new information that it receives about the
corresponding interface. A common exception to the "Devices
are created by
DeviceInfo
" rule are VirtualDevices
corresponding to virtual interfaces
created by Shill (for use-cases like PPPoE, VPN, and cellular
dongles). Cellular
instances are another exception, which are created by
Modem
instances (which are themselves a representation of the ModemManager
Modem D-Bus object). For the cellular case, DeviceInfo
sends relevant link
information to the ModemInfo
class.
A network interface on its own doesn't magically provide network connectivity,
but instead must connect to "something" (e.g., a WiFi Access Point) in order to
achieve that end result. A Service
represents that "something"; it is a
representation of an entity that can provide network connectivity if interacted
with properly. The Service
class acts as a connection state machine that
Device
piggybacks on, provides the core connect/disconnect behavior, and
provides the basic functionality for persisting network-specific configuration
options, among other things. Not unlike Device
, Service
also forms a
hierarchy in which children perform technology-specific behavior:
A Service
and Device
of matching technology type must interact (conceptually
they are bound to each other) in order for the Service
to reach a connected
state.
Service
instances in most cases are created by Provider
instances. At most
one instance exists for each child Provider
type. Provider
instances
generally create new Services
either from persisted state (see the
Profile
section) or from the D-Bus interface (see the
Manager
section).
For WiFiProvider
, Services
are also created based on network scans performed
by wpa_supplicant
, which leads to the reception of BSSAdded D-Bus signals that
trigger WiFiProvider
to create a corresponding WiFiService
.
The CellularServiceProvider
instance ensures that a CellularService
for a
Cellular
Device is created when it is ready, corresponding to the IMSI
associated with the active SIM. Additional CellularService
instances may also
be created if they match the SIM Card Id (eID or ICCID) of the active SIM.
The EthernetProvider
by default has a single EthernetService
, which the
first Ethernet
instance will use. Additional Ethernet
instances will cause
the EthernetProvider
to create additional EthernetService
instances.
A Profile
represents a set of persisted data and is used for both Device
and
Service
. Device
and Service
(base classes and children) take care of
loading from and saving to the underlying storage used by the relevant
Profile
.
Shill allows for a stack of Profiles
rather than just having a single
Profile
at a time. On startup, the Profile
stack contains a single
DefaultProfile
, which serves to provide pre-login configuration data. In
addition to the regular Profile
behavior of persisting Service
properties, a
DefaultProfile
will also persist Device
properties and a subset of Manager
properties.
On user login, the shill_login_user script is run,
which creates a Profile
for that user if one doesn't already exist, and then
pushes that Profile
onto the Profile
stack. Correspondingly,
shill_logout_user will pop the user's Profile
when
logging out. When a guest user is used, a Profile
will still be created and
pushed onto the stack as usual, but the persisted data will simply be deleted so
that the data is essentially not persisted. An EphemeralProfile
, which is
essentially a "null profile" that doesn't persist any data, is not used for
guest users. One benefit of this is resilience to Shill crashes within a single
guest user session.
Every Service
has exactly one Profile
associated with it, which is
theProfile
most recently pushed onto the Profile
stack that contains
persisted data for that Service
. An EphemeralProfile
is used exclusively for
Service
instances that are created but that have no Profile
in the Profile
stack that contains data for it (e.g., a WiFiService
that was created from a
WiFi scan but that the user has never attempted to configure or connect to). A
Service
can be "linked" to a different Profile
through the use of the
Service
kProfileProperty D-Bus property, which is how Service
instances
currently using the EphemeralProfile
can be moved over to a Profile
that
allows its configuration parameters to be persisted.
Given that Shill's D-Bus clients aside from Autotest/Tast do not create
additional Profiles
, the Profile
stack in non-test cases contains only the
DefaultProfile
and potentially a user Profile
. The EphemeralProfile
is not
part of the Profile
stack.
Manager
is the "top-level" class in Shill. Its responsibilities include:
- Keeping track of
Devices
representing interfaces managed by Shill.Manager
is informed ofDevice
additions/removals byDeviceInfo
.
- Keeping track of
Service
instances. - Maintaining the
Profile
stack, which includes updatingDevice
andService
instances whenProfiles
are pushed onto or popped from the stack. - Keeping
Service
instances sorted according to the Service ordering described in theManager
D-Bus Specification. - Initiating
Service
auto-connections (aService
determines whether or not it can auto-connect, butManager
triggers the auto-connection attempt). - Interfacing with the PowerManager daemon to trigger pre-suspend or
post-resume behavior in
Devices
andServices
. - Storing top-level properties that are set from the command-line.
Manager
also provides the top-level Shill D-Bus interface. Note that Device
,
Service
, and Profile
instances tracked by Manager
will all have
corresponding D-Bus objects that clients can interact with. Clients first learn
about these objects via the Manager
D-Bus object.
-
RTNL
- Acronym for rtnetlink.Netlink is a protocol that can be used for kernel <-> user-space and user-space <-> user-space communication. Unlike a syscall, which requires a user to initiate communication with the kernel, any entity may send netlink messages at any time. This allows the kernel to notify listeners of events without those listeners needing to do something like poll for a state change. It is based on the socket API, and therefore provides built-in asynchronous semantics through the use of socket queues. Netlink also provides support for multicast, which allows--for example--multiple user-space daemons to listen to the same events from the kernel simply by registering with the appropriate multicast group(s).
Different usages of the netlink protocol will have different information being sent and will generally want multicast groups isolated from other netlink usages. Netlink employs the concept of a family to satisfy this need, where a family can define custom multicast groups and message types. rtnetlink refers specifically to the NETLINK_ROUTE netlink family, which is defined by the kernel itself (see rtnetlink.h).