@@ -1232,6 +1232,143 @@ static void test_double_bind_connect_client(const struct test_opts *opts)
1232
1232
}
1233
1233
}
1234
1234
1235
+ #define RCVLOWAT_CREDIT_UPD_BUF_SIZE (1024 * 128)
1236
+ /* This define is the same as in 'include/linux/virtio_vsock.h':
1237
+ * it is used to decide when to send credit update message during
1238
+ * reading from rx queue of a socket. Value and its usage in
1239
+ * kernel is important for this test.
1240
+ */
1241
+ #define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64)
1242
+
1243
+ static void test_stream_rcvlowat_def_cred_upd_client (const struct test_opts * opts )
1244
+ {
1245
+ size_t buf_size ;
1246
+ void * buf ;
1247
+ int fd ;
1248
+
1249
+ fd = vsock_stream_connect (opts -> peer_cid , 1234 );
1250
+ if (fd < 0 ) {
1251
+ perror ("connect" );
1252
+ exit (EXIT_FAILURE );
1253
+ }
1254
+
1255
+ /* Send 1 byte more than peer's buffer size. */
1256
+ buf_size = RCVLOWAT_CREDIT_UPD_BUF_SIZE + 1 ;
1257
+
1258
+ buf = malloc (buf_size );
1259
+ if (!buf ) {
1260
+ perror ("malloc" );
1261
+ exit (EXIT_FAILURE );
1262
+ }
1263
+
1264
+ /* Wait until peer sets needed buffer size. */
1265
+ recv_byte (fd , 1 , 0 );
1266
+
1267
+ if (send (fd , buf , buf_size , 0 ) != buf_size ) {
1268
+ perror ("send failed" );
1269
+ exit (EXIT_FAILURE );
1270
+ }
1271
+
1272
+ free (buf );
1273
+ close (fd );
1274
+ }
1275
+
1276
+ static void test_stream_rcvlowat_def_cred_upd_server (const struct test_opts * opts )
1277
+ {
1278
+ size_t recv_buf_size ;
1279
+ struct pollfd fds ;
1280
+ size_t buf_size ;
1281
+ void * buf ;
1282
+ int fd ;
1283
+
1284
+ fd = vsock_stream_accept (VMADDR_CID_ANY , 1234 , NULL );
1285
+ if (fd < 0 ) {
1286
+ perror ("accept" );
1287
+ exit (EXIT_FAILURE );
1288
+ }
1289
+
1290
+ buf_size = RCVLOWAT_CREDIT_UPD_BUF_SIZE ;
1291
+
1292
+ if (setsockopt (fd , AF_VSOCK , SO_VM_SOCKETS_BUFFER_SIZE ,
1293
+ & buf_size , sizeof (buf_size ))) {
1294
+ perror ("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)" );
1295
+ exit (EXIT_FAILURE );
1296
+ }
1297
+
1298
+ /* Send one dummy byte here, because 'setsockopt()' above also
1299
+ * sends special packet which tells sender to update our buffer
1300
+ * size. This 'send_byte()' will serialize such packet with data
1301
+ * reads in a loop below. Sender starts transmission only when
1302
+ * it receives this single byte.
1303
+ */
1304
+ send_byte (fd , 1 , 0 );
1305
+
1306
+ buf = malloc (buf_size );
1307
+ if (!buf ) {
1308
+ perror ("malloc" );
1309
+ exit (EXIT_FAILURE );
1310
+ }
1311
+
1312
+ /* Wait until there will be 128KB of data in rx queue. */
1313
+ while (1 ) {
1314
+ ssize_t res ;
1315
+
1316
+ res = recv (fd , buf , buf_size , MSG_PEEK );
1317
+ if (res == buf_size )
1318
+ break ;
1319
+
1320
+ if (res <= 0 ) {
1321
+ fprintf (stderr , "unexpected 'recv()' return: %zi\n" , res );
1322
+ exit (EXIT_FAILURE );
1323
+ }
1324
+ }
1325
+
1326
+ /* There is 128KB of data in the socket's rx queue,
1327
+ * dequeue first 64KB, credit update is not sent.
1328
+ */
1329
+ recv_buf_size = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE ;
1330
+ recv_buf (fd , buf , recv_buf_size , 0 , recv_buf_size );
1331
+ recv_buf_size ++ ;
1332
+
1333
+ /* Updating SO_RCVLOWAT will send credit update. */
1334
+ if (setsockopt (fd , SOL_SOCKET , SO_RCVLOWAT ,
1335
+ & recv_buf_size , sizeof (recv_buf_size ))) {
1336
+ perror ("setsockopt(SO_RCVLOWAT)" );
1337
+ exit (EXIT_FAILURE );
1338
+ }
1339
+
1340
+ memset (& fds , 0 , sizeof (fds ));
1341
+ fds .fd = fd ;
1342
+ fds .events = POLLIN | POLLRDNORM | POLLERR |
1343
+ POLLRDHUP | POLLHUP ;
1344
+
1345
+ /* This 'poll()' will return once we receive last byte
1346
+ * sent by client.
1347
+ */
1348
+ if (poll (& fds , 1 , -1 ) < 0 ) {
1349
+ perror ("poll" );
1350
+ exit (EXIT_FAILURE );
1351
+ }
1352
+
1353
+ if (fds .revents & POLLERR ) {
1354
+ fprintf (stderr , "'poll()' error\n" );
1355
+ exit (EXIT_FAILURE );
1356
+ }
1357
+
1358
+ if (fds .revents & (POLLIN | POLLRDNORM )) {
1359
+ recv_buf (fd , buf , recv_buf_size , MSG_DONTWAIT , recv_buf_size );
1360
+ } else {
1361
+ /* These flags must be set, as there is at
1362
+ * least 64KB of data ready to read.
1363
+ */
1364
+ fprintf (stderr , "POLLIN | POLLRDNORM expected\n" );
1365
+ exit (EXIT_FAILURE );
1366
+ }
1367
+
1368
+ free (buf );
1369
+ close (fd );
1370
+ }
1371
+
1235
1372
static struct test_case test_cases [] = {
1236
1373
{
1237
1374
.name = "SOCK_STREAM connection reset" ,
@@ -1342,6 +1479,11 @@ static struct test_case test_cases[] = {
1342
1479
.run_client = test_double_bind_connect_client ,
1343
1480
.run_server = test_double_bind_connect_server ,
1344
1481
},
1482
+ {
1483
+ .name = "SOCK_STREAM virtio SO_RCVLOWAT + deferred cred update" ,
1484
+ .run_client = test_stream_rcvlowat_def_cred_upd_client ,
1485
+ .run_server = test_stream_rcvlowat_def_cred_upd_server ,
1486
+ },
1345
1487
{},
1346
1488
};
1347
1489
0 commit comments