| # Fuchsia Networking API Evolution |
| |
| Fuchsia Networking offers a broad range of APIs with sometimes overlapping |
| functionality. This document is the basis of ongoing API evolution. |
| |
| ## Background |
| |
| 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. |
| |
| ## Design Principles |
| |
| ### Deliberate Stabilization |
| |
| Consider this excerpt from the [FIDL API Rubric][library_structure]: |
| |
| > 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. |
| |
| ### Role Separation |
| |
| The [FIDL API Rubric][library_structure] 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. |
| |
| ### Cardinality |
| |
| 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][chromium_on_interfaces_changed]. |
| |
| ### Prior Art and Compatibility |
| |
| 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`. |
| |
| ### Time Pressure |
| |
| 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. |
| |
| ## Site Survey and Ongoing Work |
| |
| At present, these are the libraries considered in this document: |
| |
| - `fuchsia.hardware.ethernet` |
| + being replaced with `fuchsia.hardware.network` |
| + neither is planned for SDK inclusion |
| - `fuchsia.net` |
| + included in SDK |
| + should contain only common types, no protocols |
| + protocol `NameLookup` should move to `fuchsia.net.name` |
| - fuchsia.net.dhcp |
| + included in SDK via dependency in `fuchsia.netstack` |
| + planned for removal from SDK |
| - fuchsia.net.dhcpv6 |
| + not planned for SDK inclusion |
| - `fuchsia.net.filter` |
| + not planned for SDK inclusion |
| + contains only protocol `Filter` |
| + needs rework in consideration of `NETLINK_NETFILTER` (undocumented?) |
| - `fuchsia.net.http` |
| + out of scope of this document, not maintained by networking |
| - fuchsia.net.icmp |
| + not planned for SDK inclusion |
| + can possibly be removed in favor of fuchsia.posix.socket |
| - `fuchsia.net.mdns` |
| + out of scope of this document. do we need to bring it in scope? |
| - `fuchsia.net.name` |
| + not included in SDK |
| + protocol `LookupAdmin` is the role-separated pair of |
| `fuchsia.net.NameLookup`. We should pull in `NameLookup` (`Lookup`?) |
| - `fuchsia.net.neighbor` |
| + not planned for SDK inclusion |
| - `fuchsia.net.oldhttp` |
| + out of scope of this document, not maintained by networking |
| + only referenced in |
| https://source.chromium.org/chromium/chromium/src/+/master:fuchsia/http/ |
| + slated for deletion |
| - `fuchsia.net.ppp` |
| + dead code? can we delete it? can it be subsumed by |
| `fuchsia.hardware.network`? |
| - `fuchsia.net.routes` |
| + included in SDK |
| + narrow route+MAC resolution API in service of partner needs |
| - `fuchsia.net.stack` |
| + not included in SDK |
| + broad general-purpose protocol `Stack` does not employ role separation, |
| should be decomposed into several protocols after consulting industry |
| standards |
| + protocol `Log` to be replaced by https://fxbug.dev/54198 |
| - `fuchsia.net.tun` |
| + not included in SDK |
| + ownership-based |
| - `fuchsia.netstack` |
| + included in SDK |
| + protocol `Netstack` being replaced in https://fxbug.dev/21222 |
| - `fuchsia.posix.socket` |
| + not included in SDK |
| + used via fdio which is included in SDK |
| + undergoing portability improvements in https://fxbug.dev/44347 |
| |
| [library_structure]: /docs/concepts/api/fidl.md#library_structure |
| [chromium_on_interfaces_changed]: https://chromium-review.googlesource.com/c/chromium/src/+/2331860 |
| [`netlink`]: https://man7.org/linux/man-pages/man7/netlink.7.html |