Skip to content
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

CC-2174: modify CAN frame header structure to match updated struct ca… #1851

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

eldadcool
Copy link

@eldadcool eldadcool commented Sep 5, 2024

This fix allow to send CLASSIC CAN frames with a DLC value larger than 8 using the socketcan interface.

In addition it allow to parse incoming socketcan messages with the updated format
#1780
@hartkopp

@zariiii9003
Copy link
Collaborator

@lumagi could you take a look at this?

@lumagi
Copy link
Collaborator

lumagi commented Sep 18, 2024

I'll try to take a look over the next couple of days. @eldadcool do you happen to have a link to the patch set in the kernel?

@eldadcool
Copy link
Author

eldadcool commented Sep 19, 2024

I'll try to take a look over the next couple of days. @eldadcool do you happen to have a link to the patch set in the kernel?

@lumagi, sure:
The patch can be found at version 6.10.7 of the kernel, see patch at torvalds/linux@ea78005

To configure the bus using "ip link" command you require a version of iproute2 5.12 or higher: https://lore.kernel.org/netdev/[email protected]/

use the command

ip link set can0 down
ip link set type can cc-len8-dlc on
ip link set can0 up

note: can-utils support this only since this patch linux-can/can-utils@11edd1d

@hartkopp - please review my fix as well to make sure I did not misinterpret some edge cases regarding the new structure and that this will not break the usage of the old format.

@hartkopp
Copy link
Collaborator

use the command

ip link set can0 down
ip link set type can cc-len8-dlc on
ip link set can0 up

You can simply go with the latest can-utils where candump and cangen have a -8 option to create and display the DLC values over 8.
WIth the virtual CAN interfaces (e.g. vcan0) you can test the cc-len8-dlc stuff without any additional configuration. The vcan is transparent for these values.

@hartkopp - please review my fix as well to make sure I did not misinterpret some edge cases regarding the new structure and that this will not break the usage of the old format.

I'm not sure whether I can really review the patch, as I'm not that familiar with Pythons packing concept.
But if you strictly followed the data structure and the rules (len == 8 and ( len8_dlc > 8 && len8_dlc <= 0xF )) apply for valid DLC over 8 length's values - then it should be fine :-)

Many thanks,
Oliver

@eldadcool
Copy link
Author

I'm not sure whether I can really review the patch, as I'm not that familiar with Pythons packing concept. But if you strictly followed the data structure and the rules (len == 8 and ( len8_dlc > 8 && len8_dlc <= 0xF )) apply for valid DLC over 8 length's values - then it should be fine :-)

Actually, the DLC value in python-can relate directly to the data length. and it's not even verified to be a valid message by default. So potentially this could lead to sending a message with unexpected DLC value.
This reminds me of an issue I think I found in socketcan (@hartkopp) allowing unexpected lengths for CAN FD frames (10 bytes for example...) because the length value used is socketcan also relate to the data length and not to the DLC. I think we need to be aligned regarding this and very careful because fixing it might break some existing usage of socketcan or python-can.

Note the issue with socketcan only relevant for virtual can interfaces because physical interfaces does not allow FD frames with 10 bytes of data (only <8, 8, 12, 16, 20, 24, 32, 48 and 64) but it makes virtual interfaces behave differently than physical interfeces.

@hartkopp
Copy link
Collaborator

This reminds me of an issue I think I found in socketcan (@hartkopp) allowing unexpected lengths for CAN FD frames (10 bytes for example...) because the length value used is socketcan also relate to the data length and not to the DLC. I think we need to be aligned regarding this and very careful because fixing it might break some existing usage of socketcan or python-can.

Note the issue with socketcan only relevant for virtual can interfaces because physical interfaces does not allow FD frames with 10 bytes of data (only <8, 8, 12, 16, 20, 24, 32, 48 and 64) but it makes virtual interfaces behave differently than physical interfeces.

Yes, this is intentional.
The idea is that the content which is sent via virtual CAN devices is not extensively sanitized to be able to test with uncertain values and just reflect them back to user space. This is very useful to test user space applications.

Once the CAN frame content is given to a real CAN interface or received from them the functions

can_fd_dlc2len() can_fd_len2dlc() canfd_sanitize_len() are used.

https://elixir.bootlin.com/linux/v6.11/source/include/linux/can/length.h#L290

@eldadcool
Copy link
Author

Yes, this is intentional.
The idea is that the content which is sent via virtual CAN devices is not extensively sanitized to be able to test with uncertain values and just reflect them back to user space. This is very useful to test user space applications.

Cool,
In that case the current solution I proposed here sanitize the length field for FD valid values. Don't think this should lead to an issue. @lumagi, have any insights?

Copy link
Collaborator

@lumagi lumagi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks fine to me. I only had some nit-picky stuff.

if len(frame) != constants.CANFD_MTU:
# Flags not valid in non-FD frames
flags = 0
return can_id, can_dlc, flags, frame[8 : 8 + can_dlc]

if data_len not in can.util.CAN_FD_DLC:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason you don't trust the value returned by the kernel? I'm not saying it's a bad thing, just interested in why you added this.

Copy link
Author

@eldadcool eldadcool Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed with @hartkopp socketcan allow to send non valid FD frames with length not supported by CAN FD. For example, DLC=0x9 (data_len=12) and actual data_len=10 - this is invalid CAN FD frame but still could be received from the kernel.
To handle this case I added code to round up the amount of bytes.
Note that no read overflow will happen because the CANFD MTU is set to 72 (64 bytes of data) in the socketcan implementation so the additional bytes read from the frame will still be part of the struct and will probably contains 0x00s. If you prefer we can add padding with a defined value to be on the safe side.

else:
can_dlc = data_len

return can_id, can_dlc, flags, frame[8 : 8 + data_len]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very nit-picky: I know this wasn't any better before the new PR, but I don't like that we don't check that the expected data_len is actually present in the frame. Since it's Python it will simply return less data than expected.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I can add this verification to make it more robust. Should I add padding bytes , recude the data_len value or raise an exception in that case? Not sure what will be the best here...

@zariiii9003
Copy link
Collaborator

ping @eldadcool

@eldadcool
Copy link
Author

ping @eldadcool

Hii sorry, I was not very available last month...
Added replies to your comments. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants