mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
vhost, virtio, pci, pxe
Fixes all over the place. New tests for pxe. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWxedfAAoJECgfDbjSjVRp9ZoH/1zlxDy/iiJWXJI0jkcnbSof /tFbchrj/hfz0/Wr0yeKJNdU1rMgiY0lYM1F5Pp4MQDHFoFM6i7LaLUYLQq92u+w CpgTOMXwthOqn94yrBncKUN+OkB4vDW18sHd21rTh5n1oO9VjM4oQFSHpAtaDdnc 7dyryrlocBlgjARuOhW7A3KJAdPcKUer5JKdbWMDHw2wgwk1+7lx8ip7PBrFpMwW PEEw2jo/lQw/rm/Kit+BV43NBy5pks2/jWmaXqH5jgCNixEmbY150dJLLW6lAqdh xatnMxkQHpbEyf/Cy8M73v8vdOLjfQNdJ7GO0lc3CZw4bZBHbOcuzVEExvHewYw= =vpiH -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging vhost, virtio, pci, pxe Fixes all over the place. New tests for pxe. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 18 Feb 2016 15:46:39 GMT using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" * remotes/mst/tags/for_upstream: tests/vhost-user-bridge: add scattering of incoming packets vhost-user interrupt management fixes rules: filter out irrelevant files change type of pci_bridge_initfn() to void dec: convert to realize() tests: add pxe e1000 and virtio-pci tests msix: fix msix_vector_masked virtio: optimize virtio_access_is_big_endian() for little-endian targets vhost: simplify vhost_needs_vring_endian() vhost: move virtio 1.0 check to cross-endian helper virtio: move cross-endian helper to vhost vhost-net: revert support of cross-endian vnet headers virtio-net: use the backend cross-endian capabilities Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
09125c5e76
25 changed files with 428 additions and 209 deletions
|
@ -173,6 +173,7 @@ check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
|
|||
gcov-files-i386-y += hw/block/hd-geometry.c
|
||||
check-qtest-i386-y += tests/boot-order-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/pxe-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/rtc-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/ipmi-kcs-test$(EXESUF)
|
||||
check-qtest-i386-y += tests/ipmi-bt-test$(EXESUF)
|
||||
|
@ -518,7 +519,9 @@ tests/ipmi-kcs-test$(EXESUF): tests/ipmi-kcs-test.o
|
|||
tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o
|
||||
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
|
||||
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
|
||||
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
|
||||
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
|
||||
tests/boot-sector.o $(libqos-obj-y)
|
||||
tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
|
||||
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
|
||||
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
|
||||
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "hw/acpi/acpi-defs.h"
|
||||
#include "hw/smbios/smbios.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "boot-sector.h"
|
||||
|
||||
#define MACHINE_PC "pc"
|
||||
#define MACHINE_Q35 "q35"
|
||||
|
@ -51,13 +52,6 @@ typedef struct {
|
|||
struct smbios_21_entry_point smbios_ep_table;
|
||||
} test_data;
|
||||
|
||||
#define LOW(x) ((x) & 0xff)
|
||||
#define HIGH(x) ((x) >> 8)
|
||||
|
||||
#define SIGNATURE 0xdead
|
||||
#define SIGNATURE_OFFSET 0x10
|
||||
#define BOOT_SECTOR_ADDRESS 0x7c00
|
||||
|
||||
#define ACPI_READ_FIELD(field, addr) \
|
||||
do { \
|
||||
switch (sizeof(field)) { \
|
||||
|
@ -117,35 +111,6 @@ typedef struct {
|
|||
g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
|
||||
} while (0)
|
||||
|
||||
/* Boot sector code: write SIGNATURE into memory,
|
||||
* then halt.
|
||||
* Q35 machine requires a minimum 0x7e000 bytes disk.
|
||||
* (bug or feature?)
|
||||
*/
|
||||
static uint8_t boot_sector[0x7e000] = {
|
||||
/* 7c00: mov $0xdead,%ax */
|
||||
[0x00] = 0xb8,
|
||||
[0x01] = LOW(SIGNATURE),
|
||||
[0x02] = HIGH(SIGNATURE),
|
||||
/* 7c03: mov %ax,0x7c10 */
|
||||
[0x03] = 0xa3,
|
||||
[0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
[0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
/* 7c06: cli */
|
||||
[0x06] = 0xfa,
|
||||
/* 7c07: hlt */
|
||||
[0x07] = 0xf4,
|
||||
/* 7c08: jmp 0x7c07=0x7c0a-3 */
|
||||
[0x08] = 0xeb,
|
||||
[0x09] = LOW(-3),
|
||||
/* We mov 0xdead here: set value to make debugging easier */
|
||||
[SIGNATURE_OFFSET] = LOW(0xface),
|
||||
[SIGNATURE_OFFSET + 1] = HIGH(0xface),
|
||||
/* End of boot sector marker */
|
||||
[0x1FE] = 0x55,
|
||||
[0x1FF] = 0xAA,
|
||||
};
|
||||
|
||||
static const char *disk = "tests/acpi-test-disk.raw";
|
||||
static const char *data_dir = "tests/acpi-test-data";
|
||||
#ifdef CONFIG_IASL
|
||||
|
@ -737,10 +702,6 @@ static void test_smbios_structs(test_data *data)
|
|||
static void test_acpi_one(const char *params, test_data *data)
|
||||
{
|
||||
char *args;
|
||||
uint8_t signature_low;
|
||||
uint8_t signature_high;
|
||||
uint16_t signature;
|
||||
int i;
|
||||
|
||||
args = g_strdup_printf("-net none -display none %s "
|
||||
"-drive id=hd0,if=none,file=%s,format=raw "
|
||||
|
@ -749,24 +710,7 @@ static void test_acpi_one(const char *params, test_data *data)
|
|||
|
||||
qtest_start(args);
|
||||
|
||||
/* Wait at most 1 minute */
|
||||
#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
|
||||
#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
|
||||
|
||||
/* Poll until code has run and modified memory. Once it has we know BIOS
|
||||
* initialization is done. TODO: check that IP reached the halt
|
||||
* instruction.
|
||||
*/
|
||||
for (i = 0; i < TEST_CYCLES; ++i) {
|
||||
signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
|
||||
signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
signature = (signature_high << 8) | signature_low;
|
||||
if (signature == SIGNATURE) {
|
||||
break;
|
||||
}
|
||||
g_usleep(TEST_DELAY);
|
||||
}
|
||||
g_assert_cmphex(signature, ==, SIGNATURE);
|
||||
boot_sector_test();
|
||||
|
||||
test_acpi_rsdp_address(data);
|
||||
test_acpi_rsdp_table(data);
|
||||
|
@ -840,15 +784,11 @@ static void test_acpi_q35_tcg_bridge(void)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
FILE *f = fopen(disk, "w");
|
||||
int ret;
|
||||
|
||||
if (!f) {
|
||||
fprintf(stderr, "Couldn't open \"%s\": %s", disk, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fwrite(boot_sector, 1, sizeof boot_sector, f);
|
||||
fclose(f);
|
||||
ret = boot_sector_init(disk);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
|
@ -859,6 +799,6 @@ int main(int argc, char *argv[])
|
|||
qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge);
|
||||
}
|
||||
ret = g_test_run();
|
||||
unlink(disk);
|
||||
boot_sector_cleanup(disk);
|
||||
return ret;
|
||||
}
|
||||
|
|
119
tests/boot-sector.c
Normal file
119
tests/boot-sector.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* QEMU boot sector testing helpers.
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Michael S. Tsirkin <mst@redhat.com>
|
||||
* Victor Kaplansky <victork@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "boot-sector.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "qemu-common.h"
|
||||
#include "libqtest.h"
|
||||
|
||||
#define LOW(x) ((x) & 0xff)
|
||||
#define HIGH(x) ((x) >> 8)
|
||||
|
||||
#define SIGNATURE 0xdead
|
||||
#define SIGNATURE_OFFSET 0x10
|
||||
#define BOOT_SECTOR_ADDRESS 0x7c00
|
||||
|
||||
/* Boot sector code: write SIGNATURE into memory,
|
||||
* then halt.
|
||||
* Q35 machine requires a minimum 0x7e000 bytes disk.
|
||||
* (bug or feature?)
|
||||
*/
|
||||
static uint8_t boot_sector[0x7e000] = {
|
||||
/* The first sector will be placed at RAM address 00007C00, and
|
||||
* the BIOS transfers control to 00007C00
|
||||
*/
|
||||
|
||||
/* Data Segment register should be initialized, since pxe
|
||||
* boot loader can leave it dirty.
|
||||
*/
|
||||
|
||||
/* 7c00: move $0000,%ax */
|
||||
[0x00] = 0xb8,
|
||||
[0x01] = 0x00,
|
||||
[0x02] = 0x00,
|
||||
/* 7c03: move %ax,%ds */
|
||||
[0x03] = 0x8e,
|
||||
[0x04] = 0xd8,
|
||||
|
||||
/* 7c05: mov $0xdead,%ax */
|
||||
[0x05] = 0xb8,
|
||||
[0x06] = LOW(SIGNATURE),
|
||||
[0x07] = HIGH(SIGNATURE),
|
||||
/* 7c08: mov %ax,0x7c10 */
|
||||
[0x08] = 0xa3,
|
||||
[0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
[0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
|
||||
|
||||
/* 7c0b cli */
|
||||
[0x0b] = 0xfa,
|
||||
/* 7c0c: hlt */
|
||||
[0x0c] = 0xf4,
|
||||
/* 7c0e: jmp 0x7c07=0x7c0f-3 */
|
||||
[0x0d] = 0xeb,
|
||||
[0x0e] = LOW(-3),
|
||||
/* We mov 0xdead here: set value to make debugging easier */
|
||||
[SIGNATURE_OFFSET] = LOW(0xface),
|
||||
[SIGNATURE_OFFSET + 1] = HIGH(0xface),
|
||||
/* End of boot sector marker */
|
||||
[0x1FE] = 0x55,
|
||||
[0x1FF] = 0xAA,
|
||||
};
|
||||
|
||||
/* Create boot disk file. */
|
||||
int boot_sector_init(const char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "w");
|
||||
|
||||
if (!f) {
|
||||
fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
fwrite(boot_sector, 1, sizeof boot_sector, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Loop until signature in memory is OK. */
|
||||
void boot_sector_test(void)
|
||||
{
|
||||
uint8_t signature_low;
|
||||
uint8_t signature_high;
|
||||
uint16_t signature;
|
||||
int i;
|
||||
|
||||
/* Wait at most 1 minute */
|
||||
#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
|
||||
#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
|
||||
|
||||
/* Poll until code has run and modified memory. Once it has we know BIOS
|
||||
* initialization is done. TODO: check that IP reached the halt
|
||||
* instruction.
|
||||
*/
|
||||
for (i = 0; i < TEST_CYCLES; ++i) {
|
||||
signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
|
||||
signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
|
||||
signature = (signature_high << 8) | signature_low;
|
||||
if (signature == SIGNATURE) {
|
||||
break;
|
||||
}
|
||||
g_usleep(TEST_DELAY);
|
||||
}
|
||||
|
||||
g_assert_cmphex(signature, ==, SIGNATURE);
|
||||
}
|
||||
|
||||
/* unlink boot disk file. */
|
||||
void boot_sector_cleanup(const char *fname)
|
||||
{
|
||||
unlink(fname);
|
||||
}
|
26
tests/boot-sector.h
Normal file
26
tests/boot-sector.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* QEMU boot sector testing helpers.
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Michael S. Tsirkin <mst@redhat.com>
|
||||
* Victor Kaplansky <victork@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TEST_BOOT_SECTOR
|
||||
#define TEST_BOOT_SECTOR
|
||||
|
||||
/* Create boot disk file. */
|
||||
int boot_sector_init(const char *fname);
|
||||
|
||||
/* Loop until signature in memory is OK. */
|
||||
void boot_sector_test(void);
|
||||
|
||||
/* unlink boot disk file. */
|
||||
void boot_sector_cleanup(const char *fname);
|
||||
|
||||
#endif /* TEST_BOOT_SECTOR */
|
69
tests/pxe-test.c
Normal file
69
tests/pxe-test.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* PXE test cases.
|
||||
*
|
||||
* Copyright (c) 2016 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Michael S. Tsirkin <mst@redhat.com>,
|
||||
* Victor Kaplansky <victork@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include "qemu-common.h"
|
||||
#include "libqtest.h"
|
||||
#include "boot-sector.h"
|
||||
|
||||
#define NETNAME "net0"
|
||||
|
||||
static const char *disk = "tests/pxe-test-disk.raw";
|
||||
|
||||
static void test_pxe_one(const char *params)
|
||||
{
|
||||
char *args;
|
||||
|
||||
args = g_strdup_printf("-machine accel=tcg "
|
||||
"-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
|
||||
"%s ",
|
||||
disk, params);
|
||||
|
||||
qtest_start(args);
|
||||
boot_sector_test();
|
||||
qtest_quit(global_qtest);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
static void test_pxe_e1000(void)
|
||||
{
|
||||
test_pxe_one("-device e1000,netdev=" NETNAME);
|
||||
}
|
||||
|
||||
static void test_pxe_virtio_pci(void)
|
||||
{
|
||||
test_pxe_one("-device virtio-net-pci,netdev=" NETNAME);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
const char *arch = qtest_get_arch();
|
||||
|
||||
ret = boot_sector_init(disk);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
qtest_add_func("pxe/e1000", test_pxe_e1000);
|
||||
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
|
||||
}
|
||||
ret = g_test_run();
|
||||
boot_sector_cleanup(disk);
|
||||
return ret;
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
#include <sys/eventfd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <qemu/osdep.h>
|
||||
|
||||
#include <linux/vhost.h>
|
||||
|
||||
|
@ -176,6 +177,8 @@ typedef struct VubrVirtq {
|
|||
|
||||
#define VHOST_MEMORY_MAX_NREGIONS 8
|
||||
#define VHOST_USER_F_PROTOCOL_FEATURES 30
|
||||
/* v1.0 compliant. */
|
||||
#define VIRTIO_F_VERSION_1 32
|
||||
|
||||
#define VHOST_LOG_PAGE 4096
|
||||
|
||||
|
@ -284,6 +287,7 @@ typedef struct VubrDev {
|
|||
struct sockaddr_in backend_udp_dest;
|
||||
int ready;
|
||||
uint64_t features;
|
||||
int hdrlen;
|
||||
} VubrDev;
|
||||
|
||||
static const char *vubr_request_str[] = {
|
||||
|
@ -474,7 +478,8 @@ vubr_backend_udp_recvbuf(VubrDev *dev, uint8_t *buf, size_t buflen)
|
|||
static void
|
||||
vubr_consume_raw_packet(VubrDev *dev, uint8_t *buf, uint32_t len)
|
||||
{
|
||||
int hdrlen = sizeof(struct virtio_net_hdr_v1);
|
||||
int hdrlen = dev->hdrlen;
|
||||
DPRINT(" hdrlen = %d\n", dev->hdrlen);
|
||||
|
||||
if (VHOST_USER_BRIDGE_DEBUG) {
|
||||
print_buffer(buf, len);
|
||||
|
@ -536,6 +541,7 @@ vubr_post_buffer(VubrDev *dev, VubrVirtq *vq, uint8_t *buf, int32_t len)
|
|||
struct vring_avail *avail = vq->avail;
|
||||
struct vring_used *used = vq->used;
|
||||
uint64_t log_guest_addr = vq->log_guest_addr;
|
||||
int32_t remaining_len = len;
|
||||
|
||||
unsigned int size = vq->size;
|
||||
|
||||
|
@ -550,36 +556,49 @@ vubr_post_buffer(VubrDev *dev, VubrVirtq *vq, uint8_t *buf, int32_t len)
|
|||
uint16_t d_index = avail->ring[a_index];
|
||||
|
||||
int i = d_index;
|
||||
uint32_t written_len = 0;
|
||||
|
||||
DPRINT("Post packet to guest on vq:\n");
|
||||
DPRINT(" size = %d\n", vq->size);
|
||||
DPRINT(" last_avail_index = %d\n", vq->last_avail_index);
|
||||
DPRINT(" last_used_index = %d\n", vq->last_used_index);
|
||||
DPRINT(" a_index = %d\n", a_index);
|
||||
DPRINT(" u_index = %d\n", u_index);
|
||||
DPRINT(" d_index = %d\n", d_index);
|
||||
DPRINT(" desc[%d].addr = 0x%016"PRIx64"\n", i, desc[i].addr);
|
||||
DPRINT(" desc[%d].len = %d\n", i, desc[i].len);
|
||||
DPRINT(" desc[%d].flags = %d\n", i, desc[i].flags);
|
||||
DPRINT(" avail->idx = %d\n", avail_index);
|
||||
DPRINT(" used->idx = %d\n", used->idx);
|
||||
do {
|
||||
DPRINT("Post packet to guest on vq:\n");
|
||||
DPRINT(" size = %d\n", vq->size);
|
||||
DPRINT(" last_avail_index = %d\n", vq->last_avail_index);
|
||||
DPRINT(" last_used_index = %d\n", vq->last_used_index);
|
||||
DPRINT(" a_index = %d\n", a_index);
|
||||
DPRINT(" u_index = %d\n", u_index);
|
||||
DPRINT(" d_index = %d\n", d_index);
|
||||
DPRINT(" desc[%d].addr = 0x%016"PRIx64"\n", i, desc[i].addr);
|
||||
DPRINT(" desc[%d].len = %d\n", i, desc[i].len);
|
||||
DPRINT(" desc[%d].flags = %d\n", i, desc[i].flags);
|
||||
DPRINT(" avail->idx = %d\n", avail_index);
|
||||
DPRINT(" used->idx = %d\n", used->idx);
|
||||
|
||||
if (!(desc[i].flags & VRING_DESC_F_WRITE)) {
|
||||
/* FIXME: we should find writable descriptor. */
|
||||
fprintf(stderr, "Error: descriptor is not writable. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!(desc[i].flags & VRING_DESC_F_WRITE)) {
|
||||
/* FIXME: we should find writable descriptor. */
|
||||
fprintf(stderr, "Error: descriptor is not writable. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *chunk_start = (void *)gpa_to_va(dev, desc[i].addr);
|
||||
uint32_t chunk_len = desc[i].len;
|
||||
void *chunk_start = (void *)gpa_to_va(dev, desc[i].addr);
|
||||
uint32_t chunk_len = desc[i].len;
|
||||
uint32_t chunk_write_len = MIN(remaining_len, chunk_len);
|
||||
|
||||
if (len <= chunk_len) {
|
||||
memcpy(chunk_start, buf, len);
|
||||
vubr_log_write(dev, desc[i].addr, len);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Received too long packet from the backend. Dropping...\n");
|
||||
return;
|
||||
memcpy(chunk_start, buf + written_len, chunk_write_len);
|
||||
vubr_log_write(dev, desc[i].addr, chunk_write_len);
|
||||
remaining_len -= chunk_write_len;
|
||||
written_len += chunk_write_len;
|
||||
|
||||
if ((remaining_len == 0) || !(desc[i].flags & VRING_DESC_F_NEXT)) {
|
||||
break;
|
||||
}
|
||||
|
||||
i = desc[i].next;
|
||||
} while (1);
|
||||
|
||||
if (remaining_len > 0) {
|
||||
fprintf(stderr,
|
||||
"Too long packet for RX, remaining_len = %d, Dropping...\n",
|
||||
remaining_len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add descriptor to the used ring. */
|
||||
|
@ -687,7 +706,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
|
|||
VubrVirtq *rx_vq = &dev->vq[0];
|
||||
uint8_t buf[4096];
|
||||
struct virtio_net_hdr_v1 *hdr = (struct virtio_net_hdr_v1 *)buf;
|
||||
int hdrlen = sizeof(struct virtio_net_hdr_v1);
|
||||
int hdrlen = dev->hdrlen;
|
||||
int buflen = sizeof(buf);
|
||||
int len;
|
||||
|
||||
|
@ -696,6 +715,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
|
|||
}
|
||||
|
||||
DPRINT("\n\n *** IN UDP RECEIVE CALLBACK ***\n\n");
|
||||
DPRINT(" hdrlen = %d\n", hdrlen);
|
||||
|
||||
uint16_t avail_index = atomic_mb_read(&rx_vq->avail->idx);
|
||||
|
||||
|
@ -707,10 +727,12 @@ vubr_backend_recv_cb(int sock, void *ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
memset(buf, 0, hdrlen);
|
||||
/* TODO: support mergeable buffers. */
|
||||
if (hdrlen == 12)
|
||||
hdr->num_buffers = 1;
|
||||
len = vubr_backend_udp_recvbuf(dev, buf + hdrlen, buflen - hdrlen);
|
||||
|
||||
*hdr = (struct virtio_net_hdr_v1) { };
|
||||
hdr->num_buffers = 1;
|
||||
vubr_post_buffer(dev, rx_vq, buf, len + hdrlen);
|
||||
}
|
||||
|
||||
|
@ -758,7 +780,15 @@ static int
|
|||
vubr_set_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
|
||||
{
|
||||
DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
|
||||
|
||||
dev->features = vmsg->payload.u64;
|
||||
if ((dev->features & (1ULL << VIRTIO_F_VERSION_1)) ||
|
||||
(dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF))) {
|
||||
dev->hdrlen = 12;
|
||||
} else {
|
||||
dev->hdrlen = 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue