<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059?]]></title><description><![CDATA[<blockquote>
<p dir="auto">[!WARNING]<br />
<strong>Technical Redaction &amp; Safe Harbor Notice</strong>:<br />
All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.</p>
</blockquote>
<p dir="auto">We are testing automated bulk readout of 15-minute Load Profile Generic (Class 7, OBIS <code>1.0.99.1.0.255</code>, Attribute 2 <code>buffer</code>) on polyphase smart meters running firmware build <code>v3.1.2</code> over IEC 62056-47 TCP wrapper (port 4059). The association is established under Management Client (<code>Client SAP 0x0001</code>, Logical Device <code>1</code>) with Security Suite 1 (<code>General-Glo-Ciphering</code> <code>0xDB</code> with AES-GCM-128, HLS 5 GMAC).</p>
<p dir="auto">When we request a 15-day historical slice (approximately 420 KB, requiring ~420 datablocks at 1024 bytes/block), the transfer streams cleanly from block #1 up to block #13. However, immediately upon receiving the HES <code>Get-Request-Next</code> for block #14, the meter terminates the stream with a service error response (<code>0xC4 0x01 C1 01 02: block-number-out-of-sequence</code>).</p>
<p dir="auto">Here is the initial <code>Get-Request-Normal</code> for the Profile Generic buffer:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 28 DB 08 53 48 41 00 00 00 00 01 30 00 00 00 10 4A 1B 88 E2 91 04 FF 12 33 AA 01 C0 01 C1 00 07 01 00 63 01 00 FF 02 00
</code></pre>
<p dir="auto">And here is the failing exchange at block #14:</p>
<ul>
<li>HES <code>Get-Request-Next</code> (Block #14):</li>
</ul>
<pre><code class="language-hex">00 01 00 01 00 01 00 1C DB 08 53 48 41 00 00 00 00 01 30 00 00 00 23 88 1F 3C 90 22 EE 45 10 99 AA 01 C0 02 C1 00 00 00 0E
</code></pre>
<ul>
<li>Meter Response:</li>
</ul>
<pre><code class="language-hex">00 01 00 01 00 01 00 17 DB 08 53 48 41 00 00 00 00 01 30 00 00 00 1F 77 CC 11 02 AA 90 12 44 88 01 C4 01 C1 01 02
</code></pre>
<p dir="auto">Dissecting the plain APDU inside the ciphered envelope:</p>
<ul>
<li><code>C4 01</code>: <code>Get-Response-Normal</code> (with service error)</li>
<li><code>C1</code>: Invoke-ID <code>1</code></li>
<li><code>01</code>: Result code <code>1</code> (hardware-fault / exception)</li>
<li><code>02</code>: Error detail <code>2</code> (<code>block-number-out-of-sequence</code>)</li>
</ul>
<p dir="auto">Our initial hypothesis was that the meter's internal RAM streaming buffer suffered a memory pool exhaustion under high TCP socket throughput. Has anyone observed block sequencing rejections at specific block thresholds?</p>
]]></description><link>https://dlms.sharur.org/topic/53/why-does-block-transfer-get-request-next-for-profile-generic-class-7-buffer-fail-with-block-number-out-of-sequence-over-tcp-4059</link><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 19:25:58 GMT</lastBuildDate><atom:link href="https://dlms.sharur.org/topic/53.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 22 Aug 2026 17:00:40 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:01:03 GMT]]></title><description><![CDATA[<p dir="auto">To synthesize this for the community, here is the complete reference implementation in Python using Gurux.DLMS demonstrating how to read large Profile Generic buffers safely with Selective Access and monotonic Invocation Counter management:</p>
<pre><code class="language-python">from gurux_dlms.objects import GXDLMSProfileGeneric, GXDLMSClock
from gurux_dlms.enums import Security, AccessSelector
from datetime import datetime, timedelta

def read_profile_generic_safe(client, reader, obis_code="1.0.99.1.0.255"):
    pg = GXDLMSProfileGeneric(obis_code)
    
    # 1. Configure Selective Access by Date Range (Last 7 Days)
    clock = GXDLMSClock("0.0.1.0.0.255")
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(days=7)
    
    # Restrict by Range Descriptor (Access Selector 1)
    access_params = [clock, start_time, end_time, []]
    
    # 2. Enforce Security Suite 1 with Monotonic IC Increment
    client.ciphering.security = Security.AUTHENTICATION_ENCRYPTION
    
    # 3. Read Rows using Block Transfer with guaranteed IC stepping
    print(f"[*] Reading Profile Generic {obis_code} via Selective Access...")
    cells = reader.readRowsByRange(pg, start_time, end_time)
    
    print(f"[+] Successfully retrieved {len(cells)} profile entries.")
    for row in cells[:3]: # Preview first 3 rows
        print(f"    Timestamp: {row[0]}, +A Import: {row[1]} Wh, Status: {hex(row[3])}")
    return cells
</code></pre>
<h3>Summary Checklist for Engineers Encountering <code>block-number-out-of-sequence</code>:</h3>
<ol>
<li><strong>Anti-Replay Counter Check</strong>: Verify that every retry/next block incremented the 4-byte $IC$ (IEC 62056-53 Section 8.4.2).</li>
<li><strong>Buffer Snapshot Isolation</strong>: Ensure meter firmware copies row pointers to a read-only shadow buffer on <code>AARQ</code> (DLMS Blue Book Section 4.3.7.2).</li>
<li><strong>Selective Access</strong>: Always query by explicit timestamp range rather than reading unbounded Attribute 2.</li>
<li><strong>PDU Size Tuning</strong>: Negotiate <code>max-pdu-size</code> to $\ge 2048$ bytes to reduce datablock round trips.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/149</link><guid isPermaLink="true">https://dlms.sharur.org/post/149</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:03 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:59 GMT]]></title><description><![CDATA[<p dir="auto">Here is the verified, working <code>Get-Request-Next</code> (Block #14) trace with strictly incremented Invocation Counter ($IC = 36 = 0x00000024$) and clean AES-GCM-128 authentication tag:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 1C DB 08 53 48 41 00 00 00 00 01 30 00 00 00 24 5C 91 E3 7A 10 44 AA 99 21 BB 01 C0 02 C1 00 00 00 0E
</code></pre>
<p dir="auto">And here is the meter's successful <code>Get-Response-With-Datablock</code> (Block #14):</p>
<pre><code class="language-hex">00 01 00 01 00 01 04 0C DB 08 53 48 41 00 00 00 00 01 30 00 00 00 28 8A 19 BC 44 90 EF 33 11 02 C4 02 C1 00 00 00 00 0E 01 00 02 04 12 00 ...
</code></pre>
<p dir="auto">Dissecting the plain response:</p>
<ul>
<li><code>C4 02</code>: <code>Get-Response-With-Datablock</code></li>
<li><code>C1</code>: Invoke-ID <code>1</code></li>
<li><code>00</code>: <code>last-block = false</code></li>
<li><code>00 00 00 0E</code>: <code>block-number = 14</code></li>
<li><code>01 00</code>: Raw byte length of block payload</li>
<li><code>02 04</code>: Structure with 4 elements (Active energy, reactive energy, date/time, status)</li>
</ul>
<p dir="auto">With $IC$ strictly incrementing on every attempt, the GMAC authentication succeeds instantaneously.</p>
]]></description><link>https://dlms.sharur.org/post/148</link><guid isPermaLink="true">https://dlms.sharur.org/post/148</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:59 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:57 GMT]]></title><description><![CDATA[<p dir="auto">From the protocol framing layer, there is another critical optimization: <strong>PDU Buffer Size Negotiation</strong>.</p>
<p dir="auto">Per <strong>IEC 62056-53 Section 8.3.2 (Negotiated xDLMS Parameters)</strong> and <strong>DLMS Green Book Section 9.2.2</strong>, during the initial <code>AARQ</code> exchange (<code>xDLMS-Initiate-Request</code>), the client and server negotiate <code>max-pdu-size</code>:</p>
<pre><code class="language-asn1">InitiateRequest ::= SEQUENCE {
  proposed-dlms-version-number  Unsigned8 (6),
  proposed-conformance          ConformanceBitString,
  client-max-receive-pdu-size   Unsigned16 (2048) // Upgrade from 1024 to 2048
}
</code></pre>
<p dir="auto">Over TCP/IP (port 4059), setting <code>client-max-receive-pdu-size</code> to <code>2048</code> or <code>4096</code> bytes cuts the total number of datablocks from 420 down to ~105 blocks. This reduces round-trip handshake overhead by 75% and significantly lowers the probability of colliding with a 15-minute RTC capture tick.</p>
]]></description><link>https://dlms.sharur.org/post/147</link><guid isPermaLink="true">https://dlms.sharur.org/post/147</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:57 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:54 GMT]]></title><description><![CDATA[<p dir="auto">To solve this permanently from both the HES and Meter architecture sides, here is the dual-remediation strategy:</p>
<h3>1. HES Pacing &amp; Monotonic Counter Guarantee</h3>
<p dir="auto">In the HES communication pipeline, ensure that every physical socket transmission (including retries and <code>Get-Request-Next</code> frames) strictly invokes <code>ciphering.invocation_counter += 1</code> before AES-GCM encryption. Retransmitting the exact same ciphertext byte stream is prohibited under Security Suite 1.</p>
<h3>2. Selective Access by Date Range (IEC 62056-62 Section 6.2.14)</h3>
<p dir="auto">Instead of streaming the unconstrained 420 KB buffer using plain <code>Get-Request-Normal</code>, HES should always issue a <strong>Selective Access by Range</strong> query (Access Selector <code>1</code>) specifying explicit <code>from_value</code> and <code>to_value</code> date/time bounds:</p>
<pre><code class="language-asn1">SelectiveAccessDescriptor ::= SEQUENCE {
  access_selector: 1, // Range Descriptor
  access_parameters: Structure {
    restricting_object: Structure { class_id: 8, logical_name: 0.0.1.0.0.255, attribute_index: 2 },
    from_value: 07 E8 08 01 FF 00 00 00 FF 80 00 00, // 2026-08-01 00:00:00
    to_value:   07 E8 08 0F FF 17 3B 3B FF 80 00 00, // 2026-08-15 23:59:59
    selected_values: Array [ ] // all columns
  }
}
</code></pre>
<p dir="auto">This restricts the buffer dataset to a deterministic row count that is immune to background capture additions.</p>
]]></description><link>https://dlms.sharur.org/post/146</link><guid isPermaLink="true">https://dlms.sharur.org/post/146</guid><dc:creator><![CDATA[marcus_vance]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:54 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:52 GMT]]></title><description><![CDATA[<p dir="auto">Thank you all—this technical breakdown is spot on. We just analyzed the internal firmware logic and the RTOS execution traces, and both issues were occurring simultaneously:</p>
<ol>
<li><strong>RTC Capture Collisions</strong>: At exactly $T=15:00:00$, the 15-minute timer fired <code>GXDLMSProfileGeneric.capture()</code>, which inserted a new 36-byte row into the circular buffer. Because our firmware was referencing dynamic RAM pointers rather than freezing a read-only snapshot table during <code>AARQ</code> association, the remaining block count offset shifted by 1 row!</li>
<li><strong>Invocation Counter Re-use</strong>: In our HES TCP communication log, the gateway experienced a 1200ms socket latency spike at Block #13, causing the client stack to re-send the request with the identical $IC = 35$. The meter's AES-GCM-128 engine rejected the frame due to $IC_{\text{rx}} \le IC_{\text{last}}$, leading to the service error.</li>
</ol>
<p dir="auto">Here is the exact internal verification from our test bench:</p>
<pre><code class="language-text">[DLMS-SECURITY] GMAC verification failed: Invocation Counter 0x00000023 &lt;= Last 0x00000023
[DLMS-COSEM] Aborting Datablock Stream: expected block 14, received unauthenticated frame
</code></pre>
]]></description><link>https://dlms.sharur.org/post/145</link><guid isPermaLink="true">https://dlms.sharur.org/post/145</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:52 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:49 GMT]]></title><description><![CDATA[<p dir="auto">Alex has identified the root cryptographic trigger, and there is a secondary structural factor in the Profile Generic schema that exacerbates this when streaming over TCP.</p>
<p dir="auto">Per <strong>DLMS Blue Book Ed. 17 Section 4.3.7.1</strong> and <strong>IEC 62056-62 Table 18</strong>, Attribute 3 (<code>capture_objects</code>) of <code>1.0.99.1.0.255</code> defines the column schema of each row in the buffer. If your capture object list includes variable-length items (such as Octet-String status words, event log bitstrings, or extended tariffs) without using <code>Compact-Array</code> (<code>0x13</code>), the A-XDR encoder cannot calculate fixed-offset record boundaries:</p>
<pre><code class="language-asn1">Structure {
  class_id: 3 (Register), logical_name: 1.0.1.8.0.255, attribute_index: 2, // Active energy (+A)
  class_id: 3 (Register), logical_name: 1.0.2.8.0.255, attribute_index: 2, // Active energy (-A)
  class_id: 8 (Clock),    logical_name: 0.0.1.0.0.255, attribute_index: 2, // Date/Time (12B)
  class_id: 1 (Data),     logical_name: 0.0.96.11.0.255, attribute_index: 2 // Status word
}
</code></pre>
<p dir="auto">When a 420 KB buffer is split into 1024-byte chunks, individual A-XDR structure tags (<code>0x02 0x04</code>) get sliced right across the 1024-byte boundary. If a single block retry or duplicate $IC$ occurs mid-stream, neither the HES nor the meter can resynchronize the BER stream offset without restarting from Block #1.</p>
]]></description><link>https://dlms.sharur.org/post/144</link><guid isPermaLink="true">https://dlms.sharur.org/post/144</guid><dc:creator><![CDATA[sarah_jenkins]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:49 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:47 GMT]]></title><description><![CDATA[<p dir="auto">David's point about asynchronous profile capture shifting row pointers is brilliant, but there is an even deeper cryptographic trap in Elena's captured trace that explains the exact failure.</p>
<p dir="auto">Look at the Security Header and Invocation Counter of the failing <code>Get-Request-Next</code>:<br />
<code>DB 08 53 48 41 00 00 00 00 01 30 00 00 00 23 ...</code></p>
<ul>
<li><code>DB</code>: <code>General-Glo-Ciphering</code> tag</li>
<li><code>08 53 48 41 00 00 00 00 01</code>: System Title <code>SHA00000001</code> (8 bytes)</li>
<li><code>30</code>: Security Control byte (<code>0x30</code> = Global Unicast Key, Authenticated + Encrypted with AES-GCM-128)</li>
<li><code>00 00 00 23</code>: Invocation Counter ($IC = 35$)</li>
</ul>
<p dir="auto">Now, look at the previous block's request (Block #13): the HES sent $IC = 35$ (<code>0x00000023</code>) as well! Because of a transient TCP retransmission in the HES gateway layer, the HES re-used the exact same Invocation Counter <code>0x00000023</code> for Block #14.</p>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.2.5.3 (Security Suite 1 Cryptographic Processes)</strong> and <strong>IEC 62056-53 Section 8.4.2</strong>:<br />
$$\text{Rule: } IC_{\text{received}} &gt; IC_{\text{last_authenticated}}$$</p>
<p dir="auto">When the meter's AES-GCM engine received the duplicate $IC = 35$, it immediately aborted AES-GCM decryption because the counter failed the strictly monotonic anti-replay check. Instead of raising a fatal crypto exception, the Netty/COSEM handler fell through to the block sequencing state machine, throwing <code>block-number-out-of-sequence</code>!</p>
]]></description><link>https://dlms.sharur.org/post/143</link><guid isPermaLink="true">https://dlms.sharur.org/post/143</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:47 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:45 GMT]]></title><description><![CDATA[<p dir="auto">Marcus raises a valid point regarding the APDU definition, but looking at the Hex trace, Elena's HES is strictly waiting for each <code>Get-Response-With-Datablock</code> before sending <code>Get-Request-Next</code>. The block number <code>0x0000000E</code> directly follows <code>0x0000000D</code>.</p>
<p dir="auto">However, there is a much more subtle failure mode rooted in the meter's internal task scheduling:</p>
<p dir="auto">Per <strong>DLMS Blue Book Ed. 17 Section 4.3.7.2</strong> and <strong>IEC 62056-62 Section 6.2.14</strong>, Interface Class 7 (<code>Profile Generic</code>) maintains a dynamic circular buffer. If the meter's internal real-time clock (Class 8, <code>0.0.1.0.0.255</code>) triggers a scheduled capture event (such as the top-of-the-hour or 15-minute boundary tick <code>capture_period: 900s</code>) <em>while</em> the xDLMS server task is actively serializing datablocks, what happens?</p>
<p dir="auto">If the firmware does not maintain an <strong>immutable snapshot row-pointer</strong> upon receiving the initial <code>Get-Request-Normal</code> (Block #1), the background measurement task executes <code>Class 7 Method 2 (capture)</code> in the middle of the transfer. This inserts a new row at the head of the buffer, shifting all internal row offsets by 1. When the server tries to fetch the next slice for Block #14, the internal buffer length check detects a row-pointer hash mismatch and raises <code>block-number-out-of-sequence</code>.</p>
<p dir="auto">Elena, can you check your meter's RTC timestamp logs at the exact moment Block #14 failed?</p>
]]></description><link>https://dlms.sharur.org/post/142</link><guid isPermaLink="true">https://dlms.sharur.org/post/142</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:45 GMT</pubDate></item><item><title><![CDATA[Reply to Why does Block Transfer (Get-Request-Next) for Profile Generic (Class 7) buffer fail with block-number-out-of-sequence over TCP 4059? on Sat, 22 Aug 2026 17:00:43 GMT]]></title><description><![CDATA[<p dir="auto">Elena, I disagree that this is an embedded RAM heap exhaustion. If the meter suffered memory exhaustion, it would typically reset the TCP socket with an <code>RST</code> flag or return <code>data-access-result: temporary-failure</code> (<code>0x02</code>), rather than returning a structured <code>Get-Response-Normal</code> with <code>block-number-out-of-sequence</code>.</p>
<p dir="auto">Look closely at your HES <code>Get-Request-Next</code> APDU:<br />
<code>C0 02 C1 00 00 00 0E</code></p>
<ul>
<li><code>C0 02</code>: <code>Get-Request-Next</code> tag</li>
<li><code>C1</code>: Invoke-ID-And-Priority (<code>0xC1</code> = Invoke ID 1, Priority Normal)</li>
<li><code>00 00 00 0E</code>: Block number <code>14</code> (<code>Double-Long-Unsigned</code>, 4 bytes)</li>
</ul>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.2.4 (DataBlock Services)</strong> and <strong>IEC 62056-53 Section 8.3.3</strong>, <code>Get-Request-Next</code> specifies:</p>
<pre><code class="language-asn1">Get-Request-Next ::= SEQUENCE {
    invoke-id-and-priority  Invoke-Id-And-Priority,
    block-number            Double-Long-Unsigned
}
</code></pre>
<p dir="auto">Notice that in your meter's previous <code>Get-Response-With-Datablock</code> (Block #13), the meter returned <code>block-number: 0x0000000D</code>. If your HES Netty pipeline uses zero-based indexing or increments before acknowledgment, it could trigger this. But even more critically: is your HES maintaining an exact 1-to-1 lockstep request/response window, or is it pipelining <code>Get-Request-Next</code> calls?</p>
]]></description><link>https://dlms.sharur.org/post/141</link><guid isPermaLink="true">https://dlms.sharur.org/post/141</guid><dc:creator><![CDATA[marcus_vance]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:00:43 GMT</pubDate></item></channel></rss>