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> --- Changes since v1: * moved the debug print statement inside the if block and reworded accordingly. (as suggested by Igor) 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 | 40 +++++++++++++++++++++++++++++++++++++--- 1 files changed, 37 insertions(+), 3 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index b599945..7762dbb 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1024,6 +1024,43 @@ 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; + } + + DEBUG_PRINT(("RTL8139: C+ Rx mode : extracted vlan tag with tci: " + "%u\n", bswap16(rxdw1 & CP_RX_VLAN_TAG_MASK))); + } + else + { + /* reset VLAN tag flag */ + rxdw1 &= ~CP_RX_TAVA; + } + /* receive/copy to target memory */ cpu_physical_memory_write( rx_addr, buf, size ); @@ -1082,9 +1119,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