EIPStackGroup / OpENer

OpENer is an EtherNet/IP stack for I/O adapter devices. It supports multiple I/O and explicit connections and includes objects and services for making EtherNet/IP-compliant products as defined in the ODVA specification.
Other
673 stars 259 forks source link

Implicit messaging - Exclusive Owner Connection - No Output Assembly Data receive O ->T #208

Closed ToMalay closed 5 years ago

ToMalay commented 5 years ago

I'm trying to implement OpENer adapter stack in my internal network library. I try to use the exclusive owner connection type in implicit messaging system to exchange data with a scanner but i don't find how to get the output data from the scanner (O->T). I don't have any trace from the AfterAssemblyDataReceived reimplementated function so i can't copy those data to analyse it in my library. Is it a normal behavior ?

For now I change output data thanks to getAttributeSingle service on the correct instance ID and attribute ID (i think it use the explicit messaging system there); and then i use ForwardOpen service with the implicit messaging system to send input data to the scanner. I don't think it's the correct way to exchange data ...

I use EtherNet/IP explorer .NET project as scanner. (https://sourceforge.net/projects/enipexplorer/)

MartinMelikMerkumians commented 5 years ago

The O->T data will be copied into the specified output assembly (if I am not wrong).

Not sure what you mean by "I don't have any trace from the AfterAssemblyDataReceived" , but this function is just a starting point for an ENIP application to process the received data. It is empty in the demo implementation and not needed for receiving of data, as this is handled by the implicit connection itself.

ToMalay commented 5 years ago

I use AfterAssemblyDataReceived to get and then process output data in my application. It work with a setAttributeSingle service.

I thought it was call after a FowardOpen request from a scanner.

I also try to use CheckIoConnectionEvent function (called after a FowardOpen request) and use GetCipAttribute function on my output assembly but while the implicit messaging is running, if i change output data on the scanner, nothing change on OpENer side. Maybe the issue is on the scanner side.

Is it a normal process to change output data with a setAttributeSingle service and then use a forwardOpen request to intiate a communication ? Is it allow to change output data while a implicit messaging is running ?

I try to make a sort of request/response system, thus i try to implement a read and a write functions between the EIP stack and my application .

azoitl commented 5 years ago

for working with implicit connected messages based on assembly objects OpEner has two callback methods that can be utilized for handling the data:

As the name implicit connected messages implies the sending and reception of these messages is defined in the connection data given in the forwardopen request from the scanner. Therefore opener manages this for you and you don't need to take care of the sending or reception management.

ToMalay commented 5 years ago

Ok it was what i thought Maybe there is a problem on the scanner side even if i see a function that send a UDP datagram cyclically. I'll try to catch it with wireshark.

Is it strange that BeforeAssemblyDataSend is call and not AfterAssemblyDataReceived ?

ToMalay commented 5 years ago

I re-run the sample application of the OpENer repo and here is the traces : It's from when it receive the ForwardOpen request to the FowardClose request (I add traces at the begining of CheckIoConnectionEvent , AfterAssemblyDataReceived , and BeforeAssemblyDataSend)

Entering HandleDataOnTcpSocket for socket: 376 Data received on tcp: Handles data for TCP socket: 376 Send Request/Reply Data NotifyMessageRouter: routing unconnected message NotifyMessageRouter: calling notify function of class 'connection manager' notify: found instance 1 notify: calling ForwardOpen service ForwardOpen: ConConnID 4294901832, ProdConnID 4294901833, ConnSerNo 33572 We have a Non-Null request We have a Non-Matching request classid 4 (assembly) Configuration instance id 151 assembly: type bidirectional connection point 150 connection point 100 Resulting PIT value: 256 IO Exclusive Owner connection requested No PIT segment available networkhandler: UDP socket 244 networkhandler: bind UDP socket 244 networkhandler: UDP socket 240 connection manager: connect succeeded assembleFWDOpenResponse: sending success response notifyMR: notify function of class 'connection manager' returned a reply Sets time stamp for socket 376 TCP reply sent: Sets time stamp for socket 376 UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae -------_ EIP_Stack BeforeAssemblyDataSend -- instancenumber = 150 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 151 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 151 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 150 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIPStack CheckIoConnectionEvent ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instancenumber = 100 ------- EIP_Stack BeforeAssemblyDataSend -- instance_number = 10UDP port to be sent to: 8ae Connection ConnNr: 33572 timed out Entering HandleDataOnTcpSocket for socket: 376 Data received on tcp: Handles data for TCP socket: 376 Send Request/Reply Data NotifyMessageRouter: routing unconnected message NotifyMessageRouter: calling notify function of class 'connection manager' notify: found instance 1 notify: calling ForwardClose service ForwardClose: ConnSerNo 33572 networkhandler: closing socket 244 networkhandler: closing socket done 244 networkhandler: closing socket 240 networkhandler: closing socket done 240 Attempt to provide a NULL pointer to node pointer notifyMR: notify function of class 'connection manager' returned a reply Sets time stamp for socket 376 TCP reply sent: Sets time stamp for socket 376

I'm pretty sure that AfterAssemblyDataReceived is not call. Maybe I have a network config issue i couldn't find in traces. Is it the normal process ?

MartinMelikMerkumians commented 5 years ago

Hi,

based on your trace I would agree, that you seem to have network issues, as your connection has a time-out. Does your connection stays active for approx. 10s? Because this would be the initial timeout value.

ToMalay commented 5 years ago

Yes i have a timeout connection after 10s.

I find where is the trace in the source code (i.e cipconnectionmanager.c / ManageConnections) however i don't understand why it happens.

Is it link to the fact that it receive nothing ?

On wireshark i set this filter : "tcp.port==44818 || udp.port == 2222" but i didn't catch anything.

MartinMelikMerkumians commented 5 years ago

Yes, it seems that your connection times out due to not receiving messages from your scanner. The initial timeout value for a newly established connection is 10s.

I usually filter based on IP addresses to catch anything, but not seeing any traffic on 0xAF12 seems strange, as you would have to see at least the establishing Forward Open request.

ToMalay commented 5 years ago

I think it was a firewall configuration issue and because i run the scanner and the adapter on the same PC maybe it used the loopback, so i can't see network frames with wireshark. Now i work on 2 PCs and I think the implicit message go forward in the process. I'm not sure i still have the correct network configuration but it seems that the scanner can send UDP datagram.

Now i have another strange log :

networkhandler: new TCP connection network handler: accepting new TCP socket: 388 New highest socket: 388 networkhandler: opened new TCP connection on fd 388 Entering HandleDataOnTcpSocket for socket: 388 Data received on tcp: Handles data for TCP socket: 388 Register session Adds socket 388 to socket timers Sets time stamp for socket 388 Sets time stamp for socket 388 TCP reply sent: Sets time stamp for socket 388 TCP response was not fully sent Entering HandleDataOnTcpSocket for socket: 388 Data received on tcp: Handles data for TCP socket: 388 Send Request/Reply Data NotifyMessageRouter: routing unconnected message NotifyMessageRouter: calling notify function of class 'connection manager' notify: found instance 1 notify: calling ForwardOpen service ForwardOpen: ConConnID 0, ProdConnID 33181970, ConnSerNo 20754 We have a Non-Null request We have a Non-Matching request classid 4 (assembly) Configuration instance id 151 assembly: type bidirectional connection point 150 connection point 100 Resulting PIT value: 256 Exclusive Owner or Input Only connection closed - Instance type :2 Close all instance type 4 only connections networkhandler: closing socket 336 networkhandler: closing socket done 336 networkhandler: closing socket 244 networkhandler: closing socket done 244 Attempt to provide a NULL pointer to node pointer IO Exclusive Owner connection requested No PIT segment available networkhandler: UDP socket 244 networkhandler: bind UDP socket 244 networkhandler: UDP socket 336 connection manager: connect succeeded assembleFWDOpenResponse: sending success response notifyMR: notify function of class 'connection manager' returned a reply Sets time stamp for socket 388 TCP reply sent: Sets time stamp for socket 388 UDP port to be sent to: 8ae Entering HandleDataOnTcpSocket for socket: 388 Data received on tcp: Handles data for TCP socket: 388 unregister session encap.c: Unregister Session Command networkhandler: closing socket 388 networkhandler: closing socket done 388 Processing UDP consuming message Starting data length: 75 data length after sequence count: 73 Run/Idle handler: 0x1Setting extended status: 60Processing UDP consuming message Starting data length: 75 data length after sequence count: 73 Run/Idle handler: 0x1Setting extended status: 60UDP port to be sent to: 8ae Processing UDP consuming message Starting data length: 75 data length after sequence count: 73 Run/Idle handler: 0x1Setting extended status: 60UDP port to be sent to: 8ae Processing UDP consuming message Starting data length: 75 data length after sequence count: 73 Run/Idle handler: 0x1Setting extended status: 60UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae UDP port to be sent to: 8ae Connection ConnNr: 20754 timed out Close all instance type 3 only connections Close all instance type 4 only connections

I can see the FowardOpen request on wireshark and then i have a unregister session request.

Do you something that can explain why the session close automatically ?

I change my scanner application to the Hilscher EtherNet/IP Tool.

MartinMelikMerkumians commented 5 years ago

The unregistration of the session is not harmful. This just means, that your scanner closes his class 3 and encapsulation session after the successful forward open command. Class1 connection do not rely on an open session.

MartinMelikMerkumians commented 5 years ago

@ToMalay Can we close this issue?

ToMalay commented 5 years ago

Yes It was my network config. I have to disable my firewall and don't use the network loopback (use another PC or VM) to exchange data with a scanner