Network T. Pauly
Internet-Draft Apple Inc.
Intended status: Informational February 7, 2017
Expires: August 11, 2017

Software Guidelines for Protocol Evolution


This document outlines a set of recommendations and guidelines for how networking software should be designed to enable the development, testing, and deployment of new protocols and protocol features. The focus is primarily on the API contract that a client-side networking library should present to applications using networking features, and how that library can be architected to maximize flexibility and longevity.

Specific areas of protocol development that should be enabled include:

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on August 11, 2017.

Copyright Notice

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents ( in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

Table of Contents

1. Introduction

Wide deployments of networking protocols often lag behind the specifications of those protocols. This means that network users worldwide often are not using the latest protocol developments, and the design of protocols must take into account the fact that they will likely not be adopted quickly. There are many reasons for this delay, but one significant cause is the difficulty for client applications to take advantage of new features due to inflexible software implementations. This is evidenced by the fact that protocols that require changing an API (Application Programming Interface) contract with applications are often difficult to deploy at large scale. As an example, consider that modifying congestion control algorithms (which generally has no API impact) is a fairly common occurrence on modern operating systems, while changes such as IPv6 or TCP Fast-Open [RFC7413] that require API modification can take years or decades to deploy. While there are certainly protocols that are held back by ossified networks, ossified networking APIs also contribute to the problem.

This document outlines a set of recommendations and guidelines for how networking software should be designed to enable the development, testing, and deployment of new protocols and protocol features. The focus is primarily on the API contract that a client-side networking library should present to applications using networking features, and how that library can be architected to maximize flexibility and longevity.

1.1. Problem Statement

A common term for inflexibility of networking protocols is "ossification". Ossification can take many forms, but all of these result in the inability to change from existing patterns of protocol usage. This harms networks and clients by reducing their functionality, security, and efficiency. In some cases, ossification is imposed by "middleboxes" such as firewalls and NAT gateways. To remedy these cases, there must either be change in the middleboxes, or concessions made by new protocols to account for these middleboxes. In other cases, however, the ossification is a side-effect of software architecture. Protocol features that do not fit the traditional POSIX Sockets model, for example, are difficult to enable.

Of course, not all inflexibility is incorrect. Applications often require a deterministic set of features, and changing the fundamental assumptions of the protocols they use could lead to non-functional networks. To account for this, it is helpful to distinguish between the reasons for inflexibility:

If the inflexibility of applications is limited to only what must be specified, and no more, the protocol stack implementation will have more freedom to adopt and offer new features. Achieving this goal requires careful consideration of not only what a protocol does, and how it is exposed to applications, but also how that exposure may interact with other protocol features and potentially ossify implementations.

Specific areas of protocol development that should be enabled include:

1.2. Requirements Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119].

2. Guideline Summary

Each of the guidelines described in this document is a direct response to a form of software ossification.

Application interfaces should be derived from usage patterns
Connection establishment should attempt a tree of options
Parameters should not be protocol-specific
Dynamically evaluate network state and operating system policy

These guidelines are explored in more detail below.

3. Terminology

This document uses some specific terminology in the explanation of the guidelines.

3.1. Endpoint

An identifier for a network service. Generally there is a concept of both a local and remote endpoint. Endpoints are the targets of network connections. If an endpoint of a given type cannot be directly used, it should be resolved into one or more endpoints of another type. Examples of endpoint types include:

3.2. Derived Endpoint

A derived endpoint is an endpoint that is not the original target of an API client, but an endpoint derived from that original endpoint. Derivation may take the form of hostname resolution into addresses, synthesis between address types, or changing to a different endpoint entirely based on a configuration requirement. For example, if a proxy server must be used for a connection, the endpoint that represents the proxy is a derived endpoint.

3.3. Path

A view of network properties that can be used to communicate to an endpoint from the current system. This is sometimes referred to as a Provisioning Domain (PvD) [RFC7556]. One way to view a path is as a route lookup with more data included than just the next hop. The path may include properties of the addresses and routes being used, the network interfaces being used, and other metadata about the network learned from configuration or negotiation.

3.4. Connection

A flow of data between two endpoints, using one or more paths. An connection is created with a set of parameters indicating client preferences.

3.5. Multi-stream

Any case in which more than one logical stream of data, or responses and replies, are multiplexed over a single network connection.

3.6. Multi-path

Any case in which a connection uses more than one path off of the local device to split up or migrate its traffic.

3.7. 0-RTT Protocol

Any protocol that can send upper level protocol data without first conduction a handshake or negotiation at its own layer. Examples include TCP Fast-Open and TLS 1.3 [I-D.ietf-tls-tls13].

4. Guidelines

4.1. Application interfaces should be derived from usage patterns

Many protocols share similar usage patterns. Some of these take the form of connection lifetime: most protocols have a step of establishing a connection, followed by a step in which communication is established and data can be transferred, followed by a step in which the connection is removed. For protocols like TCP and TLS [RFC5246], the connection may be established through a handshake of packets; for protocols like UDP, the connection may be implicit. Other usage patterns include the model for data transfer: TCP, TLS, and various proxying protocols provide a bi-directional stream of bytes; UDP and DTLS [RFC6347] provide datagram transport; and HTTP/2 [RFC7540] and SCTP [RFC4960] can provide message or chunk-based semantics.

Ossification is introduced to the stack when an application must use different code for two protocols that both offer reliable, connected stream abstractions. An application that was written using POSIX Sockets to access TCP cannot easily switch to another stream abstraction that is not provided beneath the sockets API. Unifying APIs that have the same data transfer model is particularly important for making it easy for applications to adopt security or privacy protocols.

The recommendation to promote flexibility is to provide a set of common, primitive APIs for interacting with networking connections that may be used generically for all protocols.

Connection types:

Data transfer modes:

4.2. Connection establishment should attempt a tree of options

Networking APIs should not assume that a connection attempt request by an application should only correspond to a single set of connection establishment attempts at the protocol level. If only one option is allowed per attempt, the application must make a choice about which protocol to use, which endpoint (such as IP address) to target, and which network interface to use. An application does not necessarily have all of the necessary information to make this choice unless it has a high degree of knowledge about the network state through the operating system's interfaces; and even if it can make a nuanced decision, it will likely make some assumptions that are based on the networks it was developed and tested in. To be specific, if an application must choose between several IPv4 and IPv6 addresses, and was developed in an IPv4-environment, it is likely that it will tend towards choosing IPv4 or not working correctly with IPv6.

The idea of racing attempts for IPv4 and IPv6 addresses, known as "Happy Eyeballs" [RFC6555], is the classic example of the multiple-options approach. Since networks may be ossified around only supporting IPv4, a Happy Eyeballs client will support attempting both IPv4 and IPv6 addresses for a hostname in parallel, generally with one attempt starting shortly after the first if the connection is not immediately established. Happy Eyeballs allowed IPv6 to be more widely and successfully used throughout the Internet, since clients could adjust to ossified networks, but still prefer certain protocols.

This approach should not be limited to racing IPv4 and IPv6 attempts. Its fundamental premise applies to many scenarios, and allows clients to elude ossification caused by networks.

There are several types of racing that can occur during connection establishment:

Each of these kinds of racing represents a potential branching point of a tree of options for a single connection establishment. They may be used in combination. The recommended order of operations for branching is to first branch for multiple paths, then branch for protocol stack options, and finally branch one or more times for derived endpoints. This order is based on the fact that protocol options and endpoint derivation (resolution) is often specific to a Path.

4.2.1. Derived Endpoint Racing

If an connection originally targets a single endpoint, there may be multiple endpoints of a different type that can be derived from the original. The connection library should order the derived endpoints preference and expected performance.

DNS hostname-to-address resolution is the most common endpoint derivation step. When trying to connect to a hostname endpoint on a traditional IP network, the implementation should send DNS queries for both A (IPv4) and AAAA (IPv6) records. Once the client has received responses for both address families, it should order the addresses in such a way that it will try both IPv4 and IPv6 if possible. Each resolved address endpoint represents a new branch of the tree, which can be attempted independently from other addresses. The connection attempt over each address should start after some delay, based on the expected Round Trip Time for the route to the address. Once the connection establishment for one address has completed, the other branches should be cancelled.

DNS-Based Service Discovery can also provide an endpoint derivation step. When trying to connect to a named service, the client may discover one or more hostname and port pairs on the local network using multicast DNS. These hostnames should each be treated as a branch which can be attempted independently from other hostnames. Each of these hostnames may also resolve to one or more addresses, thus creating two layers of branching.

4.2.2. Path Racing

If a client has multiple network interfaces available to it, such as mobile client with both Wi-Fi and Cellular connectivity, it can attempt a connection over either interface. This represents a branch point in the connection establishment. Like with derived endpoints, the interfaces should be ranked based on preference, policy, and performance. Attempts should be started on one interface, and then on other interfaces successively after delays based on expected RTT. Once a connection has been established over one interface, attempts on other interfaces should be cancelled.

This same approach applies to any situation in which the client is aware of multiple links or view of the network. Multiple Paths, each with a coherent set of addresses, routes, DNS server, and more, may share a single interface; they may also represent virtual interface services such as Virtual Private Networks (VPNs).

4.2.3. Protocol Stack Racing

Differences in possible protocol compositions and options can also provide a branching point in connection establishment. This allows clients to be resilient to situations in which a certain protocol is not functioning on a network, or a server.

A common case in which this approach is used is for connections with optional proxy server configurations. A single connection may be allowed to use an HTTP-based proxy, a SOCKS-based proxy, or connect directly. These options should be ranked and tried in succession.

This approach also allows a client to attempt different protocol stacks that may enhance performance characteristics if possible on the network. For example, a UDP-based protocol stack could be attempted first, and if it fails to establish the connection, a TCP-based protocol stack can be attempted.

4.2.4. Impacts of Racing on APIs

The fact that multiple underlying protocol negotations may be attempted for a single logical connection leads to some restrictions on what APIs can guarantee.

4.3. Parameters should not be protocol-specific

Applications that rely on implementation details of a protocol can contribute to network stack ossification. Programming interfaces should not expose options that are specific to one protocol. Instead, parameters should describe usage patterns and client intentions.

APIs should be audited carefully to avoid introducing functions and parameters that can limit future protocols developments. It should generally be possible to allow clients to have the necessary control over protocols to function well in a protocol-agnostic fashion.

For example, a protocol-specific parameter would enable the LEDBAT congestion control algorithm on TCP [RFC6817]. This potentially becomes meaningless if another protocol that doesn't use equivalent congestion control should be used. Either the connection will not be able to use anything other than TCP, or else the request of the client will not be respected. If the API instead offers a parameter to specify that delay is acceptable and the traffic is considered a background transfer, LEDBAT can be inferred for TCP, and other protocols could adjust their behavior as well.

Another example is the interface exposed for MPTCP [RFC6824] subflow management. If a client directly calls a function to open a new subflow on a specific interface, the API becomes highly specific to MPTCP. The client will need to check to see if MPTCP was successfully negotiated before trying to open a new subflow, or else it will receive unexpected errors. If the interface instead offers a parameter to list which interfaces and interface types are allowed or prohibited, along with preferences for how to distribute data flows when possible, the client does not need to be directly aware of the multipath protocol. These preferences can even be used by non-multipath protocols, such as when setting the order of the list of paths to race.

An ideal security interface should work in a similar way. A client should be able to provide its credentials and evaluate the credentials of the remote peer, without relying on details of specific implementation details of TLS. Security should be a fundamental part of the networking model, and be provided beneath the connection API.

This guideline is the basis for creating a common interface for any data pipe over a network, whether that is TCP, UDP, TLS, or an application-protocol (HTTP/2 or QUIC) stream.

4.4. Dynamically evaluate network state and operating system policy

Even if there are no other impediments to adopting new protocol or protocol options, an implementation may ossify if it has no way to determine when a different protocol or set of options should be used. Without information about which endpoint is preferred, endpoint racing degenerates to deterministically trying the same option first every time; without knowing if use of multiple interfaces is allowed, a client will always use its default interface; without information about which protocols should be used to certain endpoints on certain interfaces, there can be no meaningful racing of protocols.

In order to take advantage of flexibility, an implementation should dynamically evaluate the combination of three elements:

Policies should be evaluated for each endpoint that is being evaluated in the connection establishment tree, since a client should not assume that conditions are the same for all endpoints. Two different hostnames may prefer different paths (an external or private internal network, for example), and two different addresses may use different routes, and thus different paths. Different routes may also imply different historical RTT values, which can influence the preference and timing for racing endpoints.

System policies may be specific to application or service properties. On the system, one application may have more privileges or permission than another, allowing it to use other interfaces. An application may also be required to use a specific VPN or proxy for security reasons.

A system may also have efficiency reasons to load balance eligible processes across different paths, or prefer to reuse paths that are currently active. Checking the policy with centralized system entity allows the connections to choose paths that coordinate with other connections on the system.

5. Guideline Adoption

The original POSIX Sockets API does not directly contradict any of these guidelines: indeed, it represents the degenerate case of a connection in which there are no derived endpoints (because connections are made with an IP address and port), the default or bound interface is always used, and there is only one protocol option per data mode (TCP for streams, UDP for datagrams).

However, as the common interface of applications with the network moves up to target resolvable endpoints, work on multi-interface devices, with protocol stacks that require security and multi-path and multi-stream support, the design must not be compromised in a way that would lead to network ossification.

Any of these guidelines can be implemented independently to incrementally enhance an existing API. A complete adoption will, however, provide the most flexibility for clients to adopt new protocols and protocol features.

6. Security Considerations

This memo has no direct security considerations.

7. IANA Considerations

This memo includes no request to IANA.

8. Acknowledgments

Thanks to Josh Graessley and Stuart Cheshire for their help in the design of the original implementation of Happy Eyeballs for Apple that began this work.

9. References

9.1. Normative References

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.

9.2. Informative References

[I-D.ietf-tls-tls13] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", Internet-Draft draft-ietf-tls-tls13-18, October 2016.
[RFC4960] Stewart, R., "Stream Control Transmission Protocol", RFC 4960, DOI 10.17487/RFC4960, September 2007.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008.
[RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347, January 2012.
[RFC6555] Wing, D. and A. Yourtchenko, "Happy Eyeballs: Success with Dual-Stack Hosts", RFC 6555, DOI 10.17487/RFC6555, April 2012.
[RFC6817] Shalunov, S., Hazel, G., Iyengar, J. and M. Kuehlewind, "Low Extra Delay Background Transport (LEDBAT)", RFC 6817, DOI 10.17487/RFC6817, December 2012.
[RFC6824] Ford, A., Raiciu, C., Handley, M. and O. Bonaventure, "TCP Extensions for Multipath Operation with Multiple Addresses", RFC 6824, DOI 10.17487/RFC6824, January 2013.
[RFC7413] Cheng, Y., Chu, J., Radhakrishnan, S. and A. Jain, "TCP Fast Open", RFC 7413, DOI 10.17487/RFC7413, December 2014.
[RFC7540] Belshe, M., Peon, R. and M. Thomson, "Hypertext Transfer Protocol Version 2 (HTTP/2)", RFC 7540, DOI 10.17487/RFC7540, May 2015.
[RFC7556] Anipko, D., "Multiple Provisioning Domain Architecture", RFC 7556, DOI 10.17487/RFC7556, June 2015.

Author's Address

Tommy Pauly Apple Inc. 1 Infinite Loop Cupertino, California 95014 US EMail: