qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 2/2] rtl8139: add vlan tag extraction


From: Benjamin Poirier
Subject: [Qemu-devel] [PATCH v2 2/2] rtl8139: add vlan tag extraction
Date: Mon, 8 Nov 2010 20:46:21 -0500

Add support to the emulated hardware to remove vlan tags in packets
going from the network to the guest.

Signed-off-by: Benjamin Poirier <address@hidden>
Cc: Igor V. Kovalenko <address@hidden>

---
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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]