From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 09 Dec 2023 07:24:11 +0000 Subject: [PATCH] add stmac read mac form eeprom --- kernel/tools/testing/selftests/net/tcp_mmap.c | 140 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 105 insertions(+), 35 deletions(-) diff --git a/kernel/tools/testing/selftests/net/tcp_mmap.c b/kernel/tools/testing/selftests/net/tcp_mmap.c index e8c5dff..00f837c 100644 --- a/kernel/tools/testing/selftests/net/tcp_mmap.c +++ b/kernel/tools/testing/selftests/net/tcp_mmap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2018 Google Inc. * Author: Eric Dumazet (edumazet@google.com) @@ -44,21 +45,6 @@ * cpu usage user:0.046 sys:3.559, 110.016 usec per MB, 65529 c-switches * received 32768 MB (99.9939 % mmap'ed) in 7.43764 s, 36.9577 Gbit * cpu usage user:0.035 sys:3.467, 106.873 usec per MB, 65530 c-switches - * - * License (GPLv2): - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE #include <pthread.h> @@ -85,7 +71,7 @@ #define MSG_ZEROCOPY 0x4000000 #endif -#define FILE_SZ (1UL << 35) +#define FILE_SZ (1ULL << 35) static int cfg_family = AF_INET6; static socklen_t cfg_alen = sizeof(struct sockaddr_in6); static int cfg_port = 8787; @@ -96,7 +82,9 @@ static int xflg; /* hash received data (simple xor) (-h option) */ static int keepflag; /* -k option: receiver shall keep all received file in memory (no munmap() calls) */ -static int chunk_size = 512*1024; +static size_t chunk_size = 512*1024; + +static size_t map_align; unsigned long htotal; @@ -132,6 +120,31 @@ htotal = temp; } +#define ALIGN_UP(x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1)) +#define ALIGN_PTR_UP(p, ptr_align_to) ((typeof(p))ALIGN_UP((unsigned long)(p), ptr_align_to)) + + +static void *mmap_large_buffer(size_t need, size_t *allocated) +{ + void *buffer; + size_t sz; + + /* Attempt to use huge pages if possible. */ + sz = ALIGN_UP(need, map_align); + buffer = mmap(NULL, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); + + if (buffer == (void *)-1) { + sz = need; + buffer = mmap(NULL, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buffer != (void *)-1) + fprintf(stderr, "MAP_HUGETLB attempt failed, look at /sys/kernel/mm/hugepages for optimal performance\n"); + } + *allocated = sz; + return buffer; +} + void *child_thread(void *arg) { unsigned long total_mmap = 0, total = 0; @@ -140,9 +153,11 @@ int flags = MAP_SHARED; struct timeval t0, t1; char *buffer = NULL; + void *raddr = NULL; void *addr = NULL; double throughput; struct rusage ru; + size_t buffer_sz; int lu, fd; fd = (int)(unsigned long)arg; @@ -150,15 +165,19 @@ gettimeofday(&t0, NULL); fcntl(fd, F_SETFL, O_NDELAY); - buffer = malloc(chunk_size); - if (!buffer) { - perror("malloc"); + buffer = mmap_large_buffer(chunk_size, &buffer_sz); + if (buffer == (void *)-1) { + perror("mmap"); goto error; } if (zflg) { - addr = mmap(NULL, chunk_size, PROT_READ, flags, fd, 0); - if (addr == (void *)-1) + raddr = mmap(NULL, chunk_size + map_align, PROT_READ, flags, fd, 0); + if (raddr == (void *)-1) { + perror("mmap"); zflg = 0; + } else { + addr = ALIGN_PTR_UP(raddr, map_align); + } } while (1) { struct pollfd pfd = { .fd = fd, .events = POLLIN, }; @@ -169,9 +188,10 @@ socklen_t zc_len = sizeof(zc); int res; - zc.address = (__u64)addr; + memset(&zc, 0, sizeof(zc)); + zc.address = (__u64)((unsigned long)addr); zc.length = chunk_size; - zc.recv_skip_hint = 0; + res = getsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, &zc, &zc_len); if (res == -1) @@ -182,6 +202,10 @@ total_mmap += zc.length; if (xflg) hash_zone(addr, zc.length); + /* It is more efficient to unmap the pages right now, + * instead of doing this in next TCP_ZEROCOPY_RECEIVE. + */ + madvise(addr, zc.length, MADV_DONTNEED); total += zc.length; } if (zc.recv_skip_hint) { @@ -233,10 +257,10 @@ ru.ru_nvcsw); } error: - free(buffer); + munmap(buffer, buffer_sz); close(fd); if (zflg) - munmap(addr, chunk_size); + munmap(raddr, chunk_size + map_align); pthread_exit(0); } @@ -284,8 +308,15 @@ static void do_accept(int fdlisten) { + pthread_attr_t attr; + int rcvlowat; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + rcvlowat = chunk_size; if (setsockopt(fdlisten, SOL_SOCKET, SO_RCVLOWAT, - &chunk_size, sizeof(chunk_size)) == -1) { + &rcvlowat, sizeof(rcvlowat)) == -1) { perror("setsockopt SO_RCVLOWAT"); } @@ -302,7 +333,7 @@ perror("accept"); continue; } - res = pthread_create(&th, NULL, child_thread, + res = pthread_create(&th, &attr, child_thread, (void *)(unsigned long)fd); if (res) { errno = res; @@ -312,18 +343,43 @@ } } +/* Each thread should reserve a big enough vma to avoid + * spinlock collisions in ptl locks. + * This size is 2MB on x86_64, and is exported in /proc/meminfo. + */ +static unsigned long default_huge_page_size(void) +{ + FILE *f = fopen("/proc/meminfo", "r"); + unsigned long hps = 0; + size_t linelen = 0; + char *line = NULL; + + if (!f) + return 0; + while (getline(&line, &linelen, f) > 0) { + if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) { + hps <<= 10; + break; + } + } + free(line); + fclose(f); + return hps; +} + int main(int argc, char *argv[]) { struct sockaddr_storage listenaddr, addr; unsigned int max_pacing_rate = 0; - unsigned long total = 0; + uint64_t total = 0; char *host = NULL; int fd, c, on = 1; + size_t buffer_sz; char *buffer; int sflg = 0; int mss = 0; - while ((c = getopt(argc, argv, "46p:svr:w:H:zxkP:M:")) != -1) { + while ((c = getopt(argc, argv, "46p:svr:w:H:zxkP:M:C:a:")) != -1) { switch (c) { case '4': cfg_family = PF_INET; @@ -363,9 +419,23 @@ case 'P': max_pacing_rate = atoi(optarg) ; break; + case 'C': + chunk_size = atol(optarg); + break; + case 'a': + map_align = atol(optarg); + break; default: exit(1); } + } + if (!map_align) { + map_align = default_huge_page_size(); + /* if really /proc/meminfo is not helping, + * we use the default x86_64 hugepagesize. + */ + if (!map_align) + map_align = 2*1024*1024; } if (sflg) { int fdlisten = socket(cfg_family, SOCK_STREAM, 0); @@ -395,8 +465,8 @@ } do_accept(fdlisten); } - buffer = mmap(NULL, chunk_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + buffer = mmap_large_buffer(chunk_size, &buffer_sz); if (buffer == (char *)-1) { perror("mmap"); exit(1); @@ -431,17 +501,17 @@ zflg = 0; } while (total < FILE_SZ) { - long wr = FILE_SZ - total; + int64_t wr = FILE_SZ - total; if (wr > chunk_size) wr = chunk_size; /* Note : we just want to fill the pipe with 0 bytes */ - wr = send(fd, buffer, wr, zflg ? MSG_ZEROCOPY : 0); + wr = send(fd, buffer, (size_t)wr, zflg ? MSG_ZEROCOPY : 0); if (wr <= 0) break; total += wr; } close(fd); - munmap(buffer, chunk_size); + munmap(buffer, buffer_sz); return 0; } -- Gitblit v1.6.2