linux-can / linux

Linux kernel source tree
Other
1 stars 1 forks source link

Add support to not interactively reassamble (E)TP messages #6

Open olerem opened 4 years ago

olerem commented 4 years ago

In some cases, for example on sniffing the CAN bus for (E)TP messages, we may need to reassemble the messages without interacting with communication partners: A<--------->B .........^-----C A and B nodes a re communicating, node C is listening without responding to (E)TP requests.

hartkopp commented 4 years ago

Hi @olerem , I had a similar requirement with ISO-TP and the isotpsniffer. In the case of ISO-TP I created two sockets that monitor the traffic from A->B and B->A. The two protocol engines assume to be real communication partners and therefore reassemble the received PDUs and provide the data at socket read. BUT they do not send any ACKs which would disturb the real communication. To get into this 'read-only' mode the socket option 'flags' CAN_ISOTP_LISTEN_MODE is set. Maybe this mode could make sense for J1939 too??

olerem commented 4 years ago

Yes, it is probably the way i'll go. I just need time. Probably one or two weeks of active work.

josemic commented 4 years ago

Please consider discussion in https://github.com/linux-can/can-utils/issues/207.

josemic commented 4 years ago

Hi @olerem,

I have create for testing purposes such an reassembling mechanism in TTCN. (Which is actually the wrong place, but it works fine. ) Here is the central code, perhaps it is of use to you:

 while (condition1)
  {
    //T1.start;

    alt 
    {

      /*  []syncport.receive("halt") {
      condition1:=false  } */
      []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_cm := { requestToSend := ?}}}) -> value v_can_frame_j1939 { 
        //T1.stop; 
        msgSizeInBytes := v_can_frame_j1939.can_pdu.tp_cm.requestToSend.msgSizeInBytes
        receivedUnacknowledgedData := ''O
        receivedUnacknowledgedMsgSizeInBytes := 0
        pgnOfMultiPacketMessage := v_can_frame_j1939.can_pdu.tp_cm.requestToSend.pgnOfMultiPacketMessage
        ps := v_can_frame_j1939.can_j1939.ps
        sa := v_can_frame_j1939.can_j1939.sa
        //log incoming message 
        log ("received requestToSend: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
        alt // connection open requested
        {
          []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_cm := { clearToSend := {ctrl := '11'O, 
                    totalNumberOfPackets := ?,
                    nextPacketNumber :=1, 
                    reserved4 := ?,
                    reserved5 := ?, 
                    pgnOfMultiPacketMessage := ?}}}}) -> value v_can_frame_j1939 { 
            //T1.stop; 
            nextExpectedPacketNumber := v_can_frame_j1939.can_pdu.tp_cm.clearToSend.nextPacketNumber
            //log incoming message 
            log ("received clearToSend: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
            alt // connection open - receivig data
            {
              []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_dt := ?}}) -> value v_can_frame_j1939 { 
                //T1.stop; 
                if ((msgSizeInBytes - receivedUnacknowledgedMsgSizeInBytes) > 7) {
                  tp_dt_can_id := j1939id2canid(v_can_frame_j1939.can_j1939) // actuallay it is only necessary to store it once
                  receivedUnacknowledgedData := receivedUnacknowledgedData & v_can_frame_j1939.can_pdu.tp_dt.data
                  receivedUnacknowledgedMsgSizeInBytes := receivedUnacknowledgedMsgSizeInBytes + 7
                  nextExpectedPacketNumber := nextExpectedPacketNumber + 1 }
                else {
                  log("v_can_frame_j1939.can_j1939: ", v_can_frame_j1939.can_j1939)
                  tp_dt_can_id := j1939id2canid(v_can_frame_j1939.can_j1939) // actuallay it is only necessary to store it once
                  receivedUnacknowledgedData := receivedUnacknowledgedData & substr(v_can_frame_j1939.can_pdu.tp_dt.data
                    ,0 , (msgSizeInBytes - receivedUnacknowledgedMsgSizeInBytes))
                  nextExpectedPacketNumber := 0 
                  receivedUnacknowledgedMsgSizeInBytes := msgSizeInBytes
                }
                //log incoming message 
                log ("received tp_dt: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
                repeat
              }
              []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_cm := { clearToSend := ?}}}) -> value v_can_frame_j1939 { 
                //T1.stop; 
                //log incoming message 
                log ("received clearToSend: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
                repeat
              }
              []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_cm := { endOfMessageAcknowledgement := ?}}}) -> value v_can_frame_j1939 { 
                //T1.stop; 
                //log incoming message 
                log ("received endOfMessageAcknowledgement: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
                if (receivedUnacknowledgedMsgSizeInBytes == msgSizeInBytes) {
                  var octetstring receivedData
                  //var PGN pgn := v_can_frame_j1939.can_pdu.tp_cm.endOfMessageAcknowledgement.pgnOfMultiPacketMessage
                  if (oct2int((int2oct(pgnOfMultiPacketMessage, 3) and4b '00FF00'O)>> 1 ) < 240) {
                    log ("pgnOfMultiPacketMessage: ", pgnOfMultiPacketMessage, ", ", int2oct(pgnOfMultiPacketMessage, 3))
                    log ("ps: ", ps)
                    log ("sa: ", sa)
                    receivedData := int2oct(oct2int((int2oct(pgnOfMultiPacketMessage, 3) and4b '03FFFF'O)>> 1 ), 2) & ps & sa & receivedUnacknowledgedData
                  }
                  else
                  {
                    log ("pgnOfMultiPacketMessage: ", pgnOfMultiPacketMessage, ", ", int2oct(pgnOfMultiPacketMessage, 3))
                    log ("sa: ", sa)
                    receivedData := (int2oct(pgnOfMultiPacketMessage, 3) and4b '03FFFF'O) & sa & receivedUnacknowledgedData
                  }
                  //var octetstring receivedData := (tp_dt_can_id and4b  '0003FFFF'O) & receivedUnacknowledgedData
                  log("tp_dt_can_id: ", tp_dt_can_id)
                  //var octetstring receivedData := tp_dt_can_id & receivedUnacknowledgedData
                  //var octetstring receivedData := receivedUnacknowledgedData
                  //log ("received tp_dt frame with PGN: ",  receivedData);
                  // changed by MJ

                  //receivedData := receivedUnacknowledgedData
                  log ("received multipart frame",  receivedData);
                  v_can_frame_j1939:=f_decode_CAN_frame_j1939(receivedData)
                  log ("received tp_dt frame j1939: ",  v_can_frame_j1939);
                }
                else {
                  log ("received incomplete message frame: ",  receivedUnacknowledgedData);
                }
              }
            }
          }
          []pt_isobus.receive(CAN_frame_j1939:{can_j1939 := ?, can_pdu := {tp_cm := { connectionAbort := ?}}}) -> value v_can_frame_j1939 { 
            //T1.stop; 
            //log incoming message 
            log ("received connectionAbort: ",  v_can_frame_j1939, v_can_frame_j1939.can_j1939.sa, v_can_frame_j1939.can_j1939.ps);
          }
        }

      } 
      []pt_isobus.receive(CAN_frame_j1939:?) -> value v_can_frame_j1939 { 
        //T1.stop; 
        //log incoming message 
        //log ("received: ",  v_can_frame_j1939);
      } 

      //[]T1.timeout; 

    }//endalt
  }
}//endfunction  var boolean condition1

All TP / ETP data coming for a single destination address / source address pair is forwarded to such a process.

olerem commented 4 years ago

ok, thx