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

Configure Feed

Select the types of activity you want to include in your feed.

selftests/net: Add SHA256 computation over data sent in tcp_mmap

Add option to compute and send SHA256 over data sent (-i).

This is to ensure the correctness of data received.
Data is randomly populated from /dev/urandom.

Tested:
./tcp_mmap -s -z -i
./tcp_mmap -z -H $ADDR -i
SHA256 is correct

./tcp_mmap -s -i
./tcp_mmap -H $ADDR -i
SHA256 is correct

Signed-off-by: Coco Li <lixiaoyan@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20230321081202.2370275-2-lixiaoyan@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Xiaoyan Li and committed by
Paolo Abeni
5c5945dc 593ef60c

+92 -12
+1 -1
tools/testing/selftests/net/Makefile
··· 89 89 include ../lib.mk 90 90 91 91 $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma 92 - $(OUTPUT)/tcp_mmap: LDLIBS += -lpthread 92 + $(OUTPUT)/tcp_mmap: LDLIBS += -lpthread -lcrypto 93 93 $(OUTPUT)/tcp_inq: LDLIBS += -lpthread 94 94 $(OUTPUT)/bind_bhash: LDLIBS += -lpthread 95 95
+91 -11
tools/testing/selftests/net/tcp_mmap.c
··· 66 66 #include <poll.h> 67 67 #include <linux/tcp.h> 68 68 #include <assert.h> 69 + #include <openssl/pem.h> 69 70 70 71 #ifndef MSG_ZEROCOPY 71 72 #define MSG_ZEROCOPY 0x4000000 73 + #endif 74 + 75 + #ifndef min 76 + #define min(a, b) ((a) < (b) ? (a) : (b)) 72 77 #endif 73 78 74 79 #define FILE_SZ (1ULL << 35) ··· 86 81 static int zflg; /* zero copy option. (MSG_ZEROCOPY for sender, mmap() for receiver */ 87 82 static int xflg; /* hash received data (simple xor) (-h option) */ 88 83 static int keepflag; /* -k option: receiver shall keep all received file in memory (no munmap() calls) */ 84 + static int integrity; /* -i option: sender and receiver compute sha256 over the data.*/ 89 85 90 86 static size_t chunk_size = 512*1024; 91 87 92 88 static size_t map_align; 93 89 94 90 unsigned long htotal; 91 + unsigned int digest_len; 95 92 96 93 static inline void prefetch(const void *x) 97 94 { ··· 155 148 156 149 void *child_thread(void *arg) 157 150 { 151 + unsigned char digest[SHA256_DIGEST_LENGTH]; 158 152 unsigned long total_mmap = 0, total = 0; 159 153 struct tcp_zerocopy_receive zc; 154 + unsigned char *buffer = NULL; 160 155 unsigned long delta_usec; 156 + EVP_MD_CTX *ctx = NULL; 161 157 int flags = MAP_SHARED; 162 158 struct timeval t0, t1; 163 - char *buffer = NULL; 164 159 void *raddr = NULL; 165 160 void *addr = NULL; 166 161 double throughput; ··· 189 180 addr = ALIGN_PTR_UP(raddr, map_align); 190 181 } 191 182 } 183 + if (integrity) { 184 + ctx = EVP_MD_CTX_new(); 185 + if (!ctx) { 186 + perror("cannot enable SHA computing"); 187 + goto error; 188 + } 189 + EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); 190 + } 192 191 while (1) { 193 192 struct pollfd pfd = { .fd = fd, .events = POLLIN, }; 194 193 int sub; ··· 208 191 209 192 memset(&zc, 0, sizeof(zc)); 210 193 zc.address = (__u64)((unsigned long)addr); 211 - zc.length = chunk_size; 194 + zc.length = min(chunk_size, FILE_SZ - lu); 212 195 213 196 res = getsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, 214 197 &zc, &zc_len); ··· 217 200 218 201 if (zc.length) { 219 202 assert(zc.length <= chunk_size); 203 + if (integrity) 204 + EVP_DigestUpdate(ctx, addr, zc.length); 220 205 total_mmap += zc.length; 221 206 if (xflg) 222 207 hash_zone(addr, zc.length); ··· 230 211 } 231 212 if (zc.recv_skip_hint) { 232 213 assert(zc.recv_skip_hint <= chunk_size); 233 - lu = read(fd, buffer, zc.recv_skip_hint); 214 + lu = read(fd, buffer, min(zc.recv_skip_hint, 215 + FILE_SZ - total)); 234 216 if (lu > 0) { 217 + if (integrity) 218 + EVP_DigestUpdate(ctx, buffer, lu); 235 219 if (xflg) 236 220 hash_zone(buffer, lu); 237 221 total += lu; 238 222 } 223 + if (lu == 0) 224 + goto end; 239 225 } 240 226 continue; 241 227 } 242 228 sub = 0; 243 229 while (sub < chunk_size) { 244 - lu = read(fd, buffer + sub, chunk_size - sub); 230 + lu = read(fd, buffer + sub, min(chunk_size - sub, 231 + FILE_SZ - total)); 245 232 if (lu == 0) 246 233 goto end; 247 234 if (lu < 0) 248 235 break; 236 + if (integrity) 237 + EVP_DigestUpdate(ctx, buffer + sub, lu); 249 238 if (xflg) 250 239 hash_zone(buffer + sub, lu); 251 240 total += lu; ··· 263 236 end: 264 237 gettimeofday(&t1, NULL); 265 238 delta_usec = (t1.tv_sec - t0.tv_sec) * 1000000 + t1.tv_usec - t0.tv_usec; 239 + 240 + if (integrity) { 241 + fcntl(fd, F_SETFL, 0); 242 + EVP_DigestFinal_ex(ctx, digest, &digest_len); 243 + lu = read(fd, buffer, SHA256_DIGEST_LENGTH); 244 + if (lu != SHA256_DIGEST_LENGTH) 245 + perror("Error: Cannot read SHA256\n"); 246 + 247 + if (memcmp(digest, buffer, 248 + SHA256_DIGEST_LENGTH)) 249 + fprintf(stderr, "Error: SHA256 of the data is not right\n"); 250 + else 251 + printf("\nSHA256 is correct\n"); 252 + } 266 253 267 254 throughput = 0; 268 255 if (delta_usec) ··· 409 368 return hps; 410 369 } 411 370 371 + static void randomize(void *target, size_t count) 372 + { 373 + static int urandom = -1; 374 + ssize_t got; 375 + 376 + urandom = open("/dev/urandom", O_RDONLY); 377 + if (urandom < 0) { 378 + perror("open /dev/urandom"); 379 + exit(1); 380 + } 381 + got = read(urandom, target, count); 382 + if (got != count) { 383 + perror("read /dev/urandom"); 384 + exit(1); 385 + } 386 + } 387 + 412 388 int main(int argc, char *argv[]) 413 389 { 390 + unsigned char digest[SHA256_DIGEST_LENGTH]; 414 391 struct sockaddr_storage listenaddr, addr; 415 392 unsigned int max_pacing_rate = 0; 393 + EVP_MD_CTX *ctx = NULL; 394 + unsigned char *buffer; 416 395 uint64_t total = 0; 417 396 char *host = NULL; 418 397 int fd, c, on = 1; 419 398 size_t buffer_sz; 420 - char *buffer; 421 399 int sflg = 0; 422 400 int mss = 0; 423 401 424 - while ((c = getopt(argc, argv, "46p:svr:w:H:zxkP:M:C:a:")) != -1) { 402 + while ((c = getopt(argc, argv, "46p:svr:w:H:zxkP:M:C:a:i")) != -1) { 425 403 switch (c) { 426 404 case '4': 427 405 cfg_family = PF_INET; ··· 486 426 case 'a': 487 427 map_align = atol(optarg); 488 428 break; 429 + case 'i': 430 + integrity = 1; 431 + break; 489 432 default: 490 433 exit(1); 491 434 } ··· 531 468 } 532 469 533 470 buffer = mmap_large_buffer(chunk_size, &buffer_sz); 534 - if (buffer == (char *)-1) { 471 + if (buffer == (unsigned char *)-1) { 535 472 perror("mmap"); 536 473 exit(1); 537 474 } ··· 564 501 perror("setsockopt SO_ZEROCOPY, (-z option disabled)"); 565 502 zflg = 0; 566 503 } 504 + if (integrity) { 505 + randomize(buffer, buffer_sz); 506 + ctx = EVP_MD_CTX_new(); 507 + if (!ctx) { 508 + perror("cannot enable SHA computing"); 509 + exit(1); 510 + } 511 + EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); 512 + } 567 513 while (total < FILE_SZ) { 514 + size_t offset = total % chunk_size; 568 515 int64_t wr = FILE_SZ - total; 569 516 570 - if (wr > chunk_size) 571 - wr = chunk_size; 572 - /* Note : we just want to fill the pipe with 0 bytes */ 573 - wr = send(fd, buffer, (size_t)wr, zflg ? MSG_ZEROCOPY : 0); 517 + if (wr > chunk_size - offset) 518 + wr = chunk_size - offset; 519 + /* Note : we just want to fill the pipe with random bytes */ 520 + wr = send(fd, buffer + offset, 521 + (size_t)wr, zflg ? MSG_ZEROCOPY : 0); 574 522 if (wr <= 0) 575 523 break; 524 + if (integrity) 525 + EVP_DigestUpdate(ctx, buffer + offset, wr); 576 526 total += wr; 527 + } 528 + if (integrity && total == FILE_SZ) { 529 + EVP_DigestFinal_ex(ctx, digest, &digest_len); 530 + send(fd, digest, (size_t)SHA256_DIGEST_LENGTH, 0); 577 531 } 578 532 close(fd); 579 533 munmap(buffer, buffer_sz);