linux/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2020 Cloudflare
   3/*
   4 * Test suite for SOCKMAP/SOCKHASH holding listening sockets.
   5 * Covers:
   6 *  1. BPF map operations - bpf_map_{update,lookup delete}_elem
   7 *  2. BPF redirect helpers - bpf_{sk,msg}_redirect_map
   8 *  3. BPF reuseport helper - bpf_sk_select_reuseport
   9 */
  10
  11#include <linux/compiler.h>
  12#include <errno.h>
  13#include <error.h>
  14#include <limits.h>
  15#include <netinet/in.h>
  16#include <pthread.h>
  17#include <stdlib.h>
  18#include <string.h>
  19#include <sys/select.h>
  20#include <unistd.h>
  21
  22#include <bpf/bpf.h>
  23#include <bpf/libbpf.h>
  24
  25#include "bpf_util.h"
  26#include "test_progs.h"
  27#include "test_sockmap_listen.skel.h"
  28
  29#define IO_TIMEOUT_SEC 30
  30#define MAX_STRERR_LEN 256
  31#define MAX_TEST_NAME 80
  32
  33#define _FAIL(errnum, fmt...)                                                  \
  34        ({                                                                     \
  35                error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
  36                CHECK_FAIL(true);                                              \
  37        })
  38#define FAIL(fmt...) _FAIL(0, fmt)
  39#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
  40#define FAIL_LIBBPF(err, msg)                                                  \
  41        ({                                                                     \
  42                char __buf[MAX_STRERR_LEN];                                    \
  43                libbpf_strerror((err), __buf, sizeof(__buf));                  \
  44                FAIL("%s: %s", (msg), __buf);                                  \
  45        })
  46
  47/* Wrappers that fail the test on error and report it. */
  48
  49#define xaccept_nonblock(fd, addr, len)                                        \
  50        ({                                                                     \
  51                int __ret =                                                    \
  52                        accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC);   \
  53                if (__ret == -1)                                               \
  54                        FAIL_ERRNO("accept");                                  \
  55                __ret;                                                         \
  56        })
  57
  58#define xbind(fd, addr, len)                                                   \
  59        ({                                                                     \
  60                int __ret = bind((fd), (addr), (len));                         \
  61                if (__ret == -1)                                               \
  62                        FAIL_ERRNO("bind");                                    \
  63                __ret;                                                         \
  64        })
  65
  66#define xclose(fd)                                                             \
  67        ({                                                                     \
  68                int __ret = close((fd));                                       \
  69                if (__ret == -1)                                               \
  70                        FAIL_ERRNO("close");                                   \
  71                __ret;                                                         \
  72        })
  73
  74#define xconnect(fd, addr, len)                                                \
  75        ({                                                                     \
  76                int __ret = connect((fd), (addr), (len));                      \
  77                if (__ret == -1)                                               \
  78                        FAIL_ERRNO("connect");                                 \
  79                __ret;                                                         \
  80        })
  81
  82#define xgetsockname(fd, addr, len)                                            \
  83        ({                                                                     \
  84                int __ret = getsockname((fd), (addr), (len));                  \
  85                if (__ret == -1)                                               \
  86                        FAIL_ERRNO("getsockname");                             \
  87                __ret;                                                         \
  88        })
  89
  90#define xgetsockopt(fd, level, name, val, len)                                 \
  91        ({                                                                     \
  92                int __ret = getsockopt((fd), (level), (name), (val), (len));   \
  93                if (__ret == -1)                                               \
  94                        FAIL_ERRNO("getsockopt(" #name ")");                   \
  95                __ret;                                                         \
  96        })
  97
  98#define xlisten(fd, backlog)                                                   \
  99        ({                                                                     \
 100                int __ret = listen((fd), (backlog));                           \
 101                if (__ret == -1)                                               \
 102                        FAIL_ERRNO("listen");                                  \
 103                __ret;                                                         \
 104        })
 105
 106#define xsetsockopt(fd, level, name, val, len)                                 \
 107        ({                                                                     \
 108                int __ret = setsockopt((fd), (level), (name), (val), (len));   \
 109                if (__ret == -1)                                               \
 110                        FAIL_ERRNO("setsockopt(" #name ")");                   \
 111                __ret;                                                         \
 112        })
 113
 114#define xsend(fd, buf, len, flags)                                             \
 115        ({                                                                     \
 116                ssize_t __ret = send((fd), (buf), (len), (flags));             \
 117                if (__ret == -1)                                               \
 118                        FAIL_ERRNO("send");                                    \
 119                __ret;                                                         \
 120        })
 121
 122#define xrecv_nonblock(fd, buf, len, flags)                                    \
 123        ({                                                                     \
 124                ssize_t __ret = recv_timeout((fd), (buf), (len), (flags),      \
 125                                             IO_TIMEOUT_SEC);                  \
 126                if (__ret == -1)                                               \
 127                        FAIL_ERRNO("recv");                                    \
 128                __ret;                                                         \
 129        })
 130
 131#define xsocket(family, sotype, flags)                                         \
 132        ({                                                                     \
 133                int __ret = socket(family, sotype, flags);                     \
 134                if (__ret == -1)                                               \
 135                        FAIL_ERRNO("socket");                                  \
 136                __ret;                                                         \
 137        })
 138
 139#define xbpf_map_delete_elem(fd, key)                                          \
 140        ({                                                                     \
 141                int __ret = bpf_map_delete_elem((fd), (key));                  \
 142                if (__ret < 0)                                               \
 143                        FAIL_ERRNO("map_delete");                              \
 144                __ret;                                                         \
 145        })
 146
 147#define xbpf_map_lookup_elem(fd, key, val)                                     \
 148        ({                                                                     \
 149                int __ret = bpf_map_lookup_elem((fd), (key), (val));           \
 150                if (__ret < 0)                                               \
 151                        FAIL_ERRNO("map_lookup");                              \
 152                __ret;                                                         \
 153        })
 154
 155#define xbpf_map_update_elem(fd, key, val, flags)                              \
 156        ({                                                                     \
 157                int __ret = bpf_map_update_elem((fd), (key), (val), (flags));  \
 158                if (__ret < 0)                                               \
 159                        FAIL_ERRNO("map_update");                              \
 160                __ret;                                                         \
 161        })
 162
 163#define xbpf_prog_attach(prog, target, type, flags)                            \
 164        ({                                                                     \
 165                int __ret =                                                    \
 166                        bpf_prog_attach((prog), (target), (type), (flags));    \
 167                if (__ret < 0)                                               \
 168                        FAIL_ERRNO("prog_attach(" #type ")");                  \
 169                __ret;                                                         \
 170        })
 171
 172#define xbpf_prog_detach2(prog, target, type)                                  \
 173        ({                                                                     \
 174                int __ret = bpf_prog_detach2((prog), (target), (type));        \
 175                if (__ret < 0)                                               \
 176                        FAIL_ERRNO("prog_detach2(" #type ")");                 \
 177                __ret;                                                         \
 178        })
 179
 180#define xpthread_create(thread, attr, func, arg)                               \
 181        ({                                                                     \
 182                int __ret = pthread_create((thread), (attr), (func), (arg));   \
 183                errno = __ret;                                                 \
 184                if (__ret)                                                     \
 185                        FAIL_ERRNO("pthread_create");                          \
 186                __ret;                                                         \
 187        })
 188
 189#define xpthread_join(thread, retval)                                          \
 190        ({                                                                     \
 191                int __ret = pthread_join((thread), (retval));                  \
 192                errno = __ret;                                                 \
 193                if (__ret)                                                     \
 194                        FAIL_ERRNO("pthread_join");                            \
 195                __ret;                                                         \
 196        })
 197
 198static int poll_read(int fd, unsigned int timeout_sec)
 199{
 200        struct timeval timeout = { .tv_sec = timeout_sec };
 201        fd_set rfds;
 202        int r;
 203
 204        FD_ZERO(&rfds);
 205        FD_SET(fd, &rfds);
 206
 207        r = select(fd + 1, &rfds, NULL, NULL, &timeout);
 208        if (r == 0)
 209                errno = ETIME;
 210
 211        return r == 1 ? 0 : -1;
 212}
 213
 214static int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
 215                          unsigned int timeout_sec)
 216{
 217        if (poll_read(fd, timeout_sec))
 218                return -1;
 219
 220        return accept(fd, addr, len);
 221}
 222
 223static int recv_timeout(int fd, void *buf, size_t len, int flags,
 224                        unsigned int timeout_sec)
 225{
 226        if (poll_read(fd, timeout_sec))
 227                return -1;
 228
 229        return recv(fd, buf, len, flags);
 230}
 231
 232static void init_addr_loopback4(struct sockaddr_storage *ss, socklen_t *len)
 233{
 234        struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
 235
 236        addr4->sin_family = AF_INET;
 237        addr4->sin_port = 0;
 238        addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 239        *len = sizeof(*addr4);
 240}
 241
 242static void init_addr_loopback6(struct sockaddr_storage *ss, socklen_t *len)
 243{
 244        struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
 245
 246        addr6->sin6_family = AF_INET6;
 247        addr6->sin6_port = 0;
 248        addr6->sin6_addr = in6addr_loopback;
 249        *len = sizeof(*addr6);
 250}
 251
 252static void init_addr_loopback(int family, struct sockaddr_storage *ss,
 253                               socklen_t *len)
 254{
 255        switch (family) {
 256        case AF_INET:
 257                init_addr_loopback4(ss, len);
 258                return;
 259        case AF_INET6:
 260                init_addr_loopback6(ss, len);
 261                return;
 262        default:
 263                FAIL("unsupported address family %d", family);
 264        }
 265}
 266
 267static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
 268{
 269        return (struct sockaddr *)ss;
 270}
 271
 272static int enable_reuseport(int s, int progfd)
 273{
 274        int err, one = 1;
 275
 276        err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
 277        if (err)
 278                return -1;
 279        err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
 280                          sizeof(progfd));
 281        if (err)
 282                return -1;
 283
 284        return 0;
 285}
 286
 287static int socket_loopback_reuseport(int family, int sotype, int progfd)
 288{
 289        struct sockaddr_storage addr;
 290        socklen_t len;
 291        int err, s;
 292
 293        init_addr_loopback(family, &addr, &len);
 294
 295        s = xsocket(family, sotype, 0);
 296        if (s == -1)
 297                return -1;
 298
 299        if (progfd >= 0)
 300                enable_reuseport(s, progfd);
 301
 302        err = xbind(s, sockaddr(&addr), len);
 303        if (err)
 304                goto close;
 305
 306        if (sotype & SOCK_DGRAM)
 307                return s;
 308
 309        err = xlisten(s, SOMAXCONN);
 310        if (err)
 311                goto close;
 312
 313        return s;
 314close:
 315        xclose(s);
 316        return -1;
 317}
 318
 319static int socket_loopback(int family, int sotype)
 320{
 321        return socket_loopback_reuseport(family, sotype, -1);
 322}
 323
 324static void test_insert_invalid(int family, int sotype, int mapfd)
 325{
 326        u32 key = 0;
 327        u64 value;
 328        int err;
 329
 330        value = -1;
 331        err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 332        if (!err || errno != EINVAL)
 333                FAIL_ERRNO("map_update: expected EINVAL");
 334
 335        value = INT_MAX;
 336        err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 337        if (!err || errno != EBADF)
 338                FAIL_ERRNO("map_update: expected EBADF");
 339}
 340
 341static void test_insert_opened(int family, int sotype, int mapfd)
 342{
 343        u32 key = 0;
 344        u64 value;
 345        int err, s;
 346
 347        s = xsocket(family, sotype, 0);
 348        if (s == -1)
 349                return;
 350
 351        errno = 0;
 352        value = s;
 353        err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 354        if (!err || errno != EOPNOTSUPP)
 355                FAIL_ERRNO("map_update: expected EOPNOTSUPP");
 356
 357        xclose(s);
 358}
 359
 360static void test_insert_bound(int family, int sotype, int mapfd)
 361{
 362        struct sockaddr_storage addr;
 363        socklen_t len;
 364        u32 key = 0;
 365        u64 value;
 366        int err, s;
 367
 368        init_addr_loopback(family, &addr, &len);
 369
 370        s = xsocket(family, sotype, 0);
 371        if (s == -1)
 372                return;
 373
 374        err = xbind(s, sockaddr(&addr), len);
 375        if (err)
 376                goto close;
 377
 378        errno = 0;
 379        value = s;
 380        err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 381        if (!err || errno != EOPNOTSUPP)
 382                FAIL_ERRNO("map_update: expected EOPNOTSUPP");
 383close:
 384        xclose(s);
 385}
 386
 387static void test_insert(int family, int sotype, int mapfd)
 388{
 389        u64 value;
 390        u32 key;
 391        int s;
 392
 393        s = socket_loopback(family, sotype);
 394        if (s < 0)
 395                return;
 396
 397        key = 0;
 398        value = s;
 399        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 400        xclose(s);
 401}
 402
 403static void test_delete_after_insert(int family, int sotype, int mapfd)
 404{
 405        u64 value;
 406        u32 key;
 407        int s;
 408
 409        s = socket_loopback(family, sotype);
 410        if (s < 0)
 411                return;
 412
 413        key = 0;
 414        value = s;
 415        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 416        xbpf_map_delete_elem(mapfd, &key);
 417        xclose(s);
 418}
 419
 420static void test_delete_after_close(int family, int sotype, int mapfd)
 421{
 422        int err, s;
 423        u64 value;
 424        u32 key;
 425
 426        s = socket_loopback(family, sotype);
 427        if (s < 0)
 428                return;
 429
 430        key = 0;
 431        value = s;
 432        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 433
 434        xclose(s);
 435
 436        errno = 0;
 437        err = bpf_map_delete_elem(mapfd, &key);
 438        if (!err || (errno != EINVAL && errno != ENOENT))
 439                /* SOCKMAP and SOCKHASH return different error codes */
 440                FAIL_ERRNO("map_delete: expected EINVAL/EINVAL");
 441}
 442
 443static void test_lookup_after_insert(int family, int sotype, int mapfd)
 444{
 445        u64 cookie, value;
 446        socklen_t len;
 447        u32 key;
 448        int s;
 449
 450        s = socket_loopback(family, sotype);
 451        if (s < 0)
 452                return;
 453
 454        key = 0;
 455        value = s;
 456        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 457
 458        len = sizeof(cookie);
 459        xgetsockopt(s, SOL_SOCKET, SO_COOKIE, &cookie, &len);
 460
 461        xbpf_map_lookup_elem(mapfd, &key, &value);
 462
 463        if (value != cookie) {
 464                FAIL("map_lookup: have %#llx, want %#llx",
 465                     (unsigned long long)value, (unsigned long long)cookie);
 466        }
 467
 468        xclose(s);
 469}
 470
 471static void test_lookup_after_delete(int family, int sotype, int mapfd)
 472{
 473        int err, s;
 474        u64 value;
 475        u32 key;
 476
 477        s = socket_loopback(family, sotype);
 478        if (s < 0)
 479                return;
 480
 481        key = 0;
 482        value = s;
 483        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 484        xbpf_map_delete_elem(mapfd, &key);
 485
 486        errno = 0;
 487        err = bpf_map_lookup_elem(mapfd, &key, &value);
 488        if (!err || errno != ENOENT)
 489                FAIL_ERRNO("map_lookup: expected ENOENT");
 490
 491        xclose(s);
 492}
 493
 494static void test_lookup_32_bit_value(int family, int sotype, int mapfd)
 495{
 496        u32 key, value32;
 497        int err, s;
 498
 499        s = socket_loopback(family, sotype);
 500        if (s < 0)
 501                return;
 502
 503        mapfd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP, sizeof(key),
 504                               sizeof(value32), 1, 0);
 505        if (mapfd < 0) {
 506                FAIL_ERRNO("map_create");
 507                goto close;
 508        }
 509
 510        key = 0;
 511        value32 = s;
 512        xbpf_map_update_elem(mapfd, &key, &value32, BPF_NOEXIST);
 513
 514        errno = 0;
 515        err = bpf_map_lookup_elem(mapfd, &key, &value32);
 516        if (!err || errno != ENOSPC)
 517                FAIL_ERRNO("map_lookup: expected ENOSPC");
 518
 519        xclose(mapfd);
 520close:
 521        xclose(s);
 522}
 523
 524static void test_update_existing(int family, int sotype, int mapfd)
 525{
 526        int s1, s2;
 527        u64 value;
 528        u32 key;
 529
 530        s1 = socket_loopback(family, sotype);
 531        if (s1 < 0)
 532                return;
 533
 534        s2 = socket_loopback(family, sotype);
 535        if (s2 < 0)
 536                goto close_s1;
 537
 538        key = 0;
 539        value = s1;
 540        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 541
 542        value = s2;
 543        xbpf_map_update_elem(mapfd, &key, &value, BPF_EXIST);
 544        xclose(s2);
 545close_s1:
 546        xclose(s1);
 547}
 548
 549/* Exercise the code path where we destroy child sockets that never
 550 * got accept()'ed, aka orphans, when parent socket gets closed.
 551 */
 552static void test_destroy_orphan_child(int family, int sotype, int mapfd)
 553{
 554        struct sockaddr_storage addr;
 555        socklen_t len;
 556        int err, s, c;
 557        u64 value;
 558        u32 key;
 559
 560        s = socket_loopback(family, sotype);
 561        if (s < 0)
 562                return;
 563
 564        len = sizeof(addr);
 565        err = xgetsockname(s, sockaddr(&addr), &len);
 566        if (err)
 567                goto close_srv;
 568
 569        key = 0;
 570        value = s;
 571        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 572
 573        c = xsocket(family, sotype, 0);
 574        if (c == -1)
 575                goto close_srv;
 576
 577        xconnect(c, sockaddr(&addr), len);
 578        xclose(c);
 579close_srv:
 580        xclose(s);
 581}
 582
 583/* Perform a passive open after removing listening socket from SOCKMAP
 584 * to ensure that callbacks get restored properly.
 585 */
 586static void test_clone_after_delete(int family, int sotype, int mapfd)
 587{
 588        struct sockaddr_storage addr;
 589        socklen_t len;
 590        int err, s, c;
 591        u64 value;
 592        u32 key;
 593
 594        s = socket_loopback(family, sotype);
 595        if (s < 0)
 596                return;
 597
 598        len = sizeof(addr);
 599        err = xgetsockname(s, sockaddr(&addr), &len);
 600        if (err)
 601                goto close_srv;
 602
 603        key = 0;
 604        value = s;
 605        xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST);
 606        xbpf_map_delete_elem(mapfd, &key);
 607
 608        c = xsocket(family, sotype, 0);
 609        if (c < 0)
 610                goto close_srv;
 611
 612        xconnect(c, sockaddr(&addr), len);
 613        xclose(c);
 614close_srv:
 615        xclose(s);
 616}
 617
 618/* Check that child socket that got created while parent was in a
 619 * SOCKMAP, but got accept()'ed only after the parent has been removed
 620 * from SOCKMAP, gets cloned without parent psock state or callbacks.
 621 */
 622static void test_accept_after_delete(int family, int sotype, int mapfd)
 623{
 624        struct sockaddr_storage addr;
 625        const u32 zero = 0;
 626        int err, s, c, p;
 627        socklen_t len;
 628        u64 value;
 629
 630        s = socket_loopback(family, sotype | SOCK_NONBLOCK);
 631        if (s == -1)
 632                return;
 633
 634        len = sizeof(addr);
 635        err = xgetsockname(s, sockaddr(&addr), &len);
 636        if (err)
 637                goto close_srv;
 638
 639        value = s;
 640        err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST);
 641        if (err)
 642                goto close_srv;
 643
 644        c = xsocket(family, sotype, 0);
 645        if (c == -1)
 646                goto close_srv;
 647
 648        /* Create child while parent is in sockmap */
 649        err = xconnect(c, sockaddr(&addr), len);
 650        if (err)
 651                goto close_cli;
 652
 653        /* Remove parent from sockmap */
 654        err = xbpf_map_delete_elem(mapfd, &zero);
 655        if (err)
 656                goto close_cli;
 657
 658        p = xaccept_nonblock(s, NULL, NULL);
 659        if (p == -1)
 660                goto close_cli;
 661
 662        /* Check that child sk_user_data is not set */
 663        value = p;
 664        xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST);
 665
 666        xclose(p);
 667close_cli:
 668        xclose(c);
 669close_srv:
 670        xclose(s);
 671}
 672
 673/* Check that child socket that got created and accepted while parent
 674 * was in a SOCKMAP is cloned without parent psock state or callbacks.
 675 */
 676static void test_accept_before_delete(int family, int sotype, int mapfd)
 677{
 678        struct sockaddr_storage addr;
 679        const u32 zero = 0, one = 1;
 680        int err, s, c, p;
 681        socklen_t len;
 682        u64 value;
 683
 684        s = socket_loopback(family, sotype | SOCK_NONBLOCK);
 685        if (s == -1)
 686                return;
 687
 688        len = sizeof(addr);
 689        err = xgetsockname(s, sockaddr(&addr), &len);
 690        if (err)
 691                goto close_srv;
 692
 693        value = s;
 694        err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST);
 695        if (err)
 696                goto close_srv;
 697
 698        c = xsocket(family, sotype, 0);
 699        if (c == -1)
 700                goto close_srv;
 701
 702        /* Create & accept child while parent is in sockmap */
 703        err = xconnect(c, sockaddr(&addr), len);
 704        if (err)
 705                goto close_cli;
 706
 707        p = xaccept_nonblock(s, NULL, NULL);
 708        if (p == -1)
 709                goto close_cli;
 710
 711        /* Check that child sk_user_data is not set */
 712        value = p;
 713        xbpf_map_update_elem(mapfd, &one, &value, BPF_NOEXIST);
 714
 715        xclose(p);
 716close_cli:
 717        xclose(c);
 718close_srv:
 719        xclose(s);
 720}
 721
 722struct connect_accept_ctx {
 723        int sockfd;
 724        unsigned int done;
 725        unsigned int nr_iter;
 726};
 727
 728static bool is_thread_done(struct connect_accept_ctx *ctx)
 729{
 730        return READ_ONCE(ctx->done);
 731}
 732
 733static void *connect_accept_thread(void *arg)
 734{
 735        struct connect_accept_ctx *ctx = arg;
 736        struct sockaddr_storage addr;
 737        int family, socktype;
 738        socklen_t len;
 739        int err, i, s;
 740
 741        s = ctx->sockfd;
 742
 743        len = sizeof(addr);
 744        err = xgetsockname(s, sockaddr(&addr), &len);
 745        if (err)
 746                goto done;
 747
 748        len = sizeof(family);
 749        err = xgetsockopt(s, SOL_SOCKET, SO_DOMAIN, &family, &len);
 750        if (err)
 751                goto done;
 752
 753        len = sizeof(socktype);
 754        err = xgetsockopt(s, SOL_SOCKET, SO_TYPE, &socktype, &len);
 755        if (err)
 756                goto done;
 757
 758        for (i = 0; i < ctx->nr_iter; i++) {
 759                int c, p;
 760
 761                c = xsocket(family, socktype, 0);
 762                if (c < 0)
 763                        break;
 764
 765                err = xconnect(c, (struct sockaddr *)&addr, sizeof(addr));
 766                if (err) {
 767                        xclose(c);
 768                        break;
 769                }
 770
 771                p = xaccept_nonblock(s, NULL, NULL);
 772                if (p < 0) {
 773                        xclose(c);
 774                        break;
 775                }
 776
 777                xclose(p);
 778                xclose(c);
 779        }
 780done:
 781        WRITE_ONCE(ctx->done, 1);
 782        return NULL;
 783}
 784
 785static void test_syn_recv_insert_delete(int family, int sotype, int mapfd)
 786{
 787        struct connect_accept_ctx ctx = { 0 };
 788        struct sockaddr_storage addr;
 789        socklen_t len;
 790        u32 zero = 0;
 791        pthread_t t;
 792        int err, s;
 793        u64 value;
 794
 795        s = socket_loopback(family, sotype | SOCK_NONBLOCK);
 796        if (s < 0)
 797                return;
 798
 799        len = sizeof(addr);
 800        err = xgetsockname(s, sockaddr(&addr), &len);
 801        if (err)
 802                goto close;
 803
 804        ctx.sockfd = s;
 805        ctx.nr_iter = 1000;
 806
 807        err = xpthread_create(&t, NULL, connect_accept_thread, &ctx);
 808        if (err)
 809                goto close;
 810
 811        value = s;
 812        while (!is_thread_done(&ctx)) {
 813                err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST);
 814                if (err)
 815                        break;
 816
 817                err = xbpf_map_delete_elem(mapfd, &zero);
 818                if (err)
 819                        break;
 820        }
 821
 822        xpthread_join(t, NULL);
 823close:
 824        xclose(s);
 825}
 826
 827static void *listen_thread(void *arg)
 828{
 829        struct sockaddr unspec = { AF_UNSPEC };
 830        struct connect_accept_ctx *ctx = arg;
 831        int err, i, s;
 832
 833        s = ctx->sockfd;
 834
 835        for (i = 0; i < ctx->nr_iter; i++) {
 836                err = xlisten(s, 1);
 837                if (err)
 838                        break;
 839                err = xconnect(s, &unspec, sizeof(unspec));
 840                if (err)
 841                        break;
 842        }
 843
 844        WRITE_ONCE(ctx->done, 1);
 845        return NULL;
 846}
 847
 848static void test_race_insert_listen(int family, int socktype, int mapfd)
 849{
 850        struct connect_accept_ctx ctx = { 0 };
 851        const u32 zero = 0;
 852        const int one = 1;
 853        pthread_t t;
 854        int err, s;
 855        u64 value;
 856
 857        s = xsocket(family, socktype, 0);
 858        if (s < 0)
 859                return;
 860
 861        err = xsetsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
 862        if (err)
 863                goto close;
 864
 865        ctx.sockfd = s;
 866        ctx.nr_iter = 10000;
 867
 868        err = pthread_create(&t, NULL, listen_thread, &ctx);
 869        if (err)
 870                goto close;
 871
 872        value = s;
 873        while (!is_thread_done(&ctx)) {
 874                err = bpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST);
 875                /* Expecting EOPNOTSUPP before listen() */
 876                if (err && errno != EOPNOTSUPP) {
 877                        FAIL_ERRNO("map_update");
 878                        break;
 879                }
 880
 881                err = bpf_map_delete_elem(mapfd, &zero);
 882                /* Expecting no entry after unhash on connect(AF_UNSPEC) */
 883                if (err && errno != EINVAL && errno != ENOENT) {
 884                        FAIL_ERRNO("map_delete");
 885                        break;
 886                }
 887        }
 888
 889        xpthread_join(t, NULL);
 890close:
 891        xclose(s);
 892}
 893
 894static void zero_verdict_count(int mapfd)
 895{
 896        unsigned int zero = 0;
 897        int key;
 898
 899        key = SK_DROP;
 900        xbpf_map_update_elem(mapfd, &key, &zero, BPF_ANY);
 901        key = SK_PASS;
 902        xbpf_map_update_elem(mapfd, &key, &zero, BPF_ANY);
 903}
 904
 905enum redir_mode {
 906        REDIR_INGRESS,
 907        REDIR_EGRESS,
 908};
 909
 910static const char *redir_mode_str(enum redir_mode mode)
 911{
 912        switch (mode) {
 913        case REDIR_INGRESS:
 914                return "ingress";
 915        case REDIR_EGRESS:
 916                return "egress";
 917        default:
 918                return "unknown";
 919        }
 920}
 921
 922static void redir_to_connected(int family, int sotype, int sock_mapfd,
 923                               int verd_mapfd, enum redir_mode mode)
 924{
 925        const char *log_prefix = redir_mode_str(mode);
 926        struct sockaddr_storage addr;
 927        int s, c0, c1, p0, p1;
 928        unsigned int pass;
 929        socklen_t len;
 930        int err, n;
 931        u64 value;
 932        u32 key;
 933        char b;
 934
 935        zero_verdict_count(verd_mapfd);
 936
 937        s = socket_loopback(family, sotype | SOCK_NONBLOCK);
 938        if (s < 0)
 939                return;
 940
 941        len = sizeof(addr);
 942        err = xgetsockname(s, sockaddr(&addr), &len);
 943        if (err)
 944                goto close_srv;
 945
 946        c0 = xsocket(family, sotype, 0);
 947        if (c0 < 0)
 948                goto close_srv;
 949        err = xconnect(c0, sockaddr(&addr), len);
 950        if (err)
 951                goto close_cli0;
 952
 953        p0 = xaccept_nonblock(s, NULL, NULL);
 954        if (p0 < 0)
 955                goto close_cli0;
 956
 957        c1 = xsocket(family, sotype, 0);
 958        if (c1 < 0)
 959                goto close_peer0;
 960        err = xconnect(c1, sockaddr(&addr), len);
 961        if (err)
 962                goto close_cli1;
 963
 964        p1 = xaccept_nonblock(s, NULL, NULL);
 965        if (p1 < 0)
 966                goto close_cli1;
 967
 968        key = 0;
 969        value = p0;
 970        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
 971        if (err)
 972                goto close_peer1;
 973
 974        key = 1;
 975        value = p1;
 976        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
 977        if (err)
 978                goto close_peer1;
 979
 980        n = write(mode == REDIR_INGRESS ? c1 : p1, "a", 1);
 981        if (n < 0)
 982                FAIL_ERRNO("%s: write", log_prefix);
 983        if (n == 0)
 984                FAIL("%s: incomplete write", log_prefix);
 985        if (n < 1)
 986                goto close_peer1;
 987
 988        key = SK_PASS;
 989        err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass);
 990        if (err)
 991                goto close_peer1;
 992        if (pass != 1)
 993                FAIL("%s: want pass count 1, have %d", log_prefix, pass);
 994
 995        n = read(c0, &b, 1);
 996        if (n < 0)
 997                FAIL_ERRNO("%s: read", log_prefix);
 998        if (n == 0)
 999                FAIL("%s: incomplete read", log_prefix);
1000
1001close_peer1:
1002        xclose(p1);
1003close_cli1:
1004        xclose(c1);
1005close_peer0:
1006        xclose(p0);
1007close_cli0:
1008        xclose(c0);
1009close_srv:
1010        xclose(s);
1011}
1012
1013static void test_skb_redir_to_connected(struct test_sockmap_listen *skel,
1014                                        struct bpf_map *inner_map, int family,
1015                                        int sotype)
1016{
1017        int verdict = bpf_program__fd(skel->progs.prog_stream_verdict);
1018        int parser = bpf_program__fd(skel->progs.prog_stream_parser);
1019        int verdict_map = bpf_map__fd(skel->maps.verdict_map);
1020        int sock_map = bpf_map__fd(inner_map);
1021        int err;
1022
1023        err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0);
1024        if (err)
1025                return;
1026        err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0);
1027        if (err)
1028                goto detach;
1029
1030        redir_to_connected(family, sotype, sock_map, verdict_map,
1031                           REDIR_INGRESS);
1032
1033        xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT);
1034detach:
1035        xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER);
1036}
1037
1038static void test_msg_redir_to_connected(struct test_sockmap_listen *skel,
1039                                        struct bpf_map *inner_map, int family,
1040                                        int sotype)
1041{
1042        int verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
1043        int verdict_map = bpf_map__fd(skel->maps.verdict_map);
1044        int sock_map = bpf_map__fd(inner_map);
1045        int err;
1046
1047        err = xbpf_prog_attach(verdict, sock_map, BPF_SK_MSG_VERDICT, 0);
1048        if (err)
1049                return;
1050
1051        redir_to_connected(family, sotype, sock_map, verdict_map, REDIR_EGRESS);
1052
1053        xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT);
1054}
1055
1056static void redir_to_listening(int family, int sotype, int sock_mapfd,
1057                               int verd_mapfd, enum redir_mode mode)
1058{
1059        const char *log_prefix = redir_mode_str(mode);
1060        struct sockaddr_storage addr;
1061        int s, c, p, err, n;
1062        unsigned int drop;
1063        socklen_t len;
1064        u64 value;
1065        u32 key;
1066
1067        zero_verdict_count(verd_mapfd);
1068
1069        s = socket_loopback(family, sotype | SOCK_NONBLOCK);
1070        if (s < 0)
1071                return;
1072
1073        len = sizeof(addr);
1074        err = xgetsockname(s, sockaddr(&addr), &len);
1075        if (err)
1076                goto close_srv;
1077
1078        c = xsocket(family, sotype, 0);
1079        if (c < 0)
1080                goto close_srv;
1081        err = xconnect(c, sockaddr(&addr), len);
1082        if (err)
1083                goto close_cli;
1084
1085        p = xaccept_nonblock(s, NULL, NULL);
1086        if (p < 0)
1087                goto close_cli;
1088
1089        key = 0;
1090        value = s;
1091        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
1092        if (err)
1093                goto close_peer;
1094
1095        key = 1;
1096        value = p;
1097        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
1098        if (err)
1099                goto close_peer;
1100
1101        n = write(mode == REDIR_INGRESS ? c : p, "a", 1);
1102        if (n < 0 && errno != EACCES)
1103                FAIL_ERRNO("%s: write", log_prefix);
1104        if (n == 0)
1105                FAIL("%s: incomplete write", log_prefix);
1106        if (n < 1)
1107                goto close_peer;
1108
1109        key = SK_DROP;
1110        err = xbpf_map_lookup_elem(verd_mapfd, &key, &drop);
1111        if (err)
1112                goto close_peer;
1113        if (drop != 1)
1114                FAIL("%s: want drop count 1, have %d", log_prefix, drop);
1115
1116close_peer:
1117        xclose(p);
1118close_cli:
1119        xclose(c);
1120close_srv:
1121        xclose(s);
1122}
1123
1124static void test_skb_redir_to_listening(struct test_sockmap_listen *skel,
1125                                        struct bpf_map *inner_map, int family,
1126                                        int sotype)
1127{
1128        int verdict = bpf_program__fd(skel->progs.prog_stream_verdict);
1129        int parser = bpf_program__fd(skel->progs.prog_stream_parser);
1130        int verdict_map = bpf_map__fd(skel->maps.verdict_map);
1131        int sock_map = bpf_map__fd(inner_map);
1132        int err;
1133
1134        err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0);
1135        if (err)
1136                return;
1137        err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0);
1138        if (err)
1139                goto detach;
1140
1141        redir_to_listening(family, sotype, sock_map, verdict_map,
1142                           REDIR_INGRESS);
1143
1144        xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT);
1145detach:
1146        xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER);
1147}
1148
1149static void test_msg_redir_to_listening(struct test_sockmap_listen *skel,
1150                                        struct bpf_map *inner_map, int family,
1151                                        int sotype)
1152{
1153        int verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
1154        int verdict_map = bpf_map__fd(skel->maps.verdict_map);
1155        int sock_map = bpf_map__fd(inner_map);
1156        int err;
1157
1158        err = xbpf_prog_attach(verdict, sock_map, BPF_SK_MSG_VERDICT, 0);
1159        if (err)
1160                return;
1161
1162        redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS);
1163
1164        xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT);
1165}
1166
1167static void test_reuseport_select_listening(int family, int sotype,
1168                                            int sock_map, int verd_map,
1169                                            int reuseport_prog)
1170{
1171        struct sockaddr_storage addr;
1172        unsigned int pass;
1173        int s, c, err;
1174        socklen_t len;
1175        u64 value;
1176        u32 key;
1177
1178        zero_verdict_count(verd_map);
1179
1180        s = socket_loopback_reuseport(family, sotype | SOCK_NONBLOCK,
1181                                      reuseport_prog);
1182        if (s < 0)
1183                return;
1184
1185        len = sizeof(addr);
1186        err = xgetsockname(s, sockaddr(&addr), &len);
1187        if (err)
1188                goto close_srv;
1189
1190        key = 0;
1191        value = s;
1192        err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST);
1193        if (err)
1194                goto close_srv;
1195
1196        c = xsocket(family, sotype, 0);
1197        if (c < 0)
1198                goto close_srv;
1199        err = xconnect(c, sockaddr(&addr), len);
1200        if (err)
1201                goto close_cli;
1202
1203        if (sotype == SOCK_STREAM) {
1204                int p;
1205
1206                p = xaccept_nonblock(s, NULL, NULL);
1207                if (p < 0)
1208                        goto close_cli;
1209                xclose(p);
1210        } else {
1211                char b = 'a';
1212                ssize_t n;
1213
1214                n = xsend(c, &b, sizeof(b), 0);
1215                if (n == -1)
1216                        goto close_cli;
1217
1218                n = xrecv_nonblock(s, &b, sizeof(b), 0);
1219                if (n == -1)
1220                        goto close_cli;
1221        }
1222
1223        key = SK_PASS;
1224        err = xbpf_map_lookup_elem(verd_map, &key, &pass);
1225        if (err)
1226                goto close_cli;
1227        if (pass != 1)
1228                FAIL("want pass count 1, have %d", pass);
1229
1230close_cli:
1231        xclose(c);
1232close_srv:
1233        xclose(s);
1234}
1235
1236static void test_reuseport_select_connected(int family, int sotype,
1237                                            int sock_map, int verd_map,
1238                                            int reuseport_prog)
1239{
1240        struct sockaddr_storage addr;
1241        int s, c0, c1, p0, err;
1242        unsigned int drop;
1243        socklen_t len;
1244        u64 value;
1245        u32 key;
1246
1247        zero_verdict_count(verd_map);
1248
1249        s = socket_loopback_reuseport(family, sotype, reuseport_prog);
1250        if (s < 0)
1251                return;
1252
1253        /* Populate sock_map[0] to avoid ENOENT on first connection */
1254        key = 0;
1255        value = s;
1256        err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST);
1257        if (err)
1258                goto close_srv;
1259
1260        len = sizeof(addr);
1261        err = xgetsockname(s, sockaddr(&addr), &len);
1262        if (err)
1263                goto close_srv;
1264
1265        c0 = xsocket(family, sotype, 0);
1266        if (c0 < 0)
1267                goto close_srv;
1268
1269        err = xconnect(c0, sockaddr(&addr), len);
1270        if (err)
1271                goto close_cli0;
1272
1273        if (sotype == SOCK_STREAM) {
1274                p0 = xaccept_nonblock(s, NULL, NULL);
1275                if (p0 < 0)
1276                        goto close_cli0;
1277        } else {
1278                p0 = xsocket(family, sotype, 0);
1279                if (p0 < 0)
1280                        goto close_cli0;
1281
1282                len = sizeof(addr);
1283                err = xgetsockname(c0, sockaddr(&addr), &len);
1284                if (err)
1285                        goto close_cli0;
1286
1287                err = xconnect(p0, sockaddr(&addr), len);
1288                if (err)
1289                        goto close_cli0;
1290        }
1291
1292        /* Update sock_map[0] to redirect to a connected socket */
1293        key = 0;
1294        value = p0;
1295        err = xbpf_map_update_elem(sock_map, &key, &value, BPF_EXIST);
1296        if (err)
1297                goto close_peer0;
1298
1299        c1 = xsocket(family, sotype, 0);
1300        if (c1 < 0)
1301                goto close_peer0;
1302
1303        len = sizeof(addr);
1304        err = xgetsockname(s, sockaddr(&addr), &len);
1305        if (err)
1306                goto close_srv;
1307
1308        errno = 0;
1309        err = connect(c1, sockaddr(&addr), len);
1310        if (sotype == SOCK_DGRAM) {
1311                char b = 'a';
1312                ssize_t n;
1313
1314                n = xsend(c1, &b, sizeof(b), 0);
1315                if (n == -1)
1316                        goto close_cli1;
1317
1318                n = recv_timeout(c1, &b, sizeof(b), 0, IO_TIMEOUT_SEC);
1319                err = n == -1;
1320        }
1321        if (!err || errno != ECONNREFUSED)
1322                FAIL_ERRNO("connect: expected ECONNREFUSED");
1323
1324        key = SK_DROP;
1325        err = xbpf_map_lookup_elem(verd_map, &key, &drop);
1326        if (err)
1327                goto close_cli1;
1328        if (drop != 1)
1329                FAIL("want drop count 1, have %d", drop);
1330
1331close_cli1:
1332        xclose(c1);
1333close_peer0:
1334        xclose(p0);
1335close_cli0:
1336        xclose(c0);
1337close_srv:
1338        xclose(s);
1339}
1340
1341/* Check that redirecting across reuseport groups is not allowed. */
1342static void test_reuseport_mixed_groups(int family, int sotype, int sock_map,
1343                                        int verd_map, int reuseport_prog)
1344{
1345        struct sockaddr_storage addr;
1346        int s1, s2, c, err;
1347        unsigned int drop;
1348        socklen_t len;
1349        u64 value;
1350        u32 key;
1351
1352        zero_verdict_count(verd_map);
1353
1354        /* Create two listeners, each in its own reuseport group */
1355        s1 = socket_loopback_reuseport(family, sotype, reuseport_prog);
1356        if (s1 < 0)
1357                return;
1358
1359        s2 = socket_loopback_reuseport(family, sotype, reuseport_prog);
1360        if (s2 < 0)
1361                goto close_srv1;
1362
1363        key = 0;
1364        value = s1;
1365        err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST);
1366        if (err)
1367                goto close_srv2;
1368
1369        key = 1;
1370        value = s2;
1371        err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST);
1372
1373        /* Connect to s2, reuseport BPF selects s1 via sock_map[0] */
1374        len = sizeof(addr);
1375        err = xgetsockname(s2, sockaddr(&addr), &len);
1376        if (err)
1377                goto close_srv2;
1378
1379        c = xsocket(family, sotype, 0);
1380        if (c < 0)
1381                goto close_srv2;
1382
1383        err = connect(c, sockaddr(&addr), len);
1384        if (sotype == SOCK_DGRAM) {
1385                char b = 'a';
1386                ssize_t n;
1387
1388                n = xsend(c, &b, sizeof(b), 0);
1389                if (n == -1)
1390                        goto close_cli;
1391
1392                n = recv_timeout(c, &b, sizeof(b), 0, IO_TIMEOUT_SEC);
1393                err = n == -1;
1394        }
1395        if (!err || errno != ECONNREFUSED) {
1396                FAIL_ERRNO("connect: expected ECONNREFUSED");
1397                goto close_cli;
1398        }
1399
1400        /* Expect drop, can't redirect outside of reuseport group */
1401        key = SK_DROP;
1402        err = xbpf_map_lookup_elem(verd_map, &key, &drop);
1403        if (err)
1404                goto close_cli;
1405        if (drop != 1)
1406                FAIL("want drop count 1, have %d", drop);
1407
1408close_cli:
1409        xclose(c);
1410close_srv2:
1411        xclose(s2);
1412close_srv1:
1413        xclose(s1);
1414}
1415
1416#define TEST(fn, ...)                                                          \
1417        {                                                                      \
1418                fn, #fn, __VA_ARGS__                                           \
1419        }
1420
1421static void test_ops_cleanup(const struct bpf_map *map)
1422{
1423        const struct bpf_map_def *def;
1424        int err, mapfd;
1425        u32 key;
1426
1427        def = bpf_map__def(map);
1428        mapfd = bpf_map__fd(map);
1429
1430        for (key = 0; key < def->max_entries; key++) {
1431                err = bpf_map_delete_elem(mapfd, &key);
1432                if (err && errno != EINVAL && errno != ENOENT)
1433                        FAIL_ERRNO("map_delete: expected EINVAL/ENOENT");
1434        }
1435}
1436
1437static const char *family_str(sa_family_t family)
1438{
1439        switch (family) {
1440        case AF_INET:
1441                return "IPv4";
1442        case AF_INET6:
1443                return "IPv6";
1444        default:
1445                return "unknown";
1446        }
1447}
1448
1449static const char *map_type_str(const struct bpf_map *map)
1450{
1451        const struct bpf_map_def *def;
1452
1453        def = bpf_map__def(map);
1454        if (IS_ERR(def))
1455                return "invalid";
1456
1457        switch (def->type) {
1458        case BPF_MAP_TYPE_SOCKMAP:
1459                return "sockmap";
1460        case BPF_MAP_TYPE_SOCKHASH:
1461                return "sockhash";
1462        default:
1463                return "unknown";
1464        }
1465}
1466
1467static const char *sotype_str(int sotype)
1468{
1469        switch (sotype) {
1470        case SOCK_DGRAM:
1471                return "UDP";
1472        case SOCK_STREAM:
1473                return "TCP";
1474        default:
1475                return "unknown";
1476        }
1477}
1478
1479static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
1480                     int family, int sotype)
1481{
1482        const struct op_test {
1483                void (*fn)(int family, int sotype, int mapfd);
1484                const char *name;
1485                int sotype;
1486        } tests[] = {
1487                /* insert */
1488                TEST(test_insert_invalid),
1489                TEST(test_insert_opened),
1490                TEST(test_insert_bound, SOCK_STREAM),
1491                TEST(test_insert),
1492                /* delete */
1493                TEST(test_delete_after_insert),
1494                TEST(test_delete_after_close),
1495                /* lookup */
1496                TEST(test_lookup_after_insert),
1497                TEST(test_lookup_after_delete),
1498                TEST(test_lookup_32_bit_value),
1499                /* update */
1500                TEST(test_update_existing),
1501                /* races with insert/delete */
1502                TEST(test_destroy_orphan_child, SOCK_STREAM),
1503                TEST(test_syn_recv_insert_delete, SOCK_STREAM),
1504                TEST(test_race_insert_listen, SOCK_STREAM),
1505                /* child clone */
1506                TEST(test_clone_after_delete, SOCK_STREAM),
1507                TEST(test_accept_after_delete, SOCK_STREAM),
1508                TEST(test_accept_before_delete, SOCK_STREAM),
1509        };
1510        const char *family_name, *map_name, *sotype_name;
1511        const struct op_test *t;
1512        char s[MAX_TEST_NAME];
1513        int map_fd;
1514
1515        family_name = family_str(family);
1516        map_name = map_type_str(map);
1517        sotype_name = sotype_str(sotype);
1518        map_fd = bpf_map__fd(map);
1519
1520        for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
1521                snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name,
1522                         sotype_name, t->name);
1523
1524                if (t->sotype != 0 && t->sotype != sotype)
1525                        continue;
1526
1527                if (!test__start_subtest(s))
1528                        continue;
1529
1530                t->fn(family, sotype, map_fd);
1531                test_ops_cleanup(map);
1532        }
1533}
1534
1535static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
1536                       int family, int sotype)
1537{
1538        const struct redir_test {
1539                void (*fn)(struct test_sockmap_listen *skel,
1540                           struct bpf_map *map, int family, int sotype);
1541                const char *name;
1542        } tests[] = {
1543                TEST(test_skb_redir_to_connected),
1544                TEST(test_skb_redir_to_listening),
1545                TEST(test_msg_redir_to_connected),
1546                TEST(test_msg_redir_to_listening),
1547        };
1548        const char *family_name, *map_name;
1549        const struct redir_test *t;
1550        char s[MAX_TEST_NAME];
1551
1552        family_name = family_str(family);
1553        map_name = map_type_str(map);
1554
1555        for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
1556                snprintf(s, sizeof(s), "%s %s %s", map_name, family_name,
1557                         t->name);
1558
1559                if (!test__start_subtest(s))
1560                        continue;
1561
1562                t->fn(skel, map, family, sotype);
1563        }
1564}
1565
1566static void test_reuseport(struct test_sockmap_listen *skel,
1567                           struct bpf_map *map, int family, int sotype)
1568{
1569        const struct reuseport_test {
1570                void (*fn)(int family, int sotype, int socket_map,
1571                           int verdict_map, int reuseport_prog);
1572                const char *name;
1573                int sotype;
1574        } tests[] = {
1575                TEST(test_reuseport_select_listening),
1576                TEST(test_reuseport_select_connected),
1577                TEST(test_reuseport_mixed_groups),
1578        };
1579        int socket_map, verdict_map, reuseport_prog;
1580        const char *family_name, *map_name, *sotype_name;
1581        const struct reuseport_test *t;
1582        char s[MAX_TEST_NAME];
1583
1584        family_name = family_str(family);
1585        map_name = map_type_str(map);
1586        sotype_name = sotype_str(sotype);
1587
1588        socket_map = bpf_map__fd(map);
1589        verdict_map = bpf_map__fd(skel->maps.verdict_map);
1590        reuseport_prog = bpf_program__fd(skel->progs.prog_reuseport);
1591
1592        for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
1593                snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name,
1594                         sotype_name, t->name);
1595
1596                if (t->sotype != 0 && t->sotype != sotype)
1597                        continue;
1598
1599                if (!test__start_subtest(s))
1600                        continue;
1601
1602                t->fn(family, sotype, socket_map, verdict_map, reuseport_prog);
1603        }
1604}
1605
1606static void udp_redir_to_connected(int family, int sotype, int sock_mapfd,
1607                                   int verd_mapfd, enum redir_mode mode)
1608{
1609        const char *log_prefix = redir_mode_str(mode);
1610        struct sockaddr_storage addr;
1611        int c0, c1, p0, p1;
1612        unsigned int pass;
1613        int retries = 100;
1614        socklen_t len;
1615        int err, n;
1616        u64 value;
1617        u32 key;
1618        char b;
1619
1620        zero_verdict_count(verd_mapfd);
1621
1622        p0 = socket_loopback(family, sotype | SOCK_NONBLOCK);
1623        if (p0 < 0)
1624                return;
1625        len = sizeof(addr);
1626        err = xgetsockname(p0, sockaddr(&addr), &len);
1627        if (err)
1628                goto close_peer0;
1629
1630        c0 = xsocket(family, sotype | SOCK_NONBLOCK, 0);
1631        if (c0 < 0)
1632                goto close_peer0;
1633        err = xconnect(c0, sockaddr(&addr), len);
1634        if (err)
1635                goto close_cli0;
1636        err = xgetsockname(c0, sockaddr(&addr), &len);
1637        if (err)
1638                goto close_cli0;
1639        err = xconnect(p0, sockaddr(&addr), len);
1640        if (err)
1641                goto close_cli0;
1642
1643        p1 = socket_loopback(family, sotype | SOCK_NONBLOCK);
1644        if (p1 < 0)
1645                goto close_cli0;
1646        err = xgetsockname(p1, sockaddr(&addr), &len);
1647        if (err)
1648                goto close_cli0;
1649
1650        c1 = xsocket(family, sotype | SOCK_NONBLOCK, 0);
1651        if (c1 < 0)
1652                goto close_peer1;
1653        err = xconnect(c1, sockaddr(&addr), len);
1654        if (err)
1655                goto close_cli1;
1656        err = xgetsockname(c1, sockaddr(&addr), &len);
1657        if (err)
1658                goto close_cli1;
1659        err = xconnect(p1, sockaddr(&addr), len);
1660        if (err)
1661                goto close_cli1;
1662
1663        key = 0;
1664        value = p0;
1665        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
1666        if (err)
1667                goto close_cli1;
1668
1669        key = 1;
1670        value = p1;
1671        err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
1672        if (err)
1673                goto close_cli1;
1674
1675        n = write(c1, "a", 1);
1676        if (n < 0)
1677                FAIL_ERRNO("%s: write", log_prefix);
1678        if (n == 0)
1679                FAIL("%s: incomplete write", log_prefix);
1680        if (n < 1)
1681                goto close_cli1;
1682
1683        key = SK_PASS;
1684        err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass);
1685        if (err)
1686                goto close_cli1;
1687        if (pass != 1)
1688                FAIL("%s: want pass count 1, have %d", log_prefix, pass);
1689
1690again:
1691        n = read(mode == REDIR_INGRESS ? p0 : c0, &b, 1);
1692        if (n < 0) {
1693                if (errno == EAGAIN && retries--)
1694                        goto again;
1695                FAIL_ERRNO("%s: read", log_prefix);
1696        }
1697        if (n == 0)
1698                FAIL("%s: incomplete read", log_prefix);
1699
1700close_cli1:
1701        xclose(c1);
1702close_peer1:
1703        xclose(p1);
1704close_cli0:
1705        xclose(c0);
1706close_peer0:
1707        xclose(p0);
1708}
1709
1710static void udp_skb_redir_to_connected(struct test_sockmap_listen *skel,
1711                                       struct bpf_map *inner_map, int family)
1712{
1713        int verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
1714        int verdict_map = bpf_map__fd(skel->maps.verdict_map);
1715        int sock_map = bpf_map__fd(inner_map);
1716        int err;
1717
1718        err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0);
1719        if (err)
1720                return;
1721
1722        skel->bss->test_ingress = false;
1723        udp_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map,
1724                               REDIR_EGRESS);
1725        skel->bss->test_ingress = true;
1726        udp_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map,
1727                               REDIR_INGRESS);
1728
1729        xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT);
1730}
1731
1732static void test_udp_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
1733                           int family)
1734{
1735        const char *family_name, *map_name;
1736        char s[MAX_TEST_NAME];
1737
1738        family_name = family_str(family);
1739        map_name = map_type_str(map);
1740        snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, __func__);
1741        if (!test__start_subtest(s))
1742                return;
1743        udp_skb_redir_to_connected(skel, map, family);
1744}
1745
1746static void run_tests(struct test_sockmap_listen *skel, struct bpf_map *map,
1747                      int family)
1748{
1749        test_ops(skel, map, family, SOCK_STREAM);
1750        test_ops(skel, map, family, SOCK_DGRAM);
1751        test_redir(skel, map, family, SOCK_STREAM);
1752        test_reuseport(skel, map, family, SOCK_STREAM);
1753        test_reuseport(skel, map, family, SOCK_DGRAM);
1754        test_udp_redir(skel, map, family);
1755}
1756
1757void test_sockmap_listen(void)
1758{
1759        struct test_sockmap_listen *skel;
1760
1761        skel = test_sockmap_listen__open_and_load();
1762        if (!skel) {
1763                FAIL("skeleton open/load failed");
1764                return;
1765        }
1766
1767        skel->bss->test_sockmap = true;
1768        run_tests(skel, skel->maps.sock_map, AF_INET);
1769        run_tests(skel, skel->maps.sock_map, AF_INET6);
1770
1771        skel->bss->test_sockmap = false;
1772        run_tests(skel, skel->maps.sock_hash, AF_INET);
1773        run_tests(skel, skel->maps.sock_hash, AF_INET6);
1774
1775        test_sockmap_listen__destroy(skel);
1776}
1777