@ -135,6 +135,10 @@ enum {
TEST_FLAGS_END ,
} ;
enum {
VHOST_USER_NET ,
} ;
typedef struct TestServer {
gchar * socket_path ;
gchar * mig_path ;
@ -154,10 +158,25 @@ typedef struct TestServer {
bool test_fail ;
int test_flags ;
int queues ;
struct vhost_user_ops * vu_ops ;
} TestServer ;
struct vhost_user_ops {
/* Device types. */
int type ;
void ( * append_opts ) ( TestServer * s , GString * cmd_line ,
const char * chr_opts ) ;
/* VHOST-USER commands. */
void ( * set_features ) ( TestServer * s , CharBackend * chr ,
VhostUserMsg * msg ) ;
void ( * get_protocol_features ) ( TestServer * s ,
CharBackend * chr , VhostUserMsg * msg ) ;
} ;
static const char * init_hugepagefs ( void ) ;
static TestServer * test_server_new ( const gchar * name ) ;
static TestServer * test_server_new ( const gchar * name ,
struct vhost_user_ops * ops ) ;
static void test_server_free ( TestServer * server ) ;
static void test_server_listen ( TestServer * server ) ;
@ -167,7 +186,7 @@ enum test_memfd {
TEST_MEMFD_NO ,
} ;
static void append_vhost_opts ( TestServer * s , GString * cmd_line ,
static void append_vhost_net_ opts ( TestServer * s , GString * cmd_line ,
const char * chr_opts )
{
g_string_append_printf ( cmd_line , QEMU_CMD_CHR QEMU_CMD_NETDEV ,
@ -332,25 +351,15 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
break ;
case VHOST_USER_SET_FEATURES :
g_assert_cmpint ( msg . payload . u64 & ( 0x1ULL < < VHOST_USER_F_PROTOCOL_FEATURES ) ,
! = , 0ULL ) ;
if ( s - > test_flags = = TEST_FLAGS_DISCONNECT ) {
qemu_chr_fe_disconnect ( chr ) ;
s - > test_flags = TEST_FLAGS_BAD ;
if ( s - > vu_ops - > set_features ) {
s - > vu_ops - > set_features ( s , chr , & msg ) ;
}
break ;
case VHOST_USER_GET_PROTOCOL_FEATURES :
/* send back features to qemu */
msg . flags | = VHOST_USER_REPLY_MASK ;
msg . size = sizeof ( m . payload . u64 ) ;
msg . payload . u64 = 1 < < VHOST_USER_PROTOCOL_F_LOG_SHMFD ;
msg . payload . u64 | = 1 < < VHOST_USER_PROTOCOL_F_CROSS_ENDIAN ;
if ( s - > queues > 1 ) {
msg . payload . u64 | = 1 < < VHOST_USER_PROTOCOL_F_MQ ;
if ( s - > vu_ops - > get_protocol_features ) {
s - > vu_ops - > get_protocol_features ( s , chr , & msg ) ;
}
p = ( uint8_t * ) & msg ;
qemu_chr_fe_write_all ( chr , p , VHOST_USER_HDR_SIZE + msg . size ) ;
break ;
case VHOST_USER_GET_VRING_BASE :
@ -467,7 +476,8 @@ static const char *init_hugepagefs(void)
# endif
}
static TestServer * test_server_new ( const gchar * name )
static TestServer * test_server_new ( const gchar * name ,
struct vhost_user_ops * ops )
{
TestServer * server = g_new0 ( TestServer , 1 ) ;
char template [ ] = " /tmp/vhost-test-XXXXXX " ;
@ -495,6 +505,7 @@ static TestServer *test_server_new(const gchar *name)
server - > log_fd = - 1 ;
server - > queues = 1 ;
server - > vu_ops = ops ;
return server ;
}
@ -669,11 +680,11 @@ static void vhost_user_test_cleanup(void *s)
static void * vhost_user_test_setup ( GString * cmd_line , void * arg )
{
TestServer * server = test_server_new ( " vhost-user-test " ) ;
TestServer * server = test_server_new ( " vhost-user-test " , arg ) ;
test_server_listen ( server ) ;
append_mem_opts ( server , cmd_line , 256 , TEST_MEMFD_AUTO ) ;
append_vhost _opts( server , cmd_line , " " ) ;
server - > vu_ops - > append _opts( server , cmd_line , " " ) ;
g_test_queue_destroy ( vhost_user_test_cleanup , server ) ;
@ -682,11 +693,11 @@ static void *vhost_user_test_setup(GString *cmd_line, void *arg)
static void * vhost_user_test_setup_memfd ( GString * cmd_line , void * arg )
{
TestServer * server = test_server_new ( " vhost-user-test " ) ;
TestServer * server = test_server_new ( " vhost-user-test " , arg ) ;
test_server_listen ( server ) ;
append_mem_opts ( server , cmd_line , 256 , TEST_MEMFD_YES ) ;
append_vhost _opts( server , cmd_line , " " ) ;
server - > vu_ops - > append _opts( server , cmd_line , " " ) ;
g_test_queue_destroy ( vhost_user_test_cleanup , server ) ;
@ -720,7 +731,7 @@ static void test_migrate(void *obj, void *arg, QGuestAllocator *alloc)
return ;
}
dest = test_server_new ( " dest " ) ;
dest = test_server_new ( " dest " , s - > vu_ops ) ;
dest_cmdline = g_string_new ( qos_get_current_command_line ( ) ) ;
uri = g_strdup_printf ( " %s%s " , " unix: " , dest - > mig_path ) ;
@ -730,7 +741,7 @@ static void test_migrate(void *obj, void *arg, QGuestAllocator *alloc)
test_server_listen ( dest ) ;
g_string_append_printf ( dest_cmdline , " -incoming %s " , uri ) ;
append_mem_opts ( dest , dest_cmdline , 256 , TEST_MEMFD_AUTO ) ;
append_vhost _opts( dest , dest_cmdline , " " ) ;
dest - > vu_ops - > append _opts( dest , dest_cmdline , " " ) ;
to = qtest_init ( dest_cmdline - > str ) ;
/* This would be where you call qos_allocate_objects(to, NULL), if you want
@ -831,11 +842,11 @@ connect_thread(gpointer data)
static void * vhost_user_test_setup_reconnect ( GString * cmd_line , void * arg )
{
TestServer * s = test_server_new ( " reconnect " ) ;
TestServer * s = test_server_new ( " reconnect " , arg ) ;
g_thread_new ( " connect " , connect_thread , s ) ;
append_mem_opts ( s , cmd_line , 256 , TEST_MEMFD_AUTO ) ;
append_vhost _opts( s , cmd_line , " ,server " ) ;
s - > vu_ops - > append _opts( s , cmd_line , " ,server " ) ;
g_test_queue_destroy ( vhost_user_test_cleanup , s ) ;
@ -866,13 +877,13 @@ static void test_reconnect(void *obj, void *arg, QGuestAllocator *alloc)
static void * vhost_user_test_setup_connect_fail ( GString * cmd_line , void * arg )
{
TestServer * s = test_server_new ( " connect-fail " ) ;
TestServer * s = test_server_new ( " connect-fail " , arg ) ;
s - > test_fail = true ;
g_thread_new ( " connect " , connect_thread , s ) ;
append_mem_opts ( s , cmd_line , 256 , TEST_MEMFD_AUTO ) ;
append_vhost _opts( s , cmd_line , " ,server " ) ;
s - > vu_ops - > append _opts( s , cmd_line , " ,server " ) ;
g_test_queue_destroy ( vhost_user_test_cleanup , s ) ;
@ -881,13 +892,13 @@ static void *vhost_user_test_setup_connect_fail(GString *cmd_line, void *arg)
static void * vhost_user_test_setup_flags_mismatch ( GString * cmd_line , void * arg )
{
TestServer * s = test_server_new ( " flags-mismatch " ) ;
TestServer * s = test_server_new ( " flags-mismatch " , arg ) ;
s - > test_flags = TEST_FLAGS_DISCONNECT ;
g_thread_new ( " connect " , connect_thread , s ) ;
append_mem_opts ( s , cmd_line , 256 , TEST_MEMFD_AUTO ) ;
append_vhost _opts( s , cmd_line , " ,server " ) ;
s - > vu_ops - > append _opts( s , cmd_line , " ,server " ) ;
g_test_queue_destroy ( vhost_user_test_cleanup , s ) ;
@ -924,11 +935,47 @@ static void test_multiqueue(void *obj, void *arg, QGuestAllocator *alloc)
wait_for_rings_started ( s , s - > queues * 2 ) ;
}
static void vu_net_set_features ( TestServer * s , CharBackend * chr ,
VhostUserMsg * msg )
{
g_assert_cmpint ( msg - > payload . u64 &
( 0x1ULL < < VHOST_USER_F_PROTOCOL_FEATURES ) , ! = , 0ULL ) ;
if ( s - > test_flags = = TEST_FLAGS_DISCONNECT ) {
qemu_chr_fe_disconnect ( chr ) ;
s - > test_flags = TEST_FLAGS_BAD ;
}
}
static void vu_net_get_protocol_features ( TestServer * s , CharBackend * chr ,
VhostUserMsg * msg )
{
/* send back features to qemu */
msg - > flags | = VHOST_USER_REPLY_MASK ;
msg - > size = sizeof ( m . payload . u64 ) ;
msg - > payload . u64 = 1 < < VHOST_USER_PROTOCOL_F_LOG_SHMFD ;
msg - > payload . u64 | = 1 < < VHOST_USER_PROTOCOL_F_CROSS_ENDIAN ;
if ( s - > queues > 1 ) {
msg - > payload . u64 | = 1 < < VHOST_USER_PROTOCOL_F_MQ ;
}
qemu_chr_fe_write_all ( chr , ( uint8_t * ) msg , VHOST_USER_HDR_SIZE + msg - > size ) ;
}
/* Each VHOST-USER device should have its ops structure defined. */
static struct vhost_user_ops g_vu_net_ops = {
. type = VHOST_USER_NET ,
. append_opts = append_vhost_net_opts ,
. set_features = vu_net_set_features ,
. get_protocol_features = vu_net_get_protocol_features ,
} ;
static void register_vhost_user_test ( void )
{
QOSGraphTestOptions opts = {
. before = vhost_user_test_setup ,
. subprocess = true ,
. arg = & g_vu_net_ops ,
} ;
qemu_add_opts ( & qemu_chardev_opts ) ;