<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc2629 version 1.2.3 -->

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
]>

<?rfc toc="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>

<rfc ipr="trust200902" docName="draft-tiesel-taps-socketintents-bsdsockets-02" category="info">

  <front>
    <title abbrev="Socket Intents for BSD Sockets">A Socket Intents Prototype for the BSD Socket API – Experiences, Lessons Learned and Considerations</title>

    <author initials="P.S." surname="Tiesel" fullname="Philipp S. Tiesel">
      <organization>TU Berlin</organization>
      <address>
        <postal>
          <street>Marchstr. 23</street>
          <city>Berlin</city>
          <country>Germany</country>
        </postal>
        <email>philipp@inet.tu-berlin.de</email>
      </address>
    </author>
    <author initials="T." surname="Enghardt" fullname="Theresa Enghardt">
      <organization>TU Berlin</organization>
      <address>
        <postal>
          <street>Marchstr. 23</street>
          <city>Berlin</city>
          <country>Germany</country>
        </postal>
        <email>theresa@inet.tu-berlin.de</email>
      </address>
    </author>

    <date year="2018" month="July" day="02"/>

    <area>Transport</area>
    <workgroup>TAPS Working Group</workgroup>
    <keyword>Internet-Draft</keyword>

    <abstract>


<t>This document describes a prototype implementation of
Socket Intents <xref target="I-D.tiesel-taps-socketintents"/> for the
BSD Socket API as an illustrative example
how Socket Intents could be implemented.
It described the experiences made with the prototype
and lessons learned from trying to extend the BSD Socket API.</t>



    </abstract>


  </front>

  <middle>


<section anchor="introduction" title="Introduction">

<t>With the proliferation of devices that have multiple paths to the
internet and an increasing number of transport protocols available, the number
of transport options to serve a communication unit explodes.
Implementing a heuristic or strategy for choosing from this
overwhelming set of transport options by each application puts a huge
burden on the application developer.
Thus, the decisions regarding all transport options mentioned so far
should be supported and, if requested by the application, automated
within the transport layer.</t>

<t>Socket Intents <xref target="I-D.tiesel-taps-socketintents"/> allow an application
to express what it knows, assumes, expects or wants to prioritize
regarding its own network communication.
This information can than be used by the OS to perform destination
selection, path selection and transport protocol stack instance
selection.</t>

<t>Our Socket Intents prototype for the BSD Socket API is a first
attempt to automate transport option selection within the OS.
It is primarily targeted at path and destination address selection and
tries to be as close as possible to the semantics of the BSD Socket API.
The prototype mostly excludes the problem of transport protocol stack
instance selection, which is more closely discussed in
<xref target="I-D.tiesel-taps-communitgrany"/>.</t>

<t>We implemented the prototype as a wrapper for the BSD Socket API
that communicates to a central Multiple Access Manager that makes the
actual decisions and can optimize across applications.
The whole implementation was done in about 15k lines of C code.
The code is available at <eref target="https://github.com/fg-inet/socket-intents/">Github</eref>
under BSD License.</t>

<t>This document describes our Socket Intents prototype for the
BSD Socket API.
It details important aspects of the implementation and the API
variants we developed over time based on lessons learned. Finally, it
summarizes these lessons and points out why the BSD Socket API is not
particularly well suited to integrate automated transport protocol stack
instance selection. Furthermore, it describes the limitations for destination
address and path selection within the BSD Socket API.</t>

</section>
<section anchor="prototype-architecture" title="Prototype Architecture">

<t>The Socket Intents prototype consists of the following components, also
shown in <xref target="prototypearch"/>:</t>

<t><list style="symbols">
  <t>The Socket Intents API, a BSD Socket API wrapper for applications to
use, including a representation of the actual Socket Intents.</t>
  <t>The Socket Intents Library which implements the Socket Intents API.
It sends requests to the Multiple Access Manager, e.g. before
establishing a connection, and gets back a response regarding what
interface to use.</t>
  <t>The Multiple Access Manager (MAM), a daemon which gets informed about
all application requests and has knowledge of the available network
interfaces.</t>
  <t>The Policy, a dynamically loaded library hosted by the MAM. It
chooses which of the available interfaces to use based on the
available knowledge about them and the Socket Intents.</t>
  <t>Data collectors that that reside inside the MAM and that provide
information like bandwidth usage, smoothed RTT estimate and RSSI for wireless links to the policy.</t>
</list></t>

<figure title="Components of the Socket Intents Prototype" anchor="prototypearch"><artwork align="center"><![CDATA[
+------------------------+
|      Application       |
|                        |                   +-------------------+
+-{ Socket Intents API }-+  (MAM Request)    |  Multiple Access  |
|                        | ----------------> |      Manager      |
|     Socket Intents     |  (MAM Response)   | +---------------+ |
|        Library         | <---------------- | |    Policy     | |
+------------------------+                   | +---------------+ |
|      BSD Sockets       |                   | |Data Collectors| |
+------------------------+                   +-+---------------+-+
]]></artwork></figure>

</section>
<section anchor="multiple-access-manager" title="Multiple Access Manager">

<t>The Multiple Access Manager (MAM) is the central transport option
selection instance on a host.
It is realized as a daemon that runs in userspace and receives
requests from each application that uses the Socket Intents Library.</t>

<t>The MAM hosts the Policy, which is the actual decision making
component, e.g., deciding which source address and therefore which
source interface to use.
Upon events, such as an application requesting to resolve a name or to
connect a socket (see <xref target="apivar"/> for details), the Socket Intents
Library issues a MAM request and the MAM invokes a callback to the
policy – see <xref target="policy"/> for details - which can either communicate
its decision right away or defer its decision, e.g., when it has to
wait for the results of name resolution.
The results and decisions are communicated back to the Socket
Intents Library through the MAM response, where they are applied to the
actual socket, see also <xref target="prototypearch"/>.</t>

<t>To support the policy, the MAM maintains a list of IP prefixes that are
configured on the local interfaces and available for outgoing
communications.
As destination address selection and path selection are highly
dependent on each other, the MAM integrates DNS resolution and maintains
separate resolver configurations per prefix (see <xref target="ANRW17-MH"/> for
further discussion on multiple PvDs and DNS resolution).
Furthermore, the MAM includes data collectors which periodically gather
statistics on the available paths, see <xref target="pmeasure"/> for details.</t>

<section anchor="policy" title="Policy">

<t>In the Socket Intents prototype, the Policy implements the decision logic for
selecting among available transport options. In our current implementation,
only one policy can be active at a given time. We implement different
interchangeable policies as dynamically loaded libraries, which are hosted by
the Multi Access Manager (MAM), see <xref target="prototypearch"/>. When launching the MAM,
the user has to choose a policy and supply a policy configuration, which can
contain additional information to configure the policy.</t>

<t>Examples of policy configuration include:</t>

<t><list style="symbols">
  <t>A list of IP prefixes configured on local interfaces to consider as source for the communication</t>
  <t>Name server(s) to use for each of the IP prefixes</t>
  <t>Preferences to instrument the policy, e.g., default prefix to use</t>
</list></t>

<t>The policy is initialized with this configuration and then waits for the
callback of an incoming MAM request.</t>

<t>Upon a callback, the policy can use information from the MAM request,
such as Socket Intents, and information available within the MAM, such
as recently measured path characteristics (see <xref target="pmeasure"/>), to make
decisions.</t>

<t>Policy decisions can include:</t>

<t><list style="symbols">
  <t>The source address(es) used for name resolution</t>
  <t>How to order the results of name resolution (i.e., preferring certain
IP addresses over others)</t>
  <t>Picking an IP protocol version</t>
  <t>Picking a transport protocol (Note that in our current implementation, we are
constrained by the Socket API, so our policy cannot override the transport
protocol chosen by an application.)</t>
  <t>Setting socket options (e.g., disable TCP Nagle)</t>
  <t>Choosing a source address for the outgoing communication</t>
  <t>Reusing a socket from a given socket set (only for the API variant
described in <xref target="socketconnectapi"/>)</t>
</list></t>

<t>Note that in our current implementation, the policy is a piece of code
which can in principle execute arbitrary instructions.
We assume this is acceptable for an experimental platform but would prefer
an abstract description like a domain-specific language for a
production system.</t>

</section>
<section anchor="pmeasure" title="Path characteristics data collectors">

<t>The data collectors are implemented as a component of the MAM, within a
callback that is executed periodically, e.g., every 100 ms. When this
callback is invoked, the MAM passively gathers statistics about the
current usage and properties of the available local interfaces and
stores them in per-interface or per-network prefix data structures.</t>

<t>Measured properties include:</t>

<t><list style="symbols">
  <t>Minimum Smoothed Round Trip Time (SRTT) of current TCP connections
using a network prefix, as an estimate for last-mile latency</t>
  <t>Median SRTT of current TCP connections using a network prefix, as an
alternate estimate for last-mile latency</t>
  <t>Median of Round Trip Time variations within connections</t>
  <t>Median variation of Smoothed Round Trip Times across connections</t>
  <t>Median of percentage of segments deemed lost of all transmitted segments of
current TCP connections, as an estimate of upstream packet loss</t>
  <t>Maximum transmitted and received bytes per second over an interface
within the last 5 minutes, as an estimate for maximum available bandwidth</t>
  <t>On 802.11 interfaces, the Received Signal Strength Indicator (RSSI) of
the last received frame on that interface, as an estimate for
reception strength</t>
  <t>On 802.11 interfaces, the modulation rate of the last received and the
last transmitted unicast data frame on that interface, as an estimate
for the available data transmission rate on the first hop</t>
  <t>On 802.11 interfaces, the latest Channel Utilization as parsed from a
Beacon frame, as an estimate of congestion on the wireless medium</t>
</list></t>

<t>See <xref target="ANRW18-Metrics"/> for more discussion of the gathered metrics.</t>

<t>When a policy callback is invoked, the policy can use the latest
measured properties to guide its decisions, see <xref target="policy"/>.</t>

<t>Note that we do not perform active measurements from within the MAM to
avoid overhead.</t>

</section>
</section>
<section anchor="socket-intents-representation" title="Socket Intents Representation">

<t>As described in <xref target="I-D.tiesel-taps-socketintents"/>, Socket Intents are
pieces of information about upcoming traffic. An application can share
the information that it has available through the Socket Intents API.</t>

<t>In our implementation, Socket Intents are represented as socket
options for get/setsockopt on its own socket option level (SOL_INTENTS).</t>

<t>For some of the API variants, we had to introduce socket option lists,
i.e., data structures that can hold multiple socket options and
therefore multiple Socket Intents.</t>

<t>Which of these variants is actually used depends on the API variant,
see <xref target="apivar"/>.</t>

</section>
<section anchor="apivar" title="The Socket Intents API Variants">

<t>The Socket Intents API is a wrapper around the BSD Socket API. It sends
requests to the Multiple Access Manager (MAM) at certain events, e.g.,
before a connection is established, and applies the suggestions that it
gets from the MAM, e.g., to bind to a certain local interface or to set
a certain socket option.</t>

<t>There exist different variants of this API, see <xref target="apivar"/>, that
try to fit different concepts:</t>

<t><list style="symbols">
  <t>The Classic API with muacc_context, see <xref target="muacccontextapi"/>, was
attempting to stick as close as possible to the call sequence of
BSD Sockets.</t>
  <t>The second variant of the classic API does all transport option
selection in <spanx style="verb">getaddrinfo</spanx>, see <xref target="getaddrinfoapi"/>.
This variant tries to simplify the implementation without deriving
too much from the usage of BSD Sockets.
It minimizes the changes to the BSD Socket API, but adds
additional overhead to the application.</t>
  <t>The <spanx style="verb">socketconnect</spanx> API, see <xref target="socketconnectapi"/>, tries to automate
as much functionality as possible and adds support for automating
connection caching.
It replaces the usual sequence of BSD Socket API calls with a
single call.</t>
</list></t>

<section anchor="muacccontextapi" title="Classic API / muacc_context">

<t>In the first variant, we add a parameter called <spanx style="verb">muacc_context</spanx> to
the BSD Socket API calls and to getaddrinfo.
This parameter holds properties provided by the socket calls and
retains them across function calls to enable automation of the
connection properties by our Socket Intents Prototype.
The shadow data structures behind the <spanx style="verb">muacc_context</spanx> parameter are
initialized by API wrapper at the time of the first call (which we
assume to be muacc_getaddrinfo most of the time) with most of its
fields empty.
Then within each call to our modified Socket API, it is filled with
data.</t>

<t>Properties include:</t>

<t><list style="symbols">
  <t>Socket file descriptor</t>
  <t>API calls that were already performed on this context</t>
  <t>domain, type, and protocol of the socket</t>
  <t>remote hostname</t>
  <t>remote address</t>
  <t>hints for resolving the remote address</t>
  <t>local address to bind to that the application requested</t>
  <t>local address to bind to that the MAM suggested</t>
  <t>current socket options that were set</t>
  <t>socket options suggested by MAM</t>
</list></t>

<section anchor="muaccgetaddrinfo" title="muacc_getaddrinfo()">

<t>This function resolves a host name or service to an addrinfo data
structure, usually containing an IP address or port.
Internally, the Socket Intents
prototype sends a <spanx style="verb">getaddrinfo</spanx> request to the MAM, which should do the
name resolution.
It can, e.g., resolve the name over multiple available interfaces at
the same time, and then order the results according to a policy
decision, or only return results obtained over a specific interface.</t>

<t>SIGNATURE:</t>

<t>int muacc_getaddrinfo(muacc_context_t *ctx, const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called with an empty context, which is then filled within the function.</t>
  <t hangText='hostname:'>
  Remote host name to be resolved</t>
  <t hangText='servname:'>
  Remote service to be resolved</t>
  <t hangText='hints:'>
  Hints for resolving the name</t>
  <t hangText='res:'>
  Data structure for result of name resolution</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or an error code as provided by getaddrinfo().</t>

</section>
<section anchor="muaccsocket" title="muacc_socket()">

<t>This function creates a socket file descriptor just like the regular socket call.</t>

<t>SIGNATURE:</t>

<t>int muacc_socket(muacc_context_t *ctx, int domain, int type, int protocol)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called after muacc_getaddrinfo(), since domain, type, and protocol can depend on the type of resolved address.</t>
  <t hangText='domain:'>
  Domain of the socket</t>
  <t hangText='type:'>
  Type of the socket</t>
  <t hangText='protocol:'>
  Protocol of the socket</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns a file descriptor of the new socket on success, or -1 on failure.</t>

</section>
<section anchor="muaccsetsockopt" title="muacc_setsockopt()">

<t>This call allows to set socket options (including Socket Intents).
For Socket Intents, this function can be called on a valid
<spanx style="verb">muacc_context</spanx> and an invalided file descriptor (-1) to provide
assertional hints to <spanx style="verb">muacc_getaddrinfo()</spanx>.</t>

<t>SIGNATURE:</t>

<t>int muacc_setsockopt(muacc_context_t *ctx, int socket, int level, int option_name, const void *option_value, socklen_t option_len)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called to set Intents as socket options within the context.</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
  <t hangText='level:'>
  Level of the socket option to set</t>
  <t hangText='option_name:'>
  Name of the socket option to set</t>
  <t hangText='option_value:'>
  Value of the socket option to set</t>
  <t hangText='option_len:'>
  Length of the socket option to set</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
<section anchor="muaccconnect" title="muacc_connect()">

<t>Like the regular connect call, but also binds to the source address
selected by the Socket Intents Policy and applies socket options
suggested by the Socket Intents Policy.</t>

<t>SIGNATURE:</t>

<t>int muacc_connect(muacc_context_t *ctx, int socket, const struct sockaddr *address, socklen_t address_len)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function is mostly called after all Socket Intents for this connection have been set via muacc_setsockopt().</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
  <t hangText='address:'>
  Remote address to connect to</t>
  <t hangText='address_len:'>
  Length of the remote address</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
<section anchor="muaccclose" title="muacc_close()">

<t>Like regular close, but also cleans up state held in shadow structures
behind <spanx style="verb">muacc_context</spanx></t>

<t>SIGNATURE:</t>

<t>int muacc_close(muacc_context_t *ctx, int socket)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='ctx:'>
  Context that can contain properties of this socket/connection and retains them across function calls. This function deinitializes and releases the context.</t>
  <t hangText='socket:'>
  Socket file descriptor</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or -1 on failure.</t>

</section>
</section>
<section anchor="getaddrinfoapi" title="Classic API / getaddrinfo">

<t>In this variant, Socket Intents are passed directly to <spanx style="verb">getaddrinfo()</spanx>
as part of the <spanx style="verb">hints</spanx> parameter.
The name resolution is done by the MAM, which makes all decisions and
stores them in the “result” data structure as list of options ordered
by preference.
Subsequently, applications can use this information for calls to the
unmodified BSD Socket API or other APIs.
We provide helpers to apply all socket options from the “result”
data structure.</t>

<t>All relevant infos are stored in our addrinfo struct (see <xref target="muacc_addrinfo"/>)</t>

<t>SIGNATURE:</t>

<t>int muacc_ai_getaddrinfo(const char * hostname, const char * service,
const struct muacc_addrinfo * hints, struct muacc_addrinfo ** result)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='hostname:'>
  Remote host name to be resolved</t>
  <t hangText='service:'>
  Remote service to be resolved</t>
  <t hangText='hints:'>
  Hints for resolving the name. Contents include family, socket type, protocol, socket options (including Socket Intents for this socket/connection), local address to bind to.</t>
  <t hangText='result:'>
  Data structure for result of name resolution</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success, or an error code as provided by getaddrinfo().</t>

<figure title="Definition of the muacc_addrinfo struct" anchor="muacc_addrinfo"><artwork type="C" align="center"><![CDATA[
/** Extended version of the standard library's struct addrinfo
 *
 * This is used both as hint and as result from the
 * muacc_ai_getaddrinfo * function. This structure
 * differs from struct addrinfo only in the three members
 * ai_bindaddrlen, ai_bindaddr and ai_socketopt.
 */
struct muacc_addrinfo {
    int ai_flags;
    int ai_family;
    int ai_socktype;
    int ai_protocol;

    /** Not included in struct addrinfo. Purpose:
      * 1. If the structure is given to muacc_ai_getaddrinfo
      *    as hints, you set socket intents that influence MAM's
      *    source and destination as well as transport protocol
      *    selection
      * 2. The recommended socket options MAM will be returned
      *    through this attribute.
      */
    struct socketopt *ai_sockopts;

    int ai_addrlen;
    struct sockaddr *ai_addr;
    char *ai_canonname;

    /** Not included in struct addrinfo.
      * Length of ai_bindaddr.
      */
    int ai_bindaddrlen;
    /** Not included in struct addrinfo.
      * Contains the address, which the MAM recommends us to bind to.
      */
    struct sockaddr *ai_bindaddr;

    struct muacc_addrinfo *ai_next;
};
]]></artwork></figure>

<t><xref target="getaddrinfo_api_example"/> shows an example usage of the classic API with most functionality in getaddrinfo.</t>

</section>
<section anchor="socketconnectapi" title="Socketconnect API">

<t>In this API variant, we move the functionality of resolving a hostname
and connecting to the resulting address into one function called
<spanx style="verb">socketconnect()</spanx>.
This API makes it possible to call socketconnect not only for
each connection, but also to multiplex messages across multiple
existing sockets.</t>

<t>This function returns a file descriptor of a connected socket for
the application to use.
This socket can either be a newly created one or a
socket that existed previously and is now being reused.
Furthermore, a socket can belong to a socket set of sockets with common
destination and service.
These sockets may, e.g., be bound to different local addresses, but are
treated as interchangeable by the API implementation.
So if the application passes a socket file descriptor to this function,
it may get back a different file descriptor to a socket from the same
set, e.g., to use the connection over a different local interface for
its following communication.</t>

<t>SIGNATURE:</t>

<t>int socketconnect(int *socket, const char *host, size_t hostlen, const char *serv, size_t servlen, struct socketopt *sockopts, int domain, int type, int proto)</t>

<t>ARGUMENTS:</t>

<t><list style="hanging">
  <t hangText='socket:'>
  Existing socket file descriptor as representant to a socket set, “-1” to create a new socket, or “0” to automatically try to find a suitable socket set</t>
  <t hangText='host:'>
  Remote hostname to be resolved</t>
  <t hangText='hostlen:'>
  Length of remote hostname</t>
  <t hangText='serv:'>
  Remote service or port</t>
  <t hangText='servlen:'>
  Length of remote service</t>
  <t hangText='socketopts:'>
  List of socket options, including Socket Intents</t>
  <t hangText='domain:'>
  Domain of the socket</t>
  <t hangText='type:'>
  Type of the socket</t>
  <t hangText='proto:'>
  Protocol of the socket</t>
</list></t>

<t>RETURN VALUE:</t>

<t>Returns 0 on success if socket is from an existing socket set, 1 on success if socket was newly created, or -1 on fail.</t>

<t><xref target="socketconnect_api_example"/> shows an example usage of the Socketconnect API.</t>

</section>
</section>
<section anchor="api-implementation-experiences-lessons-learned" title="API Implementation Experiences &amp; Lessons Learned">

<t>While designing and implementing the different parts of the system as
described in this document, we faced several challenges.
In the Multiple Access Manager discovering the currently available
paths and statistics about their performance turned out to be quite
complex and had to be implemented in a partially platform-dependent way.
However, the most challenging parts were the Socket Intents API and
Library, on which we focus in the following sections.</t>

<section anchor="namereslink" title="The Missing Link to Name Resolution">

<t>Transport option selection is most useful if crucial information, such as Socket
Intents or other socket options, is available as early as possible, i.e., for
name resolution. The primary problem here is the order of the function calls
that are involved in name resolution, destination selection, protocol, and path
selection, and how they are linked.</t>

<t>In the classic BSD Socket API, most functions either take a socket file
descriptor as argument or return it, and thus link different function calls to
the same flow. However, <spanx style="verb">getaddrinfo()</spanx> is not linked to a socket file
descriptor, and it is typically called before the socket is created. At this
point, it is not yet possible to set a socket option, because the socket does
not exist yet.</t>

<t>Consequently, across BSD Socket API calls, several choices are being made
before it is possible to set a Socket Intent: A call to <spanx style="verb">getaddrinfo()</spanx> returns
a linked list of <spanx style="verb">addrinfo</spanx> structs, where each entry contains an <spanx style="verb">ai_family</spanx>
(IP version), the pair of <spanx style="verb">ai_socktype</spanx> and <spanx style="verb">ai_protocol</spanx> (transport protocol),
and a <spanx style="verb">sockaddr</spanx> struct containing an IP address and port to connect to. Then
a socket of the given family, type, and protocol is created. Only after this
has been done, socket options can be set on the socket, but at this point
destination, IP version, and transport protocol are already fixed.
Before calling <spanx style="verb">connect()</spanx>, only the path to be used (i.e., the local address
to bind to) can still be chosen, but the available paths and which one to
prefer may be constrained by the choice of destination.</t>

<t>The three variants described in <xref target="apivar"/> work around this problem in
different ways:</t>

<t><list style="symbols">
  <t>The approach in <xref target="getaddrinfoapi"/> places the whole
automation of transport option selection into the <spanx style="verb">getaddrinfo()</spanx>
function.
The results are returned in an extended <spanx style="verb">addrinfo</spanx> struct and have to be
applied manually by the application, including binding to a source address
representing the selected path and applying all socket options provided in a
list, for each connection attempt.</t>
  <t>The approach in <xref target="muacccontextapi"/> adds a context to all socket- and
name resolution-related API calls.</t>
  <t>The approach in <xref target="socketconnectapi"/> puts all functionality into
one call.</t>
</list></t>

<t>All of these approaches add the missing link between name resolution and the
other parts of the API, but add a lot of state keeping either to the API, which
the application developer has to manage, or to the Socket Intents library.</t>

</section>
<section anchor="fdharm" title="File Descriptors Considered Harmful">

<t>When using BSD sockets, file descriptors are the abstraction for network flows.
Depending on the transport protocol used, their semantics changes and these
file handles represent streams (SOCK_STREAM), associations (SOCK_DRAM) or
network interfaces (SOCK_RAW). This does not provide a unified API, but is
merely an artifact of squeezing networking into the “Everything is a file”
UNIX philosophy.</t>

<t>File descriptors make no good abstraction for automated protocol stack
instance selection as applications have to adopt to changed semantics,
e.g., whether message boundaries are preserved, depending on the
transport protocol chosen.</t>

<t>File descriptors make no good abstraction for destination instance
selection and path selection either.
Once a socket has been created, its protocol stack instance is fixed, so
selecting a path by binding to a local address and connecting to a destination
instance is now only possible using this protocol stack instance. If such a
connection attempt fails, it is possible to retry using another path and
destination, but changing the protocol stack instance requires creating a new
socket with a different file descriptor.</t>

<t>For further discussion of other asynchronous I/O weirdness with file
descriptors see end of <xref target="async-api"/>.</t>

</section>
<section anchor="async-api" title="Asynchronous API Anarchy">

<t>Network I/O is asynchronous, but asynchronous I/O within the POSIX
filesystem API is hard to use. There are at least three different
asynchronous I/O APIs for each operating system.</t>

<t>To implement asynchronous I/O for our Socket Intents prototype, we
wrapped one of the asynchronous I/O APIs that is available on most
platforms: <spanx style="verb">select()</spanx>.
To make Socket Intents accessible to more applications and on more
platforms, a production-grade system would need to wrap all
asynchronous I/O APIs and implement most of the socket creation logic,
path selection and connection logic within these wrappers.
However, mixing asynchronous I/O and multithreading may lead to
unintuitive behavior, e.g., calling our prototype’s select() from
different threads could lead to anything from deadlocks to busy waiting.</t>

<t>Another issue is that we use Unix domain sockets to communicate between
our Multiple Access Manager and the Socket Intents API library called
by the application, so we need to make sure that the application does
not block on communication with the Multiple Access Manager.</t>

<t>Also the problems with using file descriptors get even worse.
If a Socket API call should return immediately, it needs to provide the
application with a reference to a flow that has not yet been fully set
up, i.e., a reference to a “future” socket.
An implementation of such an asynchronous API has to return an
unconnected socket file descriptor, on which the application then
calls, e.g., <spanx style="verb">select()</spanx>, and starts using it once it becomes readable
and writable.
If the destination, path and transport protocol have not been chosen
yet at this point, the file descriptor returned by the implementation
might not yet have the final family and transport protocol.
When the implementation later creates the final socket of the right
type, it can re-bind it to the file-id of the originally returned
file descriptor using <spanx style="verb">dup2</spanx>.
This procedure can easily lead to time-of-check to time-of-use confusion.
To make things even worse, the application can copy the “future” file
descriptor using <spanx style="verb">dup</spanx>, which is rarely useful for sockets, but in
combination with file descriptors used as “future” it leads to unexpected
behavior.</t>

</section>
<section anchor="here-be-dragons-hiding-in-shadow-structures" title="Here Be Dragons hiding in Shadow Structures">

<t>The API variants described in <xref target="socketconnectapi"/> and <xref target="muacccontextapi"/>
need to keep a lot of state in shadow structures that cannot be passed
between the Socket API calls otherwise.
This state needs to be cleaned up when the last copy of the file
descriptor is closed or the last socket held for reuse has timed out.
In addition, access to these shadow structures has to be thread-safe.</t>

<t>Implementing both has turned out to be extremely error-prone and there
is a high amount of unspecified behavior and platform-dependent
extensions in the system library. These issues guarantee that an
implementation of transport option selection that nicely integrates with
BSD Sockets will come with lots of limitations and will not be portable
across POSIX-compliant operating systems.</t>

</section>
</section>
<section anchor="conclusion" title="Conclusion">

<t>Adding transport option selection to BSD Sockets is hard, as the API
calls are not designed to defer making and applying choices to a moment
where all information needed for transport option selection is
available.</t>

<t>After all, if limiting transport option selection to the granularity
BSD Sockets typically provide today (TCP connections and
UDP associations), the API variant described in <xref target="getaddrinfoapi"/>
seems to be a good compromise, even if it forces the application to try
all candidates itself (either in a sequential or partial parallel
fashion).
This option is easily deployable, but does not include automation of
techniques like connection caching or HTTP pipelining.</t>

<t>The most versatile API variant described in <xref target="socketconnectapi"/>
implements connection caching on the transport layer.
This comes at the cost of heavily modifying existing applications.
If feasible, given the unnecessary complexity of the file I/O
integration of BSD sockets, it seems easier to move to a totally
different system like <xref target="I-D.trammell-taps-post-sockets"/>.</t>

</section>
<section anchor="acknowledgments" title="Acknowledgments">

<t>The API variant described in <xref target="getaddrinfoapi"/> was originally drafted and implemented by Tobias Kaiser <eref target="mailto:mail@tb-kaiser.de">mail@tb-kaiser.de</eref> as part of his BA thesis.</t>

<t>This work has been supported by Leibniz Prize project funds of DFG - German Research Foundation: Gottfried Wilhelm Leibniz-Preis 2011 (FKZ FE 570/4-1).</t>

</section>


  </middle>

  <back>


    <references title='Informative References'>





<reference  anchor="RFC2119" target='https://www.rfc-editor.org/info/rfc2119'>
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author initials='S.' surname='Bradner' fullname='S. Bradner'><organization /></author>
<date year='1997' month='March' />
<abstract><t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t></abstract>
</front>
<seriesInfo name='BCP' value='14'/>
<seriesInfo name='RFC' value='2119'/>
<seriesInfo name='DOI' value='10.17487/RFC2119'/>
</reference>



<reference  anchor="RFC6824" target='https://www.rfc-editor.org/info/rfc6824'>
<front>
<title>TCP Extensions for Multipath Operation with Multiple Addresses</title>
<author initials='A.' surname='Ford' fullname='A. Ford'><organization /></author>
<author initials='C.' surname='Raiciu' fullname='C. Raiciu'><organization /></author>
<author initials='M.' surname='Handley' fullname='M. Handley'><organization /></author>
<author initials='O.' surname='Bonaventure' fullname='O. Bonaventure'><organization /></author>
<date year='2013' month='January' />
<abstract><t>TCP/IP communication is currently restricted to a single path per connection, yet multiple paths often exist between peers.  The simultaneous use of these multiple paths for a TCP/IP session would improve resource usage within the network and, thus, improve user experience through higher throughput and improved resilience to network failure.</t><t>Multipath TCP provides the ability to simultaneously use multiple paths between peers.  This document presents a set of extensions to traditional TCP to support multipath operation.  The protocol offers the same type of service to applications as TCP (i.e., reliable bytestream), and it provides the components necessary to establish and use multiple TCP flows across potentially disjoint paths.  This  document defines an Experimental Protocol for the Internet community.</t></abstract>
</front>
<seriesInfo name='RFC' value='6824'/>
<seriesInfo name='DOI' value='10.17487/RFC6824'/>
</reference>



<reference  anchor="RFC7413" target='https://www.rfc-editor.org/info/rfc7413'>
<front>
<title>TCP Fast Open</title>
<author initials='Y.' surname='Cheng' fullname='Y. Cheng'><organization /></author>
<author initials='J.' surname='Chu' fullname='J. Chu'><organization /></author>
<author initials='S.' surname='Radhakrishnan' fullname='S. Radhakrishnan'><organization /></author>
<author initials='A.' surname='Jain' fullname='A. Jain'><organization /></author>
<date year='2014' month='December' />
<abstract><t>This document describes an experimental TCP mechanism called TCP Fast Open (TFO).  TFO allows data to be carried in the SYN and SYN-ACK packets and consumed by the receiving end during the initial connection handshake, and saves up to one full round-trip time (RTT) compared to the standard TCP, which requires a three-way handshake (3WHS) to complete before data can be exchanged.  However, TFO deviates from the standard TCP semantics, since the data in the SYN could be replayed to an application in some rare circumstances.  Applications should not use TFO unless they can tolerate this issue, as detailed in the Applicability section.</t></abstract>
</front>
<seriesInfo name='RFC' value='7413'/>
<seriesInfo name='DOI' value='10.17487/RFC7413'/>
</reference>



<reference  anchor="RFC7556" target='https://www.rfc-editor.org/info/rfc7556'>
<front>
<title>Multiple Provisioning Domain Architecture</title>
<author initials='D.' surname='Anipko' fullname='D. Anipko' role='editor'><organization /></author>
<date year='2015' month='June' />
<abstract><t>This document is a product of the work of the Multiple Interfaces Architecture Design team.  It outlines a solution framework for some of the issues experienced by nodes that can be attached to multiple networks simultaneously.  The framework defines the concept of a Provisioning Domain (PvD), which is a consistent set of network configuration information.  PvD-aware nodes learn PvD-specific information from the networks they are attached to and/or other sources.  PvDs are used to enable separation and configuration consistency in the presence of multiple concurrent connections.</t></abstract>
</front>
<seriesInfo name='RFC' value='7556'/>
<seriesInfo name='DOI' value='10.17487/RFC7556'/>
</reference>



<reference anchor="I-D.tiesel-taps-socketintents">
<front>
<title>Socket Intents</title>

<author initials='P' surname='Tiesel' fullname='Philipp Tiesel'>
    <organization />
</author>

<author initials='T' surname='Enghardt' fullname='Theresa Enghardt'>
    <organization />
</author>

<author initials='A' surname='Feldmann' fullname='Anja Feldmann'>
    <organization />
</author>

<date month='October' day='28' year='2017' />

<abstract><t>This document outlines Socket Intents, a concept that allows applications to share their knowledge about upcoming communication and express their performance preferences in a generic, intuitive and, portable way.  Using Socket Intents, an application can express what it knows, assumes, expects, or wants regarding its network communication.  The information provided by Socket Intents can be used by the network stack to optimize communication in a best-effort way.  Socket Intent can be used to stem against the complexity of exploiting transport diversity, e.g., to automate the choice among multiple paths, provisioning domains or protocols.  By shifting this complexity from the application developer to the operating system, it enables the use of these transport features to a wider range of applications.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-tiesel-taps-socketintents-01' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-tiesel-taps-socketintents-01.txt' />
</reference>



<reference anchor="I-D.tiesel-taps-communitgrany">
<front>
<title>Communication Units Granularity Considerations for Multi-Path Aware Transport Selection</title>

<author initials='P' surname='Tiesel' fullname='Philipp Tiesel'>
    <organization />
</author>

<author initials='T' surname='Enghardt' fullname='Theresa Enghardt'>
    <organization />
</author>

<date month='May' day='2' year='2018' />

<abstract><t>This document provides an approach how to reason about the composition of multi-path aware transport stacks.  It discusses how to compose the functionality needed by stacking existing internet protocols and the fundamental mechanisms that are used in multi-path systems and the consequences of applying them to different granularities of communication units, e.g, on a message or stream granularity.  This document is targeted as guidance for automation of destination selection, path selection, and transport protocol selection.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-tiesel-taps-communitgrany-02' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-tiesel-taps-communitgrany-02.txt' />
</reference>



<reference anchor="I-D.trammell-taps-post-sockets">
<front>
<title>Post Sockets, An Abstract Programming Interface for the Transport Layer</title>

<author initials='B' surname='Trammell' fullname='Brian Trammell'>
    <organization />
</author>

<author initials='C' surname='Perkins' fullname='Colin Perkins'>
    <organization />
</author>

<author initials='T' surname='Pauly' fullname='Tommy Pauly'>
    <organization />
</author>

<author initials='M' surname='Kuehlewind' fullname='Mirja Kuehlewind'>
    <organization />
</author>

<author initials='C' surname='Wood' fullname='Christopher Wood'>
    <organization />
</author>

<date month='October' day='27' year='2017' />

<abstract><t>This document describes Post Sockets, an asynchronous abstract programming interface for the atomic transmission of messages in an inherently multipath environment.  Post replaces connections with long-lived associations between endpoints, with the possibility to cache cryptographic state in order to reduce amortized connection latency.  We present this abstract interface as an illustration of what is possible with present developments in transport protocols when freed from the strictures of the current sockets API.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-trammell-taps-post-sockets-03' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-trammell-taps-post-sockets-03.txt' />
</reference>

<reference anchor="ANRW17-MH" >
  <front>
    <title>Multi-Homed on a Single Link</title>
    <author initials="P." surname="Tiesel" fullname="Philipp S. Tiesel">
      <organization></organization>
    </author>
    <author initials="B." surname="May" fullname="Bernd May">
      <organization></organization>
    </author>
    <author initials="A." surname="Feldmann" fullname="Anja Feldmann">
      <organization></organization>
    </author>
    <date year="2016"/>
  </front>
  <seriesInfo name="Proceedings of the 2016 workshop on Applied Networking Research Workshop - ANRW" value="16"/>
  <seriesInfo name="DOI" value="10.1145/2959424.2959434"/>
</reference>


<reference anchor="ANRW18-Metrics" >
  <front>
    <title>Metrics for access network selection (ANRW 2018)</title>
    <author >
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>


    </references>


<section anchor="api-usage-examples" title="API Usage Examples">

<section anchor="classic_api_example" title="Usage Example of the Classic / muacc_context API">

<t>In this example, a client application sets up a connection to a remote host and sends data
to it. It specifies two Socket Intents on this connection: The Category of Bulk
Transfer and the File Size of 1 MB.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Create and initialize a context to retain information across function
// calls
muacc_context_t ctx;
muacc_init_context(&ctx);

int socket = -1;

struct addrinfo *result = NULL;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

// Set Socket Intents for this connection. Note that the "socket" is
// still invalid, but it does not yet need to exist at this time. The
// Socket Intents prototype just sets the Intent within the
// muacc_context data structure.

enum intent_category category = INTENT_BULKTRANSFER;
muacc_setsockopt(&ctx, socket, SOL_INTENTS,
    INTENT_CATEGORY, &category, sizeof(enum intent_category));

int filesize = LENGTH_OF_DATA;
muacc_setsockopt(&ctx, socket, SOL_INTENTS,
    INTENT_FILESIZE, &filesize, sizeof(int));


// Resolve a host name. This involves a request to the MAM, which can
// automatically choose a suitable local interface or other parameters
// for the DNS request and set other parameters, such as preferred
// address family or transport protocol.
muacc_getaddrinfo(&ctx, "example.org", NULL, NULL, &result);

// Create the socket with the address family, type, and protocol
// obtained by getaddrinfo.
socket = muacc_socket(&ctx, result->ai_family, result->ai_socktype,
    result->ai_protocol);

// Connect the socket to the remote endpoint as determined by
// getaddrinfo.  This involves another request to MAM, which may at this
// point, e.g., choose to bind the socket to a local IP address before
// connecting it.
muacc_connect(&ctx, socket, result->ai_addr, result->ai_addrlen);

// Send data to the remote host over the socket.
write(socket, &buf, LENGTH_OF_DATA);

// Close the socket. This de-initializes any data that was stored within
// the muacc_context.
muacc_close(&ctx, socket);

]]></artwork></figure>

</section>
<section anchor="getaddrinfo_api_example" title="Usage Example of the Classic / getaddrinfo API">

<t>As in <xref target="classic_api_example"/>, the application sets the Intents “Category” and “File Size”.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Define Intents to be set later
enum intent_category category = INTENT_BULKTRANSFER;
int filesize = LENGTH_OF_DATA;

struct socketopt intents = { .level = SOL_INTENTS,
    .optname = INTENT_CATEGORY, .optval = &category, .next = NULL};
struct socketopt filesize_intent = { .level = SOL_INTENTS,
    .optname = INTENT_FILESIZE, .optval = &filesize, .next = NULL};

intents.next = &filesize_intent;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

struct muacc_addrinfo intent_hints = { .ai_flags = 0,
    .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = 0,
    .ai_sockopts = &intents, .ai_addr = NULL, .ai_addrlen = 0,
    .ai_bindaddr = NULL, .ai_bindaddrlen = 0, .ai_next = NULL };

struct muacc_addrinfo *result = NULL;

muacc_ai_getaddrinfo("example.org", NULL, &intent_hints,
    &result);

// Create and connect the socket, using the information obtained through
// getaddrinfo
int fd;
fd = socket(result->ai_family, result->ai_socktype,
    result->ai_protocol);
muacc_ai_simple_connect(fd, result);

// Send data to the remote host over the socket, then close it.
write(fd, &buf, LENGTH_OF_DATA);
close(fd);

muacc_ai_freeaddrinfo(result);

]]></artwork></figure>

</section>
<section anchor="socketconnect_api_example" title="Usage Example of the Socketconnect API">

<t>As in <xref target="classic_api_example"/>, the application sets the Intents “Category” and “File Size”.
As we provide <spanx style="verb">-1</spanx> as socket, no we do not reuse existing connections.</t>

<figure><artwork type="C"><![CDATA[
#define LENGTH_OF_DATA 1048576

// Define Intents to be set later
enum intent_category category = INTENT_BULKTRANSFER;
int filesize = LENGTH_OF_DATA;

struct socketopt intents = { .level = SOL_INTENTS,
    .optname = INTENT_CATEGORY, .optval = &category, .next = NULL};
struct socketopt filesize_intent = { .level = SOL_INTENTS,
    .optname = INTENT_FILESIZE, .optval = &filesize, .next = NULL};

intents.next = &filesize_intent;

// Initialize a buffer of data to send later.
char buf[LENGTH_OF_DATA];
memset(&buf, 0, LENGTH_OF_DATA);

int socket = -1;

// Get a socket that is connected to the given host and service,
// with the given Intents
socketconnect(&socket, "example.org", 11, "80", 2, &intents, AF_INET,
    SOCK_STREAM, 0);

// Send data to the remote host over the socket.
write(socket, &buf, LENGTH_OF_DATA);

// Close the socket and tear down the data structure kept for it
// in the library
socketclose(socket);
]]></artwork></figure>

</section>
</section>
<section anchor="changes" title="Changes">

<section anchor="since-01" title="Since -01">
<t><list style="symbols">
  <t>Updated list of gathered path characteristics</t>
  <t>Reordered start of Policy section to make it clearer</t>
</list></t>

</section>
<section anchor="since-00" title="Since -00">
<t><list style="symbols">
  <t>Fixed Author’s affiliations and funding</t>
  <t>Fixed acknowledgments</t>
</list></t>

</section>
</section>


  </back>

<!-- ##markdown-source:
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
KELpgOZTXVHJj34zEbK5zXmRXjLdzgBdXolQgnEGF3Dm34tGHNlSkRthhnlE
PkcaIJwZBOrcvp9FhO6oxH3ETSejVzUT7KbdI9k3OjdHsdEBQ87CitzDQE04
0xOOa8eH0eNlY+qe+vykVRIfOBSbZNdpoC+yS9g0Oa7FuByzcj4OA2M92V/b
PW9B7DFP7QVzYW/k7OZnGAmP5Qk/vDhtEDisZH+d+viESDeDEwj+QOEP9oOd
Sc/fH4aifUaPch3JD0OFg3ukg+lWpHpmODqm1sXHh8NpPYxvZP4vnr5VMtH0
rbrpTW90lf7yV73p/0ftn/HjdrrR0syHseFPsdK/7isagvSla8dPCUdPLiZ8
1QtgRl4oFZF7ITbfGccfPAE2Mt++aKbiSDHXXiD51H09nNCNn4wOPfLTfDHa
Cftx5/IH9ujo4flRJflVjDqBcFRjRinKToWkL0DoduoOWlJPrfYUkDBa+tAs
UoJZVeV/XkmGVXNrXRe0ySL1Q/0KNcGirdC+w1nQGhhzh8YQWb5ID+KNWFTO
hZ1ogenJ9x0S/pOHLH+NbP/vFenH/C1wH7a7nB5eti2hJijfabveSxw8xHGi
uB5c93+M/f2vivhfFbFTRQz9d5r7WXwiwFedtDljH4jmQGEUPtFWIjRA8BPk
GX+qrXvm8StP4D1Ze3hIl76/T78eTCKN4bUQ70FH9dz/nzVoJYjjCOcpvmXA
SetuR4+3biOdt7MGA/jPt0gax2OBBV8wX0c5F0LukVRwmhBtO+eGi9P7hyq6
jJ3a15uUSxb9UYfwAY+xL8ThhTOnjXYkW493tJNZ3YbIOK+LLHROiyUZEKa+
30pNDPYU5Xz2eNusyup3ZNoviKCzKDeEoCU3H/ePJr2Y7f8HpxvjxQGOAAA=

-->

</rfc>

