linux/samples/bpf/test_map_in_map_user.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2017 Facebook
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of version 2 of the GNU General Public
   6 * License as published by the Free Software Foundation.
   7 */
   8#include <sys/resource.h>
   9#include <sys/socket.h>
  10#include <arpa/inet.h>
  11#include <stdint.h>
  12#include <assert.h>
  13#include <errno.h>
  14#include <stdlib.h>
  15#include <stdio.h>
  16#include "libbpf.h"
  17#include "bpf_load.h"
  18
  19#define PORT_A          (map_fd[0])
  20#define PORT_H          (map_fd[1])
  21#define REG_RESULT_H    (map_fd[2])
  22#define INLINE_RESULT_H (map_fd[3])
  23#define A_OF_PORT_A     (map_fd[4]) /* Test case #0 */
  24#define H_OF_PORT_A     (map_fd[5]) /* Test case #1 */
  25#define H_OF_PORT_H     (map_fd[6]) /* Test case #2 */
  26
  27static const char * const test_names[] = {
  28        "Array of Array",
  29        "Hash of Array",
  30        "Hash of Hash",
  31};
  32
  33#define NR_TESTS (sizeof(test_names) / sizeof(*test_names))
  34
  35static void check_map_id(int inner_map_fd, int map_in_map_fd, uint32_t key)
  36{
  37        struct bpf_map_info info = {};
  38        uint32_t info_len = sizeof(info);
  39        int ret, id;
  40
  41        ret = bpf_obj_get_info_by_fd(inner_map_fd, &info, &info_len);
  42        assert(!ret);
  43
  44        ret = bpf_map_lookup_elem(map_in_map_fd, &key, &id);
  45        assert(!ret);
  46        assert(id == info.id);
  47}
  48
  49static void populate_map(uint32_t port_key, int magic_result)
  50{
  51        int ret;
  52
  53        ret = bpf_map_update_elem(PORT_A, &port_key, &magic_result, BPF_ANY);
  54        assert(!ret);
  55
  56        ret = bpf_map_update_elem(PORT_H, &port_key, &magic_result,
  57                                  BPF_NOEXIST);
  58        assert(!ret);
  59
  60        ret = bpf_map_update_elem(A_OF_PORT_A, &port_key, &PORT_A, BPF_ANY);
  61        assert(!ret);
  62        check_map_id(PORT_A, A_OF_PORT_A, port_key);
  63
  64        ret = bpf_map_update_elem(H_OF_PORT_A, &port_key, &PORT_A, BPF_NOEXIST);
  65        assert(!ret);
  66        check_map_id(PORT_A, H_OF_PORT_A, port_key);
  67
  68        ret = bpf_map_update_elem(H_OF_PORT_H, &port_key, &PORT_H, BPF_NOEXIST);
  69        assert(!ret);
  70        check_map_id(PORT_H, H_OF_PORT_H, port_key);
  71}
  72
  73static void test_map_in_map(void)
  74{
  75        struct sockaddr_in6 in6 = { .sin6_family = AF_INET6 };
  76        uint32_t result_key = 0, port_key;
  77        int result, inline_result;
  78        int magic_result = 0xfaceb00c;
  79        int ret;
  80        int i;
  81
  82        port_key = rand() & 0x00FF;
  83        populate_map(port_key, magic_result);
  84
  85        in6.sin6_addr.s6_addr16[0] = 0xdead;
  86        in6.sin6_addr.s6_addr16[1] = 0xbeef;
  87        in6.sin6_port = port_key;
  88
  89        for (i = 0; i < NR_TESTS; i++) {
  90                printf("%s: ", test_names[i]);
  91
  92                in6.sin6_addr.s6_addr16[7] = i;
  93                ret = connect(-1, (struct sockaddr *)&in6, sizeof(in6));
  94                assert(ret == -1 && errno == EBADF);
  95
  96                ret = bpf_map_lookup_elem(REG_RESULT_H, &result_key, &result);
  97                assert(!ret);
  98
  99                ret = bpf_map_lookup_elem(INLINE_RESULT_H, &result_key,
 100                                          &inline_result);
 101                assert(!ret);
 102
 103                if (result != magic_result || inline_result != magic_result) {
 104                        printf("Error. result:%d inline_result:%d\n",
 105                               result, inline_result);
 106                        exit(1);
 107                }
 108
 109                bpf_map_delete_elem(REG_RESULT_H, &result_key);
 110                bpf_map_delete_elem(INLINE_RESULT_H, &result_key);
 111
 112                printf("Pass\n");
 113        }
 114}
 115
 116int main(int argc, char **argv)
 117{
 118        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
 119        char filename[256];
 120
 121        assert(!setrlimit(RLIMIT_MEMLOCK, &r));
 122
 123        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 124
 125        if (load_bpf_file(filename)) {
 126                printf("%s", bpf_log_buf);
 127                return 1;
 128        }
 129
 130        test_map_in_map();
 131
 132        return 0;
 133}
 134