linux/tools/testing/selftests/bpf/progs/test_btf_map_in_map.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/* Copyright (c) 2020 Facebook */
   3#include <linux/bpf.h>
   4#include <bpf/bpf_helpers.h>
   5
   6struct inner_map {
   7        __uint(type, BPF_MAP_TYPE_ARRAY);
   8        __uint(max_entries, 1);
   9        __type(key, int);
  10        __type(value, int);
  11} inner_map1 SEC(".maps"),
  12  inner_map2 SEC(".maps");
  13
  14struct inner_map_sz2 {
  15        __uint(type, BPF_MAP_TYPE_ARRAY);
  16        __uint(max_entries, 2);
  17        __type(key, int);
  18        __type(value, int);
  19} inner_map_sz2 SEC(".maps");
  20
  21struct outer_arr {
  22        __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
  23        __uint(max_entries, 3);
  24        __uint(key_size, sizeof(int));
  25        __uint(value_size, sizeof(int));
  26        /* it's possible to use anonymous struct as inner map definition here */
  27        __array(values, struct {
  28                __uint(type, BPF_MAP_TYPE_ARRAY);
  29                /* changing max_entries to 2 will fail during load
  30                 * due to incompatibility with inner_map definition */
  31                __uint(max_entries, 1);
  32                __type(key, int);
  33                __type(value, int);
  34        });
  35} outer_arr SEC(".maps") = {
  36        /* (void *) cast is necessary because we didn't use `struct inner_map`
  37         * in __inner(values, ...)
  38         * Actually, a conscious effort is required to screw up initialization
  39         * of inner map slots, which is a great thing!
  40         */
  41        .values = { (void *)&inner_map1, 0, (void *)&inner_map2 },
  42};
  43
  44struct inner_map_sz3 {
  45        __uint(type, BPF_MAP_TYPE_ARRAY);
  46        __uint(map_flags, BPF_F_INNER_MAP);
  47        __uint(max_entries, 3);
  48        __type(key, int);
  49        __type(value, int);
  50} inner_map3 SEC(".maps"),
  51  inner_map4 SEC(".maps");
  52
  53struct inner_map_sz4 {
  54        __uint(type, BPF_MAP_TYPE_ARRAY);
  55        __uint(map_flags, BPF_F_INNER_MAP);
  56        __uint(max_entries, 5);
  57        __type(key, int);
  58        __type(value, int);
  59} inner_map5 SEC(".maps");
  60
  61struct outer_arr_dyn {
  62        __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
  63        __uint(max_entries, 3);
  64        __uint(key_size, sizeof(int));
  65        __uint(value_size, sizeof(int));
  66        __array(values, struct {
  67                __uint(type, BPF_MAP_TYPE_ARRAY);
  68                __uint(map_flags, BPF_F_INNER_MAP);
  69                __uint(max_entries, 1);
  70                __type(key, int);
  71                __type(value, int);
  72        });
  73} outer_arr_dyn SEC(".maps") = {
  74        .values = {
  75                [0] = (void *)&inner_map3,
  76                [1] = (void *)&inner_map4,
  77                [2] = (void *)&inner_map5,
  78        },
  79};
  80
  81struct outer_hash {
  82        __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
  83        __uint(max_entries, 5);
  84        __uint(key_size, sizeof(int));
  85        /* Here everything works flawlessly due to reuse of struct inner_map
  86         * and compiler will complain at the attempt to use non-inner_map
  87         * references below. This is great experience.
  88         */
  89        __array(values, struct inner_map);
  90} outer_hash SEC(".maps") = {
  91        .values = {
  92                [0] = &inner_map2,
  93                [4] = &inner_map1,
  94        },
  95};
  96
  97struct sockarr_sz1 {
  98        __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
  99        __uint(max_entries, 1);
 100        __type(key, int);
 101        __type(value, int);
 102} sockarr_sz1 SEC(".maps");
 103
 104struct sockarr_sz2 {
 105        __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
 106        __uint(max_entries, 2);
 107        __type(key, int);
 108        __type(value, int);
 109} sockarr_sz2 SEC(".maps");
 110
 111struct outer_sockarr_sz1 {
 112        __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
 113        __uint(max_entries, 1);
 114        __uint(key_size, sizeof(int));
 115        __uint(value_size, sizeof(int));
 116        __array(values, struct sockarr_sz1);
 117} outer_sockarr SEC(".maps") = {
 118        .values = { (void *)&sockarr_sz1 },
 119};
 120
 121int input = 0;
 122
 123SEC("raw_tp/sys_enter")
 124int handle__sys_enter(void *ctx)
 125{
 126        struct inner_map *inner_map;
 127        int key = 0, val;
 128
 129        inner_map = bpf_map_lookup_elem(&outer_arr, &key);
 130        if (!inner_map)
 131                return 1;
 132        val = input;
 133        bpf_map_update_elem(inner_map, &key, &val, 0);
 134
 135        inner_map = bpf_map_lookup_elem(&outer_hash, &key);
 136        if (!inner_map)
 137                return 1;
 138        val = input + 1;
 139        bpf_map_update_elem(inner_map, &key, &val, 0);
 140
 141        inner_map = bpf_map_lookup_elem(&outer_arr_dyn, &key);
 142        if (!inner_map)
 143                return 1;
 144        val = input + 2;
 145        bpf_map_update_elem(inner_map, &key, &val, 0);
 146
 147        return 0;
 148}
 149
 150char _license[] SEC("license") = "GPL";
 151