igmp: mask the port number before shifting by it

The RTL tag carries a 4-bit port number for received frames, and the two
places that turn it into a mask bit take the whole byte:

	entry.pmask |= (1L << (IGMP_I->rtl_tag.pmask >> 8));

The comment beside it already says only the low four bits count, but nothing
takes them. rtl837x_stp.c:424 does the same extraction and does mask:

	stp_scratch = ((uint8_t)HTONS(STP_I->rtl_tag.pmask)) & 0x0f;

With a count above 15 the result is not a bit at all. SDCC narrows the 1L to
16 bits and emits the shift as a djnz loop, so a count of 200 spins the loop
200 times and leaves zero behind: the join adds no port and the leave clears
none, neither saying anything. It also spends those iterations inside packet
handling.

Mask to four bits and shift a uint16_t, which is the width the surrounding
code works in. Six bytes of BANK1.

Worth saying that this does not make snooping work on its own. struct
igmp_pkt has no vlan_tag field while struct eth_in describes the same frame
with one, so every IP and IGMP field below rtl_tag is read four bytes early.
This commit is contained in:
d00f committed 2026-09-08 23:51:25 +02:00
1 parent 5ecce86ef1
commit 624f93a28a
1 file changed
+2 -2
+2 -2
View File
@@ -295,7 +295,7 @@ void igmp_packet_handler(void) __banked
entry.pmask |= ((uint16_t)sfr_data[3]) << 2; entry.pmask |= ((uint16_t)sfr_data[3]) << 2;
} }
// Update (found) entry with portmask from trapped Packet // Update (found) entry with portmask from trapped Packet
entry.pmask |= (1L << (IGMP_I->rtl_tag.pmask >> 8)); // Swap bytes from network order, only 4 LSB count entry.pmask |= ((uint16_t)1) << ((IGMP_I->rtl_tag.pmask >> 8) & 0x0f); // Swap bytes from network order, only 4 LSB count
// print_string("\nPort-Mask: "); print_short(entry.pmask); write_char('\n'); // print_string("\nPort-Mask: "); print_short(entry.pmask); write_char('\n');
} else if (IGMP_I->igmp_rtype == 0x3){ // Leave group } else if (IGMP_I->igmp_rtype == 0x3){ // Leave group
if (sfr_data[2] & 0x10) { if (sfr_data[2] & 0x10) {
@@ -312,7 +312,7 @@ void igmp_packet_handler(void) __banked
write_char('\n'); write_char('\n');
#endif #endif
// Remove portmask of IGMP packet from entry // Remove portmask of IGMP packet from entry
entry.pmask &= ~(1L << (IGMP_I->rtl_tag.pmask >> 8)); // Swap bytes from network order, only 4 LSB count entry.pmask &= ~(((uint16_t)1) << ((IGMP_I->rtl_tag.pmask >> 8) & 0x0f)); // Swap bytes from network order, only 4 LSB count
// print_string("\nPort-Mask: "); print_short(entry.pmask); write_char('\n'); // print_string("\nPort-Mask: "); print_short(entry.pmask); write_char('\n');
} else { } else {
print_string("IGMP Entry already deleted\n"); print_string("IGMP Entry already deleted\n");