Fuchsia Networking offers a broad range of APIs with sometimes overlapping functionality. This document is the basis of ongoing API evolution.
At the time of writing, Fuchsia Networking APIs are the result of rapid evolution and often-unintentional stabilization, resulting in a large surface with out-of-tree consumers. Many of these APIs evolved before newer FIDL features were available, making in-place migration even more difficult.
More than other system areas, Networking must be mindful of its APIs becoming prematurely load bearing.
Consider this excerpt from the FIDL API Rubric:
How you decompose these definitions into libraries has a large effect on the consumers of these definitions because a FIDL library is the unit of dependency and distribution for your protocols.
Be mindful of this when creating new protocols. Undue grouping of protocols, even when semantically logical, can produce unwanted distribution coupling. In other words, consider minting new libraries for new protocols to avoid premature inclusion in the SDK.
Consider fuchsia.net.Connectivity
as a motivating example: by having been placed in fuchsia.net
, its inclusion in the SDK was entangled with that library; it was de-facto stabilized without a formal decision.
Note that fuchsia.net.Connectivity
was removed in 5500eec6aa48c65516eae4d5ef4.
The FIDL API Rubric advises:
To decide whether to decompose a library into smaller libraries, consider the following questions:
- Do the customers for the library break down into separate roles that would want to use a subset of the functionality or declarations in the library? If so, consider breaking the library into separate libraries that target each role.
We prefer a different framing in Networking: separate your API into different roles by breaking it into multiple protocols; separate your API into different stabilization units by breaking into multiple libraries.
Consider fuchsia.netstack/Netstack
and fuchsia.net.stack/Stack
as motivating examples: neither encode access roles, requiring that any agent that wishes to observe the system state is also granted access to modify it. In practice, this needlessly grants consumers such as Chromium write-access to networking internals.
Avoid introducing APIs that are non-orthogonal to existing APIs. Providing multiple entry points for the same purpose can lead to confusion for consumers and subtle behaviour differences.
Consider fuchsia.netstack/Netstack.GetInterfaces
and fuchsia.netstack/Netstack.OnInterfacesChanged
as motivating examples: OnInterfacesChanged
provides a superset of the functionality of GetInterfaces
by emitting a synthetic event upon binding, yet consumers misunderstood and misused the API.
Consider compatibility with existing software when designing APIs. As Fuchsia's product requirements grow in scope, so will the burden of porting software to platform-specific APIs; consider how your API might be translated to an existing API that is widely used in the industry. Furthermore, existing APIs have evolved to provide solutions to problems we may not have considered, it behooves us to learn from their efforts.
The obvious motivating example here is POSIX sockets; fuchsia.posix.socket
evolved directly to address this need, complete with the over-fitting described above. At the time of writing, the API transports C structures on the wire directly, creating portability problems and resulting in an ABI that is not fully defined in FIDL.
A less-obvious motivating example is netlink
; networking management APIs are not standardized in POSIX, yet netlink
is widely used in existing software to interact with Linux's networking subsystems. Both fuchsia.netstack/Netstack
and fuchsia.net.stack/Stack
were designed without considering equivalent functionality provided by netlink
.
It will sometimes be necessary to provide partners with SDK-exposed APIs on a time scale that does not permit a reasoned general-purpose solution to be designed. Prefer the narrowest possible design that provides for the partner's needs to avoid acquiring unintended consumers. Provide your API in a new protocol to ease future deprecation.
This approach allows us to respond quickly without compromising our design principles in the long term.
At present, these are the libraries considered in this document:
fuchsia.hardware.ethernet
fuchsia.hardware.network
fuchsia.net
NameLookup
should move to fuchsia.net.name
fuchsia.netstack
fuchsia.net.filter
Filter
NETLINK_NETFILTER
(undocumented?)fuchsia.net.http
fuchsia.net.mdns
fuchsia.net.name
LookupAdmin
is the role-separated pair of fuchsia.net.NameLookup
. We should pull in NameLookup
(Lookup
?)fuchsia.net.neighbor
fuchsia.net.oldhttp
fuchsia.net.ppp
fuchsia.hardware.network
?fuchsia.net.routes
fuchsia.net.stack
Stack
does not employ role separation, should be decomposed into several protocols after consulting industry standardsLog
to be replaced by https://fxbug.dev/54198fuchsia.net.tun
fuchsia.netstack
Netstack
being replaced in https://fxbug.dev/21222fuchsia.posix.socket