linux/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2018 Facebook
   3
   4#include <stdlib.h>
   5#include <string.h>
   6#include <unistd.h>
   7
   8#include <arpa/inet.h>
   9#include <net/if.h>
  10#include <netinet/in.h>
  11#include <sys/socket.h>
  12#include <sys/types.h>
  13
  14
  15#include <bpf/bpf.h>
  16#include <bpf/libbpf.h>
  17
  18#include "bpf_rlimit.h"
  19#include "cgroup_helpers.h"
  20
  21#define CGROUP_PATH             "/skb_cgroup_test"
  22#define NUM_CGROUP_LEVELS       4
  23
  24/* RFC 4291, Section 2.7.1 */
  25#define LINKLOCAL_MULTICAST     "ff02::1"
  26
  27static int mk_dst_addr(const char *ip, const char *iface,
  28                       struct sockaddr_in6 *dst)
  29{
  30        memset(dst, 0, sizeof(*dst));
  31
  32        dst->sin6_family = AF_INET6;
  33        dst->sin6_port = htons(1025);
  34
  35        if (inet_pton(AF_INET6, ip, &dst->sin6_addr) != 1) {
  36                log_err("Invalid IPv6: %s", ip);
  37                return -1;
  38        }
  39
  40        dst->sin6_scope_id = if_nametoindex(iface);
  41        if (!dst->sin6_scope_id) {
  42                log_err("Failed to get index of iface: %s", iface);
  43                return -1;
  44        }
  45
  46        return 0;
  47}
  48
  49static int send_packet(const char *iface)
  50{
  51        struct sockaddr_in6 dst;
  52        char msg[] = "msg";
  53        int err = 0;
  54        int fd = -1;
  55
  56        if (mk_dst_addr(LINKLOCAL_MULTICAST, iface, &dst))
  57                goto err;
  58
  59        fd = socket(AF_INET6, SOCK_DGRAM, 0);
  60        if (fd == -1) {
  61                log_err("Failed to create UDP socket");
  62                goto err;
  63        }
  64
  65        if (sendto(fd, &msg, sizeof(msg), 0, (const struct sockaddr *)&dst,
  66                   sizeof(dst)) == -1) {
  67                log_err("Failed to send datagram");
  68                goto err;
  69        }
  70
  71        goto out;
  72err:
  73        err = -1;
  74out:
  75        if (fd >= 0)
  76                close(fd);
  77        return err;
  78}
  79
  80int get_map_fd_by_prog_id(int prog_id)
  81{
  82        struct bpf_prog_info info = {};
  83        __u32 info_len = sizeof(info);
  84        __u32 map_ids[1];
  85        int prog_fd = -1;
  86        int map_fd = -1;
  87
  88        prog_fd = bpf_prog_get_fd_by_id(prog_id);
  89        if (prog_fd < 0) {
  90                log_err("Failed to get fd by prog id %d", prog_id);
  91                goto err;
  92        }
  93
  94        info.nr_map_ids = 1;
  95        info.map_ids = (__u64) (unsigned long) map_ids;
  96
  97        if (bpf_obj_get_info_by_fd(prog_fd, &info, &info_len)) {
  98                log_err("Failed to get info by prog fd %d", prog_fd);
  99                goto err;
 100        }
 101
 102        if (!info.nr_map_ids) {
 103                log_err("No maps found for prog fd %d", prog_fd);
 104                goto err;
 105        }
 106
 107        map_fd = bpf_map_get_fd_by_id(map_ids[0]);
 108        if (map_fd < 0)
 109                log_err("Failed to get fd by map id %d", map_ids[0]);
 110err:
 111        if (prog_fd >= 0)
 112                close(prog_fd);
 113        return map_fd;
 114}
 115
 116int check_ancestor_cgroup_ids(int prog_id)
 117{
 118        __u64 actual_ids[NUM_CGROUP_LEVELS], expected_ids[NUM_CGROUP_LEVELS];
 119        __u32 level;
 120        int err = 0;
 121        int map_fd;
 122
 123        expected_ids[0] = get_cgroup_id("/.."); /* root cgroup */
 124        expected_ids[1] = get_cgroup_id("");
 125        expected_ids[2] = get_cgroup_id(CGROUP_PATH);
 126        expected_ids[3] = 0; /* non-existent cgroup */
 127
 128        map_fd = get_map_fd_by_prog_id(prog_id);
 129        if (map_fd < 0)
 130                goto err;
 131
 132        for (level = 0; level < NUM_CGROUP_LEVELS; ++level) {
 133                if (bpf_map_lookup_elem(map_fd, &level, &actual_ids[level])) {
 134                        log_err("Failed to lookup key %d", level);
 135                        goto err;
 136                }
 137                if (actual_ids[level] != expected_ids[level]) {
 138                        log_err("%llx (actual) != %llx (expected), level: %u\n",
 139                                actual_ids[level], expected_ids[level], level);
 140                        goto err;
 141                }
 142        }
 143
 144        goto out;
 145err:
 146        err = -1;
 147out:
 148        if (map_fd >= 0)
 149                close(map_fd);
 150        return err;
 151}
 152
 153int main(int argc, char **argv)
 154{
 155        int cgfd = -1;
 156        int err = 0;
 157
 158        if (argc < 3) {
 159                fprintf(stderr, "Usage: %s iface prog_id\n", argv[0]);
 160                exit(EXIT_FAILURE);
 161        }
 162
 163        cgfd = cgroup_setup_and_join(CGROUP_PATH);
 164        if (cgfd < 0)
 165                goto err;
 166
 167        if (send_packet(argv[1]))
 168                goto err;
 169
 170        if (check_ancestor_cgroup_ids(atoi(argv[2])))
 171                goto err;
 172
 173        goto out;
 174err:
 175        err = -1;
 176out:
 177        close(cgfd);
 178        cleanup_cgroup_environment();
 179        printf("[%s]\n", err ? "FAIL" : "PASS");
 180        return err;
 181}
 182