skip to content

Why does reading Acct-Input-Octets (42) alone under-report a long-lived subscriber link, and what completes the count?

level: middleimportance: should knowfreq 42%

answer

  1. the counter is narrower than the link
  2. thirty-two bits does not last long
  3. a second attribute holds the overflow
  4. wraps every 4 GiB
  5. gigawords times 2^32 plus octets

basics

~20 s

Acct-Input-Octets (42) is a 32-bit counter, so it wraps every 4,294,967,296 octets — 4 GiB. Acct-Input-Gigawords (52) counts how many times it has wrapped, and the true total is gigawords times 2^32, plus the octets.

solid answer

~40 s

`Acct-Input-Octets (42)` and `Acct-Output-Octets (43)` are 32-bit unsigned counters, so each wraps back to zero every 2^32 octets — 4 GiB, which a 100 Mbit/s subscriber link fills in under six minutes. `Acct-Input-Gigawords (52)` and `Acct-Output-Gigawords (53)` carry the high-order half: each counts how many times its partner has wrapped. The real figure is `gigawords * 2^32 + octets`, computed per direction, because input and output each have their own pair. A collector that reads only the low half bills every subscriber modulo 4 GiB, which turns the heaviest users into the lightest ones. Not every access device sends the gigaword attributes, so a collector must also detect a wrap by noticing a counter that decreases between consecutive records.

code

pseudocode · 15 lines
pseudocode
function total_input_octets(record):
    gigawords = record.Acct-Input-Gigawords   // absent -> 0
    octets    = record.Acct-Input-Octets
    return gigawords * 4294967296 + octets

// worked: 3 wraps, then 1073741824 octets showing
//   3 * 4294967296 = 12884901888
//   12884901888 + 1073741824 = 13958643712 octets
//   which is exactly 13 GiB

function wraps_without_gigawords(previous, current):
    // fallback when the device sends no gigaword attribute
    if current.Acct-Input-Octets < previous.Acct-Input-Octets:
        return 1        // the counter went backwards: it wrapped
    return 0

go deeper

for a junior

Know that the RADIUS traffic counters are 32 bits wide and that a second attribute exists to hold the overflow, so volume is never read from one attribute alone.

for a middle

Explain the arithmetic and the exact wrap point: gigawords counts wraps of 2^32 octets, per direction, and is multiplied rather than added.

for a senior

Show that you would validate the assumption in production — detect wraps from consecutive interim records when a device sends no gigawords, and alarm on totals that go backwards.

for a principal

Treat measurement error as a revenue and audit position: decide what under-measurement the co-operative can tolerate, and what the interim reporting rate must be to keep it there.

## A 64-bit number carried as two 32-bit attributes RADIUS accounting reports volume with counters that were sized for dial-up links, and they were never widened in place. `Acct-Input-Octets (42)` and `Acct-Output-Octets (43)` are 32-bit unsigned integers. A 32-bit unsigned counter's modulus is 2^32, so it returns to zero after **4,294,967,296 octets — exactly 4 GiB**. Rather than change the attribute, the protocol added a second attribute per direction to carry the high-order half: - `Acct-Input-Gigawords (52)` counts how many times `Acct-Input-Octets (42)` has wrapped during this session. - `Acct-Output-Gigawords (53)` does the same for `Acct-Output-Octets (43)`. The reassembly is arithmetic, not interpretation: ```pseudocode total_input = Acct-Input-Gigawords * 4294967296 + Acct-Input-Octets ``` ## Why this is routine rather than exotic The wrap is easy to dismiss as an edge case, and on a subscriber link it is not one: - A 100 Mbit/s link running flat out moves 4 GiB in roughly **5.7 minutes**. - A residential connection that stays up for a month wraps hundreds of times before anyone sends a `Stop (2)`. - Because the wrap happens inside a session, it is invisible in the `Stop (2)` record alone — the final `Acct-Input-Octets (42)` is simply the remainder, and it looks like a perfectly plausible small number. That last point is what makes the defect expensive. A bill computed from the low half alone is not obviously wrong; it is quietly wrong, and it is wrong in the subscriber's favour precisely for the subscribers who use the most. ## Reading the pair correctly | Attribute | Width | What it holds | |---|---|---| | `Acct-Input-Octets (42)` | 32 bits | Octets received, modulo 2^32 | | `Acct-Input-Gigawords (52)` | 32 bits | Number of times that counter wrapped | | `Acct-Output-Octets (43)` | 32 bits | Octets sent, modulo 2^32 | | `Acct-Output-Gigawords (53)` | 32 bits | Number of times that counter wrapped | Three rules keep the arithmetic honest: 1. **Multiply, do not concatenate or add.** The gigaword value is a count of wraps, so it is multiplied by 2^32. Adding it to the octet count directly, as though it were a volume in gigabytes, produces a number that is wrong by nine orders of magnitude and still looks like a plausible figure. 2. **Treat each direction separately.** There is no combined pair; input and output each carry their own high and low halves. 3. **Treat a missing gigaword attribute as zero, but verify that assumption.** A device that never sends the attribute is indistinguishable, in one record, from a device whose counter has not yet wrapped. ## When the device sends no gigawords at all Not every access device emits the gigaword attributes, and a collector cannot demand them. The fallback is to watch the sequence rather than the record: - Compare `Acct-Input-Octets (42)` in consecutive `Interim-Update (3)` records for the same session. The counter is cumulative and monotonic, so a value that **decreases** means it wrapped between the two records. - Each decrease is one wrap, provided the interim period is short enough that the counter cannot wrap twice between records. On a fast link a long interim period destroys this method entirely, which is a second reason `Acct-Interim-Interval (85)` is an engineering decision rather than a default to leave alone. - Reconstruct the total by adding 2^32 for each observed decrease. This is strictly worse than reading the gigawords, because a lost interim record hides a wrap forever. ## Where the defect hides in a deployment The arithmetic is trivial, so the interesting question is why estates get it wrong for years at a time: - The low counter is always present and always plausible, so nothing about a wrapped figure looks like an error. There is no null, no exception and no gap in the record. - Test links never run long enough to wrap. Four gibibytes is a rounding error in a laboratory session and a few minutes on a real subscriber link. - The subscribers who suffer the largest under-measurement are the ones least likely to complain, because the error is always in their favour. - Two collectors can disagree silently — one reading both halves and one reading only the low half — and the discrepancy looks like a reconciliation problem rather than a parsing bug. The cheap audit is to compare the volume a session reports against what `Acct-Session-Time (46)` makes physically possible at the link's rate. A month-long session that reports less than 4 GiB on a fast link is not a light user; it is a collector that dropped the high half. ## What a good answer states as the limit The counters measure octets the access device saw for that session. They do not say anything about what the traffic was, whether it was delivered, or how it was distributed over time — only `Acct-Session-Time (46)` and the interim records give any time resolution at all. Stating that limit is as much a part of the answer as the arithmetic.

  • How do you detect a wrap when the device sends no gigaword attributes?
    Compare consecutive `Interim-Update (3)` records for the session. The counter is cumulative, so a value that decreases means it wrapped in between, and you add 2^32 for each decrease. It fails if the interim period is long enough for two wraps, or if a record is lost.
  • What is the exact wrap point, in octets?
    2^32, which is 4,294,967,296 octets or exactly 4 GiB. Quoting it as "about four billion bytes" is fine in conversation, but a collector must use the exact modulus, because an approximate constant accumulates error on every wrap.
  • Do the input and output directions share one gigaword counter?
    No. `Acct-Input-Gigawords (52)` belongs to `Acct-Input-Octets (42)` and `Acct-Output-Gigawords (53)` to `Acct-Output-Octets (43)`. Applying one wrap count to both directions corrupts whichever direction carried less traffic.

A five-digit odometer reads 00123 after a long trip, and the reading is honest — it just does not say how many times the dial went round. The gigaword attribute is the separate wrap counter, and the real distance is the number of turns times the dial's capacity, plus what is showing.

saying these in an interview costs you the question

  • Says the octet counters are 64-bit and never wrap
  • Reads Acct-Input-Gigawords (52) as gigabytes transferred
  • Adds the gigaword value to the octet count directly
  • Thinks the counters reset at each Interim-Update
  • Assumes one gigaword pair covers both directions