-
Notifications
You must be signed in to change notification settings - Fork 202
Abort SDO server upload when the object has zero length #587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Abort SDO server upload when the object has zero length #587
Conversation
A data size of zero bytes cannot be encoded in the "number of bytes that do not contain data" semantics, as that would require n=4, which is however limited to two bits (maximum value 3). So the SDO expedited upload protocol simply cannot convey that condition. The current implementation however still tries and thereby corrupts the server command specifier field value. Avoid that protocol violation by responding with an SDO abort code of 0800 0024h, No data available. Add a test case for this condition, verifying that the client raises the appropriate SdoAbortedError exception.
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
Sorry but I do not agree implementing this as it would exclude a use-case for zero-length data. While there are some of the SDO protocols that doesn't support zero sized data (e.g. expedited and block), normal (segmented) transfer does support it. The use case for zero length data is console or serial data, which may or may not be available in the remote at the time of the SDO operation. An example is 7.5.2.29 OS prompt, object 0x1026 subindex 1-3. The standard quote "This object is mappable to an event driven PDO or polled by SDO". This means this must support zero-length data, as there might not be any data available when the subindex is polled by SDO. For this use case, the remote would unexpectantly receive the SDO abort "No data" from the client, which is not good. |
Why is it "not good" to receive an SDO abort message with appropriate abort code? Either way, the SDO transaction ends with that message. How is receiving an empty response (beacuse no data is available) any different from receiving an SDO abort message with the reason "no data available"? Have you seen such behavior on actual devices, as a reference? I mean this is our SDO server component, we can choose freely how to handle that case, as long as we don't violate the protocol. Just because it is possible for some responses to indicate a length of zero, that doesn't mean it is in any way more correct than the alternative. We can just as well distinguish by request type. The server decides whether a segmented or expedited transfer response is sent. So nothing stops us from sending a response with
So the client might just not follow up with any SDO upload segment requests. So how can we be sure the SDO transfer has ended? The standard allows three cases:
If the client doesn't continue requesting a segment because we sent a size of zero, that's fine and the next SDO request will implicitly terminate the transaction. It then counts as an unsuccessful transfer, same as if we sent the SDO abort code. Worst case, the client might send an SDO abort indication in response to our size=0 response. If not, it's absoutely equivalent in terms of bus traffic whether we use the SDO abort or the upload initiate response. |
One more thought, which might be closer to your understanding of the use case @sveinse: We get a request to upload data from some object. The response indicates segmented transfer and a zero size (or even unknown size). The client can then keep requesting an SDO upload segment repeatedly, and gets a zero-length response each time if no data is still available. But that never ends the transaction. The SDO channel stays blocked and bound to the requested object, so each segment request can transfer up to 7 bytes at once, without further initiation. It ends when the server sends a c=1 response, client or server abort the transfer, or client sends a new upload initiate request. Now which of these cases work with our current SDO upload segment implementation? Especially, does the "streaming" approach with continuously getting back zero bytes, but not ending the transaction actually work? Otherwise, I'd rather start with this quick fix, then we can restructure to make the other solution work. As for block upload, that's still waiting in PR #559, so no concern currently. |
I think two main reasons: Its an anti-pattern to communicate non-errors as errors. Errors (SDO abort) are exceptions, i.e. unexpected events. This is a common design principle for all communication systems I've been working on at least. (-- and I feel as strongly about this as you do about little-endian 😊) The second reason is that the SDO abort is transmitted to the other party. It might not expect to receive a "No data available" just for responding with 0 length data.
Yes, I have a unit. Not public, so I have nothing to reference to unfortunately. It implement a serial console using the OS command object with zero-length SDO pollable subindex as described earlier. To determine if this is a one-off implementation specific detail, I think perhaps we should attempt to reach out to CiA and hear if they have an opinion. It is a bit odd that not all SDO variants support 0-length data, so it might be that this use case is unintended. If it is, I agree that this library does not need to implement 0-length SDO and we can close this discussion.
The standard is showing in Figure 23 under 7.2.4.3.5 that segments are always present when e=0. This means that one must have at least one segment exchange when e=0. The only way to prevent exchange of segments is when e=1, which we both agree doesn't work with 0-length data.
Yes. But the argument here is that 0-length data is covered by case no 2. See below for sequence.
The SDO bus is a "single channel" communication scheme, with only one active transmission per SDO server. Even though its technically possible to keep a transmission "alive" by keep responding 0-sized data packages with c=0, it will block all the other SDO communication. So any messages should finish as quickly as possible.
|
After trying to google this, I think I need to conclude that 0-length data is a very uncommon corner of SDO. I find absolutely no examples of zero-length data or examples. I read the entire SDO chapter in the spec, and it never mentioned zero length data. I think I am sensing between the lines that it's a not intended use-case. Otherwise it would have been mentioned. I'm also not finding any reference to SDO abort "no data available" being used on zero length data. I tried looking briefly at a couple of open source canopen libraries, but I couldn't find any use of it. -- I think this corner is probably a case no one has considered it seems. For fun: Google AI sais (which definitely might be wrong): |
Your responses are well thought out and I agree with your assessment.
Now to the really important points: Our server currently gives totally bogus responses for an object with zero data to encode.
Whatever we do, we should fix the clear protocol violations. Aborting the transfer as suggested is just a simple reaction to the special case. If you feel like supporting more of the possible response behaviors, I'm open to consider adding them. The SDO abort is not set in stone, just the most obvious valid choice for me. But feel free to make an alternative PR with a different choice. If it ends up requiring a matching response to the following upload segment request, that should be implemented as well though. The current approach avoids that by ending the transaction (which can easily be retried anyway). |
I have to humbly admit that I had completely overlooked that this PR is discussing the SDO server, not the client. That changes things completely.
Agreed. The current implementation is not handling 0 sized data right and must be fixed. On upload its the server's privilege to chose expedited vs segmented, so it makes sense its also the server's privilege (and our choice) to not support zero-length data. This will be compliant with the standard.
Again, I'm sorry for this apparent 180 degrees turn - I missed a crucial piece of information. I should have read the PR better before typing off. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can say this PR has been thoroughly discussed. Approved.
A data size of zero bytes cannot be encoded in the "number of bytes that do not contain data" semantics, as that would require n=4, which is however limited to two bits (maximum value 3). So the SDO expedited upload protocol simply cannot convey that condition. The current implementation however still tries and thereby corrupts the server command specifier field value.
Avoid that protocol violation by responding with an SDO abort code of 0800 0024h, No data available.
Add a test case for this condition, verifying that the client raises the appropriate SdoAbortedError exception.
Inspired by the discussion in #566.