Transport Layer
The transport layer is the one used most commonly by application programmers.
A transport layer API can be uniform for a wide variety of applications
whereas the underlying network technology might vary widely.
The transport layer entity (part of the kernel, separate networking
process, maybe even hardware) sits on top of the network layer, using its
services, but logically is in communication with the destination transport
entity. Thus we have our first glimpse of the big picture, from the physical
layer bit signals up to an application process.
Two hosts stacks and apps talking via them; logical and physical data flow.
By introducing the transport layer between the network layer and the
application, you make efficient, robust communication possible in the event
of problems in the subnets and WANs. Note that this isolation is still
valuable even when you have a reliable, connection-oriented service offered
by the network layer. When something goes wrong in the network (router
crashes, bad routing, loss of line, etc) the transport layer entities can
cope with the failure.
In order to get reliable and efficient use of the network for the application
processes, the transport layer faces many of the same issues as the data
link layer (flow control, error control, sequencing, etc). One big difference
that makes these issues harder to deal with is the storage capacity of
the subnet. Bits can't be stored on a wire between data link layers. But
a store-and-forward packet switched network can keep packets around for
some time, maybe after their associated timer has expired, before they
are suddenly delivered.
The most common combination is an unreliable network layer with a reliable
transport layer service offered to programmers. The programmers view in
this case is a byte pipe between two processes on machines on the network.
Tanenbaum calls the units exchanged by the transport layer entities
TPDU (transport protocol data units), to distinguish them from packets
(network layer) and frames (data link layer) and bit streams (physical
layer). TCP calls them segments.
Services offered
Reliable, connection-oriented
A minimal set of services offered by a reliable, connection-oriented transport
layer would include a means of 1) waiting for a connection, 2) initiating
a connection, 3) sending and receiving data, and 4) disconnecting.
Reliability is created by uniquely identifiying each segment. This allows
for the detection of duplicates and the identification of missing segments.
Unreliable, connection-less (datagram)
A minimal set of services offered by a unreliable, connection-less transport
layer includes only a means of sending and receiving data. Note how much
simpler this is because of lack of connection.
Note the overloaded use of the term datagram. Here it is for a transport
level service. In the network layer it refers to the philosophy of the
network.
Effect of network layer services
How easy or hard it is to offer these services depends on the underlying
network layer. For example, with an unreliable, best effort network layer,
there is a lot of work to do in the transport layer to provide a reliable
service. The unreliable service is trivial. This is the case with the Internet
protocols.
With a reliable network, such as ATM, it is much easier to provide a
reliable service, and doesn't make any sense to have an unreliable service.
It is interesting to think about the wasted effort and space implicit in
a reliable transport service built on top of a reliable network.
Addressing
In the same way that a single physical medium must be multiplexed at times,
the protocol stack in a host must be multiplexed, or shared, by many application
processes at once. This means the network layer address (e.g. IP address)
isn't sufficient to identify the process using a transport layer connection
(e.g. a socket). Tanenbaum calls these end point address TSAP (transport
service access points). One way of seeing why a unique TSAP is necessary
is to ask yourself the question, "to which process does a transport TPDU
get delivered when it arrives?"
In the Internet suite the multiplexing of TCP segments is done by port
numbers. Each process using a socket is given a unique (to that machine)
port number. Then the combination of IP address + port number is a unique
identifier for that process.
How does a client process know the TSAP of a server process? Some possibilities
-
TSAPs are well-known, documented, static. Works ok for basic sorts of services
that all servers provide. Example would be Internet well-known services
(ports below 1024).
-
A TSAP server runs on a well-known TSAP. A protocol is used for clients
to query the TSAP server to find the TSAP given a name for the service.
This is like a name server. The services are identified by string names,
the name server returns the TSAP (e.g. a port number).
-
A metaserver is used for the initial connection. The metaserver (server
server, or super server) answers requests on many TSAPs, starts the proper
server process, then gives the incoming connection to the new process.
This also saves having to launch many infrequently used server processes.
The Internet inetd is an example of this.
Connecting
The three-way handshake is a connection establishment protocol. Each host
uses a different starting sequence number. Sequence numbers must uniquely
identify packets, with no potential for duplication because of delaye packets.
Consider three scenarios.
Host 1 sends CONN REQ containing sequence number x to host
2.
Host 2 sends ACCEPT to host 1 containing an ACK for x, and proposing
sequence number y.
Host 1 sends first DATA TPDU numbered x, ACK for seq num y.
Host 1 selects x knowing that no other TPDUs numbered x can be outstanding.
Similarly for host 2 and y.
Packet storage and duplicates
Reliability is made more difficult by the fact that packets can be stored
in the network. A delayed packet may be duplicated by a host since its
timer may expire causing a resend. What happens when a duplicate packet
arrives? How does the receiver know it's a duplicate?
Delayed duplicates are bad for connecting since the initial request
to connect may be delayed and duplicated.
The problem is more manageable if you can put a bound on the time which
a packet can live in the network. There are three ways to achieve this:
-
restricted subnet design - requires central control of the net, coordinated
changes, careful and limited design.
-
hop counters - each router decrements hop count. When count reaches zero
the packet is discarded. IP uses this.
-
timestamping - simple idea, requires reasonably accurate global clock.
Throw away old packets.
Knowing an upper bound for the life of a packet in the network allows you
to use sequence numbers and clocks to identify delayed duplicates. The
sequence number for a packet is chosen based on a time-of-day clock (a
counter that is regularly incremented). Rules are established for picking
sequence numbers such that each transport entity can detect illegal sequence
numbers. The sequence numbers must be large enough to ensure that no two
outstanding TPDUs have the same sequence number.
Duplicate CONN REQ
A delayed duplicate CONN REQ containing sequence number x arrives to host
2.
Host 2 sends ACCEPT to host 1 containing an ACK for x, and proposing
sequence number y.
Host 1 detects illegal seq num x being acknowledged, so REJECTs request.
Host 2 receives REJECT and figures out it was fooled by delayed duplicate,
so drops any further effort.
Duplicate CONN REQ and DATA ACK
A delayed duplicate CONN REQ containing sequence number x arrives to host
2.
Host 2 sends ACCEPT to host 1 containing an ACK for x, and proposing
sequence number y.
Host 2 receives a delayed duplicate DATA TPDU for x, with an ACK for
seq num z. Host 2 knows this is bad since it proposed y, not z. Host 2
discards this TPDU.
Host 1 sends REJECT for the ACCEPT sent for the first duplicate, since
it detects illegal sequence number x.
Host 2 receives REJECT and figures out it was fooled by delayed duplicate,
so drops any further effort.
Disconnecting
Dropping connections isn't trivial either, as it turns out. An asymetric
release means that either host can destroy the connection (like hanging
up the telephone). But data can be lost since there is no coordination
between parties, so data that is "in the pipe" is lost once the connection
is destroyed. Symmetric release requires both parties to agree to a release.
If both parties know they are done sending data, and agree, then no data
is lost.
A famous problem deals with the failure of this sort of protocol. The
problem is determining when the blue armies should attack the white army.
If you substitue "drop connection" for "attack" you have the problem that
interests us.
Two army problem
White army in valley. Blue arm in hills on either side of valley. White
army can defeat either blue army in isolation, but blue armies together
can defeat white army. How do the blue armies coordinate an attack on the
white army? Their only communication is via messenging through the valley
where messengers may be lost (i.e. an unreliable channel).
Blue army #1 sends message: attack at time X. Blue army #2 receives
this message and sends an acknowledgment to it. Does the attack happen
at time X? No, since blue army #2 can't know that it's ack was received.
Adding an ack to the ack (three-way handshake) doesn't help, since now
blue army #1 doesn't know if his ack to the ack got through, and if it
didn't blue army #2 won't attack, so blue army #1 shouldn't attack either.
You can prove that no protocol can solve this problem. Suppose such
a protocol existed. The last message sent is either essential or it is
not. If it is not, it can be lost or dropped with no adverse affect. Drop
all non-essential messages. Now all messages remaining are essential. What
if the last message is lost? Since it is essential, the protocol fails.
So we have a contradiction.
Timers are used in practice to make conclusions about when it is safe
to drop connections. See TCP example.