Subject: [Sip] Dedicated Review: draft-ietf-rohc-sigcomp-sip-03

From: Adam Roach <[email-masked]>
Date: Tue, 31 Oct 2006 10:04:49 -0600

I have been asked to perform a dedicated review on the document 
draft-ietf-rohc-sigcomp-sip-03. My comments follow. Note that I have 
implemented this specification, any many of my comments arise from 
issues I identified during such implementation.

------------------------------------------------------------------------

Remote identifiers in outgoing requests: The current document uses the 
"+sip.instance" Contact header-field parameter (if present) to identify 
compartments, and the sigcomp-id parameter otherwise. Page 9 contains 
specific text that specifies that senders SHOULD NOT include a 
sigcomp-id parameter if the URI is being conveyed in a SIP contact 
header field which includes a "+sip.instance" parameter.

Unfortunately, this doesn't work very well in practice; the root cause 
of the problems that arise is that the ability to receive compressed 
messages is fundamentally tied to the URI. Semantically separating the 
compartment identifier from the URI breaks this a bit.

So, for example, if I were to fit this into the resiprocate code base, I 
would need to perform all manner of cross-layer plumbing and make some 
really ugly SigComp-related hacks all the way up in the registry code.

The problems that arise, however, are probably best demonstrated using a 
network in which the proxy that performs SigComp compression and 
decompression is not the same network element as the registrar.

User Agent          Edge Proxy        Proxy Registrar
     |                   |                   |
     |                   |                   |
     |                   |                   |
     |REGISTER           |                   |
     |------------------>|                   |
     |Contact: <sip:user@ua;comp=sigcomp>;+sip.instance=<uuid>
     |                   |                   |
     |                   |REGISTER           |
     |                   |------------------>|
     |                   |Contact: <sip:user@ua;comp=sigcomp>;
     |                   |         +sip.instance=<uuid>
     |                   |Path: <sip:edgeproxy>
     |                   |                   |
     |                   |200                |
     |                   |<------------------|
     |                   |Path: <sip:edgeproxy>
     |                   |                   |
     |200                |                   |
     |<------------------|                   |
     |Path: <sip:edgeproxy>                  |
     |                   |                   |

                     Time Passes

User Agent          Edge Proxy        Proxy Registrar
     |                   |                   |
     |                   |                   |<-- INVITE --
     |                   |                   |
     |                   |INVITE sip:user@ua;comp=sigcomp
     |                   |<------------------|
     |                   |Route: <sip:edgeproxy>
     |                   |                   |
     |                   |                   |
     |INVITE sip:user@ua;comp=sigcomp        |
     |<------------------|                   |
     |How does the EP know which compartment to use?
     |                   |                   |
     |                   |                   |
     |                   |                   |

Here, the problem arises because the Contact header field parameter 
isn't visible to the edge proxy on subsequent messages. Once again, the 
fundamental issue here is that the compartment identifier really needs 
to be an integral part of the URI, as opposed to a header field parameter.

I would propose removing the use of +sip.instance for compartment 
identification at all.

That said, the draft should point out the value of using the same 
identifier for the +sip.instance parameter on the Contact header field 
and the sigcomp-id on the URI in the contact header: by using the same 
identifier in both places, you'll get *really* good compression of the 
second one in almost all compression schemes. (In other words: 'Contact: 
<sip:user@host;comp=sigcomp;sigcomp-id=urn%3auuid%3a0C67446E-F1A1-11D9-94D3-000A95A0E128>;+sip.instance="<urn:uuid:0C67446E-F1A1-11D9-94D3-000A95A0E128>"' 
will compress pretty well because of the high degree of redundancy).

------------------------------------------------------------------------

Identification of messages in incoming requests without a "sigcomp-id" 
parameter: the draft currently says that these should be identified by 
the "sent-by" parameter of the top most Via header field, for legacy 
compatibility.

This raises a few issues.

First: this should almost certainly be "the received parameter, if 
present; and the sent-by field otherwise." In particular, an edge proxy 
is likely to see a *TON* of devices that have placed, e.g., 
"192.168.0.100" (or choose any other NAT default DHCP address) in the 
sent-by field. They will not all correlate to the same user agent.

Second: the draft doesn't indicate whether the port number should be 
taken into account.

Finally, in legacy applications, my experience (from SIPits) is that the 
predominant legacy means of compartment identification is to use the IP 
Address/Port for datagram messages, and the actual TCP connection itself 
for stream messages. I would propose that we will achieve the greatest 
compatibility with legacy applications if we use the same scheme.

------------------------------------------------------------------------

Outgoing responses: Because of the way SIP handles Via header fields, 
any compartment identifier present in the Via header field for an 
inbound request will be copied into the outgoing response. This might 
not be immediately obvious to implementors, so it probably bears 
mentioning. e.g:

   Outgoing responses: the remote application identifier is the same as
      the previously-received request that initiated the transaction the
      response belongs to. Note that, due to standard SIP Via header field
      processing, this identifier will be present in the top-most Via
      header field in such responses.

------------------------------------------------------------------------

Although not a bug in the draft per se, in implementing this 
specification, I encountered an interesting situation: the use of the 
"comp=sigcomp" parameter on URIs used in Record-Route requires 
considerable thought, and should probably be discussed in the draft. In 
particular, a proxy wants to advertise the route towards the client as 
supporting SigComp; however, advertising the route towards the core of 
the network might lead to the unfortunate case in which proxies in the 
core of the network are using SigComp to talk to each other. 
Consequently, proxies that implement this mechanism will want to insert 
two route headers in dialog-establishing requests: the one towards the 
client will indicate "comp=sigcomp" on its URI; while the other one will 
not.

------------------------------------------------------------------------

I'm having a lot of difficulty parsing the final paragraph in section 3.2:

   Compressors that make use of initial state memory MUST implement the
   SigComp Negative Acknowledgement (NACK) Mechanism [RFC4077].  (Note
   that there is no such requirement on decompressors, but see also
   Section 6.)  For this requirement, initial state memory is defined as
   the assumption of a non-zero SMS value before having received an
   advertisement of non-zero SMS (e.g., via returned parameters as
   specified in section 9.4.9 of [RFC3320]); ANY/SigComp as defined in
   [RFC3320] does not have initial state memory.

There are two separate points of confusion for me:

   1. I don't understand the assertion that decompressors don't need to
      implement RFC 4077. Decompressors serve the critical role of
      generating NACK messages when decompression fails. (And, in fact,
      text at the end of section 6.3 implies that NACK implementation is
      required in decompressors as well).

   2. The document has already established that stateless compression
      (i.e., compression that doesn't take advantage of initial state
      memory) is pointless for SIP endpoints -- so the clause
      "Compressors that make use of initial state memory" pretty much
      collapses to just "Compressors."

So, unless I've missed something, this paragraph should be rewritten as:

    SIP/SigComp endpoints MUST implement the SigComp Negative
    Acknowledgement (NACK) Mechanism [RFC4077].

It's not clear that it belongs in section 3.2 after being simplified; in 
fact, it seems to be redundant with the entire contents of section 3.4.

------------------------------------------------------------------------

Section 6.1: This section asserts that the URN used to identify 
compartments MUST be persistent across reboots. While this isn't 
necessarily a *harmful* property, I don't understand its utility. In 
particular, this requirement adds additional implementation complexity 
to edge proxies that wouldn't otherwise have to persist this information.

Thinking about this from another angle: if an implementation isn't 
persisting compartment *STATES* across reboots, what value is there in 
persisting compartment *IDENTIFIERS* across reboots?

------------------------------------------------------------------------

Nit: for clarity, the ANBF describing the SIP URI sigcomp-id parameter 
should probably call it something like "uri-sip-sigcomp-id" instead of 
just "sip-sigcomp-id" (to better distinguish it from "via-sip-sigcomp-id").

------------------------------------------------------------------------

Nit: The angle brackets for the via header field parameter sigcomp-id 
seem superfluous -- or, at the very least, redundant with the quotation 
marks. I suspect this syntax was "borrowed" from the 
draft-ietf-sip-outbound syntax for "+sip.instance", which, in turn, is 
dictated by RFC 3840. RFC 3840 includes this notation because the 
"+sip.instance" string, when used with callee caps, is used for equality 
comparison as a quoted string:

   If the filter is an equality over a quoted string, the output is a
   less than (<), followed by the quoted string, followed by a greater
   than (>).

This doesn't apply to what we're doing here, so the angle brackets don't 
seem necessary.

------------------------------------------------------------------------

Nit: The example of a sigcomp-id parameter on page 8 uses a colon 
instead of an equals sign after "sigcomp-id".

------------------------------------------------------------------------

There is text on page 11 (starting "As there is no way to signal...", 
and continuing to the end of the paragraph) which appears to be 
obsoleted by section 3.4.

------------------------------------------------------------------------

The first two paragraphs of section 6.5 talk about the mechanisms by 
which registrars can be non-adjacent to the registering user agent in a 
network.

The third paragraph then seems to make an assumption that registrars 
must always be adjacent to the registering user agent -- it assumes that 
the "SIP application generating a 200 response for a REGISTER" is also 
the node performing compression.

Beyond this point, I think I simply don't understand what the third 
paragraph is trying to say. I think the text needs to be cleaned up 
significantly.

Finally, in the case of non-adjacent registrars, section 6.5 appears to 
require the edge proxy (that is, the proxy implementing SigComp) to 
track registration state. If this is the intention, it should be 
explicitly called out.

------------------------------------------------------------------------

Similar to section 6.5: section 6.6 requires proxies that perform 
SigComp compression to become both dialog stateful, including tracking 
of multiple usages within a dialog. This verges on terrifying, from an 
implementation perspective.

------------------------------------------------------------------------

Section 6.3 through 6.6 in general: I think we're making this much more 
complicated than it needs to be.

Compression for a single transaction will never be a win. Bytecode 
overhead will eat any savings on the request; then, bytecode overhead 
will eat any savings on the response. Then, the transaction will be 
over. In practice, I've never seen a case in which these first messages 
don't expand. So, overall, opening a compartment for a single 
transaction will be a net loss. You're better off not compressing.

Compression for a dialog, for similar reasons, is likely to be a wash in 
most cases. In particular, one of the strongest motivators for SigComp 
in current applications is reduction of call setup times. If you're 
expanding the first message sent in either direction, you lose this 
advantage altogether.

So, in practice, the only construct that really seems to make much sense 
for compartment lifetime is registration.

I would argue that we should describe the compartment lifetime as being 
bound to a registration (with the option to keep them open longer), and 
leave it at that.

------------------------------------------------------------------------

The description of service route and path handling in the example is 
confusing at best; I think it's probably outright inaccurate:

   When the outbound proxy receives a 200 (OK) response (3) for the
   REGISTER request, it constructs the route future incoming requests
   will follow (using the Contact and the Path header fields) and the
   route future outgoing requests will follow (using the Contact and the
   Service-Route header fields).  Both the Path and the Service-Route
   header fields contain the outbound proxy's URI.  The Contact header
   field contains the user agent's URI, which carries the user agent's
   SIP/SigComp identifier 'UA-id'.

The problem that I see with this text is that it implies that the 
outbound proxy is somehow in charge of storing the Path and the 
Service-Route for the duration of the registration. In practice, the 
User Agent stores the Service-Route, and the registrar (or some adjunct 
proxy to the registrar) stores the Path. The only role the outbound 
proxy can play in this is by inserting itself into the Service-Route and 
Path at registration time. For the Path, this is done when the REGISTER 
message passes through it, not when the 200 response to the REGISTER 
passes through it. For Service-Route, RFC 3608 is very clear that the 
outbound proxy can't play a role in the construction of the service 
route (see section 6.2 of RFC 3608).

Continuing:

   On receiving the 200 (OK) response (4), the user agent constructs the
   route future incoming requests will follow (using the Path header
   field) and the route future outgoing requests will follow (using the
   Service-Route header field).  The user agent is supposed to open a
   new compartment for 'Outbound-id' for the duration of the
   registration, as discussed in Section 6.4.  However, since the user
   agent has already a compartment for 'Outbound-id', it reuses that
   comparment, as discussed in Section 6.3.

The user agent doesn't use the Path header field for anything (RFC 3327, 
section 5.1: "The general operation of the UA is to ignore the Path 
header field in the response.")

------------------------------------------------------------------------

Nit: The example section really should include at least one 
representative SIP message demonstrating the syntax of the new 
parameters. Here's one you can use (making some assumptions about the 
resolution of points I raised above):

    REGISTER sip:estacado.net SIP/2.0
    Via: SIP/2.0/UDP 192.0.2.247:2078;branch=z9hG4bK-et736vsjirav;
         rport;sigcomp-id="urn:uuid:2e5fdc76-00be-4314-8202-1116fa82a473"
    From: "Joe User" <sip:[email-masked]>;tag=6to4gh7t5j
    To: "Bob User" <sip:[email-masked]>
    Call-ID: 3c26700c1adb-lu1lz5ri5orr
    CSeq: 215196 REGISTER
    Max-Forwards: 70
    Contact: <sip:[email-masked]:2078;
             sigcomp-id=urn%3auuid%3a2e5fdc76-00be-4314-8202-1116fa82a473">;
             q=1.0;
             +sip.instance="<urn:uuid:2e5fdc76-00be-4314-8202-1116fa82a473>"
    Expires: 60
    Content-Length: 0

------------------------------------------------------------------------

Appendix A is a cut-and-paste from draft-ietf-rohc-sigcomp-impl-guide, 
which will almost certainly beat draft-ietf-rohc-sigcomp-sip to RFC. I 
think you really just want a normative reference to 
draft-ietf-rohc-sigcomp-impl-guide to refer to the well-known shim. 
(This also impacts the final paragraph of section 4).

------------------------------------------------------------------------

Please discuss on the ROHC mailing list, as this is a ROHC working group 
item.

/a

_______________________________________________
Sip mailing list  https://www1.ietf.org/mailman/listinfo/sip
This list is for NEW development of the core SIP Protocol
Use [email-masked] for questions on current sip
Use [email-masked] for new developments on the application of sip

---

From: Adam Roach <[email-masked]>
Date: Tue, 31 Oct 2006 12:35:20 -0600

Adam Roach wrote:
> In practice, the User Agent stores the Service-Route, and the 
> registrar (or some adjunct proxy to the registrar) stores the Path. 
> The only role the outbound proxy can play in this is by inserting 
> itself into the Service-Route and Path at registration time.

I messed this up.  The outbound proxy can't insert itself into the 
Service-Route; it can only insert itself into the Path.

/a