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

Merge branch 'selftests-drv-net-ncdevmem-fix-error-paths'

Jakub Kicinski says:

====================
selftests: drv-net: ncdevmem: fix error paths

Make ncdevmem clean up after itself. While at it make sure it sets
HDS threshold to 0 automatically.

v1: https://lore.kernel.org/20250822200052.1675613-1-kuba@kernel.org
====================

Link: https://patch.msgid.link/20250825180447.2252977-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+588 -208
+588 -208
tools/testing/selftests/drivers/net/hw/ncdevmem.c
··· 39 39 #define __EXPORTED_HEADERS__ 40 40 41 41 #include <linux/uio.h> 42 + #include <stdarg.h> 42 43 #include <stdio.h> 43 44 #include <stdlib.h> 44 45 #include <unistd.h> ··· 98 97 static uint32_t tx_dmabuf_id; 99 98 static int waittime_ms = 500; 100 99 100 + /* System state loaded by current_config_load() */ 101 + #define MAX_FLOWS 8 102 + static int ntuple_ids[MAX_FLOWS] = { -1, -1, -1, -1, -1, -1, -1, -1, }; 103 + 101 104 struct memory_buffer { 102 105 int fd; 103 106 size_t size; ··· 120 115 size_t off, int n); 121 116 }; 122 117 118 + static void pr_err(const char *fmt, ...) 119 + { 120 + va_list args; 121 + 122 + fprintf(stderr, "%s: ", TEST_PREFIX); 123 + 124 + va_start(args, fmt); 125 + vfprintf(stderr, fmt, args); 126 + va_end(args); 127 + 128 + if (errno != 0) 129 + fprintf(stderr, ": %s", strerror(errno)); 130 + fprintf(stderr, "\n"); 131 + } 132 + 123 133 static struct memory_buffer *udmabuf_alloc(size_t size) 124 134 { 125 135 struct udmabuf_create create; ··· 143 123 144 124 ctx = malloc(sizeof(*ctx)); 145 125 if (!ctx) 146 - error(1, ENOMEM, "malloc failed"); 126 + return NULL; 147 127 148 128 ctx->size = size; 149 129 150 130 ctx->devfd = open("/dev/udmabuf", O_RDWR); 151 - if (ctx->devfd < 0) 152 - error(1, errno, 153 - "%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n", 154 - TEST_PREFIX); 131 + if (ctx->devfd < 0) { 132 + pr_err("[skip,no-udmabuf: Unable to access DMA buffer device file]"); 133 + goto err_free_ctx; 134 + } 155 135 156 136 ctx->memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING); 157 - if (ctx->memfd < 0) 158 - error(1, errno, "%s: [skip,no-memfd]\n", TEST_PREFIX); 137 + if (ctx->memfd < 0) { 138 + pr_err("[skip,no-memfd]"); 139 + goto err_close_dev; 140 + } 159 141 160 142 ret = fcntl(ctx->memfd, F_ADD_SEALS, F_SEAL_SHRINK); 161 - if (ret < 0) 162 - error(1, errno, "%s: [skip,fcntl-add-seals]\n", TEST_PREFIX); 143 + if (ret < 0) { 144 + pr_err("[skip,fcntl-add-seals]"); 145 + goto err_close_memfd; 146 + } 163 147 164 148 ret = ftruncate(ctx->memfd, size); 165 - if (ret == -1) 166 - error(1, errno, "%s: [FAIL,memfd-truncate]\n", TEST_PREFIX); 149 + if (ret == -1) { 150 + pr_err("[FAIL,memfd-truncate]"); 151 + goto err_close_memfd; 152 + } 167 153 168 154 memset(&create, 0, sizeof(create)); 169 155 ··· 177 151 create.offset = 0; 178 152 create.size = size; 179 153 ctx->fd = ioctl(ctx->devfd, UDMABUF_CREATE, &create); 180 - if (ctx->fd < 0) 181 - error(1, errno, "%s: [FAIL, create udmabuf]\n", TEST_PREFIX); 154 + if (ctx->fd < 0) { 155 + pr_err("[FAIL, create udmabuf]"); 156 + goto err_close_fd; 157 + } 182 158 183 159 ctx->buf_mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, 184 160 ctx->fd, 0); 185 - if (ctx->buf_mem == MAP_FAILED) 186 - error(1, errno, "%s: [FAIL, map udmabuf]\n", TEST_PREFIX); 161 + if (ctx->buf_mem == MAP_FAILED) { 162 + pr_err("[FAIL, map udmabuf]"); 163 + goto err_close_fd; 164 + } 187 165 188 166 return ctx; 167 + 168 + err_close_fd: 169 + close(ctx->fd); 170 + err_close_memfd: 171 + close(ctx->memfd); 172 + err_close_dev: 173 + close(ctx->devfd); 174 + err_free_ctx: 175 + free(ctx); 176 + return NULL; 189 177 } 190 178 191 179 static void udmabuf_free(struct memory_buffer *ctx) ··· 257 217 putchar(p[i]); 258 218 } 259 219 260 - void validate_buffer(void *line, size_t size) 220 + int validate_buffer(void *line, size_t size) 261 221 { 262 222 static unsigned char seed = 1; 263 223 unsigned char *ptr = line; ··· 272 232 "Failed validation: expected=%u, actual=%u, index=%lu\n", 273 233 expected, ptr[i], i); 274 234 errors++; 275 - if (errors > 20) 276 - error(1, 0, "validation failed."); 235 + if (errors > 20) { 236 + pr_err("validation failed"); 237 + return -1; 238 + } 277 239 } 278 240 seed++; 279 241 if (seed == do_validation) ··· 283 241 } 284 242 285 243 fprintf(stdout, "Validated buffer\n"); 244 + return 0; 245 + } 246 + 247 + static int 248 + __run_command(char *out, size_t outlen, const char *cmd, va_list args) 249 + { 250 + char command[256]; 251 + FILE *fp; 252 + 253 + vsnprintf(command, sizeof(command), cmd, args); 254 + 255 + fprintf(stderr, "Running: %s\n", command); 256 + fp = popen(command, "r"); 257 + if (!fp) 258 + return -1; 259 + if (out) { 260 + size_t len; 261 + 262 + if (!fgets(out, outlen, fp)) 263 + return -1; 264 + 265 + /* Remove trailing newline if present */ 266 + len = strlen(out); 267 + if (len && out[len - 1] == '\n') 268 + out[len - 1] = '\0'; 269 + } 270 + return pclose(fp); 271 + } 272 + 273 + static int run_command(const char *cmd, ...) 274 + { 275 + va_list args; 276 + int ret; 277 + 278 + va_start(args, cmd); 279 + ret = __run_command(NULL, 0, cmd, args); 280 + va_end(args); 281 + 282 + return ret; 283 + } 284 + 285 + static int ethtool_add_flow(const char *format, ...) 286 + { 287 + char local_output[256], cmd[256]; 288 + const char *id_start; 289 + int flow_idx, ret; 290 + char *endptr; 291 + long flow_id; 292 + va_list args; 293 + 294 + for (flow_idx = 0; flow_idx < MAX_FLOWS; flow_idx++) 295 + if (ntuple_ids[flow_idx] == -1) 296 + break; 297 + if (flow_idx == MAX_FLOWS) { 298 + fprintf(stderr, "Error: too many flows\n"); 299 + return -1; 300 + } 301 + 302 + snprintf(cmd, sizeof(cmd), "ethtool -N %s %s", ifname, format); 303 + 304 + va_start(args, format); 305 + ret = __run_command(local_output, sizeof(local_output), cmd, args); 306 + va_end(args); 307 + 308 + if (ret != 0) 309 + return ret; 310 + 311 + /* Extract the ID from the output */ 312 + id_start = strstr(local_output, "Added rule with ID "); 313 + if (!id_start) 314 + return -1; 315 + id_start += strlen("Added rule with ID "); 316 + 317 + flow_id = strtol(id_start, &endptr, 10); 318 + if (endptr == id_start || flow_id < 0 || flow_id > INT_MAX) 319 + return -1; 320 + 321 + fprintf(stderr, "Added flow rule with ID %ld\n", flow_id); 322 + ntuple_ids[flow_idx] = flow_id; 323 + return flow_id; 286 324 } 287 325 288 326 static int rxq_num(int ifindex) ··· 392 270 return num; 393 271 } 394 272 395 - #define run_command(cmd, ...) \ 396 - ({ \ 397 - char command[256]; \ 398 - memset(command, 0, sizeof(command)); \ 399 - snprintf(command, sizeof(command), cmd, ##__VA_ARGS__); \ 400 - fprintf(stderr, "Running: %s\n", command); \ 401 - system(command); \ 402 - }) 403 - 404 - static int reset_flow_steering(void) 273 + static void reset_flow_steering(void) 405 274 { 406 - /* Depending on the NIC, toggling ntuple off and on might not 407 - * be allowed. Additionally, attempting to delete existing filters 408 - * will fail if no filters are present. Therefore, do not enforce 409 - * the exit status. 410 - */ 275 + int i; 411 276 412 - run_command("ethtool -K %s ntuple off >&2", ifname); 413 - run_command("ethtool -K %s ntuple on >&2", ifname); 414 - run_command( 415 - "ethtool -n %s | grep 'Filter:' | awk '{print $2}' | xargs -n1 ethtool -N %s delete >&2", 416 - ifname, ifname); 417 - return 0; 277 + for (i = 0; i < MAX_FLOWS; i++) { 278 + if (ntuple_ids[i] == -1) 279 + continue; 280 + run_command("ethtool -N %s delete %d", 281 + ifname, ntuple_ids[i]); 282 + ntuple_ids[i] = -1; 283 + } 418 284 } 419 285 420 286 static const char *tcp_data_split_str(int val) ··· 419 309 } 420 310 } 421 311 422 - static int configure_headersplit(bool on) 312 + static struct ethtool_rings_get_rsp *get_ring_config(void) 313 + { 314 + struct ethtool_rings_get_req *get_req; 315 + struct ethtool_rings_get_rsp *get_rsp; 316 + struct ynl_error yerr; 317 + struct ynl_sock *ys; 318 + 319 + ys = ynl_sock_create(&ynl_ethtool_family, &yerr); 320 + if (!ys) { 321 + fprintf(stderr, "YNL: %s\n", yerr.msg); 322 + return NULL; 323 + } 324 + 325 + get_req = ethtool_rings_get_req_alloc(); 326 + ethtool_rings_get_req_set_header_dev_index(get_req, ifindex); 327 + get_rsp = ethtool_rings_get(ys, get_req); 328 + ethtool_rings_get_req_free(get_req); 329 + 330 + ynl_sock_destroy(ys); 331 + 332 + return get_rsp; 333 + } 334 + 335 + static void restore_ring_config(const struct ethtool_rings_get_rsp *config) 336 + { 337 + struct ethtool_rings_get_req *get_req; 338 + struct ethtool_rings_get_rsp *get_rsp; 339 + struct ethtool_rings_set_req *req; 340 + struct ynl_error yerr; 341 + struct ynl_sock *ys; 342 + int ret; 343 + 344 + if (!config) 345 + return; 346 + 347 + ys = ynl_sock_create(&ynl_ethtool_family, &yerr); 348 + if (!ys) { 349 + fprintf(stderr, "YNL: %s\n", yerr.msg); 350 + return; 351 + } 352 + 353 + req = ethtool_rings_set_req_alloc(); 354 + ethtool_rings_set_req_set_header_dev_index(req, ifindex); 355 + ethtool_rings_set_req_set_tcp_data_split(req, 356 + ETHTOOL_TCP_DATA_SPLIT_UNKNOWN); 357 + if (config->_present.hds_thresh) 358 + ethtool_rings_set_req_set_hds_thresh(req, config->hds_thresh); 359 + 360 + ret = ethtool_rings_set(ys, req); 361 + if (ret < 0) 362 + fprintf(stderr, "YNL restoring HDS cfg: %s\n", ys->err.msg); 363 + 364 + get_req = ethtool_rings_get_req_alloc(); 365 + ethtool_rings_get_req_set_header_dev_index(get_req, ifindex); 366 + get_rsp = ethtool_rings_get(ys, get_req); 367 + ethtool_rings_get_req_free(get_req); 368 + 369 + /* use explicit value if UKNOWN didn't give us the previous */ 370 + if (get_rsp->tcp_data_split != config->tcp_data_split) { 371 + ethtool_rings_set_req_set_tcp_data_split(req, 372 + config->tcp_data_split); 373 + ret = ethtool_rings_set(ys, req); 374 + if (ret < 0) 375 + fprintf(stderr, "YNL restoring expl HDS cfg: %s\n", 376 + ys->err.msg); 377 + } 378 + 379 + ethtool_rings_get_rsp_free(get_rsp); 380 + ethtool_rings_set_req_free(req); 381 + 382 + ynl_sock_destroy(ys); 383 + } 384 + 385 + static int 386 + configure_headersplit(const struct ethtool_rings_get_rsp *old, bool on) 423 387 { 424 388 struct ethtool_rings_get_req *get_req; 425 389 struct ethtool_rings_get_rsp *get_rsp; ··· 510 326 511 327 req = ethtool_rings_set_req_alloc(); 512 328 ethtool_rings_set_req_set_header_dev_index(req, ifindex); 513 - /* 0 - off, 1 - auto, 2 - on */ 514 - ethtool_rings_set_req_set_tcp_data_split(req, on ? 2 : 0); 329 + if (on) { 330 + ethtool_rings_set_req_set_tcp_data_split(req, 331 + ETHTOOL_TCP_DATA_SPLIT_ENABLED); 332 + if (old->_present.hds_thresh) 333 + ethtool_rings_set_req_set_hds_thresh(req, 0); 334 + } else { 335 + ethtool_rings_set_req_set_tcp_data_split(req, 336 + ETHTOOL_TCP_DATA_SPLIT_UNKNOWN); 337 + } 515 338 ret = ethtool_rings_set(ys, req); 516 339 if (ret < 0) 517 340 fprintf(stderr, "YNL failed: %s\n", ys->err.msg); ··· 545 354 return run_command("ethtool -X %s equal %d >&2", ifname, start_queue); 546 355 } 547 356 548 - static int configure_channels(unsigned int rx, unsigned int tx) 357 + static void reset_rss(void) 358 + { 359 + run_command("ethtool -X %s default >&2", ifname, start_queue); 360 + } 361 + 362 + static int check_changing_channels(unsigned int rx, unsigned int tx) 549 363 { 550 364 struct ethtool_channels_get_req *gchan; 551 365 struct ethtool_channels_set_req *schan; ··· 606 410 ethtool_channels_set_req_set_tx_count(schan, tx - rx); 607 411 } 608 412 609 - ret = ethtool_channels_set(ys, schan); 610 - if (ret) 611 - fprintf(stderr, "YNL set channels: %s\n", ys->err.msg); 612 413 } else if (chan->_present.rx_count) { 613 414 ethtool_channels_set_req_set_rx_count(schan, rx); 614 415 ethtool_channels_set_req_set_tx_count(schan, tx); 615 - 616 - ret = ethtool_channels_set(ys, schan); 617 - if (ret) 618 - fprintf(stderr, "YNL set channels: %s\n", ys->err.msg); 619 416 } else { 620 417 fprintf(stderr, "Error: device has neither combined nor rx channels\n"); 621 418 ret = -1; 419 + goto exit_free_schan; 622 420 } 421 + 422 + ret = ethtool_channels_set(ys, schan); 423 + if (ret) { 424 + fprintf(stderr, "YNL set channels: %s\n", ys->err.msg); 425 + } else { 426 + /* We were expecting a failure, go back to previous settings */ 427 + ethtool_channels_set_req_set_combined_count(schan, 428 + chan->combined_count); 429 + ethtool_channels_set_req_set_rx_count(schan, chan->rx_count); 430 + ethtool_channels_set_req_set_tx_count(schan, chan->tx_count); 431 + 432 + ret = ethtool_channels_set(ys, schan); 433 + if (ret) 434 + fprintf(stderr, "YNL un-setting channels: %s\n", 435 + ys->err.msg); 436 + } 437 + 438 + exit_free_schan: 623 439 ethtool_channels_set_req_free(schan); 624 440 exit_free_chan: 625 441 ethtool_channels_get_rsp_free(chan); ··· 646 438 const char *type = "tcp6"; 647 439 const char *server_addr; 648 440 char buf[40]; 441 + int flow_id; 649 442 650 443 inet_ntop(AF_INET6, &server_sin->sin6_addr, buf, sizeof(buf)); 651 444 server_addr = buf; ··· 657 448 } 658 449 659 450 /* Try configure 5-tuple */ 660 - if (run_command("ethtool -N %s flow-type %s %s %s dst-ip %s %s %s dst-port %s queue %d >&2", 661 - ifname, 662 - type, 663 - client_ip ? "src-ip" : "", 664 - client_ip ?: "", 665 - server_addr, 666 - client_ip ? "src-port" : "", 667 - client_ip ? port : "", 668 - port, start_queue)) 451 + flow_id = ethtool_add_flow("flow-type %s %s %s dst-ip %s %s %s dst-port %s queue %d", 452 + type, 453 + client_ip ? "src-ip" : "", 454 + client_ip ?: "", 455 + server_addr, 456 + client_ip ? "src-port" : "", 457 + client_ip ? port : "", 458 + port, start_queue); 459 + if (flow_id < 0) { 669 460 /* If that fails, try configure 3-tuple */ 670 - if (run_command("ethtool -N %s flow-type %s dst-ip %s dst-port %s queue %d >&2", 671 - ifname, 672 - type, 673 - server_addr, 674 - port, start_queue)) 461 + flow_id = ethtool_add_flow("flow-type %s dst-ip %s dst-port %s queue %d", 462 + type, server_addr, port, start_queue); 463 + if (flow_id < 0) 675 464 /* If that fails, return error */ 676 465 return -1; 466 + } 677 467 678 468 return 0; 679 469 } ··· 687 479 688 480 *ys = ynl_sock_create(&ynl_netdev_family, &yerr); 689 481 if (!*ys) { 482 + netdev_queue_id_free(queues); 690 483 fprintf(stderr, "YNL: %s\n", yerr.msg); 691 484 return -1; 692 485 } ··· 766 557 return -1; 767 558 } 768 559 769 - static void enable_reuseaddr(int fd) 560 + static int enable_reuseaddr(int fd) 770 561 { 771 562 int opt = 1; 772 563 int ret; 773 564 774 565 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)); 775 - if (ret) 776 - error(1, errno, "%s: [FAIL, SO_REUSEPORT]\n", TEST_PREFIX); 566 + if (ret) { 567 + pr_err("SO_REUSEPORT failed"); 568 + return -1; 569 + } 777 570 778 571 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 779 - if (ret) 780 - error(1, errno, "%s: [FAIL, SO_REUSEADDR]\n", TEST_PREFIX); 572 + if (ret) { 573 + pr_err("SO_REUSEADDR failed"); 574 + return -1; 575 + } 576 + 577 + return 0; 781 578 } 782 579 783 580 static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6) ··· 826 611 827 612 static int do_server(struct memory_buffer *mem) 828 613 { 614 + struct ethtool_rings_get_rsp *ring_config; 829 615 char ctrl_data[sizeof(int) * 20000]; 830 616 size_t non_page_aligned_frags = 0; 831 617 struct sockaddr_in6 client_addr; ··· 838 622 char *tmp_mem = NULL; 839 623 struct ynl_sock *ys; 840 624 char iobuf[819200]; 625 + int ret, err = -1; 841 626 char buffer[256]; 842 627 int socket_fd; 843 628 int client_fd; 844 - int ret; 845 629 846 630 ret = parse_address(server_ip, atoi(port), &server_sin); 847 - if (ret < 0) 848 - error(1, 0, "parse server address"); 631 + if (ret < 0) { 632 + pr_err("parse server address"); 633 + return -1; 634 + } 849 635 850 - if (reset_flow_steering()) 851 - error(1, 0, "Failed to reset flow steering\n"); 636 + ring_config = get_ring_config(); 637 + if (!ring_config) { 638 + pr_err("Failed to get current ring configuration"); 639 + return -1; 640 + } 852 641 853 - if (configure_headersplit(1)) 854 - error(1, 0, "Failed to enable TCP header split\n"); 642 + if (configure_headersplit(ring_config, 1)) { 643 + pr_err("Failed to enable TCP header split"); 644 + goto err_free_ring_config; 645 + } 855 646 856 647 /* Configure RSS to divert all traffic from our devmem queues */ 857 - if (configure_rss()) 858 - error(1, 0, "Failed to configure rss\n"); 648 + if (configure_rss()) { 649 + pr_err("Failed to configure rss"); 650 + goto err_reset_headersplit; 651 + } 859 652 860 653 /* Flow steer our devmem flows to start_queue */ 861 - if (configure_flow_steering(&server_sin)) 862 - error(1, 0, "Failed to configure flow steering\n"); 654 + if (configure_flow_steering(&server_sin)) { 655 + pr_err("Failed to configure flow steering"); 656 + goto err_reset_rss; 657 + } 863 658 864 659 sleep(1); 865 660 866 - if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) 867 - error(1, 0, "Failed to bind\n"); 661 + if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) { 662 + pr_err("Failed to bind"); 663 + goto err_reset_flow_steering; 664 + } 868 665 869 666 tmp_mem = malloc(mem->size); 870 667 if (!tmp_mem) 871 - error(1, ENOMEM, "malloc failed"); 668 + goto err_unbind; 872 669 873 670 socket_fd = socket(AF_INET6, SOCK_STREAM, 0); 874 - if (socket_fd < 0) 875 - error(1, errno, "%s: [FAIL, create socket]\n", TEST_PREFIX); 671 + if (socket_fd < 0) { 672 + pr_err("Failed to create socket"); 673 + goto err_free_tmp; 674 + } 876 675 877 - enable_reuseaddr(socket_fd); 676 + if (enable_reuseaddr(socket_fd)) 677 + goto err_close_socket; 878 678 879 679 fprintf(stderr, "binding to address %s:%d\n", server_ip, 880 680 ntohs(server_sin.sin6_port)); 881 681 882 682 ret = bind(socket_fd, &server_sin, sizeof(server_sin)); 883 - if (ret) 884 - error(1, errno, "%s: [FAIL, bind]\n", TEST_PREFIX); 683 + if (ret) { 684 + pr_err("Failed to bind"); 685 + goto err_close_socket; 686 + } 885 687 886 688 ret = listen(socket_fd, 1); 887 - if (ret) 888 - error(1, errno, "%s: [FAIL, listen]\n", TEST_PREFIX); 689 + if (ret) { 690 + pr_err("Failed to listen"); 691 + goto err_close_socket; 692 + } 889 693 890 694 client_addr_len = sizeof(client_addr); 891 695 ··· 914 678 fprintf(stderr, "Waiting or connection on %s:%d\n", buffer, 915 679 ntohs(server_sin.sin6_port)); 916 680 client_fd = accept(socket_fd, &client_addr, &client_addr_len); 681 + if (client_fd < 0) { 682 + pr_err("Failed to accept"); 683 + goto err_close_socket; 684 + } 917 685 918 686 inet_ntop(AF_INET6, &client_addr.sin6_addr, buffer, 919 687 sizeof(buffer)); ··· 948 708 continue; 949 709 } 950 710 if (ret == 0) { 951 - fprintf(stderr, "client exited\n"); 711 + errno = 0; 712 + pr_err("client exited"); 952 713 goto cleanup; 953 714 } 954 715 ··· 987 746 dmabuf_cmsg->frag_size, dmabuf_cmsg->frag_token, 988 747 total_received, dmabuf_cmsg->dmabuf_id); 989 748 990 - if (dmabuf_cmsg->dmabuf_id != dmabuf_id) 991 - error(1, 0, 992 - "received on wrong dmabuf_id: flow steering error\n"); 749 + if (dmabuf_cmsg->dmabuf_id != dmabuf_id) { 750 + pr_err("received on wrong dmabuf_id: flow steering error"); 751 + goto err_close_client; 752 + } 993 753 994 754 if (dmabuf_cmsg->frag_size % getpagesize()) 995 755 non_page_aligned_frags++; ··· 1001 759 dmabuf_cmsg->frag_offset, 1002 760 dmabuf_cmsg->frag_size); 1003 761 1004 - if (do_validation) 1005 - validate_buffer(tmp_mem, 1006 - dmabuf_cmsg->frag_size); 1007 - else 762 + if (do_validation) { 763 + if (validate_buffer(tmp_mem, 764 + dmabuf_cmsg->frag_size)) 765 + goto err_close_client; 766 + } else { 1008 767 print_nonzero_bytes(tmp_mem, 1009 768 dmabuf_cmsg->frag_size); 769 + } 1010 770 1011 771 ret = setsockopt(client_fd, SOL_SOCKET, 1012 772 SO_DEVMEM_DONTNEED, &token, 1013 773 sizeof(token)); 1014 - if (ret != 1) 1015 - error(1, 0, 1016 - "SO_DEVMEM_DONTNEED not enough tokens"); 774 + if (ret != 1) { 775 + pr_err("SO_DEVMEM_DONTNEED not enough tokens"); 776 + goto err_close_client; 777 + } 1017 778 } 1018 - if (!is_devmem) 1019 - error(1, 0, "flow steering error\n"); 779 + if (!is_devmem) { 780 + pr_err("flow steering error"); 781 + goto err_close_client; 782 + } 1020 783 1021 784 fprintf(stderr, "total_received=%lu\n", total_received); 1022 785 } ··· 1032 785 page_aligned_frags, non_page_aligned_frags); 1033 786 1034 787 cleanup: 788 + err = 0; 1035 789 1036 - free(tmp_mem); 790 + err_close_client: 1037 791 close(client_fd); 792 + err_close_socket: 1038 793 close(socket_fd); 794 + err_free_tmp: 795 + free(tmp_mem); 796 + err_unbind: 1039 797 ynl_sock_destroy(ys); 1040 - 1041 - return 0; 798 + err_reset_flow_steering: 799 + reset_flow_steering(); 800 + err_reset_rss: 801 + reset_rss(); 802 + err_reset_headersplit: 803 + restore_ring_config(ring_config); 804 + err_free_ring_config: 805 + ethtool_rings_get_rsp_free(ring_config); 806 + return err; 1042 807 } 1043 808 1044 - void run_devmem_tests(void) 809 + int run_devmem_tests(void) 1045 810 { 811 + struct ethtool_rings_get_rsp *ring_config; 812 + struct netdev_queue_id *queues; 1046 813 struct memory_buffer *mem; 1047 814 struct ynl_sock *ys; 815 + int err = -1; 1048 816 1049 817 mem = provider->alloc(getpagesize() * NUM_PAGES); 818 + if (!mem) { 819 + pr_err("Failed to allocate memory buffer"); 820 + return -1; 821 + } 822 + 823 + ring_config = get_ring_config(); 824 + if (!ring_config) { 825 + pr_err("Failed to get current ring configuration"); 826 + goto err_free_mem; 827 + } 1050 828 1051 829 /* Configure RSS to divert all traffic from our devmem queues */ 1052 - if (configure_rss()) 1053 - error(1, 0, "rss error\n"); 830 + if (configure_rss()) { 831 + pr_err("rss error"); 832 + goto err_free_ring_config; 833 + } 1054 834 1055 - if (configure_headersplit(1)) 1056 - error(1, 0, "Failed to configure header split\n"); 835 + if (configure_headersplit(ring_config, 1)) { 836 + pr_err("Failed to configure header split"); 837 + goto err_reset_rss; 838 + } 1057 839 1058 - if (!bind_rx_queue(ifindex, mem->fd, 1059 - calloc(num_queues, sizeof(struct netdev_queue_id)), 1060 - num_queues, &ys)) 1061 - error(1, 0, "Binding empty queues array should have failed\n"); 840 + queues = netdev_queue_id_alloc(num_queues); 841 + if (!queues) { 842 + pr_err("Failed to allocate empty queues array"); 843 + goto err_reset_headersplit; 844 + } 1062 845 1063 - if (configure_headersplit(0)) 1064 - error(1, 0, "Failed to configure header split\n"); 846 + if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) { 847 + pr_err("Binding empty queues array should have failed"); 848 + goto err_unbind; 849 + } 1065 850 1066 - if (!bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) 1067 - error(1, 0, "Configure dmabuf with header split off should have failed\n"); 851 + if (configure_headersplit(ring_config, 0)) { 852 + pr_err("Failed to configure header split"); 853 + goto err_reset_headersplit; 854 + } 1068 855 1069 - if (configure_headersplit(1)) 1070 - error(1, 0, "Failed to configure header split\n"); 856 + queues = create_queues(); 857 + if (!queues) { 858 + pr_err("Failed to create queues"); 859 + goto err_reset_headersplit; 860 + } 1071 861 1072 - if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) 1073 - error(1, 0, "Failed to bind\n"); 862 + if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) { 863 + pr_err("Configure dmabuf with header split off should have failed"); 864 + goto err_unbind; 865 + } 866 + 867 + if (configure_headersplit(ring_config, 1)) { 868 + pr_err("Failed to configure header split"); 869 + goto err_reset_headersplit; 870 + } 871 + 872 + queues = create_queues(); 873 + if (!queues) { 874 + pr_err("Failed to create queues"); 875 + goto err_reset_headersplit; 876 + } 877 + 878 + if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys)) { 879 + pr_err("Failed to bind"); 880 + goto err_reset_headersplit; 881 + } 1074 882 1075 883 /* Deactivating a bound queue should not be legal */ 1076 - if (!configure_channels(num_queues, num_queues)) 1077 - error(1, 0, "Deactivating a bound queue should be illegal.\n"); 884 + if (!check_changing_channels(num_queues, num_queues)) { 885 + pr_err("Deactivating a bound queue should be illegal"); 886 + goto err_unbind; 887 + } 1078 888 1079 - /* Closing the netlink socket does an implicit unbind */ 889 + err = 0; 890 + goto err_unbind; 891 + 892 + err_unbind: 1080 893 ynl_sock_destroy(ys); 1081 - 894 + err_reset_headersplit: 895 + restore_ring_config(ring_config); 896 + err_reset_rss: 897 + reset_rss(); 898 + err_free_ring_config: 899 + ethtool_rings_get_rsp_free(ring_config); 900 + err_free_mem: 1082 901 provider->free(mem); 902 + return err; 1083 903 } 1084 904 1085 905 static uint64_t gettimeofday_ms(void) ··· 1166 852 pfd.fd = fd; 1167 853 1168 854 ret = poll(&pfd, 1, waittime_ms); 1169 - if (ret == -1) 1170 - error(1, errno, "poll"); 855 + if (ret == -1) { 856 + pr_err("poll"); 857 + return -1; 858 + } 1171 859 1172 860 return ret && (pfd.revents & POLLERR); 1173 861 } 1174 862 1175 - static void wait_compl(int fd) 863 + static int wait_compl(int fd) 1176 864 { 1177 865 int64_t tstop = gettimeofday_ms() + waittime_ms; 1178 866 char control[CMSG_SPACE(100)] = {}; ··· 1188 872 msg.msg_controllen = sizeof(control); 1189 873 1190 874 while (gettimeofday_ms() < tstop) { 1191 - if (!do_poll(fd)) 875 + ret = do_poll(fd); 876 + if (ret < 0) 877 + return ret; 878 + if (!ret) 1192 879 continue; 1193 880 1194 881 ret = recvmsg(fd, &msg, MSG_ERRQUEUE); 1195 882 if (ret < 0) { 1196 883 if (errno == EAGAIN) 1197 884 continue; 1198 - error(1, errno, "recvmsg(MSG_ERRQUEUE)"); 1199 - return; 885 + pr_err("recvmsg(MSG_ERRQUEUE)"); 886 + return -1; 1200 887 } 1201 - if (msg.msg_flags & MSG_CTRUNC) 1202 - error(1, 0, "MSG_CTRUNC\n"); 888 + if (msg.msg_flags & MSG_CTRUNC) { 889 + pr_err("MSG_CTRUNC"); 890 + return -1; 891 + } 1203 892 1204 893 for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) { 1205 894 if (cm->cmsg_level != SOL_IP && ··· 1218 897 continue; 1219 898 1220 899 serr = (void *)CMSG_DATA(cm); 1221 - if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) 1222 - error(1, 0, "wrong origin %u", serr->ee_origin); 1223 - if (serr->ee_errno != 0) 1224 - error(1, 0, "wrong errno %d", serr->ee_errno); 900 + if (serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY) { 901 + pr_err("wrong origin %u", serr->ee_origin); 902 + return -1; 903 + } 904 + if (serr->ee_errno != 0) { 905 + pr_err("wrong errno %d", serr->ee_errno); 906 + return -1; 907 + } 1225 908 1226 909 hi = serr->ee_data; 1227 910 lo = serr->ee_info; 1228 911 1229 912 fprintf(stderr, "tx complete [%d,%d]\n", lo, hi); 1230 - return; 913 + return 0; 1231 914 } 1232 915 } 1233 916 1234 - error(1, 0, "did not receive tx completion"); 917 + pr_err("did not receive tx completion"); 918 + return -1; 1235 919 } 1236 920 1237 921 static int do_client(struct memory_buffer *mem) ··· 1250 924 ssize_t line_size = 0; 1251 925 struct cmsghdr *cmsg; 1252 926 char *line = NULL; 927 + int ret, err = -1; 1253 928 size_t len = 0; 1254 929 int socket_fd; 1255 930 __u32 ddmabuf; 1256 931 int opt = 1; 1257 - int ret; 1258 932 1259 933 ret = parse_address(server_ip, atoi(port), &server_sin); 1260 - if (ret < 0) 1261 - error(1, 0, "parse server address"); 1262 - 1263 - socket_fd = socket(AF_INET6, SOCK_STREAM, 0); 1264 - if (socket_fd < 0) 1265 - error(1, socket_fd, "create socket"); 1266 - 1267 - enable_reuseaddr(socket_fd); 1268 - 1269 - ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, 1270 - strlen(ifname) + 1); 1271 - if (ret) 1272 - error(1, errno, "bindtodevice"); 1273 - 1274 - if (bind_tx_queue(ifindex, mem->fd, &ys)) 1275 - error(1, 0, "Failed to bind\n"); 934 + if (ret < 0) { 935 + pr_err("parse server address"); 936 + return -1; 937 + } 1276 938 1277 939 if (client_ip) { 1278 940 ret = parse_address(client_ip, atoi(port), &client_sin); 1279 - if (ret < 0) 1280 - error(1, 0, "parse client address"); 941 + if (ret < 0) { 942 + pr_err("parse client address"); 943 + return ret; 944 + } 945 + } 1281 946 947 + socket_fd = socket(AF_INET6, SOCK_STREAM, 0); 948 + if (socket_fd < 0) { 949 + pr_err("create socket"); 950 + return -1; 951 + } 952 + 953 + if (enable_reuseaddr(socket_fd)) 954 + goto err_close_socket; 955 + 956 + ret = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, 957 + strlen(ifname) + 1); 958 + if (ret) { 959 + pr_err("bindtodevice"); 960 + goto err_close_socket; 961 + } 962 + 963 + if (bind_tx_queue(ifindex, mem->fd, &ys)) { 964 + pr_err("Failed to bind"); 965 + goto err_close_socket; 966 + } 967 + 968 + if (client_ip) { 1282 969 ret = bind(socket_fd, &client_sin, sizeof(client_sin)); 1283 - if (ret) 1284 - error(1, errno, "bind"); 970 + if (ret) { 971 + pr_err("bind"); 972 + goto err_unbind; 973 + } 1285 974 } 1286 975 1287 976 ret = setsockopt(socket_fd, SOL_SOCKET, SO_ZEROCOPY, &opt, sizeof(opt)); 1288 - if (ret) 1289 - error(1, errno, "set sock opt"); 977 + if (ret) { 978 + pr_err("set sock opt"); 979 + goto err_unbind; 980 + } 1290 981 1291 982 fprintf(stderr, "Connect to %s %d (via %s)\n", server_ip, 1292 983 ntohs(server_sin.sin6_port), ifname); 1293 984 1294 985 ret = connect(socket_fd, &server_sin, sizeof(server_sin)); 1295 - if (ret) 1296 - error(1, errno, "connect"); 986 + if (ret) { 987 + pr_err("connect"); 988 + goto err_unbind; 989 + } 1297 990 1298 991 while (1) { 1299 992 free(line); ··· 1325 980 if (max_chunk) { 1326 981 msg.msg_iovlen = 1327 982 (line_size + max_chunk - 1) / max_chunk; 1328 - if (msg.msg_iovlen > MAX_IOV) 1329 - error(1, 0, 1330 - "can't partition %zd bytes into maximum of %d chunks", 1331 - line_size, MAX_IOV); 983 + if (msg.msg_iovlen > MAX_IOV) { 984 + pr_err("can't partition %zd bytes into maximum of %d chunks", 985 + line_size, MAX_IOV); 986 + goto err_free_line; 987 + } 1332 988 1333 989 for (int i = 0; i < msg.msg_iovlen; i++) { 1334 990 iov[i].iov_base = (void *)(i * max_chunk); ··· 1360 1014 *((__u32 *)CMSG_DATA(cmsg)) = ddmabuf; 1361 1015 1362 1016 ret = sendmsg(socket_fd, &msg, MSG_ZEROCOPY); 1363 - if (ret < 0) 1364 - error(1, errno, "Failed sendmsg"); 1017 + if (ret < 0) { 1018 + pr_err("Failed sendmsg"); 1019 + goto err_free_line; 1020 + } 1365 1021 1366 1022 fprintf(stderr, "sendmsg_ret=%d\n", ret); 1367 1023 1368 - if (ret != line_size) 1369 - error(1, errno, "Did not send all bytes %d vs %zd", ret, 1370 - line_size); 1024 + if (ret != line_size) { 1025 + pr_err("Did not send all bytes %d vs %zd", ret, line_size); 1026 + goto err_free_line; 1027 + } 1371 1028 1372 - wait_compl(socket_fd); 1029 + if (wait_compl(socket_fd)) 1030 + goto err_free_line; 1373 1031 } 1374 1032 1375 1033 fprintf(stderr, "%s: tx ok\n", TEST_PREFIX); 1376 1034 1035 + err = 0; 1036 + 1037 + err_free_line: 1377 1038 free(line); 1039 + err_unbind: 1040 + ynl_sock_destroy(ys); 1041 + err_close_socket: 1378 1042 close(socket_fd); 1379 - 1380 - if (ys) 1381 - ynl_sock_destroy(ys); 1382 - 1383 - return 0; 1043 + return err; 1384 1044 } 1385 1045 1386 1046 int main(int argc, char *argv[]) 1387 1047 { 1388 1048 struct memory_buffer *mem; 1389 1049 int is_server = 0, opt; 1390 - int ret; 1050 + int ret, err = 1; 1391 1051 1392 1052 while ((opt = getopt(argc, argv, "ls:c:p:v:q:t:f:z:")) != -1) { 1393 1053 switch (opt) { ··· 1430 1078 } 1431 1079 } 1432 1080 1433 - if (!ifname) 1434 - error(1, 0, "Missing -f argument\n"); 1081 + if (!ifname) { 1082 + pr_err("Missing -f argument"); 1083 + return 1; 1084 + } 1435 1085 1436 1086 ifindex = if_nametoindex(ifname); 1437 1087 ··· 1442 1088 if (!server_ip && !client_ip) { 1443 1089 if (start_queue < 0 && num_queues < 0) { 1444 1090 num_queues = rxq_num(ifindex); 1445 - if (num_queues < 0) 1446 - error(1, 0, "couldn't detect number of queues\n"); 1447 - if (num_queues < 2) 1448 - error(1, 0, 1449 - "number of device queues is too low\n"); 1091 + if (num_queues < 0) { 1092 + pr_err("couldn't detect number of queues"); 1093 + return 1; 1094 + } 1095 + if (num_queues < 2) { 1096 + pr_err("number of device queues is too low"); 1097 + return 1; 1098 + } 1450 1099 /* make sure can bind to multiple queues */ 1451 1100 start_queue = num_queues / 2; 1452 1101 num_queues /= 2; 1453 1102 } 1454 1103 1455 - if (start_queue < 0 || num_queues < 0) 1456 - error(1, 0, "Both -t and -q are required\n"); 1104 + if (start_queue < 0 || num_queues < 0) { 1105 + pr_err("Both -t and -q are required"); 1106 + return 1; 1107 + } 1457 1108 1458 - run_devmem_tests(); 1459 - return 0; 1109 + return run_devmem_tests(); 1460 1110 } 1461 1111 1462 1112 if (start_queue < 0 && num_queues < 0) { 1463 1113 num_queues = rxq_num(ifindex); 1464 - if (num_queues < 2) 1465 - error(1, 0, "number of device queues is too low\n"); 1114 + if (num_queues < 2) { 1115 + pr_err("number of device queues is too low"); 1116 + return 1; 1117 + } 1466 1118 1467 1119 num_queues = 1; 1468 1120 start_queue = rxq_num(ifindex) - num_queues; 1469 1121 1470 - if (start_queue < 0) 1471 - error(1, 0, "couldn't detect number of queues\n"); 1122 + if (start_queue < 0) { 1123 + pr_err("couldn't detect number of queues"); 1124 + return 1; 1125 + } 1472 1126 1473 1127 fprintf(stderr, "using queues %d..%d\n", start_queue, start_queue + num_queues); 1474 1128 } ··· 1484 1122 for (; optind < argc; optind++) 1485 1123 fprintf(stderr, "extra arguments: %s\n", argv[optind]); 1486 1124 1487 - if (start_queue < 0) 1488 - error(1, 0, "Missing -t argument\n"); 1125 + if (start_queue < 0) { 1126 + pr_err("Missing -t argument"); 1127 + return 1; 1128 + } 1489 1129 1490 - if (num_queues < 0) 1491 - error(1, 0, "Missing -q argument\n"); 1130 + if (num_queues < 0) { 1131 + pr_err("Missing -q argument"); 1132 + return 1; 1133 + } 1492 1134 1493 - if (!server_ip) 1494 - error(1, 0, "Missing -s argument\n"); 1135 + if (!server_ip) { 1136 + pr_err("Missing -s argument"); 1137 + return 1; 1138 + } 1495 1139 1496 - if (!port) 1497 - error(1, 0, "Missing -p argument\n"); 1140 + if (!port) { 1141 + pr_err("Missing -p argument"); 1142 + return 1; 1143 + } 1498 1144 1499 1145 mem = provider->alloc(getpagesize() * NUM_PAGES); 1500 - ret = is_server ? do_server(mem) : do_client(mem); 1501 - provider->free(mem); 1146 + if (!mem) { 1147 + pr_err("Failed to allocate memory buffer"); 1148 + return 1; 1149 + } 1502 1150 1503 - return ret; 1151 + ret = is_server ? do_server(mem) : do_client(mem); 1152 + if (ret) 1153 + goto err_free_mem; 1154 + 1155 + err = 0; 1156 + 1157 + err_free_mem: 1158 + provider->free(mem); 1159 + return err; 1504 1160 }