Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vsock/test: two tests to check credit update logic

Both tests are almost same, only differs in two 'if' conditions, so
implemented in a single function. Tests check, that credit update
message is sent:

1) During setting SO_RCVLOWAT value of the socket.
2) When number of 'rx_bytes' become smaller than SO_RCVLOWAT value.

Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arseniy Krasnov and committed by
David S. Miller
542e893f 0fe17989

+175
+175
tools/testing/vsock/vsock_test.c
··· 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_credit_update_test(const struct test_opts *opts, 1277 + bool low_rx_bytes_test) 1278 + { 1279 + size_t recv_buf_size; 1280 + struct pollfd fds; 1281 + size_t buf_size; 1282 + void *buf; 1283 + int fd; 1284 + 1285 + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 1286 + if (fd < 0) { 1287 + perror("accept"); 1288 + exit(EXIT_FAILURE); 1289 + } 1290 + 1291 + buf_size = RCVLOWAT_CREDIT_UPD_BUF_SIZE; 1292 + 1293 + if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, 1294 + &buf_size, sizeof(buf_size))) { 1295 + perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)"); 1296 + exit(EXIT_FAILURE); 1297 + } 1298 + 1299 + if (low_rx_bytes_test) { 1300 + /* Set new SO_RCVLOWAT here. This enables sending credit 1301 + * update when number of bytes if our rx queue become < 1302 + * SO_RCVLOWAT value. 1303 + */ 1304 + recv_buf_size = 1 + VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; 1305 + 1306 + if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, 1307 + &recv_buf_size, sizeof(recv_buf_size))) { 1308 + perror("setsockopt(SO_RCVLOWAT)"); 1309 + exit(EXIT_FAILURE); 1310 + } 1311 + } 1312 + 1313 + /* Send one dummy byte here, because 'setsockopt()' above also 1314 + * sends special packet which tells sender to update our buffer 1315 + * size. This 'send_byte()' will serialize such packet with data 1316 + * reads in a loop below. Sender starts transmission only when 1317 + * it receives this single byte. 1318 + */ 1319 + send_byte(fd, 1, 0); 1320 + 1321 + buf = malloc(buf_size); 1322 + if (!buf) { 1323 + perror("malloc"); 1324 + exit(EXIT_FAILURE); 1325 + } 1326 + 1327 + /* Wait until there will be 128KB of data in rx queue. */ 1328 + while (1) { 1329 + ssize_t res; 1330 + 1331 + res = recv(fd, buf, buf_size, MSG_PEEK); 1332 + if (res == buf_size) 1333 + break; 1334 + 1335 + if (res <= 0) { 1336 + fprintf(stderr, "unexpected 'recv()' return: %zi\n", res); 1337 + exit(EXIT_FAILURE); 1338 + } 1339 + } 1340 + 1341 + /* There is 128KB of data in the socket's rx queue, dequeue first 1342 + * 64KB, credit update is sent if 'low_rx_bytes_test' == true. 1343 + * Otherwise, credit update is sent in 'if (!low_rx_bytes_test)'. 1344 + */ 1345 + recv_buf_size = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; 1346 + recv_buf(fd, buf, recv_buf_size, 0, recv_buf_size); 1347 + 1348 + if (!low_rx_bytes_test) { 1349 + recv_buf_size++; 1350 + 1351 + /* Updating SO_RCVLOWAT will send credit update. */ 1352 + if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, 1353 + &recv_buf_size, sizeof(recv_buf_size))) { 1354 + perror("setsockopt(SO_RCVLOWAT)"); 1355 + exit(EXIT_FAILURE); 1356 + } 1357 + } 1358 + 1359 + fds.fd = fd; 1360 + fds.events = POLLIN | POLLRDNORM | POLLERR | 1361 + POLLRDHUP | POLLHUP; 1362 + 1363 + /* This 'poll()' will return once we receive last byte 1364 + * sent by client. 1365 + */ 1366 + if (poll(&fds, 1, -1) < 0) { 1367 + perror("poll"); 1368 + exit(EXIT_FAILURE); 1369 + } 1370 + 1371 + if (fds.revents & POLLERR) { 1372 + fprintf(stderr, "'poll()' error\n"); 1373 + exit(EXIT_FAILURE); 1374 + } 1375 + 1376 + if (fds.revents & (POLLIN | POLLRDNORM)) { 1377 + recv_buf(fd, buf, recv_buf_size, MSG_DONTWAIT, recv_buf_size); 1378 + } else { 1379 + /* These flags must be set, as there is at 1380 + * least 64KB of data ready to read. 1381 + */ 1382 + fprintf(stderr, "POLLIN | POLLRDNORM expected\n"); 1383 + exit(EXIT_FAILURE); 1384 + } 1385 + 1386 + free(buf); 1387 + close(fd); 1388 + } 1389 + 1390 + static void test_stream_cred_upd_on_low_rx_bytes(const struct test_opts *opts) 1391 + { 1392 + test_stream_credit_update_test(opts, true); 1393 + } 1394 + 1395 + static void test_stream_cred_upd_on_set_rcvlowat(const struct test_opts *opts) 1396 + { 1397 + test_stream_credit_update_test(opts, false); 1398 + } 1399 + 1235 1400 static struct test_case test_cases[] = { 1236 1401 { 1237 1402 .name = "SOCK_STREAM connection reset", ··· 1506 1341 .name = "SOCK_STREAM double bind connect", 1507 1342 .run_client = test_double_bind_connect_client, 1508 1343 .run_server = test_double_bind_connect_server, 1344 + }, 1345 + { 1346 + .name = "SOCK_STREAM virtio credit update + SO_RCVLOWAT", 1347 + .run_client = test_stream_rcvlowat_def_cred_upd_client, 1348 + .run_server = test_stream_cred_upd_on_set_rcvlowat, 1349 + }, 1350 + { 1351 + .name = "SOCK_STREAM virtio credit update + low rx_bytes", 1352 + .run_client = test_stream_rcvlowat_def_cred_upd_client, 1353 + .run_server = test_stream_cred_upd_on_low_rx_bytes, 1509 1354 }, 1510 1355 {}, 1511 1356 };