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