blob: e10e7adcd63f64d7bbd4de86f3ac831b826315be [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>PLC4X &#x2013; </title>
<script src="../../js/jquery.slim.min.js" type="text/javascript"></script>
<!--script src="../../js/popper.min.js" type="javascript"></script-->
<script src="../../js/bootstrap.bundle.min.js" type="text/javascript"></script>
<!-- The tooling for adding images and links to Apache events -->
<script src="https://www.apachecon.com/event-images/snippet.js" type="text/javascript"></script>
<!-- FontAwesome -->
<link rel="stylesheet" href="../../css/all.min.css" type="text/css"/>
<!-- Bootstrap -->
<link rel="stylesheet" href="../../css/bootstrap.min.css" type="text/css"/>
<!-- Some Maven Site defaults -->
<link rel="stylesheet" href="../../css/maven-base.css" type="text/css"/>
<link rel="stylesheet" href="../../css/maven-theme.css" type="text/css"/>
<!-- The PLC4X version of a bootstrap theme -->
<link rel="stylesheet" href="../../css/themes/plc4x.css" type="text/css" id="pagestyle"/>
<!-- A custom style for printing content -->
<link rel="stylesheet" href="../../css/print.css" type="text/css" media="print"/>
<meta http-equiv="Content-Language" content="en"/>
</head>
<body class="composite">
<nav class="navbar navbar-light navbar-expand-md bg-faded justify-content-center border-bottom">
<!--a href="/" class="navbar-brand d-flex w-50 mr-auto">Navbar 3</a-->
<a href="https://plc4x.apache.org/" id="bannerLeft"><img src="../../images/apache_plc4x_logo_small.png" alt="Apache PLC4X"/></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsingNavbar3">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse w-100" id="collapsingNavbar3">
<ul class="navbar-nav w-100 justify-content-center">
<li class="nav-item">
<a class="nav-link" href="../../index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../users/index.html">Users</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../developers/index.html">Developers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../apache/index.html">Apache</a>
</li>
</ul>
<ul class="nav navbar-nav ml-auto justify-content-end">
<li class="nav-item row valign-middle">
<a class="acevent" data-format="wide" data-mode="light" data-event="random" style="width:240px;height:60px;"></a>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="row h-100">
<main role="main" class="ml-sm-auto px-4 w-100 h-100">
<div class="sect1">
<h2 id="deltav_industrial_ethernet_communication">DeltaV Industrial Ethernet Communication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The DeltaV protocol is used in the Emerson DeltaV system.
In contrast to most other systems, this is a combination of PLC and Control System.
As Emerson seems to insist on the devices not being PLCs, but controllers, well call them this way in this document.
Same with the Control System, these seem to be called OS (Operator System).</p>
</div>
<div class="sect2">
<h3 id="disclaimer">Disclaimer</h3>
<div class="paragraph">
<p>As we had absolutely no information on the details of the protocol, we started by taking an existing DeltaV training system and replaced the network switch with a hub and used this to take network captures of the entire network traffic of the DeltaV network.</p>
</div>
<div class="paragraph">
<p>These network captures and some knowledge of the normal system operation were all we had.</p>
</div>
<div class="paragraph">
<p>All information we got, we got by inspecting these captures, building hypothesis and implementing tooling to verify these assumptions.</p>
</div>
<div class="paragraph">
<p>Definitely we will not have interpreted everything correct and we&#8217;ll probably do a lot of updating of this page.</p>
</div>
<div class="paragraph">
<p>Due to this uncertainty we are only implementing a <code>promiscuous mode</code> driver, which will be able to read ongoing traffic without the ability to actively interact with the system.</p>
</div>
<div class="paragraph">
<p>Read <a href="reverse-engineering.html">here</a> for a document on how we proceeded with reverse engineering this protocol.</p>
</div>
</div>
<div class="sect2">
<h3 id="the_wrapper_protocol">The Wrapper Protocol</h3>
<div class="paragraph">
<p>All communication seems to be done using the <code>UDP</code> protocol on port <code>18507</code>.</p>
</div>
<div class="paragraph">
<p>When working with the dumps it seems that this version of the DeltaV protocol was implemented by wrapping another protocol within a thin wrapper protocol.
We have seen this for almost all other industrial controller types.
We are hereby assuming that the inner protocol is the version of the DeltaV protocol, which is used for serial communication.</p>
</div>
<div class="paragraph">
<p>The general structure of such a wrapper packet seems to look like this:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../../images/deltav-wrapper-packet.svg" alt="deltav wrapper packet" width="896" height="400"/>
</div>
</div>
<div class="paragraph">
<p>After the fixed header of <code>0xFACE</code> comes a short value providing the <code>Payload Length</code>.</p>
</div>
<div class="paragraph">
<p>After the payload probably comes the message type.
Here we have observed the internal structure of packets with the same type to be very similar, so we&#8217;re quite sure this is a type.</p>
</div>
<div class="paragraph">
<p>The <code>Message Id</code> seems to be a counter existing for every communication between two partners, which is incremented for every packet sent to the other partner.</p>
</div>
<div class="paragraph">
<p>We have observed every unit to have a unique <code>Sender Id</code>, however a controller has been seen to have a differing id when communicating with a different operator system.
What we did notice however, was that controllers usually had numerical ids while the OSes had hexadecimal letters.
So an id of <code>0x0002</code> would probably imply a controller and an id of <code>0x000d</code> would imply an operator system.
But we could be wrong with this assumption and this just being a result of convention.</p>
</div>
<div class="paragraph">
<p>The 3 bytes after the id seem to relate to a timestamp.
Inspecting the packets and correlating this to the timestamps in our packet captures, lead us to the assumption that this timestamp uses the first 14 bits for encoding seconds and the last 10 bits for encoding the sub-second fraction.
While a 3 byte timestamp is only able to measure a 10 minute time-slot and is probably not usable for absolute time measuring, it might be useful to measure transfer times.
For this a 4 byte value would have been a waste of network capacity and a 2 byte value wouldn&#8217;t be able to measure more than 60 seconds, which might be too short when taking into account packet resending and network timeouts.
So for now we are assuming this format is used.</p>
</div>
<div class="paragraph">
<p>The following 3 bytes seem to have a constant value of <code>0x800400</code> for most packets, except the ones with a type of <code>0x03</code> and <code>0x04</code>.
For these two types the value seems to be <code>0x004400</code>. Here we currently can&#8217;t make an assumption on the meaning of these fields.
However as the <code>0x003</code> and <code>0x004</code> seem to be the first packets used for establishing the connection between the OS and the controller, these could somehow relate to the connection state.</p>
</div>
<div class="paragraph">
<p>After these mysterious 3 bytes comes the actual payload of the packet.
The details of these will be discussed later in this document.</p>
</div>
<div class="paragraph">
<p>At the end comes a short value that seems to be a completely different value for every packet.
As the message id and timestamp are different for every message, we are assuming this is a simple checksum.
However we currently have no idea on how this is calculated and we haven&#8217;t invested any time in finding this out.</p>
</div>
<div class="paragraph">
<p>UDP being connectionless the DeltaV network protocol seems to require acknowledging.
This is done by sending a packet back to the originator, but with a length of <code>0x0000</code> and the same <code>type</code> and mesasge-id` as the packet that is acknowledged.</p>
</div>
</div>
<div class="sect2">
<h3 id="high_level_view_of_the_protocol">High Level View of the Protocol</h3>
<div class="paragraph">
<p>In this section we&#8217;ll describe the general structure of how the communication looks like - which message types are sent when and in which sequence.</p>
</div>
<div class="sect3">
<h4 id="connecting_an_os_to_a_controller">Connecting an OS to a Controller</h4>
<div class="listingblock">
<div class="content">
<pre>Failed to generate image: Could not find the 'seqdiag', 'seqdiag3' executable in PATH; add it to the PATH or specify its location using the 'seqdiag' document attribute
{
Controller; OS;
edge_length = 400;
span_height = 18;
default_fontsize = 12;
activation = none;
OS -&gt; Controller [label = "Type 0x0003 (Connection Request)"];
OS &lt;- Controller [label = "Type 0x0004 (Connection Response)"];
OS -&gt; Controller [label = "Type 0x0002 Subtype 0x0501 (Version Information)"];
OS &lt;-- Controller [label = "Ack"];
OS &lt;- Controller [label = "Type 0x0002 Subtype 0x0502 (Version Information)"];
OS --&gt; Controller [label = "Ack"];
}</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="regular_sync">Regular sync</h4>
<div class="paragraph">
<p>It seems that every 15 seconds two packets are exchanged.</p>
</div>
<div class="paragraph">
<p>The type of these is always <code>0x0006</code>.</p>
</div>
<div class="paragraph">
<p>One thing that is quite obvious, is that these are the only messages, for which the message id doesn&#8217;t seem to be incremented.
So these messages have the exact same id as the following request being sent out.</p>
</div>
<div class="paragraph">
<p>We are assuming that these are sort of heartbeat messages and additionally sync the message ids so the remote could see if it lost messages in the last 15 seconds.</p>
</div>
<div class="paragraph">
<p>But that is just an assumption.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Failed to generate image: no implicit conversion of nil into String
{
Controller; OS;
edge_length = 400;
span_height = 18;
default_fontsize = 12;
activation = none;
OS -&gt; Controller [label = "Type 0x0006 (Sync)"];
OS &lt;-- Controller [label = "Type 0x0006 (Sync)"];
}</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="data_changes_in_the_controller">Data changes in the Controller</h4>
<div class="paragraph">
<p>In general it seems as if all sub-types regarding normal data changes start with <code>0x04</code>.</p>
</div>
<div class="paragraph">
<p>If the value of a subscribed value changes in the controller, a message type <code>0x0002</code> with sub-type <code>0x0403</code> is sent.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Failed to generate image: no implicit conversion of nil into String
{
Controller; OS;
edge_length = 400;
span_height = 18;
default_fontsize = 12;
activation = none;
OS &lt;- Controller [label = "Type 0x0002 Subtype 0x0403 (...)"];
OS --&gt; Controller [label = "Ack"];
}</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="alarms_in_the_controller">Alarms in the Controller</h4>
<div class="paragraph">
<p>In general it seems as if all sub-types regarding events and alarms start with <code>0x03</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Failed to generate image: no implicit conversion of nil into String
{
Controller; OS;
edge_length = 400;
span_height = 18;
default_fontsize = 12;
activation = none;
OS &lt;- Controller [label = "Type 0x0002 Subtype 0x030? (...)"];
OS --&gt; Controller [label = "Ack"];
}</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<footer class="pt-4 my-md-5 pt-md-5 w-100 border-top">
<div class="row justify-content-md-center" style="font-size: 13px">
<div class="col col-6 text-center">
Copyright &#169; 2017&#x2013;2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
All rights reserved.<br/>
Apache PLC4X, PLC4X, Apache, the Apache feather logo, and the Apache PLC4X project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries. All other marks mentioned may be trademarks or registered trademarks of their respective owners.
<br/><div style="text-align:center;">Home screen image taken from <a
href="https://flic.kr/p/chEftd">Flickr</a>, "Tesla Robot Dance" by Steve Jurvetson, licensed
under <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0 Generic</a>, image cropped
and blur effect added.</div>
</div>
</div>
</footer>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="../../js/jquery.slim.min.js"></script>
<script src="../../js/popper.min.js"></script>
<script src="../../js/bootstrap.min.js"></script>
<script type="text/javascript">
$('.carousel .carousel-item').each(function(){
var next = $(this).next();
if (!next.length) {
next = $(this).siblings(':first');
}
next.children(':first-child').clone().appendTo($(this));
for (let i = 0; i < 3; i++) {
next=next.next();
if (!next.length) {
next = $(this).siblings(':first');
}
next.children(':first-child').clone().appendTo($(this));
}
});
</script>
</body>
</html>