Add support to the emulated hardware to remove vlan tags in packets going from the network to the guest.
Signed-off-by: Benjamin Poirier <benjamin.poir...@polymtl.ca> Cc: Igor V. Kovalenko <igor.v.kovale...@gmail.com> -- AFAIK, extraction is optional to get vlans working. The driver requests rx detagging but should not assume that it was done. Under Linux, the mac layer will catch the vlan ethertype. I only added this part for completeness (to emulate the hardware more truthfully..?). --- hw/rtl8139.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index ac294da..557a460 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1024,6 +1024,44 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); + if (s->CpCmd & CPlusRxVLAN && size >= ETHER_ADDR_LEN * 2 + + VLAN_HDR_LEN && be16_to_cpup((uint16_t *) &buf[ETHER_ADDR_LEN * + 2]) == ETHERTYPE_VLAN) + { + size_t new_size = size - VLAN_HDR_LEN; + + rxdw1 &= ~CP_RX_VLAN_TAG_MASK; + rxdw1 |= CP_RX_TAVA | + le16_to_cpup((uint16_t *)&buf[ETHER_HDR_LEN]); + + if (buf == buf1 || new_size < MIN_BUF_SIZE) + { + /* move the end and pad */ + memmove((uint8_t *)buf + ETHER_ADDR_LEN * 2, buf + + ETHER_ADDR_LEN * 2 + VLAN_HDR_LEN, new_size - + ETHER_ADDR_LEN * 2); + memset((uint8_t *)buf + new_size, 0, MIN_BUF_SIZE - new_size); + size = MIN_BUF_SIZE; + } + else + { + /* move the beginning */ + memmove((uint8_t *)buf + VLAN_HDR_LEN, buf, ETHER_ADDR_LEN * + 2); + buf += VLAN_HDR_LEN; + size = new_size; + } + } + else + { + /* reset VLAN tag flag */ + rxdw1 &= ~CP_RX_TAVA; + } + + DEBUG_PRINT(("RTL8139: C+ Rx mode : removed vlan tag: %u tci: %u\n", + !!(rxdw1 & CP_RX_TAVA), bswap16(rxdw1 & + CP_RX_VLAN_TAG_MASK))); + /* receive/copy to target memory */ cpu_physical_memory_write( rx_addr, buf, size ); @@ -1082,9 +1120,6 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; rxdw0 |= (size+4); - /* reset VLAN tag flag */ - rxdw1 &= ~CP_RX_TAVA; - /* update ring data */ val = cpu_to_le32(rxdw0); cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4); -- 1.7.2.3