linux-can / can-utils

Linux-CAN / SocketCAN user space applications
2.39k stars 711 forks source link

Doubt: Design choices for reading J1939 data with kernel version <5.4 #403

Closed acode-x closed 1 year ago

acode-x commented 1 year ago

Hi,

I wish to write an application whose functionality is to read data from from a set of CANIDs in a J1939 network. My env setup unfortunately only has kernel version 4.X and does not have can-j1939 kernel modules.

I plan to have minimal functionalities excluding J1939 multi packet (handle only data of 8byte length):

  1. read broadcast messages
  2. periodically request for messages and read responses

I have couple of questions in writing this application:

  1. In order to request for a PGN, should I claim an address as per J1939/81? If yes, should I use a 3rd party library, to handle address claiming in user-space?
  2. Should I use 2 sockets - 1 CAN_RAW for reading broadcast messages and 1 CAN_BCM for periodic request, where I add CANID filters for both?

I'm looking for advice on how to carry out the above design.

Thanks in advance!

marckleinebudde commented 1 year ago

Sorry, but I can only say something you probably don't want to hear. I'd rather invest in upgrading your kernel than to write yet another J1939 stack.

acode-x commented 1 year ago

Thanks @marckleinebudde,

I plan to upgrade kernel in the next few months. Until then, for achieving a minimum viable product (MVP), I wish to read only 5-10 PGN values. Can I request these values and read the responses without address claiming (J1939/81)?

marckleinebudde commented 1 year ago

I'm not that deep into J1939.

olerem commented 1 year ago

Thanks @marckleinebudde,

I plan to upgrade kernel in the next few months. Until then, for achieving a minimum viable product (MVP), I wish to read only 5-10 PGN values. Can I request these values and read the responses without address claiming (J1939/81)?

Sure you can do any part of communication without address claiming. The same way you can communication with any server by using an IP instead of resolving it over DNS.

Do I understand it correctly, your MVP will be based on CAN_RAW. There is no plans to use CAN_J1939 instead?

acode-x commented 1 year ago

Hello @olerem,

Thanks for the clarification. Yes, I would using CAN_RAW to begin with.

I am referencing a sample request message I got from a book.

request - 18EAFF00 E9 FE 00
response - 18FEE9AA FF FF FF FF 3D 00 00 00 

In above request, (FF) represents a broadcast message from the source address (00). Would I be giving the same source address (00) in my application as well?

olerem commented 1 year ago

So far I understand this question correctly - yes. You have fully freedom to format the message and address as long as you use CAN_RAW. On other hand, for a J1939 application, you wont to use NAMEs and address claiming. If you just wont to make an "hello world" for J1939, CAN_RAW is probably bad starting point.

acode-x commented 1 year ago

Understood. Thank you very much!

acode-x commented 1 year ago

Hello @olerem and @marckleinebudde,

I have 2 small followup question w.r.t above. I wish to use CAN_BCM for message throttling and migrate to CAN_J1939 later.

I wish to filter messages based on PGN and configure message throttling. But I see the following challenges:

  1. Both CAN_RAW and CAN_J1939 provide can_id mask APIs, but above it does not provide message throttling. Eg.

    rfilters[0].can_id = 0x18FEEEFE | CAN_EFF_FLAG;
    rfilters[0].can_mask = 0x00FFFF00; // PGN MASK
    setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilters, sizeof(rfilters));
  2. I understand CAN_BCM can help me with throttling. But it doesn’t have canid masks so that I can filter out PGNs. Eg.

    msg.msg_head.opcode = RX_SETUP;
    msg.msg_head.flags = SETTIMER | RX_FILTER_ID;
    msg.msg_head.can_id = 0x18FEEEFE | CAN_EFF_FLAG;
    msg.msg_head.ival1.tv_sec = 0;
    msg.msg_head.ival1.tv_usec = 0;
    msg.msg_head.ival2.tv_sec = 2;
    msg.msg_head.ival2.tv_usec = 0;
    msg.msg_head.nframes = 0;

    As you see, I give the entire can_id. Unfortunately I have only PGN information (0xFEEE) with me, and I can’t pass it to above struct.

Is there a way to solve this? Curious to know your thoughts on above.

Thanks!

olerem commented 1 year ago

It will be nice to have this functionality in j1939 stack, but i do not have time to implement it. Patches are welcome :)

hartkopp commented 1 year ago
2. I understand CAN_BCM can help me with throttling. But it doesn’t have canid masks so that I can filter out PGNs.

Yes, that's right. The idea behind the CAN_BCM was to filter for some bits in the can.data[] in cyclic messages where the data content is comparably stable. E.g. think of a turning light which flips every second but the CAN frame is sent every 50ms.

So the CAN_BCM is more about detecting alternating bits than throttling the content. For each CAN ID there are data structures holding the content to compare it to the previous reception content.

For your use case throttling within the J1939 stack might be the better approach ...

olerem commented 1 year ago

The reasons why J1939 needs own support for this are:

acode-x commented 1 year ago

Hi hartkoop and olerem, Thanks a lot for the detailed explanation. I've gained a better understanding of can/j1939 in the last few days now. I'd like to give the implementation a try some time later if possible.