Subject: [dcp] Comments and Question Re: DCP drafts

From: "Patrick R. McManus" <[email-masked]>
Date: Wed, 17 Apr 2002 15:32:24 -0400

Hi All,

I've read through the dcp drafts (dcp-02, ccids, and the problem
document) and have a collection of questions, observations, and
editorial comments to make.

First, the easy stuff (editorial comments):

p 14, # NDP - "A non-data packet is simply any packet not containing
        user data; Data-Ack packets are the canonical example."
	
	I believe this should be "DCP-Ack packets are the canonical
        example."

p 7, sec 3.3 - "reasonable time, allowing old segments to
        clear".. this is the only time in the document that the word
        segment occurs. DCP lingo seems to be packet (else segment
        needs to be defined).

-----

observation - acks of acks are a pretty non-intuitive concept if
you're starting with TCP as your knowledge base (likely the case if
people use the rfc to implement the protocol). While reading the
drafts I wondered for a very long time if an established DCP session
under CCID 2 could ever go totally idle - or if the hosts would have
to be sending dcp-ack back and forth every rtt. I now understand why
this is not so, but the heavy dusting of "acks for acks" language
throughout the document before discussion of this at the very end was
the most confusing part of a document that, overall, was very clear
and useful. There are a number of references to "at least one ack per
round trip time" that can imply this case for the sloppy (or perhaps
just first-time) reader (aka me). 

It became clear for me in section 4.3 of the ccid2 document, after I'd
read the whole dcp doc as well. My a-ha moment was realizing that the
purpose of acking an ack was to shrink a stored ack vector state - and
if the sender was quiet then the corresponding vector couldn't be
growing and therefore doesn't really need to be shrunk.

Perhaps some high level discussion of the way acks differ from dhcp
needs to make it earlier in the document - my first question mark
appeared in section 4.1.1 where it said "Some of these data packets
are DCP-DataAck packets acknowledging data and/or ack packets from the
client.", and there were many more big question marks in the margin
before it sunk in.

--

observation 2 - I like the service name addition to the rcp-request
packet. This greatly expands the namespace at a well known service
point.

--

observation 3 - This is really an API comment, and I know dealing with
API issues is tricky and/or inappropriate - but I think this comment
can be dealt with in the sense that the PMTU section does. Its going
to take me a couple paragraphs to get to my point.

It seems obvious to me that one API for DCP looks a lot like
UDP.. socket(AF_INET, SOCK_DCP, 0), recv(), send(), setsockopt(),
close(), etc.. This is particularly impt for 'reluctant applications'
currently using udp but not using cong control.

one of the reasons that apps avoid tcp today is its in-order property
wherein a sequence of 1,2,4 that is recvd will only give the
application pkts 1 and 2 until 3 is obtained. By the time 3 arrives 4
may have lost its value alltogether. DCP solves that nicely.

However, if cwnd is limiting the sending rate a similar q'ing problem
can result inside the dcp-sender's buffer. If the sender is only able
to trickle data out - the application may wish to throw away pending data
and just move on to more current stuff. 

I mention this because when programming with UDP you don't really
consider the case of send() to be signifcantly delayed at your
host. Creating a large q of data (where you had been counting on a
fraction of those packets to be dropped due to congestion you
induced!) could be a real problem. Under UDP the message might be
dropped, but not delayed beyond the needs of the transmission
medium. So this could really inhibit porting of applications that just
blast N kbit/s of data, expecting the bottleneck bandwidth to get
through and the backlog to simply be dropped as you go along.

A setsockopt() that causes send() to fail or block (or one for each!)
if new writes would be delayed by the ccid would seem to be critical
to porting current UDP based programs. Providing a mechanism to
determine if writes would be delayed by a cc policy could be a MUST in
the same sense that section 10 makes it a MUST to "allow the
application to discover DCP's current PMTU"

-----

question - for experimentation purposes is this envisioned as being
built on top of udp, IP, or ???? - has a convention been established
for port numbers or protocol numbers?

-Patrick

_______________________________________________
dcp mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/dcp

---

From: Eddie Kohler <[email-masked]>
Date: Thu, 25 Apr 2002 18:42:10 -0700

Hi Patrick, thanks very much for your comments!

> you're starting with TCP as your knowledge base ...

Totally fair observation. I've rewritten the most relevant section of the
DCCP draft; it's included below. Let us know if that helps.

> API issues is tricky and/or inappropriate - ...

Another fair observation, and not inappropriate at all. We are concerned
about balancing the needs for kernel buffering, to achieve reasonable
utilization, and responsive feedback, so old useless data doesn't get sent.
We're considering a mechanism like the sockopt() you suggest, as well as
other mechanisms, including maybe a callback design.

> for port numbers or protocol numbers?

We're envisioning it as on top of IP, parallel with UDP, although of course
layering over UDP is possible for experiments. As far as numbers go, Jon
Crowcroft kindly 'lent' the IP protocol number 33 to us for
experimentation.

Eddie

7.1.  Acks of Acks and Unidirectional Connections

    DCCP was designed to work well for both bidirectional and
    unidirectional flows of data, and for connections that transition
    between these states.  However, acknowledgements required for a
    unidirectional connection are very different from those required for
    a bidirectional connection. In particular, unidirectional
    connections need to worry about acks of acks.

    The ack-of-acks problem arises because some acknowledgement
    mechanisms are reliable. For example, an HC-Receiver using CCID 2,
    TCP-like Congestion Control, sends Ack Vectors containing completely
    reliable acknowledgement information. The HC-Sender should
    occasionally inform the HC-Receiver that it has received an ack. If
    it did not, the HC-Receiver might resend complete Ack Vector
    information, going back to the start of the connection, with every
    DCCP-Ack packet! However, note that acks-of-acks need not be
    reliable themselves: when an ack-of-acks is lost, the HC-Receiver
    will simply maintain old acknowledgement-related state for a little
    longer. Therefore, there is no need for acks of acks of acks.

    When communication is bidirectional, any required acks of acks are
    automatically contained in normal acknowledgements for data packets.
    On a unidirectional connection, however, the receiver DCCP sends no
    data, so the sender would not normally send acknowledgements.
    Therefore, the CCID in force on that half-connection must explicitly
    say whether, when, and how the HC-Sender should generate acks of
    acks.

    For example, consider a bidirectional connection where both half-
    connections use the same CCID (either 2 or 3), and where DCCP B goes
    *quiescent*. This means that the connection becomes unidirectional:
    DCCP B stops sending data, and sends only sends DCCP-Ack packets to
    DCCP A. For CCID 2, TCP-like Congestion Control, DCCP B uses Ack
    Vector to reliably communicate which packets it has received. As
    described above, DCCP A must occasionally acknowledge a pure
    acknowledgement from DCCP B, so that DCCP B can free old Ack Vector
    state. For instance, DCCP A might send a DCCP-DataAck packet every
    now and then, instead of DCCP-Data. In contrast, for CCID 3, TFRC
    Congestion Control, DCCP B's acknowledgements need not be reliable,
    since they contain cumulative loss rates; TFRC works even if every
    DCCP-Ack is lost. Therefore, DCCP A need never acknowledge an
    acknowledgement.

    When communication is unidirectional, a single CCID---in the
    example, the A-to-B CCID---controls both DCCPs' acknowledgements, in
    terms of their content, their frequency, and so forth. For
    bidirectional connections, the A-to-B CCID governs DCCP B's
    acknowledgements (including its acks of DCCP A's acks), while the B-
    to-A CCID governs DCCP A's acknowledgements.

    DCCP A switches its ack pattern from bidirectional to unidirectional
    when it notices that DCCP B has gone quiescent. It switches from
    unidirectional to bidirectional when it must acknowledge even a
    single DCCP-Data or DCCP-DataAck packet from DCCP B. (This includes
    the case where a single DCCP-Data or DCCP-DataAck packet was lost in
    transit, which is detectable using the # NDP field in the DCCP
    packet header.)

    Each CCID defines how to detect quiescence on that CCID, and how
    that CCID handles acks-of-acks on unidirectional connections. The B-
    to-A CCID defines when DCCP B has gone quiescent. Usually, this
    happens when a period (for CCID 2, roughly two round-trip times) has
    passed without B sending any data packets.  The A-to-B CCID defines
    how DCCP A handles acks-of-acks once DCCP B has gone quiescent.