Hi,

Walking to the bus stop just now, I think I finally understood Michael's
concern.

1. We assume the extremely unlikely case that two GRASP peers A and B choose
the same session ID -- let's call it C for 'clash'. This would need to be
at about the same time, too, for the ambiguity to matter.

2. We assume that A sends req_negotiate(C,...) to B, and B sends 
req_negotiate(C,...)
to A, at about the same time.

Now we have to consider the possible race condition.

- If A's req_negotiate reaches B before B has committed to using the ID value
C for its own req_negotiate, we are OK: B will find that C is already
in use (in its local session cache) and will generate a new value C'. No
race condition, no problem.

- Similarly in the other direction.

- If A's req_negotiate reaches B after B has committed to using the ID value
C, B can detect this, because C is already in its local session cache, tagged
as locally originated. So it can simply drop the req_negotiate (or send back an
M_END[O_DECLINE]).

- Similarly in the other direction. In fact, if the race condition arises
in one direction, it will automatically arise in the opposite direction too.
So both attempted negotiations will fail. That's fine; ASAs need to retry
after failure in any case. In any case it's highly unlikely, unless somebody
uses a really bad PRNG.

Is that correct? If so, it needs to be explained better in the spec.

That said, I think it's quite logical to increase the space to 32 bits, since
as Michael observed it will be stored as a uint32 anyway, in practice, and the 
impact
on CBOR size is minor.

Regards
   Brian

On 24/10/2016 16:28, Brian E Carpenter wrote:
> On 24/10/2016 09:17, Michael Richardson wrote:
>>
>> Brian E Carpenter <[email protected]> wrote:
>>     > On 21/10/2016 02:02, Michael Richardson wrote:
>>     >>
>>     >>
>>     >> Brian E Carpenter <[email protected]> wrote:
>>     >> > Oops, there was a prettifying bug in the previous version...
>>     >>
>>     >> ...
>>     >>
>>     >> > OK, so now I'll make one with multiple steps [pause while I run my
>>     >> > example generator and prettify the results]
>>
>>     1> A to B: [M_REQ_NEG, 11146801, ['EX2', 1, 6, ['NZD', 393]]]
>>     2> B to A: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 56.0]]]
>>     3> A to B: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 294.75]]]
>>     4> B to A: [M_WAIT, 11146801, 20899]
>>     5> B to A: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 84.0]]]
>>     6> A to B: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 235.8]]]
>>     7> B to A: [M_END, 11146801, [O_DECLINE, 'Insufficient funds']]
>>
>>     >> Lines 2 and 5 look identical to me.
>>
>>     > Yes, except that B increased its offer from $56 to $84.
>>
>>     >> As do lines 3 and 6.
>>
>>     > Yes, except that A reduced its request from $294 to $235
>>
>> Ah, so this is one negotiation then?
>> I thought the M_WAIT was the end of a negotiation and 5> was a second thing,
>> but of course, that makes no sense, it would start with M_REQ_NEG.
>>
>>     > There's a state machine at each end which is specific for this 
>> particular
>>     > objective. I'm a little confused about what's confusing you. (Maybe the
>>     > Appendix of examples needs explanatory text?)
>>
>> Let me add some messages and interleave a second negotiation n2:
>>
>> n1  1> A to B: [M_REQ_NEG, 11146801, ['EX2', 1, 6, ['NZD', 393]]]
>> n2 11> B to A: [M_REQ_NEG, 11146801, ['EX2', 1, 6, ['NZD', 392]]]
>>
>> Yup, both ends picked the same session-id because cosmic ray hit, and started
>> negotiation.
>>
>> n1  2> B to A: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 56.0]]]
>> n2 21> A to B: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 55.0]]]
>>
>> n1  3> A to B: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 294.75]]]
>> n1  4> B to A: [M_WAIT, 11146801, 20899]
>> n2 31> B to A: [M_NEGOTIATE, 11146801, ['EX2', 1, 6, ['NZD', 292]]]
>>
>> ..
>>
>> So, is message 31 (which looks the same as (5) above part of n1 or n2?
> 
> Two answers:
> 
> 1. n1 and n2 would be two different TCP sessions, and two different threads
> at each end.
> 
> 2. In any case, the session_ID cache (of all currently valid IDs,
> should be implemented with 2-tuples* like {ID, initiator}.)
> I coded it with 0 meaning "me", so {11146801,0} would be a session
> that I initiated, and {11146801,2406:e007:652c:1:660a:5169:6c66:4669}
> would be one that the other guy initiated.
> So if you did build a single-threaded implementation, that would be
> enough to demultiplex the sessions.
> 
>    Brian
> 
> *in practice I have more in the session cache. Gory details:
> 
> class _session_instance:
>     """Internal use only"""
>     def __init__(self, id_value, id_active, id_source):
>         self.id_value = id_value   #Integer
>         self.id_active = id_active #True if active
>         self.id_source = id_source #Source locator of ID if needed
>         self.id_dq = None          #Queue if discovering
>         self.id_sock = None        #Socket if negotiating
>         self.id_relayed = False    #True if has been relayed
> 
> # Session_ID cache contains
> #  - all currently active Session_IDs
> #  - foreign source address if any
> #  - status for each one (in use or inactive)
> #  - as memory permits, all previously seen Session_IDs (status inactive) to 
> avoid reuse
> 

_______________________________________________
Anima mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/anima

Reply via email to