mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-09-02 15:02:51 +08:00
Do not insert the management VLAN tag into a CPU-tagged frame
tcpip_output() splices the 802.1Q tag in right behind the source address, which is exactly where the ASIC expects the RTL tag of a frame the CPU addressed to a port itself. The tag then ends up behind the VLAN tag, the ASIC does not find it, and the frame goes out flooded with the 0x8899 header still on it instead of being sent to the port that was asked for. Whether a frame is CPU-tagged is a property of the frame, so decide it here from the ether-type rather than having every sender of such a frame clear management_vlan around its tcpip_output() call. stp_cnf_send() did that, and no longer has to.
This commit is contained in:
@@ -28,7 +28,6 @@ __xdata uint8_t stp_fdb_i;
|
|||||||
extern __xdata struct uip_eth_addr uip_ethaddr;
|
extern __xdata struct uip_eth_addr uip_ethaddr;
|
||||||
|
|
||||||
extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2];
|
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_buffer[CMD_BUF_SIZE];
|
||||||
extern __xdata uint8_t cmd_words_len;
|
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->fwd_delay = stp_fwddelay_s;
|
||||||
STP_O->version1_length = 0; /* RST BPDU: no version-1 information */
|
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;
|
uip_len = stp_rstp ? sizeof(struct stp_pkt) : sizeof(struct stp_pkt) - 1;
|
||||||
tcpip_output();
|
tcpip_output();
|
||||||
management_vlan = saved_mgmt_vlan;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -203,6 +203,9 @@ struct nonq_frame {
|
|||||||
// The output frame structure with 802.1Q field and the padding moved before the buffer-start
|
// 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])
|
#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)
|
void isr_timer0(void) __interrupt(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1097,8 +1100,9 @@ void tcpip_output(void)
|
|||||||
FRAME->len = uip_len;
|
FRAME->len = uip_len;
|
||||||
FRAME->reserved_2[0] = 0x00; FRAME->reserved_2[1] = 0x00;
|
FRAME->reserved_2[0] = 0x00; FRAME->reserved_2[1] = 0x00;
|
||||||
|
|
||||||
// For the management VLAN we insert an 802.1Q VLAN tag
|
// For the management VLAN we insert an 802.1Q VLAN tag, but never into a
|
||||||
if (management_vlan) {
|
// 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
|
// 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
|
// to allow space to insert the dot 1Q tag
|
||||||
for (uint8_t i = 0; i < sizeof(struct q_frame) - DOT_1Q_TAG_SIZE; i++)
|
for (uint8_t i = 0; i < sizeof(struct q_frame) - DOT_1Q_TAG_SIZE; i++)
|
||||||
|
|||||||
Reference in New Issue
Block a user