fix(sacn): Multicast kam nie an - htonl() zerriss die Gruppenadresse

Die Lampe trat seit jeher der falschen Gruppe bei. Aus Universe 1 wurde
239.255.239.255 statt 239.255.0.1, und damit lauschte sie auf einer Adresse,
auf die niemand sendet: Multicast kam nie an, Unicast lief, und der Beitritt
meldete trotzdem Erfolg - er gelang ja, nur eben fuer die falsche Gruppe.

Ursache ist ein nicht geklammertes Makro im SDK:

  #define htonl(n) (((n & 0xff) << 24) | ((n & 0xff00) << 8) | ...)

Stand die Adressrechnung direkt im Aufruf, traf die Maske nach der
Textersetzung nur den letzten Term, weil & staerker bindet als |. Nachgerechnet
ergibt das fuer Universe 1 exakt die 0xefffefff, die am EVK auf der seriellen
Konsole stand.

Die Rechnung liegt jetzt in nl_e131_group_addr() - im reinen, host-testbaren
Teil, mit Testfaellen fuer beide Byte-Haelften. Der Aufrufer reicht eine
Variable an htonl(), keinen Ausdruck mehr.

Gefunden am EVK ueber die serielle Konsole, nachdem vier Netz-Konfigurationen
und fuenf andere Theorien nichts ergeben hatten.
This commit is contained in:
Michael Sauer
2026-09-21 23:06:01 +02:00
parent 4400ea5b42
commit fdded43ab9
4 changed files with 40 additions and 2 deletions
+14
View File
@@ -192,9 +192,23 @@ static void test_universe_too_high_rejected(void)
TEST_ASSERT_FALSE(nl_e131_parse(pkt, pkt_len, &p));
}
static void test_group_address_per_annex_a(void)
{
/* 239.255.<hi>.<lo>. Der Fehler, den dieser Test festhaelt: stand die Rechnung direkt
* im htonl()-Aufruf, zerriss das nicht geklammerte SDK-Makro sie, und aus Universe 1
* wurde 239.255.239.255 - eine Gruppe, auf die niemand sendet. */
TEST_ASSERT_EQUAL_HEX32(0xefff0001u, nl_e131_group_addr(1));
TEST_ASSERT_EQUAL_HEX32(0xefff000cu, nl_e131_group_addr(12));
TEST_ASSERT_EQUAL_HEX32(0xefff012cu, nl_e131_group_addr(300));
TEST_ASSERT_EQUAL_HEX32(0xefff00ffu, nl_e131_group_addr(255));
TEST_ASSERT_EQUAL_HEX32(0xefff0100u, nl_e131_group_addr(256));
TEST_ASSERT_EQUAL_HEX32(0xeffff9ffu, nl_e131_group_addr(63999));
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_group_address_per_annex_a);
RUN_TEST(test_valid_packet);
RUN_TEST(test_full_universe);
RUN_TEST(test_empty_slot_set);