From patchwork Tue Nov 9 01:46:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Poirier X-Patchwork-Id: 70485 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 197E8B7113 for ; Tue, 9 Nov 2010 12:48:32 +1100 (EST) Received: from localhost ([127.0.0.1]:52734 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PFdJk-0005rK-DG for incoming@patchwork.ozlabs.org; Mon, 08 Nov 2010 20:48:12 -0500 Received: from [140.186.70.92] (port=60859 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PFdJ4-0005rF-Fy for qemu-devel@nongnu.org; Mon, 08 Nov 2010 20:47:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PFdJ3-00076f-7i for qemu-devel@nongnu.org; Mon, 08 Nov 2010 20:47:30 -0500 Received: from smtp.polymtl.ca ([132.207.4.11]:36331) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PFdJ3-00075X-5A for qemu-devel@nongnu.org; Mon, 08 Nov 2010 20:47:29 -0500 Received: from d1.synalogic.ca (196-81-252-216-dsl.colba.net [216.252.81.196] (may be forged)) by smtp.polymtl.ca (8.14.3/8.14.3) with ESMTP id oA91lHGp010777; Mon, 8 Nov 2010 20:47:21 -0500 From: Benjamin Poirier To: qemu-devel@nongnu.org Date: Mon, 8 Nov 2010 20:46:20 -0500 Message-Id: <1289267181-20613-1-git-send-email-benjamin.poirier@polymtl.ca> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: References: X-Poly-FromMTA: (196-81-252-216-dsl.colba.net [216.252.81.196] (may be forged)) at Tue, 9 Nov 2010 01:47:17 +0000 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Subject: [Qemu-devel] [PATCH v2 1/2] rtl8139: add vlan tag insertion X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add support to the emulated hardware to add vlan tags in packets going from the guest to the network. Signed-off-by: Benjamin Poirier Cc: Igor V. Kovalenko --- Changes since v1: * moved the debug print statement inside the if block and reworded accordingly. (as suggested by Igor) hw/rtl8139.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 files changed, 34 insertions(+), 11 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index d92981d..b599945 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -47,6 +47,8 @@ * Darwin) */ +#include + #include "hw.h" #include "pci.h" #include "qemu-timer.h" @@ -58,6 +60,10 @@ #define PCI_FREQUENCY 33000000L +/* bytes in VLAN tag */ +#define VLAN_TCI_LEN 2 +#define VLAN_HDR_LEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) + /* debug RTL8139 card C+ mode only */ //#define DEBUG_RTL8139CP 1 @@ -1913,7 +1919,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) cpu_physical_memory_read(cplus_tx_ring_desc, (uint8_t *)&val, 4); txdw0 = le32_to_cpu(val); - /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */ cpu_physical_memory_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4); txdw1 = le32_to_cpu(val); cpu_physical_memory_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4); @@ -1925,9 +1930,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) descriptor, txdw0, txdw1, txbufLO, txbufHI)); - /* TODO: the following discard cast should clean clang analyzer output */ - (void)txdw1; - /* w0 ownership flag */ #define CP_TX_OWN (1<<31) /* w0 end of ring flag */ @@ -1951,8 +1953,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* w0 bits 0...15 : buffer size */ #define CP_TX_BUFFER_SIZE (1<<16) #define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1) -/* w1 tag available flag */ -#define CP_RX_TAGC (1<<17) +/* w1 add tag flag */ +#define CP_TX_TAGC (1<<17) /* w1 bits 0...15 : VLAN tag */ #define CP_TX_VLAN_TAG_MASK ((1<<16) - 1) /* w2 low 32bit of Rx buffer ptr */ @@ -1978,12 +1980,21 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor)); + int vlan_extra_size = 0; if (txdw0 & CP_TX_FS) { DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor)); /* reset internal buffer offset */ s->cplus_txbuffer_offset = 0; + + if (txdw1 & CP_TX_TAGC) + { + vlan_extra_size = VLAN_HDR_LEN; + + DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with " + "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK))); + } } int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; @@ -1992,14 +2003,15 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* make sure we have enough space to assemble the packet */ if (!s->cplus_txbuffer) { - s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE; + s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE + VLAN_HDR_LEN; s->cplus_txbuffer = qemu_malloc(s->cplus_txbuffer_len); s->cplus_txbuffer_offset = 0; DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len)); } - while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len) + while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize + + vlan_extra_size >= s->cplus_txbuffer_len) { s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE; s->cplus_txbuffer = qemu_realloc(s->cplus_txbuffer, s->cplus_txbuffer_len); @@ -2025,6 +2037,20 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n", txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset)); + if (vlan_extra_size && txsize >= 2 * ETHER_ADDR_LEN) + { + /* copy addresses */ + cpu_physical_memory_read(tx_addr, s->cplus_txbuffer, 2 * + ETHER_ADDR_LEN); + tx_addr += 2 * ETHER_ADDR_LEN; + txsize -= 2 * ETHER_ADDR_LEN; + /* insert vlan tag */ + *(uint16_t *)(s->cplus_txbuffer + 2 * ETHER_ADDR_LEN) = + cpu_to_be16(ETHERTYPE_VLAN); + *(uint16_t *)(s->cplus_txbuffer + 2 * ETHER_ADDR_LEN + ETHER_TYPE_LEN) + = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK); + s->cplus_txbuffer_offset += 2 * ETHER_ADDR_LEN + VLAN_HDR_LEN; + } cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize); s->cplus_txbuffer_offset += txsize; @@ -2053,9 +2079,6 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* update ring data */ val = cpu_to_le32(txdw0); cpu_physical_memory_write(cplus_tx_ring_desc, (uint8_t *)&val, 4); - /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */ -// val = cpu_to_le32(txdw1); -// cpu_physical_memory_write(cplus_tx_ring_desc+4, &val, 4); /* Now decide if descriptor being processed is holding the last segment of packet */ if (txdw0 & CP_TX_LS)