Open Almeida-Oco opened 3 years ago
First of all thank you for the thorough analysis! I am currently trying to reconstruct the (possible) issue and found one thing I do not understand regarding the analysis. It is within this part:
"the newly created remote_subscription will inherit the acknowledgement states from the existing subscription (0x1234) , so we end up with the following instances of remote_subscription:
remotesubscription (0x1234) - clients{2: PENDING, 3: PENDING}, parent_: nullptr remotesubscription (0x4321) - clients{2: PENDING, 3: PENDING}, parent_: 0x4321"
If I read "eventgroupinfo::update_remote_subscription" correctly, client 2 is not copied to the second remote subscription that contains client 3. Thus we end up with:
remotesubscription (0x1234) - clients{2: PENDING, 3: PENDING}, parent_: nullptr remotesubscription (0x4321) - clients{3: PENDING}, parent_: 0x1234"
instead and the answer to the second subscription is sent as soon as the application acks it.
But because the 2nd SUBSCRIBE message that Application 2 sends to vsomeipd
has clients [2, 3] in its selective options, won't the new subscription be:
remote_subscription (0x4321) - clients_{2: PENDING, 3: PENDING}, parent_: nullptr"
before even entering eventgroupinfo::update_remote_subscription
?
Yes, you are right. Probably we should let the remote_subscription objects know their children to keep the update in sync.
Considering the following network architecture with 2 different devices connected to the same network, with the following applications, where the first row represents the central routing managers of each device:
Application 1 is offering a selective event and Application 2 and 3 will be subscribing to it, so Application 2 will send 2 SOME/IP-SD Subscribe messages to
vsomeipd
. In their selective options, the first will only contain it's own ID [2], while the second will contain both it's ID and Application 3 ID [2, 3].When
vsomeipd
receives the first SUBSCRIBE message, it will create a newremote_subscription
whose only client will be App 2 with thePENDING
state, lets say it was stored in the 0x1234 memory position, so:vsomeipd
will then proceed to send aVSOMEIP_SUBSCRIBE
local message to Application 1, and thePENDING
state will only be updated toACKED
once it replies with aVSOMEIP_SUBSCRIBE_ACK
message containing client 2. Now, if the second SUBSCRIBE message arrives and is processed before client 2 remote subscription state is changed toACKED
, then inrouting_manager_impl::on_remote_subscribe()
, in the call toeventgroupinfo::update_remote_subscription()
, as both instances are "equal", the newly createdremote_subscription
will inherit the acknowledgement states from the existing subscription (0x1234) , so we end up with the following instances ofremote_subscription
:Also, since the 0x1234 instance already had client 2, the
update_remote_subscription
will only insert client 3 in its_changed
parameter, meaning that later in thesend_subscription
call, it will only send aVSOMEIP_SUBSCRIBE
message containing client 3 to Application 1. https://github.com/GENIVI/vsomeip/blob/13f9c89ced6ffaeb1faf485152e27e1f40d234cd/implementation/routing/src/routing_manager_impl.cpp#L2742-L2757After that,
vsomeipd
will eventually receive theVSOMEIP_SUBSCRIBE_ACK
message with client 2 from Application 1 and will update the 0x1234remote_subscription
state of client 2 toACKED
in therouting_manager_impl::on_subscribe_ack()
method, but noSUBSCRIBE_ACK
Service Discovery message will be sent as theservice_discovery_impl::update_remote_subscription()
call will only send the ACK if theremote_subscription
is not pending, since client 3 state is stillPENDING
in the 0x1234 subscription that is not the case. When the nextVSOMEIP_SUBSCRIBE_ACK
message with client 3 is received, theremote_subscription
0x4321 will be updated, client 3 state will then beACKED
, which is also propagated to it's parent 0x1234. Since 0x4321 client 2 state is stillPENDING
it will not be removed from thesubscriptions_
collection ofeventgroupinfo
in https://github.com/GENIVI/vsomeip/blob/13f9c89ced6ffaeb1faf485152e27e1f40d234cd/implementation/routing/src/routing_manager_impl.cpp#L2844-L2862 Consequently, noSUBSCRIBE_ACK
message will be sent either, so we end up with the following state of the eventgroupssubscriptions_
collection:Once this happens, subsequent
SUBSCRIBE
messages sent by Application 2 will always contain the same clients in its selective option [2, 3] and no change will happen, which seems would be causing it to either enter the!_subscription->is_pending()
branch or theelse
branch ineventgroupinfo::update_remote_subscription()
, depending on which existingremote_subscription
is iterated first. https://github.com/GENIVI/vsomeip/blob/13f9c89ced6ffaeb1faf485152e27e1f40d234cd/implementation/routing/src/eventgroupinfo.cpp#L211-L250In the first case, it will inherit the state of 0x1234 and not be pending anymore, so it should send the
SUBSCRIBE_ACK
back to Application 2 and resume normal behavior(?), whereas in the second case it will be assignedset_answers(0)
and not send anySUBSCRIBE_ACK
back as it would enter thedo_not_answer
branch ofservice_discovery::send_subscription_ack()
. https://github.com/GENIVI/vsomeip/blob/13f9c89ced6ffaeb1faf485152e27e1f40d234cd/implementation/service_discovery/src/service_discovery_impl.cpp#L3557-L3593If in the
send_subscription()
call we would use something like_subscription.get_pending_clients()
instead of usingits_added
when receiving new clients for a selective event, this issue would disappear at the expense of some additional local messages.Did I miss something or is my reasoning correct?