From 82b448ceaf02776c928ad3b60034248ab526e80a Mon Sep 17 00:00:00 2001
From: Xiao Wang <jasowang@redhat.com>
Date: Fri, 10 Aug 2012 09:03:41 -0300
Subject: [RHEL6 qemu-kvm PATCH 1/9] e1000: Pad short frames to minimum size
 (60 bytes)

RH-Author: Xiao Wang <jasowang@redhat.com>
Message-id: <1344589429-3229-2-git-send-email-jasowang@redhat.com>
Patchwork-id: 40679
O-Subject: [RHEL6.4 qemu-kvm 1/9] e1000: Pad short frames to minimum size (60 bytes)
Bugzilla: 607510 819915
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>
RH-Acked-by: Vlad Yasevich <vyasevic@redhat.com>

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=819915
Upstream: manually cherry pick from 78aeb23eded2d0b765bf9145c71f80025b568acd

The OpenIndiana (Solaris) e1000g driver drops frames that are too long
or too short.  It expects to receive frames of at least the Ethernet
minimum size.  ARP requests in particular are small and will be dropped
if they are not padded appropriately, preventing a Solaris VM from
becoming visible on the network.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 hw/e1000.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/e1000.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/hw/e1000.c b/hw/e1000.c
index f5adc3d..b7be9a2 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -53,6 +53,7 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
 #define IOPORT_SIZE       0x40
 #define PNPMMIO_SIZE      0x20000
+#define MIN_BUF_SIZE      60 /* Min. octets in an ethernet frame sans FCS */
 
 /*
  * HW models:
@@ -662,10 +663,19 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     uint8_t vlan_status = 0, vlan_offset = 0;
     size_t desc_offset;
     size_t desc_size;
+    uint8_t min_buf[MIN_BUF_SIZE];
 
     if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
         return -1;
 
+    /* Pad to minimum Ethernet frame length */
+    if (size < sizeof(min_buf)) {
+        memcpy(min_buf, buf, size);
+        memset(&min_buf[size], 0, sizeof(min_buf) - size);
+        buf = min_buf;
+        size = sizeof(min_buf);
+    }
+
     if (!receive_filter(s, buf, size))
         return size;
 
-- 
1.7.11.2

