xref: /OK3568_Linux_fs/kernel/include/linux/bpf_local_storage.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2019 Facebook
4*4882a593Smuzhiyun  * Copyright 2020 Google LLC.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #ifndef _BPF_LOCAL_STORAGE_H
8*4882a593Smuzhiyun #define _BPF_LOCAL_STORAGE_H
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/bpf.h>
11*4882a593Smuzhiyun #include <linux/rculist.h>
12*4882a593Smuzhiyun #include <linux/list.h>
13*4882a593Smuzhiyun #include <linux/hash.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun #include <uapi/linux/btf.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define BPF_LOCAL_STORAGE_CACHE_SIZE	16
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun struct bpf_local_storage_map_bucket {
20*4882a593Smuzhiyun 	struct hlist_head list;
21*4882a593Smuzhiyun 	raw_spinlock_t lock;
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /* Thp map is not the primary owner of a bpf_local_storage_elem.
25*4882a593Smuzhiyun  * Instead, the container object (eg. sk->sk_bpf_storage) is.
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  * The map (bpf_local_storage_map) is for two purposes
28*4882a593Smuzhiyun  * 1. Define the size of the "local storage".  It is
29*4882a593Smuzhiyun  *    the map's value_size.
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  * 2. Maintain a list to keep track of all elems such
32*4882a593Smuzhiyun  *    that they can be cleaned up during the map destruction.
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  * When a bpf local storage is being looked up for a
35*4882a593Smuzhiyun  * particular object,  the "bpf_map" pointer is actually used
36*4882a593Smuzhiyun  * as the "key" to search in the list of elem in
37*4882a593Smuzhiyun  * the respective bpf_local_storage owned by the object.
38*4882a593Smuzhiyun  *
39*4882a593Smuzhiyun  * e.g. sk->sk_bpf_storage is the mini-map with the "bpf_map" pointer
40*4882a593Smuzhiyun  * as the searching key.
41*4882a593Smuzhiyun  */
42*4882a593Smuzhiyun struct bpf_local_storage_map {
43*4882a593Smuzhiyun 	struct bpf_map map;
44*4882a593Smuzhiyun 	/* Lookup elem does not require accessing the map.
45*4882a593Smuzhiyun 	 *
46*4882a593Smuzhiyun 	 * Updating/Deleting requires a bucket lock to
47*4882a593Smuzhiyun 	 * link/unlink the elem from the map.  Having
48*4882a593Smuzhiyun 	 * multiple buckets to improve contention.
49*4882a593Smuzhiyun 	 */
50*4882a593Smuzhiyun 	struct bpf_local_storage_map_bucket *buckets;
51*4882a593Smuzhiyun 	u32 bucket_log;
52*4882a593Smuzhiyun 	u16 elem_size;
53*4882a593Smuzhiyun 	u16 cache_idx;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun struct bpf_local_storage_data {
57*4882a593Smuzhiyun 	/* smap is used as the searching key when looking up
58*4882a593Smuzhiyun 	 * from the object's bpf_local_storage.
59*4882a593Smuzhiyun 	 *
60*4882a593Smuzhiyun 	 * Put it in the same cacheline as the data to minimize
61*4882a593Smuzhiyun 	 * the number of cachelines access during the cache hit case.
62*4882a593Smuzhiyun 	 */
63*4882a593Smuzhiyun 	struct bpf_local_storage_map __rcu *smap;
64*4882a593Smuzhiyun 	u8 data[] __aligned(8);
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /* Linked to bpf_local_storage and bpf_local_storage_map */
68*4882a593Smuzhiyun struct bpf_local_storage_elem {
69*4882a593Smuzhiyun 	struct hlist_node map_node;	/* Linked to bpf_local_storage_map */
70*4882a593Smuzhiyun 	struct hlist_node snode;	/* Linked to bpf_local_storage */
71*4882a593Smuzhiyun 	struct bpf_local_storage __rcu *local_storage;
72*4882a593Smuzhiyun 	struct rcu_head rcu;
73*4882a593Smuzhiyun 	/* 8 bytes hole */
74*4882a593Smuzhiyun 	/* The data is stored in aother cacheline to minimize
75*4882a593Smuzhiyun 	 * the number of cachelines access during a cache hit.
76*4882a593Smuzhiyun 	 */
77*4882a593Smuzhiyun 	struct bpf_local_storage_data sdata ____cacheline_aligned;
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun struct bpf_local_storage {
81*4882a593Smuzhiyun 	struct bpf_local_storage_data __rcu *cache[BPF_LOCAL_STORAGE_CACHE_SIZE];
82*4882a593Smuzhiyun 	struct hlist_head list; /* List of bpf_local_storage_elem */
83*4882a593Smuzhiyun 	void *owner;		/* The object that owns the above "list" of
84*4882a593Smuzhiyun 				 * bpf_local_storage_elem.
85*4882a593Smuzhiyun 				 */
86*4882a593Smuzhiyun 	struct rcu_head rcu;
87*4882a593Smuzhiyun 	raw_spinlock_t lock;	/* Protect adding/removing from the "list" */
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /* U16_MAX is much more than enough for sk local storage
91*4882a593Smuzhiyun  * considering a tcp_sock is ~2k.
92*4882a593Smuzhiyun  */
93*4882a593Smuzhiyun #define BPF_LOCAL_STORAGE_MAX_VALUE_SIZE				       \
94*4882a593Smuzhiyun 	min_t(u32,                                                             \
95*4882a593Smuzhiyun 	      (KMALLOC_MAX_SIZE - MAX_BPF_STACK -                              \
96*4882a593Smuzhiyun 	       sizeof(struct bpf_local_storage_elem)),                         \
97*4882a593Smuzhiyun 	      (U16_MAX - sizeof(struct bpf_local_storage_elem)))
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #define SELEM(_SDATA)                                                          \
100*4882a593Smuzhiyun 	container_of((_SDATA), struct bpf_local_storage_elem, sdata)
101*4882a593Smuzhiyun #define SDATA(_SELEM) (&(_SELEM)->sdata)
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #define BPF_LOCAL_STORAGE_CACHE_SIZE	16
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun struct bpf_local_storage_cache {
106*4882a593Smuzhiyun 	spinlock_t idx_lock;
107*4882a593Smuzhiyun 	u64 idx_usage_counts[BPF_LOCAL_STORAGE_CACHE_SIZE];
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun #define DEFINE_BPF_STORAGE_CACHE(name)				\
111*4882a593Smuzhiyun static struct bpf_local_storage_cache name = {			\
112*4882a593Smuzhiyun 	.idx_lock = __SPIN_LOCK_UNLOCKED(name.idx_lock),	\
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun u16 bpf_local_storage_cache_idx_get(struct bpf_local_storage_cache *cache);
116*4882a593Smuzhiyun void bpf_local_storage_cache_idx_free(struct bpf_local_storage_cache *cache,
117*4882a593Smuzhiyun 				      u16 idx);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* Helper functions for bpf_local_storage */
120*4882a593Smuzhiyun int bpf_local_storage_map_alloc_check(union bpf_attr *attr);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun struct bpf_local_storage_map *bpf_local_storage_map_alloc(union bpf_attr *attr);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun struct bpf_local_storage_data *
125*4882a593Smuzhiyun bpf_local_storage_lookup(struct bpf_local_storage *local_storage,
126*4882a593Smuzhiyun 			 struct bpf_local_storage_map *smap,
127*4882a593Smuzhiyun 			 bool cacheit_lockit);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun void bpf_local_storage_map_free(struct bpf_local_storage_map *smap);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun int bpf_local_storage_map_check_btf(const struct bpf_map *map,
132*4882a593Smuzhiyun 				    const struct btf *btf,
133*4882a593Smuzhiyun 				    const struct btf_type *key_type,
134*4882a593Smuzhiyun 				    const struct btf_type *value_type);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
137*4882a593Smuzhiyun 				   struct bpf_local_storage_elem *selem);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun bool bpf_selem_unlink_storage_nolock(struct bpf_local_storage *local_storage,
140*4882a593Smuzhiyun 				     struct bpf_local_storage_elem *selem,
141*4882a593Smuzhiyun 				     bool uncharge_omem);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun void bpf_selem_unlink(struct bpf_local_storage_elem *selem);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun void bpf_selem_link_map(struct bpf_local_storage_map *smap,
146*4882a593Smuzhiyun 			struct bpf_local_storage_elem *selem);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun void bpf_selem_unlink_map(struct bpf_local_storage_elem *selem);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun struct bpf_local_storage_elem *
151*4882a593Smuzhiyun bpf_selem_alloc(struct bpf_local_storage_map *smap, void *owner, void *value,
152*4882a593Smuzhiyun 		bool charge_mem);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun int
155*4882a593Smuzhiyun bpf_local_storage_alloc(void *owner,
156*4882a593Smuzhiyun 			struct bpf_local_storage_map *smap,
157*4882a593Smuzhiyun 			struct bpf_local_storage_elem *first_selem);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun struct bpf_local_storage_data *
160*4882a593Smuzhiyun bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap,
161*4882a593Smuzhiyun 			 void *value, u64 map_flags);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun #endif /* _BPF_LOCAL_STORAGE_H */
164