Skip to content

RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated, offered as reference work) - #64

Open
jordijoangimenez wants to merge 4 commits into
5G-MAG:feature/raptor-raptorq-fecfrom
jordijoangimenez:feature/raptorq-support
Open

RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated, offered as reference work)#64
jordijoangimenez wants to merge 4 commits into
5G-MAG:feature/raptor-raptorq-fecfrom
jordijoangimenez:feature/raptorq-support

Conversation

@jordijoangimenez

@jordijoangimenez jordijoangimenez commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Base branch. This pull request is based on feature/raptor-raptorq-fec, the head of #61, not on
development, because it builds on that scheme's codec abstraction. The diff therefore shows only this
pull request's own commits. GitHub will retarget it when #61 merges.

Addresses part of #1.

Dependencies and issues

Depends on: #61, and is based on its branch; #61 in turn depends on #62. Merge order is #62, then
#61, then this one.
Paired with: #65, #68 and #98, independent of this one, either order.
Closes on merge: nothing on its own. Completes #1 together with #61. #1 needs closing by hand once both are in, since neither pull request delivers it alone.

What is in this pull request

Three commits, and the diff shows only those: this pull request is based on #61's branch, not on
development, so #62's and #61's work does not appear here.

  1. fec: reinstate RaptorQ as this branch's delta — RaptorQ alongside Raptor, sharing the same codec
    interface, with its own scheme-specific OTI layout, which differs from Raptor's for the same values.
    Its repair-symbol coverage is in this commit rather than a follow-up, for the reason given on RFC 5053 Raptor FEC scheme: codec, FLUTE integration, and the missing-symbol accessor #61.
  2. examples: select the FDT schema, the FEC scheme and the redundancy level — adds -S, -F and -L
    to the example transmitter, which is how both schemes and the profiled schema were driven against a
    real receiver.

Not mandated by 3GPP

TS 26.346 V18.2.0 clause L.4.7 names Compact No-Code and Raptor for the MBMS Download Profile. RaptorQ is
neither required nor forbidden there. It is not the default, and nothing in the profile path selects it.

Verification

T1: 114 cases passing. T2: an object received byte-identical over real multicast with
FEC-OTI-FEC-Encoding-ID="6", and recovered at a 7.6% datagram loss rate where Raptor's smaller default
budget does not.

Merge order

After #62, then #61.

Rebased onto #62. That branch gained three commits from a prose read of RFC 5651 and RFC 5775, so
this branch was rebased onto its new head. Nothing in this pull request's own commits changed; the case
count above rose from 110 to 114 because the base branch's own new cases run alongside them.


Issues closed by this pull request

Closes #103, #104.

@jordijoangimenez jordijoangimenez self-assigned this Aug 11, 2026
@jordijoangimenez jordijoangimenez added the enhancement New feature or request label Aug 11, 2026
@dsilhavy dsilhavy added this to the v1.0.0 milestone Aug 13, 2026
@jordijoangimenez
jordijoangimenez marked this pull request as draft August 14, 2026 10:28
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 7bbb1e1 to 77b7f86 Compare August 22, 2026 12:57
@jordijoangimenez jordijoangimenez changed the title RFC 6330 RaptorQ FEC (not 3GPP-mandated — reference/future work, depends on #61) RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated) Aug 22, 2026
@jordijoangimenez
jordijoangimenez changed the base branch from development to feature/raptor-raptorq-fec August 22, 2026 12:59
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 77b7f86 to 61ae0ae Compare August 22, 2026 13:16
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from 5e2e338 to f43eca6 Compare August 22, 2026 13:16
@jordijoangimenez
jordijoangimenez deleted the feature/raptorq-support branch August 22, 2026 13:22
@github-project-automation github-project-automation Bot moved this from In Progress to Done in MBMS: Support for FLUTE Aug 22, 2026
@jordijoangimenez
jordijoangimenez restored the feature/raptorq-support branch August 22, 2026 13:24
@jordijoangimenez
jordijoangimenez changed the base branch from feature/rfc5053-raptor-fec to development August 22, 2026 13:24
@jordijoangimenez jordijoangimenez changed the title RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated) RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated, offered as reference work) Aug 22, 2026
@jordijoangimenez
jordijoangimenez changed the base branch from development to feature/raptor-raptorq-fec August 22, 2026 15:25
@jordijoangimenez
jordijoangimenez marked this pull request as ready for review August 22, 2026 15:38
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from f43eca6 to aa36087 Compare August 22, 2026 15:50
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 61ae0ae to 9ae681a Compare August 22, 2026 15:51
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from aa36087 to 2007684 Compare August 22, 2026 16:03
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 9ae681a to 3d25c37 Compare August 22, 2026 16:04
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from 6e55625 to f9ad94d Compare August 23, 2026 07:36
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 470df62 to db452b7 Compare August 23, 2026 07:45
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from f9ad94d to bf6b1a9 Compare August 23, 2026 12:11
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from db452b7 to 5252e03 Compare August 23, 2026 12:13
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from bf6b1a9 to ee01d44 Compare August 23, 2026 12:22
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 5252e03 to d25ff1d Compare August 23, 2026 12:25
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from ee01d44 to 929741f Compare August 23, 2026 12:37
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from d25ff1d to 59d12c7 Compare August 23, 2026 12:38
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from 929741f to 3d5abc0 Compare August 23, 2026 14:31
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch 2 times, most recently from e8adab8 to 16deddc Compare August 23, 2026 15:33
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from 3d5abc0 to 6c63c90 Compare August 23, 2026 15:33
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptorq-support branch from 16deddc to af63605 Compare August 23, 2026 15:41
@jordijoangimenez
jordijoangimenez force-pushed the feature/raptor-raptorq-fec branch from 6c63c90 to 3cf4c92 Compare August 23, 2026 15:41
@jordijoangimenez

Copy link
Copy Markdown
Contributor Author

This pull request: merge it third, after #61

Status: ready. 3 commits, 22 files, +1826/-85. 114 cases pass.

What to do

  1. Merge after RFC 5053 Raptor FEC scheme: codec, FLUTE integration, and the missing-symbol accessor #61, whose branch is its base. It is the only pull request in the set not based directly on FLUTE v1 (RFC 3926) and MBMS Download Profile conformance, plus assorted correctness fixes #62.
  2. Expect it to close no issue. That is correct and deliberate: RaptorQ is not mandated by any profile this library serves, and it is offered as reference work rather than to satisfy a requirement. If the decision above puts closes #1 on RFC 6330 RaptorQ FEC scheme (not 3GPP-mandated, offered as reference work) #64 rather than RFC 5053 Raptor FEC scheme: codec, FLUTE integration, and the missing-symbol accessor #61, that changes.
  3. Note that it refuses RaptorQ under the MBMS Download Profile, naming the clause. A 3GPP consumer cannot select it by accident.

Why it is separate from #61 at all. Raptor is required and RaptorQ is not, so they are reviewed and merged on different terms. Merging #61 without #64 leaves the library fully conformant; the reverse is not true.


How this set of pull requests came to look like this

When What Why
May 2023 #7, Forward Error Correction, from @autumn-traveller The original FEC contribution. Closed 11 Aug 2026 in favour of a from-scratch RFC 5053 implementation, after the decision to stop harmonising two divergent approaches. Its intent is carried by #61.
11 Aug 2026 #67, tunnel-mode reception + FEC + reception fixes One pull request holding three unrelated subjects, opened from a personal fork. Closed the same day and reopened as #68 from this repository.
11 Aug 2026 The stack below The remaining work split by subject, so each part could be reviewed on its own terms and merged in a stated order.
22 Aug 2026 #87 to #95 opened, then closed the same day Nine single-issue pull requests, an attempt to split the stack further. Each carries a closing comment naming the pull request its work was folded into, stating that the issue it closed is claimed by that pull request instead, and that nothing is dropped. The stated reason was to keep the number of open pull requests down. They still had to merge in a fixed order, so splitting them out raised the count from six to fifteen without making any one of them easier to review.
23 Aug 2026 #98 split out of #62 WEBRC congestion control cannot be validated in this repository. Keeping it in #62 would have forced a reviewer to accept an unverified congestion controller alongside conformance fixes that are ready.
23 Aug 2026 Four commits added to #62, two to #98 A prose read of RFC 5775 (ALC) and RFC 5651 (LCT) against the code, undertaken to scope #81's second step. Findings are listed on #81.

Where the nine closed pull requests went

Closed Its work is now in Issue Declared by
#87 RFC 5053 Raptor codec #61 #1, in part see the note below
#88 missing source symbol ESIs #61 #86 #61
#89 zlib encode and decode loops #68 #77 #68
#90 encoded object transfer length #68 #80 #68
#91 source address binding with a tunnel #62 #82 #62
#92 IPsec netlink socket leak #62 #83 #62
#93 FDT growth regression coverage #62 none, tests only n/a
#94 receiver example output path #62 #27 #62
#95 IPsec IPv6 destinations #62 #85 #62

One correction, @rjb1000. #93 is listed above as "already merged in PR #60". #60 merged the FDT growth fix on 17 August and changed no test file; tests/test_fdt_growth.cpp does not exist on development today. The regression coverage is commit 2750ff0 on #62's branch. Nothing is lost either way, but the coverage rides in with #62 rather than being already upstream.

Every open issue, and which pull request closes it

Closed on merge by Issues
#62 #27, #70, #71, #72, #73, #74, #75, #76, #82, #83, #85, #96, #97
#61 #86
#68 #66, #77, #78, #79, #80
#64, #65, #98 none

Four open issues are deliberately closed by nothing:

The stack, and the order to merge it in

development
└── #62  feature/wave3-rfc6726-compliance-fixes      merge FIRST
    ├── #61  feature/raptor-raptorq-fec              then this
    │   └── #64  feature/raptorq-support             then this
    ├── #65  feature/flute-v2-support                any time after #62
    ├── #68  feature/issue66-receiver-tunnel-mode    draft, see below
    └── #98  feature/webrc-congestion-control        draft, see below

GitHub retargets each child to development as its parent merges. All seven are mergeable, every branch builds clean, and each passes its own suite: #62 67 cases, #65 81, #61 97, #64 114, #68 77, #98 128.

One trap for whoever merges. The heads live in two repositories: #61, #68 and #98 in 5G-MAG, #62, #64 and #65 on a personal fork. The base branch feature/wave3-rfc6726-compliance-fixes exists in both, and the four pull requests based on it resolve it in 5G-MAG, not the fork. Both copies are at the same commit now and need to stay that way; a push to only one of them leaves four pull requests comparing against history that no longer exists.

@jordijoangimenez

Copy link
Copy Markdown
Contributor Author

Merge third, after #61, whose branch is its base. The only one not based directly on #62.

Closes no issue, deliberately: RaptorQ is mandated by no profile here, and it refuses RaptorQ under the MBMS Download Profile naming the clause. If closes #1 lands here instead of #61, that is the only change needed.

…ecific OTI layout

Change type
  New feature, not 3GPP. This branch is the RaptorQ delta on top of the Raptor branch and nothing
  else.

Basis
  RaptorQ is outside the set of FEC schemes 3GPP references, which is why it lives here and not on
  the compliant branches.
  TS 26.346 V18.2.0 clause L.4.7: "Regarding Application Layer FEC support, the two FEC schemes
  referenced in this specification, the Compact No-Code FEC scheme as specified in RFC 3695 [13],
  and the Raptor FEC scheme as specified in RFC 5053 [91] are optional to implement by the BM-SC
  and mandatory to support by the UE."
  RaptorQ and RFC 6330 appear nowhere in TS 26.346: zero occurrences. Not forbidden, just outside
  the referenced set.

  RFC 6330: "This document describes a Fully-Specified Forward Error Correction" scheme
  "corresponding to FEC Encoding ID 6", so its Codepoint value is 6 under the identity mapping the
  rest of this library uses.

Corrected while reinstating it
  The previous version of this branch was an unexplained revert of the removal commit, and it
  brought back the three invented FDT attribute names the Raptor branch had already replaced with
  the schema-defined FEC-OTI-Scheme-Specific-Info. Reinstating it that way would have undone a
  conformance fix.

  Worse, it shared one encoder between the two schemes, which is wrong: the same four octets carry
  DIFFERENT field widths, with Z and N the opposite way round, so encoding one scheme with the
  other's layout silently corrupts both values.

  RFC 5053 clause 3.2.3, Raptor: "a 4-octet field consisting of the parameters Z (2 octets),
  N (1 octet), and Al (1 octet)"

  RFC 6330 clause 3.3.3, RaptorQ, the Scheme-Specific parameter list:
  "The number of source blocks (Z): 8-bit unsigned integer."
  "The number of sub-blocks (N): 16-bit unsigned integer."

Change
  Reinstates RaptorQCodec, RaptorQMath, RaptorQTables and GF256LinearSystem with their headers and
  test binary, and the FecScheme::RaptorQ dispatch branches. Replaces the single encoder with one
  that selects the octet layout from the scheme, on both the encode and decode sides and at both
  the FDT-Instance and File levels, keeping the schema-defined attribute the Raptor branch
  introduced.

  Rebuilt on the Raptor branch rather than on the old lineage, so it is exactly one delta above it
  and the two non-3GPP features, this and FLUTE version 2, are now separate from each other as
  well as from the compliant core.

Verification
  T1: builds clean, ctest at the build root 35/35, the 25 from the Raptor branch plus the RaptorQ
  suite and 2 new cases. The layout difference is asserted rather than assumed: identical inputs
  Z=1, N=0x0203, Al=4 encode to AQIDBA== under RaptorQ and AAEDBA== under Raptor, and each is
  checked absent from the other's output. A round trip with N=0x0140, a value a shared one-octet
  layout would truncate, recovers all three parameters. Quotations checked with
  tools/verify-citations.py in --strict mode.

Not in this change
  No claim that RaptorQ is 3GPP conformant, because it is not in the referenced set at this
  baseline. The Raptor paths below are untouched.

Carries its own repair-symbol coverage rather than leaving it to a follow-up, for
the reason given on the Raptor commit this builds on: a fountain code that
transmits no repair symbol protects nothing, and the object-level tests that pull
every symbol in one call cannot see it. RaptorQRepairTransmissionTest drives one
datagram at a time and acknowledges each, and two of its four cases fail if the
completion condition is reverted, emitting 79 symbols instead of 90 and no repair
symbol instead of 11.

T2 for this scheme: an object recovered byte-identically over real multicast at a
7.6% datagram loss rate, where Raptor with its smaller default budget does not.
Problem
  The example transmitter drove one FDT schema, one FEC scheme and a fixed
  redundancy level, so the profiled-schema, Raptor and RaptorQ paths could not be
  exercised against a real receiver over a real socket without editing and
  rebuilding it. Code-derived, no spec claim.

Raised by
  looking for a way to drive the FEC and FDT schema paths end to end

Change
  Adds -S/--fdt-schema (draft2005, rfc3926, profiled), -F/--fec (compact, raptor,
  raptorq) and -L/--fec-redundancy-level, each mapping its argument onto the
  enumeration or value the Transmitter constructor already accepts. Defaults
  reproduce the previous behaviour, so an existing command line is unaffected.

Verification
  T2: used to capture the FDT off the wire per schema, and to run Raptor and
  RaptorQ end to end over multicast including under datagram loss. The RaptorQ
  run's FDT carries FEC-OTI-FEC-Encoding-ID="6" and the RaptorQ scheme-specific
  layout, captured by a sniffer that links no library code.

Not in this change
  Any library behaviour. This only exposes choices the library already offered.
Problem
  A Transmitter under either 3GPP profile would send a session using a FEC scheme no conformant
  receiver is obliged to decode. This branch adds RaptorQ, which neither TS 26.346 nor TS 26.517
  references.
  [source-derived]

Basis
  TS 26.346 V18.2.0 clause L.4.7: "the two FEC schemes referenced in this specification, the
  Compact No-Code FEC scheme as specified in RFC 3695 [13], and the Raptor FEC scheme as specified
  in RFC 5053 [91] are optional to implement by the BM-SC and mandatory to support by the UE."

  The set is closed and TS 26.517 does not widen it: its clause 6.2.4.5 gives the repair
  byte-range determination for FEC Encoding ID 0 and FEC Encoding ID 1 and for no other value.

Raised by
  reading the authority during this work

Change
  is_3gpp_admissible_fec_scheme() states the admissible set, and the Transmitter constructor
  refuses anything outside it under a 3GPP profile. Written as a match against the two schemes the
  clause names rather than as a rejection of RaptorQ by name: a scheme added to the enumeration
  later is then refused under a profile until someone decides otherwise, instead of being admitted
  by default.

  fec_scheme_from_encoding_id() gains FEC Encoding ID 6, without which this branch's own parser
  would refuse a received FDT declaring the scheme this branch implements.

  Refused at construction rather than at send: a session no receiver can decode is worse than a
  refusal at setup. RaptorQ remains available under Profile::Unprofiled, which is what this branch
  adds it for.

Verification
  T1: 123 cases pass, 2 new (a scheme outside the admissible set refused under both 3GPP profiles,
  and the RaptorQ encoding identifier mapping to its scheme), 0 failures. 121 passed before.

Not in this change
  Whether RaptorQ should be offered to 3GPP profiles at all. It is not, on the clause above, and
  this branch does not argue otherwise.
Problem
  The Raptor branch shortens the encoding symbol so an object too small to fill four symbols can
  still be encoded, because Raptor has no systematic index below K = 4. That shortening is
  deliberately Raptor-only, and the case proving RaptorQ is left alone could not live there: the
  enumerator does not exist on that branch.
  [code-derived]

Basis
  unverified: could not obtain RFC 6330. The claim that RaptorQ imposes no equivalent floor, because
  it pads a source block up to the smallest supported K', is inherited from this branch's own codec
  implementation and its existing comments, not re-derived from the RFC during this work.

  The assertion itself is code-derived and needs no clause: it pins the observable behaviour, that
  the symbol length is unchanged for an object RaptorQ can encode as-is. If the inherited reading of
  RFC 6330 turns out to be wrong, this case is what will fail.

Raised by
  reading the code during this work, splitting a case off the Raptor branch that could only be
  asserted here

Change
  One case, asserting that a 600-byte object at a 1024-byte session symbol keeps that symbol length
  under RaptorQ, where the same object under Raptor is shortened.

Verification
  T1: 136 cases pass, 1 new, 0 failures. 135 passed before.

Not in this change
  Nothing about the Raptor path, which is unchanged and asserted on its own branch. No claim about
  what RFC 6330 requires; see Basis.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

Development

Successfully merging this pull request may close these issues.

2 participants