1646f02ffSAndrii Nakryiko /* SPDX-License-Identifier: GPL-2.0 */
2646f02ffSAndrii Nakryiko /* Copyright (c) 2020 Facebook */
3646f02ffSAndrii Nakryiko #include <linux/bpf.h>
4646f02ffSAndrii Nakryiko #include <bpf/bpf_helpers.h>
5646f02ffSAndrii Nakryiko
6646f02ffSAndrii Nakryiko struct inner_map {
7646f02ffSAndrii Nakryiko __uint(type, BPF_MAP_TYPE_ARRAY);
8646f02ffSAndrii Nakryiko __uint(max_entries, 1);
9646f02ffSAndrii Nakryiko __type(key, int);
10646f02ffSAndrii Nakryiko __type(value, int);
11646f02ffSAndrii Nakryiko } inner_map1 SEC(".maps"),
12646f02ffSAndrii Nakryiko inner_map2 SEC(".maps");
13646f02ffSAndrii Nakryiko
14d557ea39SMartin KaFai Lau struct inner_map_sz2 {
15d557ea39SMartin KaFai Lau __uint(type, BPF_MAP_TYPE_ARRAY);
16d557ea39SMartin KaFai Lau __uint(max_entries, 2);
17d557ea39SMartin KaFai Lau __type(key, int);
18d557ea39SMartin KaFai Lau __type(value, int);
19d557ea39SMartin KaFai Lau } inner_map_sz2 SEC(".maps");
20d557ea39SMartin KaFai Lau
21646f02ffSAndrii Nakryiko struct outer_arr {
22646f02ffSAndrii Nakryiko __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
23646f02ffSAndrii Nakryiko __uint(max_entries, 3);
24*bd368cb5SHengqi Chen __type(key, int);
25*bd368cb5SHengqi Chen __type(value, int);
26646f02ffSAndrii Nakryiko /* it's possible to use anonymous struct as inner map definition here */
27646f02ffSAndrii Nakryiko __array(values, struct {
28646f02ffSAndrii Nakryiko __uint(type, BPF_MAP_TYPE_ARRAY);
29646f02ffSAndrii Nakryiko /* changing max_entries to 2 will fail during load
30646f02ffSAndrii Nakryiko * due to incompatibility with inner_map definition */
31646f02ffSAndrii Nakryiko __uint(max_entries, 1);
32646f02ffSAndrii Nakryiko __type(key, int);
33646f02ffSAndrii Nakryiko __type(value, int);
34646f02ffSAndrii Nakryiko });
35646f02ffSAndrii Nakryiko } outer_arr SEC(".maps") = {
36646f02ffSAndrii Nakryiko /* (void *) cast is necessary because we didn't use `struct inner_map`
37646f02ffSAndrii Nakryiko * in __inner(values, ...)
38646f02ffSAndrii Nakryiko * Actually, a conscious effort is required to screw up initialization
39646f02ffSAndrii Nakryiko * of inner map slots, which is a great thing!
40646f02ffSAndrii Nakryiko */
41646f02ffSAndrii Nakryiko .values = { (void *)&inner_map1, 0, (void *)&inner_map2 },
42646f02ffSAndrii Nakryiko };
43646f02ffSAndrii Nakryiko
446775dab7SDaniel Borkmann struct inner_map_sz3 {
456775dab7SDaniel Borkmann __uint(type, BPF_MAP_TYPE_ARRAY);
466775dab7SDaniel Borkmann __uint(map_flags, BPF_F_INNER_MAP);
476775dab7SDaniel Borkmann __uint(max_entries, 3);
486775dab7SDaniel Borkmann __type(key, int);
496775dab7SDaniel Borkmann __type(value, int);
506775dab7SDaniel Borkmann } inner_map3 SEC(".maps"),
516775dab7SDaniel Borkmann inner_map4 SEC(".maps");
526775dab7SDaniel Borkmann
536775dab7SDaniel Borkmann struct inner_map_sz4 {
546775dab7SDaniel Borkmann __uint(type, BPF_MAP_TYPE_ARRAY);
556775dab7SDaniel Borkmann __uint(map_flags, BPF_F_INNER_MAP);
566775dab7SDaniel Borkmann __uint(max_entries, 5);
576775dab7SDaniel Borkmann __type(key, int);
586775dab7SDaniel Borkmann __type(value, int);
596775dab7SDaniel Borkmann } inner_map5 SEC(".maps");
606775dab7SDaniel Borkmann
616775dab7SDaniel Borkmann struct outer_arr_dyn {
626775dab7SDaniel Borkmann __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
636775dab7SDaniel Borkmann __uint(max_entries, 3);
64*bd368cb5SHengqi Chen __type(key, int);
65*bd368cb5SHengqi Chen __type(value, int);
666775dab7SDaniel Borkmann __array(values, struct {
676775dab7SDaniel Borkmann __uint(type, BPF_MAP_TYPE_ARRAY);
686775dab7SDaniel Borkmann __uint(map_flags, BPF_F_INNER_MAP);
696775dab7SDaniel Borkmann __uint(max_entries, 1);
706775dab7SDaniel Borkmann __type(key, int);
716775dab7SDaniel Borkmann __type(value, int);
726775dab7SDaniel Borkmann });
736775dab7SDaniel Borkmann } outer_arr_dyn SEC(".maps") = {
746775dab7SDaniel Borkmann .values = {
756775dab7SDaniel Borkmann [0] = (void *)&inner_map3,
766775dab7SDaniel Borkmann [1] = (void *)&inner_map4,
776775dab7SDaniel Borkmann [2] = (void *)&inner_map5,
786775dab7SDaniel Borkmann },
796775dab7SDaniel Borkmann };
806775dab7SDaniel Borkmann
81646f02ffSAndrii Nakryiko struct outer_hash {
82646f02ffSAndrii Nakryiko __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
83646f02ffSAndrii Nakryiko __uint(max_entries, 5);
84*bd368cb5SHengqi Chen __type(key, int);
85646f02ffSAndrii Nakryiko /* Here everything works flawlessly due to reuse of struct inner_map
86646f02ffSAndrii Nakryiko * and compiler will complain at the attempt to use non-inner_map
87646f02ffSAndrii Nakryiko * references below. This is great experience.
88646f02ffSAndrii Nakryiko */
89646f02ffSAndrii Nakryiko __array(values, struct inner_map);
90646f02ffSAndrii Nakryiko } outer_hash SEC(".maps") = {
91646f02ffSAndrii Nakryiko .values = {
92646f02ffSAndrii Nakryiko [0] = &inner_map2,
93646f02ffSAndrii Nakryiko [4] = &inner_map1,
94646f02ffSAndrii Nakryiko },
95646f02ffSAndrii Nakryiko };
96646f02ffSAndrii Nakryiko
97d557ea39SMartin KaFai Lau struct sockarr_sz1 {
98d557ea39SMartin KaFai Lau __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
99d557ea39SMartin KaFai Lau __uint(max_entries, 1);
100d557ea39SMartin KaFai Lau __type(key, int);
101d557ea39SMartin KaFai Lau __type(value, int);
102d557ea39SMartin KaFai Lau } sockarr_sz1 SEC(".maps");
103d557ea39SMartin KaFai Lau
104d557ea39SMartin KaFai Lau struct sockarr_sz2 {
105d557ea39SMartin KaFai Lau __uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
106d557ea39SMartin KaFai Lau __uint(max_entries, 2);
107d557ea39SMartin KaFai Lau __type(key, int);
108d557ea39SMartin KaFai Lau __type(value, int);
109d557ea39SMartin KaFai Lau } sockarr_sz2 SEC(".maps");
110d557ea39SMartin KaFai Lau
111d557ea39SMartin KaFai Lau struct outer_sockarr_sz1 {
112d557ea39SMartin KaFai Lau __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
113d557ea39SMartin KaFai Lau __uint(max_entries, 1);
114*bd368cb5SHengqi Chen __type(key, int);
115*bd368cb5SHengqi Chen __type(value, int);
116d557ea39SMartin KaFai Lau __array(values, struct sockarr_sz1);
117d557ea39SMartin KaFai Lau } outer_sockarr SEC(".maps") = {
118d557ea39SMartin KaFai Lau .values = { (void *)&sockarr_sz1 },
119d557ea39SMartin KaFai Lau };
120d557ea39SMartin KaFai Lau
121646f02ffSAndrii Nakryiko int input = 0;
122646f02ffSAndrii Nakryiko
123646f02ffSAndrii Nakryiko SEC("raw_tp/sys_enter")
handle__sys_enter(void * ctx)124646f02ffSAndrii Nakryiko int handle__sys_enter(void *ctx)
125646f02ffSAndrii Nakryiko {
126646f02ffSAndrii Nakryiko struct inner_map *inner_map;
127646f02ffSAndrii Nakryiko int key = 0, val;
128646f02ffSAndrii Nakryiko
129646f02ffSAndrii Nakryiko inner_map = bpf_map_lookup_elem(&outer_arr, &key);
130646f02ffSAndrii Nakryiko if (!inner_map)
131646f02ffSAndrii Nakryiko return 1;
132646f02ffSAndrii Nakryiko val = input;
133646f02ffSAndrii Nakryiko bpf_map_update_elem(inner_map, &key, &val, 0);
134646f02ffSAndrii Nakryiko
135646f02ffSAndrii Nakryiko inner_map = bpf_map_lookup_elem(&outer_hash, &key);
136646f02ffSAndrii Nakryiko if (!inner_map)
137646f02ffSAndrii Nakryiko return 1;
138646f02ffSAndrii Nakryiko val = input + 1;
139646f02ffSAndrii Nakryiko bpf_map_update_elem(inner_map, &key, &val, 0);
140646f02ffSAndrii Nakryiko
1416775dab7SDaniel Borkmann inner_map = bpf_map_lookup_elem(&outer_arr_dyn, &key);
1426775dab7SDaniel Borkmann if (!inner_map)
1436775dab7SDaniel Borkmann return 1;
1446775dab7SDaniel Borkmann val = input + 2;
1456775dab7SDaniel Borkmann bpf_map_update_elem(inner_map, &key, &val, 0);
1466775dab7SDaniel Borkmann
147646f02ffSAndrii Nakryiko return 0;
148646f02ffSAndrii Nakryiko }
149646f02ffSAndrii Nakryiko
150646f02ffSAndrii Nakryiko char _license[] SEC("license") = "GPL";
151