From a84c5dcd0ce78f8205b965bb2237b448101146b1 Mon Sep 17 00:00:00 2001 From: logicog Date: Fri, 5 Dec 2025 06:32:10 +0100 Subject: [PATCH] IGMP refactoring --- cmd_parser.c | 8 +++++ rtl837x_common.h | 5 ++++ rtl837x_igmp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++---- rtl837x_regs.h | 15 ++++++++-- rtlplayground.c | 2 ++ 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index f59c427..d65e179 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -12,6 +12,7 @@ #include "rtl837x_regs.h" #include "rtl837x_sfr.h" #include "rtl837x_stp.h" +#include "rtl837x_igmp.h" #include "uip/uip.h" #include "version.h" @@ -741,6 +742,13 @@ void cmd_parser(void) __banked port_l2_forget(); else port_l2_learned(); + } else if (cmd_compare(0, "igmp")) { + if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) + igmp_enable(); + else if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) + igmp_show(); + else + igmp_setup(); // Reverts to default with IP-MC being flooded } else if (cmd_compare(0, "stp")) { if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) { print_string("STP enabled\n"); diff --git a/rtl837x_common.h b/rtl837x_common.h index 7b03e09..038849a 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -17,6 +17,11 @@ #define PMASK_6 0x1f8 #define PMASK_CPU 0x200 +// Defines a port mask for dropping all packets on Lookup-miss +#define LOOKUP_MISS_DROP_6 0x00015540 +#define LOOKUP_MISS_DROP_9 0x00015555 +#define LOOKUP_MISS_FLOOD 0x00000000 + // The serial buffer. Defines the command line size // Must be 2^x and <= 128 #define SBUF_SIZE 128 diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index d1ca647..050219a 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -14,10 +14,16 @@ #include "machine.h" extern __code struct machine machine; +extern __xdata uint8_t cpuPort; +extern __xdata uint8_t sfr_data[4]; void igmp_setup(void) __banked { uint8_t i; + print_string("igmp_setup called\n"); + // For now, forward all unkown IP-MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport) + REG_SET(RTL837X_IPV4_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD); + REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD); // For now, forward all unkown MC pkts (2 bits per port. 00: flood via floodmask, 01: drop, 10: trap, 11: to rport) REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00000000); //0x4f78 @@ -25,13 +31,51 @@ void igmp_setup(void) __banked // Define ports where unknown MC addresses are flooded to: REG_SET(RTL837X_MC_FLOODMASK, machine.isRTL8373 ? PMASK_9 : PMASK_6); + // Define ports where unknown MC addresses are flooded to: + if (isRTL8373) { + REG_SET(RTL837X_IPV4_UNKN_MC_FLD_PMSK, PMASK_9); + REG_SET(RTL837X_IPV6_UNKN_MC_FLD_PMSK, PMASK_9); + } else { + REG_SET(RTL837X_IPV4_UNKN_MC_FLD_PMSK, PMASK_6); + REG_SET(RTL837X_IPV6_UNKN_MC_FLD_PMSK, PMASK_6); + } + // Enable lookup of IPv4 MC addresses in table - reg_bit_set(RTL837X_L2_CTRL, 3); // 0x5350 + reg_bit_set(RTL837X_L2_CTRL, L2_CTRL_LUT_IPMC_HASH); // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // bits 16-24 configure max MC group used by that port. For now all protocols are flooded (01) for (i = machine.min_port; i <= machine.max_port; i++) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c15); + + /* Configure per-port IGMP operations when protocol messages are received + * bits 0-9 enable MC protocol snooping + * bit 10: Enable dynamic router port learning + * bit 11: Enable MRP (Multicast Routing Protocol) + * bit 12: Allow fast leave + * bit 13: Allow IGMP reporting + * bit 14: Allow queries + * bits 16-24 configure max MC group used by that port. + * Operations for IGMP packets are: + * 00: handle in HW by ASIC + * 01: flood + * 10: trap + * 10: drop + * Bits 0-1: IGMPv1, 2-3: IGMPv2, 4-5: IGMPv3, 6-7: MLDv1 (for IPv6), 8-9: MLDv2 + * For now the IGMP protocols are flooded (01), MLD which MAC-based is handled by ASIC + * All messages are allowed and maximum MC group is 0xff + */ + for (i = minPort; i <= maxPort; i++) + REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), IGMP_MAX_GROUP | IGMP_PROTOCOL_ENABLE | IGMP_FLOOD); + + // Allow all physical ports to be dynamic router ports + reg_read_m(RTL837X_IGMP_ROUTER_PORT); + if (isRTL8373) { + REG_WRITE(RTL837X_IGMP_ROUTER_PORT, PMASK_9 >> 8, PMASK_9 & 0xff, sfr_data[1], sfr_data[0]); + } else { + REG_WRITE(RTL837X_IGMP_ROUTER_PORT, PMASK_6 >> 8, PMASK_6 & 0xff, sfr_data[1], sfr_data[0]); + } + } @@ -39,13 +83,34 @@ void igmp_enable(void) __banked { uint8_t i; - REG_SET(0x50bc, 00010007); // Trap control? + print_string("igmp_enable called\n"); + // Configure trapping of unhandled IGMP protocol packets to CPU + REG_SET(RTL837X_IGMP_TRAP_CFG, IGMP_CPU_PORT | IGMP_TRAP_PRIORITY); - // Drop unknown MC messages - REG_SET(RTL837X_MC_LOOKUPMISS_ACTIONS, 0x00015540); //0x4f78 + // Drop unknown IP-MC packets + if (isRTL8373) { + REG_SET(RTL837X_IPV4_PORT_MC_LM_ACT, LOOKUP_MISS_DROP_9); + REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_DROP_9); + } else { + REG_SET(RTL837X_IPV4_PORT_MC_LM_ACT, LOOKUP_MISS_DROP_6); + REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_DROP_6); + } // Configure per-port IGMP configuration, bits 0-10 enable MC protocol snooping, // bits 16-24 configure max MC group used by that port. Trap to CPU (10) - for (i = machine.min_port; i <= machine.max_port; i++) - REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), 0x00ff7c2a); // 0x00ff7000: Handling by ASIC (00) + for (i = minPort; i <= maxPort; i++) + REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), IGMP_MAX_GROUP | IGMP_PROTOCOL_ENABLE | IGMP_ASIC); +} + + +/* + * Configures the IGMP static router port(s) that will receive all IGMP + * Report and Leave messages + */ +void igmp_router_port_set(uint16_t pmask) __banked +{ + print_string("igmp_router_port_set: "); print_short(pmask); print_string(", currently set to:\n"); + reg_read_m(RTL837X_IGMP_ROUTER_PORT); + print_sfr_data(); write_char('\n'); + REG_WRITE(RTL837X_IGMP_ROUTER_PORT, sfr_data[0], sfr_data[1], pmask >> 8, pmask & 0xff); } diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 156d23f..ba88e07 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -121,6 +121,7 @@ #define TBL_VLAN 0x03 #define RTL837X_L2_CTRL 0x5350 +#define L2_CTRL_LUT_IPMC_HASH 3 #define RTL837x_TBL_DATA_0 0x5cb0 #define RTL837x_L2_DATA_OUT_A 0x5ccc #define RTL837x_L2_DATA_OUT_B 0x5cd0 @@ -180,9 +181,19 @@ /* * Multicast handling */ -#define RTL837X_MC_LOOKUPMISS_ACTIONS 0x4f78 +#define RTL837X_IPV4_PORT_MC_LM_ACT 0x4f78 +#define RTL837X_IPV6_PORT_MC_LM_ACT 0x4f7c #define RTL837X_IGMP_PORT_CFG 0x52a0 -#define RTL837X_MC_FLOODMASK 0x5368 +#define IGMP_MAX_GROUP 0x00ff0000 +#define IGMP_PROTOCOL_ENABLE 0x00007c00 +#define IGMP_FLOOD 0x00000015 +#define IGMP_ASIC 0x00000000 +#define RTL837X_IGMP_ROUTER_PORT 0x529c +#define RTL837X_IPV4_UNKN_MC_FLD_PMSK 0x5368 +#define RTL837X_IPV6_UNKN_MC_FLD_PMSK 0x536c +#define RTL837X_IGMP_TRAP_CFG 0x50bc +#define IGMP_TRAP_PRIORITY 0x7 +#define IGMP_CPU_PORT 0x00010000 /* * Loop detection / STP diff --git a/rtlplayground.c b/rtlplayground.c index 052498e..c488fb2 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -11,6 +11,7 @@ #include "rtl837x_phy.h" #include "rtl837x_port.h" #include "rtl837x_stp.h" +#include "rtl837x_igmp.h" #include "cmd_parser.h" #include "uip/uipopt.h" #include "uip/uip.h" @@ -1812,6 +1813,7 @@ void bootloader(void) nic_setup(); vlan_setup(); port_l2_setup(); + igmp_setup(); uip_init(); uip_arp_init(); httpd_init();