This is an automated email from the ASF dual-hosted git repository. hutcheb pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 40e6a66cd868e78d4890095dc2a0dd4874c3f18d Author: Ben Hutcheson <[email protected]> AuthorDate: Sat Feb 11 12:48:51 2023 +0100 fix(plc4j/profinet): Implmented pop for the dcerpc response queue. Syncronized cyclic counter for pnio packets --- .../profinet/context/ProfinetDeviceContext.java | 14 +++-- .../java/profinet/device/ProfinetChannel.java | 3 +- .../plc4x/java/profinet/device/ProfinetDevice.java | 73 +++++++++++++++++++--- .../main/resources/protocols/profinet/pndcp.mspec | 22 +++---- 4 files changed, 87 insertions(+), 25 deletions(-) diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java index e0152ce053..128f89fa98 100644 --- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java +++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/context/ProfinetDeviceContext.java @@ -459,12 +459,18 @@ public class ProfinetDeviceContext implements DriverContext, HasConfiguration<Pr this.frameId = frameId; } - public Map<Long, ProfinetCallable<DceRpc_Packet>> getQueue() { - return queue; + public ProfinetCallable<DceRpc_Packet> popFromQueue(long sequenceNumber) { + ProfinetCallable<DceRpc_Packet> r = queue.get(sequenceNumber); + queue.remove(sequenceNumber); + return r; } - public void setQueue(Map<Long, ProfinetCallable<DceRpc_Packet>> queue) { - this.queue = queue; + public boolean hasSequenecNumberInQueue(long sequenceNumber) { + return queue.containsKey(sequenceNumber); + } + + public void addToQueue(long sequenceNumber, ProfinetCallable<DceRpc_Packet> obj) { + queue.put(sequenceNumber, obj); } public int getSessionKey() { diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java index deb608c1e0..d1c1c4ffe8 100644 --- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java +++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetChannel.java @@ -103,7 +103,7 @@ public class ProfinetChannel { } else if (ethernetPacket.getHeader().getType() == EtherType.IPV4 && ethernetPacket.getPayload().getPayload() instanceof UdpPacket) { UdpPacket payload = (UdpPacket) ethernetPacket.getPayload().getPayload(); // Check if it's a PROFINET packet - if (payload.getHeader().getDstPort().value() == -30572 || payload.getHeader().getDstPort().value() == -15536) { + if (payload.getHeader().getDstPort().value() == -30572 || payload.getHeader().getDstPort().value() == -15536 || payload.getHeader().getDstPort().value() == -15535) { isPnPacket = true; } } @@ -139,7 +139,6 @@ public class ProfinetChannel { } } } - } else if (payload instanceof Ethernet_FramePayload_LLDP) { Lldp_Pdu pdu = ((Ethernet_FramePayload_LLDP) payload).getPdu(); if (discoverer != null) { diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java index e10de6e0b4..3e281301f5 100644 --- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java +++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/device/ProfinetDevice.java @@ -70,6 +70,8 @@ public class ProfinetDevice implements PlcSubscriber{ private String deviceId; private Thread eventLoop = null; Map<String, List<Consumer<PlcSubscriptionEvent>>> registrations = new HashMap<>(); + private int offset = 0; + private boolean firstMessage = true; public ProfinetDevice(String deviceName, String deviceAccess, String subModules, BiFunction<String, String, ProfinetISO15745Profile> gsdHandler) { this.gsdHandler = gsdHandler; @@ -123,7 +125,7 @@ public class ProfinetDevice implements PlcSubscriber{ } private void recordIdAndSend(ProfinetCallable<DceRpc_Packet> callable) { - deviceContext.getQueue().put(callable.getId(), callable); + deviceContext.addToQueue(callable.getId(), callable); ProfinetMessageWrapper.sendUdpMessage( callable, deviceContext @@ -270,8 +272,8 @@ public class ProfinetDevice implements PlcSubscriber{ public void handleResponse(Ethernet_FramePayload_IPv4 packet) { logger.debug("Received packet for {}", packet.getPayload().getObjectUuid()); long objectId = packet.getPayload().getSequenceNumber(); - if (deviceContext.getQueue().containsKey(objectId)) { - deviceContext.getQueue().get(objectId).handle(packet.getPayload()); + if (deviceContext.hasSequenecNumberInQueue(objectId)) { + deviceContext.popFromQueue(objectId).handle(packet.getPayload()); } else { PnIoCm_Packet payloadPacket = packet.getPayload().getPayload(); deviceContext.setActivityUuid(packet.getPayload().getActivityUuid()); @@ -283,6 +285,12 @@ public class ProfinetDevice implements PlcSubscriber{ deviceContext.setState(ProfinetDeviceState.APPLRDY); } } + } else if (payloadPacket instanceof PnIoCm_Packet_Fault) { + DceRpcAck ack = new DceRpcAck(deviceContext.getActivityUuid(), deviceContext.getSequenceNumber()); + recordIdAndSend(ack); + } else if (payloadPacket instanceof PnIoCm_Packet_Ping) { + DceRpcAck ack = new DceRpcAck(deviceContext.getActivityUuid(), deviceContext.getSequenceNumber()); + recordIdAndSend(ack); } else { deviceContext.setState(ProfinetDeviceState.ABORT); logger.error("Unable to match Response with Requested Profinet packet"); @@ -348,10 +356,12 @@ public class ProfinetDevice implements PlcSubscriber{ Map<String, ResponseItem<PlcValue>> tags = new HashMap<>(); ReadBuffer buffer = new ReadBufferByteBased(cyclicPdu.getDataUnit().getData()); + if (firstMessage) { + offset = cyclicPdu.getCycleCounter(); + firstMessage = false; + } + try { - if (deviceContext.getModules() == null) { - logger.error("HH"); - } for (ProfinetModule module : deviceContext.getModules()) { module.parseTags(tags, deviceContext.getDeviceName(), buffer); } @@ -865,6 +875,53 @@ public class ProfinetDevice implements PlcSubscriber{ } } + public class DceRpcAck implements ProfinetCallable<DceRpc_Packet> { + + private final DceRpc_ActivityUuid activityUuid; + private long id; + + public DceRpcAck(DceRpc_ActivityUuid activityUuid, long seqNumber) { + this.activityUuid = activityUuid; + this.id = seqNumber; + } + + public CompletableFuture<Boolean> getResponseHandled() { + return null; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public DceRpc_Packet create() { + return new DceRpc_Packet( + DceRpc_PacketType.NO_CALL, + false, + true, + true, + IntegerEncoding.BIG_ENDIAN, + CharacterEncoding.ASCII, + FloatingPointEncoding.IEEE, + new DceRpc_ObjectUuid((byte) 0x00, 0x0001, Integer.decode("0x" + deviceId), Integer.decode("0x" + vendorId)), + new DceRpc_InterfaceUuid_ControllerInterface(), + activityUuid, + 0, + id, + DceRpc_Operation.CONTROL, + new PnIoCm_Packet_NoCall() + ); + } + + @Override + public void handle(DceRpc_Packet packet) { + logger.debug("Received an unintented packet"); + } + } + public class CyclicData implements ProfinetCallable<Ethernet_Frame> { private final long startTime; @@ -906,7 +963,7 @@ public class ProfinetDevice implements PlcSubscriber{ buffer.writeByte((byte) 0x00); } - int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC))) % 65536); + int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC)) + offset) % 65536); Ethernet_Frame frame = new Ethernet_Frame( deviceContext.getMacAddress(), @@ -932,7 +989,7 @@ public class ProfinetDevice implements PlcSubscriber{ deviceContext.setState(ProfinetDeviceState.ABORT); logger.error("Error serializing cyclic data for device {}", deviceContext.getDeviceName()); - int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC))) % 65536); + int elapsedTime = (int) ((((System.nanoTime() - startTime)/(MIN_CYCLE_NANO_SEC)) + offset) % 65536); Ethernet_Frame frame = new Ethernet_Frame( deviceContext.getMacAddress(), diff --git a/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec b/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec index 42a1deb7e6..dbc515c62c 100644 --- a/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec +++ b/protocols/profinet/src/main/resources/protocols/profinet/pndcp.mspec @@ -70,17 +70,17 @@ // Delay Parameter End ] ['Alarm_Low' PnDcp_Pdu_AlarmLow - [simple uint 16 alarmDstEndpoint] - [simple uint 16 alarmSrcEndpoint] - [simple uint 4 version] - [simple uint 4 errorType] - [simple uint 4 tAck] - [simple uint 4 windowSize] - [simple uint 16 senSeqNum] - [simple uint 16 ackSeqNum] - [implicit uint 16 varPartLen 'COUNT(varPart)'] - [array byte varPart length 'varPartLen'] - ] + [simple uint 16 alarmDstEndpoint] + [simple uint 16 alarmSrcEndpoint] + [simple uint 4 version] + [simple uint 4 errorType] + [simple uint 4 tAck] + [simple uint 4 windowSize] + [simple uint 16 senSeqNum] + [simple uint 16 ackSeqNum] + [implicit uint 16 varPartLen 'COUNT(varPart)'] + [array byte varPart length 'varPartLen'] + ] ['DCP_Identify_ReqPDU' PnDcp_Pdu_IdentifyReq [const uint 8 serviceId 0x05 ] // ServiceType Start
