On 28 April 2017 at 15:41, Dmitry Eremin-Solenikov
<dmitry.ereminsoleni...@linaro.org> wrote:
> On 28.04.2017 12:27, Peltonen, Janne (Nokia - FI/Espoo) wrote:
>> Hi,
>>
>>> -----Original Message-----
>>> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of Dmitry 
>>> Eremin-
>>> Solenikov
>>> Sent: Friday, April 28, 2017 11:59 AM
>>> To: lng-odp-forward <lng-odp@lists.linaro.org>
>>> Subject: [lng-odp] IPsec SA disabling
>>>
>>> Hello,
>>>
>>> While responding to Janne's email, I've come to an issue which warrants
>>> a separate discussion IMO.
>>>
>>> Consider the following scenario. Application with two thread.
>>>
>>> - First thread: gets outbound packet, finds SA through SPD, configures
>>> IPsec request, submits it.
>>>
>>> - Second thread: wants to disable SA, pending deletion.
>>>
>>> Is that an application error if SA was disabled after being looked up,
>>> but before being submitted by another thread? Yes it is.
>>
>> Yes, it would be an error.
>>
>>> Right now SA
>>> disabling/deletion is susceptible to race conditions. It requires an app
>>> to lock SA after lookup, unlock it after submission, etc.
>>
>> To avoid races one indeed currently needs some synchronization in the
>> application side. Not necessarily locks but something.
>>
>> The OFP IPsec draft code (which is just draft, trying to use the ODP API),
>> refcounts SA usage and disables an SA only after it has been removed
>> from the SAD and after ongoing operations (tracked through the refcount)
>> have completed.
>
> Basically as we already have refcounting on ODP side, I'd suggest
> reusing it in applications.
>
>>
>> Because of the above, one could wonder why even have disable() in the
>> API. The main reason is to be able to disable offloaded inbound SA
>> lookup for the SA so that the SA can be safely deleted (the application
>> needs to be able to clean up its own SA state but cannot do it if there
>> are in-flight inbound operations that may still refer (through the ctx ptr)
>> to the application SA state).
>
> How do you track references of SA instances returned from ODP after
> lookup? How will application cope with disabling/deleting SA if it is
> returned to another thread by ODP?
>
>>
>>> Should ODP
>>> provide API to 'lock' SA?
>>
>> It would be convenient to the application if disable() could be called
>> at any time. But that could impose difficult synchronization needs
>> in the ODP implementation side and therefore we thought that it is
>> better to leave that to the application which may need to do some
>> synchronization anyway due to its own needs.
>>
>> But this is definitely a good topic to ponder about. It is possible
>> that the current API got this wrong, but it is not easy to see how
>> things should be if they need to be changed.
>
> Well, right now there is a need to do synchronization on ODP side
> because odp_ipsec_sa_disable() is not an optional call.
>
>>> I was thinking about smth like:
>>>
>>> int odp_ipsec_sa_use(odp_ipsec_sa_t sa);
>>>
>>> void odp_ipsec_sa_unuse(odp_ipsec_sa_t sa);
>>>
>>> One would use first function when an app has looked up SA in it's own
>>> tables and is going to submit it via one of odp_ipsec_* processing calls
>>> (except or including SA deletion/disabling -- TBD).
>>
>> I am not sure how this would help and be better than something done
>> totally at the application side. This would anyway require a bit more
>> specification to define the semantics. For instance, when unuse() could
>> be called with respect to the enque operations and what exactly it
>> would mean.
>
> I'm just suggesting to move reference counting from application to ODP
> side, since ODP has to do refcounting anyway (_disable() should wait
> till all currently running operations with this SA finish).
>
> I thought basic refounting in mind. Probably we can get this as easy as:
>
> - odp_ipsec_sa_create:
>
>   Create SA with refcnt = 1
>
> - App looks up SA in SAD
>   odp_ipsec_sa_use(sa)
>
> - App has looked up SA in SAD, but then changed its mind
>   odp_ipsec_sa_unuse(sa)
>
> - ODP looks up SA in cache (via a request from app or via inline inbound
> operation
>   odp_ipsec_sa_use(sa)
>
> - Application receives SA via a return from IPsec.
>   - Processes it and then calls odp_ipsec_sa_unuse().
>
> - Application wants to disable SA in ASYNC mode.
>   odp_ipsec_sa_disable() marks SA for disablement.
>   - ASYNC case. It calls ipsec_sa_unuse() then returns.
>
>   - SYNC case. It waits for refcount to drop to 1, unuses it then
> returns.
>   - OR(!) SYNC case. It calls ipsec_sa_unuse(), waits for refcount to
> drop to 0, then reutrns.
>
> - odp_ipsec_sa_unuse() is called with refount becoming 0.
>   - ASYNC case:
>     submit an even.
>
>   - SYNC case:
>     do nothing.

I believe this synchronisation at application end might not be too
difficult for look-aside mode since SA create/delete call is part of
control flow and ipsec lookup is part of the data flow.
In case of inline mode when application calls odp_ipsec_sa_disable()
the SA gets disabled but there could be few transient packets which
might flow during disable operation and when application calls
odp_ipsec_sa_destroy() the destroy operation could simply fail if
there are few packets which are still processed then the application
could call the odp_ipsec_sa_destroy() after sometime when it becomes
success.

Regards,
Bala
>
> --
> With best wishes
> Dmitry

Reply via email to