aboutsummaryrefslogtreecommitdiff
path: root/hw/e1000.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@linux.vnet.ibm.com>2010-09-18 21:43:45 +0100
committerMichael S. Tsirkin <mst@redhat.com>2010-09-20 20:03:39 +0200
commit78aeb23eded2d0b765bf9145c71f80025b568acd (patch)
tree1d31734cd3afa2cef5fc7b7f0aeb31f0f44546b3 /hw/e1000.c
parent6b37c87c96a5b148685e8e6bf09d0aca953cb1a8 (diff)
downloadqemu-78aeb23eded2d0b765bf9145c71f80025b568acd.zip
qemu-78aeb23eded2d0b765bf9145c71f80025b568acd.tar.gz
qemu-78aeb23eded2d0b765bf9145c71f80025b568acd.tar.bz2
e1000: Pad short frames to minimum size (60 bytes)
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>
Diffstat (limited to 'hw/e1000.c')
-rw-r--r--hw/e1000.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/hw/e1000.c b/hw/e1000.c
index 7d7d140..532efdc 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -55,6 +55,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:
@@ -635,10 +636,19 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
uint32_t rdh_start;
uint16_t vlan_special = 0;
uint8_t vlan_status = 0, vlan_offset = 0;
+ 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 (size > s->rxbuf_size) {
DBGOUT(RX, "packet too large for buffers (%lu > %d)\n",
(unsigned long)size, s->rxbuf_size);