Subject: [sipcore] Happy Eyeballs for SIP

From: [email-masked] (Dale R. Worley)
Date: Fri, 12 Feb 2016 14:58:58 -0500

Is anyone considering writing up the actual use of Happy Eyeballs in a
SIP context?

Does anyone have any practical experience or suggestions for what HE in
SIP would be?

Dale

---

From: Jonathan Lennox <[email-masked]>
Date: Fri, 12 Feb 2016 20:12:17 +0000

> On Feb 12, 2016, at 2:58 PM, Dale R. Worley <[email-masked]> wrote:
> 

If parallel forking worked, forking to the v4 and v6 addresses (with the usual timing rules Happy Eyeballs advises) would seem to do exactly what we want — 3261’s Merged Request rules would take care of the duplicated requests.

Unfortunately, the world of B2BUAs largely breaks parallel forking.

Is there any way to unbreak it enough so as to say that if you support incoming Happy Eyeballs, you have to have request merging working?

---

From: "Olle E. Johansson" <[email-masked]>
Date: Fri, 12 Feb 2016 23:10:39 +0100

> On 12 Feb 2016, at 20:58, Dale R. Worley <[email-masked]> wrote:
> 

After discussing this for many years with many people this is my conclusion:

For connection oriented protocols - just point to existing RFC for happy eyeballs.

For UDP we have no solution, period. The only way is to handle this in DNS SRV
and have separate priorities for IPv4 and IPv6 in the order the service likes.
This is why we have tested DNS SRV with dual stacks in many SIPits and written the draft about 
dual stack issues - many IPv4 only clients crashed or failed when the first SRV priority
did not have IPv4 addresses at all. They also crashed when IPv6 was in various headers,
as documented in https://tools.ietf.org/html/draft-klatsky-dispatch-ipv6-impact-ipv4-03

One has to remember that the IPv4 and IPv6 address for a dual stack server may lead
to different servers, thus sending a UDP message at the same time to both may cause
multiple transactions and all kinds of interesting side effects. (Hadriel Kaplan reminded
me of this).

So the documentation on Happy Eyeballs in sip is pretty short: Don’t try this with UDP.
Solve the problem another way. (in fact, move to TCP/TLS as soon as you can :-) )

If someone has a cool solution to this UDP issue - preferably without loosing one round trip -
I would be more than happy to hear it!

/O

---

From: Jonathan Lennox <[email-masked]>
Date: Mon, 15 Feb 2016 19:50:39 +0000

On Feb 12, 2016, at 5:10 PM, Olle E. Johansson <[email-masked]<mailto:[email-masked]>> wrote:

On 12 Feb 2016, at 20:58, Dale R. Worley <[email-masked]<mailto:[email-masked]>> wrote:

Most of these problems are going to be true for TCP IPv6 too, aren’t they? Happy Eyeballs doesn’t make the problem worse.  If there are buggy implementations out there, this is something that you’re presumably either going to have to have the implementers fix, or else clean up with SBCs.

The “may lead to different servers” issue is under the control of the person setting up the SRV records for the SIP server, though.

So it should be possible, I think, to say that you can set up DNS records for UDP happy eyeballs only if either 1) you personally can handle merged request detection for all requests to a target, or 2) you are a pure 3261 proxy and also can guarantee that there are no B2BUAs (that modify From tag, Call-ID, or CSeq) or Gateways downstream of you.  If this is the case, then forking the SIP request to the v4 and v6 addresses would accomplish happy eyeballs.

I don’t know if this is a large enough subset of SIP environments to be interesting, though.

---

From: "Olle E. Johansson" <[email-masked]>
Date: Wed, 17 Feb 2016 16:38:45 +0100

> On 15 Feb 2016, at 20:50, Jonathan Lennox <[email-masked]> wrote:
> 
> 
>> On Feb 12, 2016, at 5:10 PM, Olle E. Johansson <[email-masked] <mailto:[email-masked]>> wrote:
>> 
>> 
>>> On 12 Feb 2016, at 20:58, Dale R. Worley <[email-masked] <mailto:[email-masked]>> wrote:
>>> 
>> as documented in https://tools.ietf.org/html/draft-klatsky-dispatch-ipv6-impact-ipv4-03 <https://tools.ietf.org/html/draft-klatsky-dispatch-ipv6-impact-ipv4-03>
> 
Oh yeah, these problems are for locating SIP servers, the stuff you do when you
build a list. It applies to all, but is critical for UDP.

> The “may lead to different servers” issue is under the control of the person setting up the SRV records for the SIP server, though.
Yes. The reason I brought it up is that many proposals for solving this for UDP has failed
on exactly that case.

> I don’t know if this is a large enough subset of SIP environments to be interesting, though.
I personally don’t think we should go down that road. We end up in discussions about multiple edge proxies with SIP outbound and without outbound and a large number of variations to SIP platform architectures. There are so many ways one can fail, even though there is a possibility of finding something that works. We may write “there may be other solutions to this problem, but this is our recommendation” to avoid falling into that can of worms.

What we can state is that finding the fastest network path by using something like Happy Eyeballs connection testing does not work over UDP.  

To handle UDP and dual stack clients and servers, we need to use DNS or other configuration methods. For UDP without outbound, the server side manages preferences in DNS. For UDP using SIP outbound a discovery method for edge proxys may configure one IPv4 edge proxy and one IPv6 edge proxy. Using one service DNS name with A and AAAA records will lead to problems. Animals (including cute kittens) may be harmed.

/O :-)

---

From: [email-masked] (Dale R. Worley)
Date: Wed, 17 Feb 2016 14:57:47 -0500

Jonathan Lennox <[email-masked]> writes:
> If parallel forking worked, forking to the v4 and v6 addresses (with
> the usual timing rules Happy Eyeballs advises) would seem to do
> exactly what we want -- 3261's Merged Request rules would take care of
> the duplicated requests.
>

B2BUAs do break parallel forking, but even without them, parallel
forking doesn't work in all cases.  Consider this case that I ran into
in the wild:

      UA A           Proxy 1         Proxy 2          UA B
        |               |               |               |
        | sip:B         |               |               |
        |-------------->|               |               |
        |               |               |               |
        | 100           |               |               |
        |<--------------|               |               |
        |               | sip:B;transport=UDP           |
        |               |-------------->|               |
        |               |               |               |
        |               |        100    |               |
        |               |     X<--------|               |
        |               |               |               |
        |               |               | sip:1.1.1.1   |
        |               |               |-------------->|
        |               |               |               |
        |               |               | 180 Ringing   |
        |               |               |<--------------|
        |               |               |               |
Since the UDP transport failed, Proxy 1 retries with TCP:
        |               | sip:B;transport=TCP           |
        |               |-------------->|               |
        |               |               |               |
        |               | 100           |               |
        |               |<--------------|               |
        |               |               |               |
        |               |               | sip:1.1.1.1   |
        |               |               |-------------->|
        |               |               |               |
        |               |               | 482 Merged Request        voicemail
        |               |               |<--------------|           server
        |               |               |               |               |
        |               |               | sip:voicemail |               |
        |               |               |------------------------------>|
        |               |               |               |               |
        |               |               | 200 OK        |               |
        |               |               |<------------------------------|
        |               |               |               |               |
        |               | 200 OK        |               |               |
        |               |<--------------|               |               |
        |               |               |               |               |
        | 200 OK        |               |               |               |
        |<--------------|               |               |               |
        |               |               |               |               |
Sence the second branch succeeded, Proxy 1 cancels the first branch, and
UA B stops ringing:
        |               | CANCEL        |               |               |
        |               |-------------->|               |               |
        |               |               |               |               |
        |               |               | CANCEL        |               |
        |               |               |-------------->|               |
        |               |               |               |               |

In this case, Proxy 1 knows to route SIP:B to Proxy 2.  For Proxy 2,
Proxy 1 has the URI "sip:proxy2", that is, without a transport
specification.  So Proxy 1 will try both TCP and UDP.  The result is
that an INVITE can arrive at Proxy 2 *twice*.  The first instance is
routed to the UAS, but the second instance is sent to the destination's
voicemail.

Now I think this syndrome is limited to situations where connectivity is
intermittent.  But it would be nice to have a mechanism whereby two
copies of one request that arrive at an entity can be recognized as
"redundant copies" and the second one discarded.

Dale

---

From: [email-masked] (Dale R. Worley)
Date: Wed, 17 Feb 2016 15:11:39 -0500

It seems to me that a short form answer is "An entity can accept UDP in a
dual-stack environment if the entity can assure that it (or some
downstream entity) will detect merged requests."

What prevents TCP from having this problem is that we expect that the
sender will send SYN and then wait to receive SYN-ACK before sending the
request.  However, I know nothing to stop a sender from sending the
packet containing the request immediately after sending the SYN packet.
If a sender was to do this successively on IPv4 and IPv6, a merged
request could result.

----------

In addition, the abstract Happy Eyeballs specification allows the sender
to change the order in which it contacts the various transport addresses
of the destination, based on the results of previous contact attempts
and perhaps configured information.  Strictly speaking, this is an
extension of 3263, and should be documented.  In a perfect world,
implementors would report to us the best ways to do that and we could
publish it.

Dale

---

From: "Olle E. Johansson" <[email-masked]>
Date: Wed, 17 Feb 2016 21:48:09 +0100

> On 17 Feb 2016, at 21:11, Dale R. Worley <[email-masked]> wrote:
> 
> downstream entity) will detect merged requests.”
Maybe, but we’re going down a slippery slope. REGISTER messages
can be different - with two contacts in both, or an IPv4 contact in the
IPv4 one and IPv6 contact in the IPv6 one.

If we are going to open up for this solution, then we’ll end up in a method-by-
method investigation and discussion.

Is it the transaction layer that handles this case - sending one request
in two copies over two different flows? I would rather see this as the
transaction layer selecting flow before sending one request.

In any case, we need to look at how SIP Outbound can be applied here.

> If a sender was to do this successively on IPv4 and IPv6, a merged
If so, then HTTP would have a problem too. I think we need to check
this assumption with Dan Wing.

Right. I don’t think the current implementations of Happy Eyeballs
actually follow the algorithms published in the RFC.

And yes, this is an extension of RFC 3263 but has to be seen
in the light of the DNS SRV RFC that says that all IP-addresses for a 
given name has to be contacted before going to the next entry.
That RFC is wide open for Happy Eyeballs and doesn’t need any
update, according to the folks in the IETF DNS directorate (which 
I have consulted). 

I fully agree that this document is needed.

/O

---

From: Paul Kyzivat <[email-masked]>
Date: Thu, 18 Feb 2016 11:16:45 -0500

> transaction layer selecting flow before sending one request.

How can this work for UDP? How can the flow that works be selected 
before sending the request?

(One answer is by using ICE (actually STUN connectivity checks) first. 
But making ICE mandatory for all SIP would be pretty radical.)

	Thanks,
	Paul

---

From: "Olle E. Johansson" <[email-masked]>
Date: Fri, 19 Feb 2016 10:09:55 +0100

My secret working group “Yay for SIP Outbound” says that moving to 
flow-oriented SIP will avoid this issue. We have time when opening a
flow to play around with Happy Eyeballs and thus avoid forking 
other messages than the REGISTER, which should be forked and
have separate reg-id’s.

/O
> On 17 Feb 2016, at 20:57, Dale R. Worley <[email-masked]> wrote:
> 
> _______________________________________________
> sipcore mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/sipcore

---

From: Robert Sparks <[email-masked]>
Date: Fri, 19 Feb 2016 08:50:59 -0600

Dale -

There's not enough in that flow to show what the problem you ran into 
really was.
If Proxy 1 was actually being a proxy, proxy 2 would have had all the 
information
it needed to treat that 2nd request as a merge. For the scenario to play 
out as you
describe, Proxy 1 had to doing something more b2b like.

RjS

---

From: [email-masked] (Dale R. Worley)
Date: Fri, 19 Feb 2016 11:36:32 -0500

Robert Sparks <[email-masked]> writes:
> really was.  If Proxy 1 was actually being a proxy, proxy 2 would have
> had all the information it needed to treat that 2nd request as a
> merge. For the scenario to play out as you describe, Proxy 1 had to
> doing something more b2b like.

Proxy 2 is within specification.  Proxies aren't required to detected
merged requests.  See RFC 3261 section 16.3:

   Notice that a proxy is not required to detect merged requests and
   MUST NOT treat merged requests as an error condition.  The endpoints
   receiving the requests will resolve the merge as described in Section
   8.2.2.2.

And it turns out that in a number of cases, you really don't want a
proxy to detect merged requests, because the second version of an INVITE
that a proxy sees may have a different request-URI (because an upstream
device is forking the call to a different destination this time).  And
the merged-requests logic doesn't check the request-URI:

   8.2.2.2 Merged Requests

   If the request has no tag in the To header field, the UAS core MUST
   check the request against ongoing transactions.  If the From tag,
   Call-ID, and CSeq exactly match those associated with an ongoing
   transaction, but the request does not match that transaction (based
   on the matching rules in Section 17.2.3), the UAS core SHOULD
   generate a 482 (Loop Detected) response and pass it to the server
   transaction.

I can see two possible resolutions:  One is that proxies do merged
request detection, but include the request-URI in the comparison.  The
other would be to create a mechanism specifically to label and detect
redundant transmissions.  Of course, the latter would be entirely new,
but I can construct situations where I can't see any other way to solve
the problem.

Dale

---

From: [email-masked] (Dale R. Worley)
Date: Fri, 19 Feb 2016 15:21:58 -0500

"Olle E. Johansson" <[email-masked]> writes:
> My secret working group "Yay for SIP Outbound" says that moving to 
> have separate reg-id's.

As long as the sender waits to receive the SYN-ACK before sending the
request, then sticking to flow-oriented SIP should fix the problem.

I am considering whether we want to introduce a merged requests rule for
proxies.  It would be much the same as for UASs, except that it would
require that the request-URI match as well as the From tag, Call-ID, and
CSeq.  That would allow multiple copies of a request to be sent on one
hop through different transports without having to worry about races
between the copies.

Dale

---

From: [email-masked] (Dale R. Worley)
Date: Tue, 23 Feb 2016 10:40:03 -0500

> Maybe, but we're going down a slippery slope. REGISTER messages

I don't think I understand you -- if the UA sends REGISTER requests with
different contacts intended to maintain concurrent registrations, the
requests will have different Call-Ids.

Dale