From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=48356 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PFClh-0003G9-BW for qemu-devel@nongnu.org; Sun, 07 Nov 2010 16:27:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PFClD-00054q-Tm for qemu-devel@nongnu.org; Sun, 07 Nov 2010 16:26:48 -0500 Received: from smtp.polymtl.ca ([132.207.4.11]:46385) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PFClD-00054f-Q3 for qemu-devel@nongnu.org; Sun, 07 Nov 2010 16:26:47 -0500 From: Benjamin Poirier Date: Sun, 7 Nov 2010 16:25:36 -0500 Message-Id: <1289165136-28207-2-git-send-email-benjamin.poirier@polymtl.ca> In-Reply-To: <1289165136-28207-1-git-send-email-benjamin.poirier@polymtl.ca> References: <1289165136-28207-1-git-send-email-benjamin.poirier@polymtl.ca> Subject: [Qemu-devel] [PATCH 2/2] rtl8139: add vlan tag extraction List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Add support to the emulated hardware to remove vlan tags in packets going from the network to the guest. Signed-off-by: Benjamin Poirier Cc: Igor V. Kovalenko -- 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