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.
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.
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.
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.
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.net.stack/Stack were designed without considering equivalent functionality provided by
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:
NameLookup should move to
LookupAdmin is the role-separated pair of
fuchsia.net.NameLookup. We should pull in
Stack does not employ role separation, should be decomposed into several protocols after consulting industry standards
Log to be replaced by https://fxbug.dev/54198
Netstack being replaced in https://fxbug.dev/21222