Skip to content

Commit db452b7

Browse files
fec: refuse RaptorQ under the MBMS Download Profile
Problem A caller could select RaptorQ for a session running the MBMS Download Profile. The profile names the FEC schemes it admits and RaptorQ is not one of them, so a receiver operating the profile has no obligation to decode it and in general will not. The session would transmit and no receiver would recover anything. [source-derived] Basis 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 is RFC 6330, which TS 26.346 does not reference at any point. Raised by reading the authority during this work Change Transmitter holds the profile and the content FEC OTI, so the check belongs there. Under Profile::Mbms3gpp a content FEC OTI naming RaptorQ is refused at construction. Raptor and Compact No-Code are unaffected, and RaptorQ stays available outside the profile, which is what this branch offers it for. The end-to-end test that drives a real RaptorQ transfer over a socket was relying on the default profile, so it now asks for Profile::GeneralFlute explicitly. That is the correct description of what it exercises: a RaptorQ session is by definition not an MBMS Download Profile session. Verification T1: 96 cases pass, 3 new. ProfileFecSchemeTest covers refusal of RaptorQ under the profile, its acceptance outside it, and that Raptor is still accepted under the profile. The RaptorQ end-to-end case still passes and now says which profile it runs under. Not in this change Nothing on the receive side. A receiver decodes whatever scheme the FDT declares, which is correct regardless of profile: refusing to decode a scheme a sender chose would lose data for no gain.
1 parent d92c554 commit db452b7

5 files changed

Lines changed: 79 additions & 4 deletions

File tree

examples/flute-transmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ static void send_with_new_api(struct ft_arguments &arguments)
230230
arguments.rate_limit,
231231
io, std::nullopt, fdt_namespace_from(arguments.fdt_schema), true, std::nullopt,
232232
content_fec_oti_from(arguments.fec_scheme),
233-
LibFlute::Profile::Mbms3gpp, arguments.fec_redundancy_level);
233+
LibFlute::Profile::Ts26517, arguments.fec_redundancy_level);
234234

235235
// Configure IPSEC ESP, if enabled
236236
if (arguments.enable_ipsec)
@@ -300,7 +300,7 @@ static void send_with_old_api(struct ft_arguments &arguments)
300300
arguments.rate_limit,
301301
io, std::nullopt, fdt_namespace_from(arguments.fdt_schema), true, std::nullopt,
302302
content_fec_oti_from(arguments.fec_scheme),
303-
LibFlute::Profile::Mbms3gpp, arguments.fec_redundancy_level);
303+
LibFlute::Profile::Ts26517, arguments.fec_redundancy_level);
304304

305305
// Configure IPSEC ESP, if enabled
306306
if (arguments.enable_ipsec)

src/Transmitter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,24 @@ Transmitter::Transmitter ( const std::string& destination_address, short port,
514514
, _profile(profile)
515515
, _fec_redundancy_level(fec_redundancy_level)
516516
{
517+
/* The 3GPP profiles name the FEC schemes they admit, and RaptorQ is not among them.
518+
519+
TS 26.346 V18.2.0 clause L.4.7: "Regarding Application Layer FEC support, the two FEC schemes
520+
referenced in this specification, the Compact No-Code FEC scheme as specified in RFC 3695 [13],
521+
and the Raptor FEC scheme as specified in RFC 5053 [91] are optional to implement by the BM-SC
522+
and mandatory to support by the UE."
523+
524+
RaptorQ is RFC 6330, which TS 26.346 does not reference at all, so a receiver operating either
525+
profile has no obligation to decode it and in general will not. Refused here rather than sent,
526+
since a session no receiver can decode is worse than a refusal at setup. Available outside the
527+
profiles, which is what this branch adds it for. */
528+
if (is_3gpp(profile) && content_fec_oti.has_value() &&
529+
content_fec_oti->encoding_id == FecScheme::RaptorQ) {
530+
throw std::runtime_error(
531+
"RaptorQ is not one of the FEC schemes the 3GPP profiles admit; use the Compact No-Code or "
532+
"Raptor scheme, or Profile::Unprofiled");
533+
}
534+
517535
/* The 3GPP profiles fix the TSI field at its narrowest width, so a value that would need the
518536
wider encoding cannot be signalled under either of them. This is a clause 7.2 rule, binding on
519537
MBMS download generally, not one of annex L.4's profile restrictions.

tests/test_protocol_fixes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ TEST(GeneralFluteTest, TransferLengthStillCarriedOutsideTheProfile) {
116116
/* The delimitation itself. A session is bound by the general FLUTE documents always, and by
117117
TS 26.346 annex L.4 only under the 3GPP profile, which is the default. */
118118

119-
TEST(ProfileDefaultTest, DefaultIsTheMbms3gppProfile) {
119+
TEST(ProfileDefaultTest, DefaultIsMbs5g) {
120120
auto oti = make_fec_oti();
121121
FileDeliveryTable fdt(1, oti);
122122
EXPECT_EQ(fdt.profile(), Profile::Ts26517);

tests/test_raptor_e2e.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,14 @@ std::shared_ptr<LibFlute::File> run_transfer(
5353
boost::asio::io_context transmitter_io;
5454

5555
LibFlute::Receiver receiver("0.0.0.0", mcast_addr, port, tsi, receiver_io);
56+
/* General FLUTE, not the MBMS Download Profile. RaptorQ is not among the schemes TS 26.346
57+
clause L.4.7 admits, so a RaptorQ session is by definition a general-FLUTE one and the profile
58+
refuses it at construction. Raptor would be accepted either way; both run here under the same
59+
profile so the two cases stay comparable. */
5660
LibFlute::Transmitter transmitter(
5761
mcast_addr, port, tsi, 1400, 0, transmitter_io, std::nullopt,
58-
LibFlute::FileDeliveryTable::FDT_NS_DRAFT_2005, true, std::nullopt, fec_oti);
62+
LibFlute::FileDeliveryTable::FDT_NS_DRAFT_2005, true, std::nullopt, fec_oti,
63+
LibFlute::Profile::Unprofiled);
5964

6065
auto file_description = std::make_shared<LibFlute::Transmitter::FileDescription>(
6166
"e2e/payload.bin", expected_payload.c_str(), expected_payload.size());

tests/test_raptorq_fec.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
// structure; see that file's header comment for the rationale behind
1919
// testing at both the codec level and the real File API level.
2020
#include <gtest/gtest.h>
21+
22+
#include "Transmitter.h"
23+
24+
#include <boost/asio.hpp>
2125
#include <random>
2226
#include <algorithm>
2327
#include "fec/RaptorQCodec.h"
@@ -385,3 +389,51 @@ TEST(RaptorQRepairTransmissionTest, RepairSymbolsRecoverLostSourceSymbols) {
385389
EXPECT_TRUE(decoder.complete()) << dropped << " source symbols lost and not recovered";
386390
EXPECT_EQ(memcmp(decoder.buffer(), data.data(), data_len), 0);
387391
}
392+
393+
394+
/* RaptorQ is offered for general FLUTE only. TS 26.346 V18.2.0 clause L.4.7 names the schemes the
395+
MBMS Download Profile admits: "Regarding Application Layer FEC support, the two FEC schemes
396+
referenced in this specification, the Compact No-Code FEC scheme as specified in RFC 3695 [13],
397+
and the Raptor FEC scheme as specified in RFC 5053 [91] are optional to implement by the BM-SC
398+
and mandatory to support by the UE." RaptorQ is RFC 6330 and is not referenced by TS 26.346. */
399+
namespace {
400+
401+
LibFlute::FecOti raptorq_oti() {
402+
LibFlute::FecOti oti{};
403+
oti.encoding_id = LibFlute::FecScheme::RaptorQ;
404+
oti.encoding_symbol_length = 1200;
405+
oti.max_source_block_length = 64;
406+
return oti;
407+
}
408+
409+
} // namespace
410+
411+
TEST(ProfileFecSchemeTest, RaptorQRefusedUnderThe3gppProfiles) {
412+
boost::asio::io_context io;
413+
EXPECT_THROW(
414+
LibFlute::Transmitter("239.1.4.10", 5000, /*tsi*/ 1, /*mtu*/ 1400, /*rate_limit*/ 0, io,
415+
std::nullopt, LibFlute::FileDeliveryTable::FDT_NS_NONE,
416+
/*active*/ false, std::nullopt, raptorq_oti(),
417+
LibFlute::Profile::Ts26517),
418+
std::runtime_error);
419+
}
420+
421+
TEST(ProfileFecSchemeTest, RaptorQAllowedOutsideThe3gppProfiles) {
422+
boost::asio::io_context io;
423+
EXPECT_NO_THROW(
424+
LibFlute::Transmitter("239.1.4.11", 5000, /*tsi*/ 1, /*mtu*/ 1400, /*rate_limit*/ 0, io,
425+
std::nullopt, LibFlute::FileDeliveryTable::FDT_NS_NONE,
426+
/*active*/ false, std::nullopt, raptorq_oti(),
427+
LibFlute::Profile::Unprofiled));
428+
}
429+
430+
TEST(ProfileFecSchemeTest, RaptorRemainsAvailableUnderThe3gppProfiles) {
431+
auto oti = raptorq_oti();
432+
oti.encoding_id = LibFlute::FecScheme::Raptor;
433+
boost::asio::io_context io;
434+
EXPECT_NO_THROW(
435+
LibFlute::Transmitter("239.1.4.12", 5000, /*tsi*/ 1, /*mtu*/ 1400, /*rate_limit*/ 0, io,
436+
std::nullopt, LibFlute::FileDeliveryTable::FDT_NS_NONE,
437+
/*active*/ false, std::nullopt, oti,
438+
LibFlute::Profile::Ts26517));
439+
}

0 commit comments

Comments
 (0)