diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 290db65..583a3d6 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -28,7 +28,6 @@ __xdata uint8_t stp_fdb_i; extern __xdata struct uip_eth_addr uip_ethaddr; extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; -extern __xdata uint16_t management_vlan; /* owned by rtlplayground.c; suppressed per-frame for BPDUs */ extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE]; extern __xdata uint8_t cmd_words_len; @@ -408,20 +407,8 @@ void stp_cnf_send(uint8_t port) __reentrant STP_O->fwd_delay = stp_fwddelay_s; STP_O->version1_length = 0; /* RST BPDU: no version-1 information */ - /* BPDUs are link-local and must egress untagged: with a management VLAN - * set, tcpip_output() splices an 802.1Q tag after the SA, shifting the - * in-frame rtl_tag out of the position the ASIC parses - the CPU tag then - * leaks onto the wire as 0x8899 and the BPDU is flooded, not sent. - * Hardware-verified fix, same as lacp_send(). */ - { - uint16_t saved_mgmt_vlan = management_vlan; - management_vlan = 0; - /* A legacy Config BPDU body is 35 bytes - without the trailing - * version-1 length byte that only the RST BPDU (36 bytes) carries. */ uip_len = stp_rstp ? sizeof(struct stp_pkt) : sizeof(struct stp_pkt) - 1; tcpip_output(); - management_vlan = saved_mgmt_vlan; - } } diff --git a/rtlplayground.c b/rtlplayground.c index 6e2d9df..02fe55c 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -203,6 +203,9 @@ struct nonq_frame { // The output frame structure with 802.1Q field and the padding moved before the buffer-start #define FRAME_Q ((__xdata struct q_frame *)&uip_buf[0]) +// Ether-type of the output frame, which is the RTL tag on a CPU-tagged frame +#define FRAME_ETHERTYPE (*(__xdata uint16_t *)&uip_buf[RTL_FRAME_DESC_SIZE + 2 * sizeof(struct uip_eth_addr)]) + void isr_timer0(void) __interrupt(1) { } @@ -1097,8 +1100,9 @@ void tcpip_output(void) FRAME->len = uip_len; FRAME->reserved_2[0] = 0x00; FRAME->reserved_2[1] = 0x00; - // For the management VLAN we insert an 802.1Q VLAN tag - if (management_vlan) { + // For the management VLAN we insert an 802.1Q VLAN tag, but never into a + // CPU-tagged frame, where the ASIC expects its tag right behind the addresses + if (management_vlan && FRAME_ETHERTYPE != HTONS(RTL_FRAME_TAG_ID)) { // Shift the ethernet header before the HW type including the rtl_frame_desc to the beginning of uip_buf // to allow space to insert the dot 1Q tag for (uint8_t i = 0; i < sizeof(struct q_frame) - DOT_1Q_TAG_SIZE; i++)