Skip to content

Commit e6a4750

Browse files
Björn Töpelborkmann
authored andcommitted
bpf, xdp: Make bpf_redirect_map() a map operation
Currently the bpf_redirect_map() implementation dispatches to the correct map-lookup function via a switch-statement. To avoid the dispatching, this change adds bpf_redirect_map() as a map operation. Each map provides its bpf_redirect_map() version, and correct function is automatically selected by the BPF verifier. A nice side-effect of the code movement is that the map lookup functions are now local to the map implementation files, which removes one additional function call. Signed-off-by: Björn Töpel <bjorn.topel@intel.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Jesper Dangaard Brouer <brouer@redhat.com> Acked-by: Toke Høiland-Jørgensen <toke@redhat.com> Link: https://lore.kernel.org/bpf/20210308112907.559576-2-bjorn.topel@gmail.com
1 parent 11d39cf commit e6a4750

File tree

8 files changed

+82
-82
lines changed

8 files changed

+82
-82
lines changed

include/linux/bpf.h

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ struct bpf_map_ops {
118118
void *owner, u32 size);
119119
struct bpf_local_storage __rcu ** (*map_owner_storage_ptr)(void *owner);
120120

121+
/* Misc helpers.*/
122+
int (*map_redirect)(struct bpf_map *map, u32 ifindex, u64 flags);
123+
121124
/* map_meta_equal must be implemented for maps that can be
122125
* used as an inner map. It is a runtime check to ensure
123126
* an inner map can be inserted to an outer map.
@@ -1450,9 +1453,9 @@ struct btf *bpf_get_btf_vmlinux(void);
14501453
/* Map specifics */
14511454
struct xdp_buff;
14521455
struct sk_buff;
1456+
struct bpf_dtab_netdev;
1457+
struct bpf_cpu_map_entry;
14531458

1454-
struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key);
1455-
struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key);
14561459
void __dev_flush(void);
14571460
int dev_xdp_enqueue(struct net_device *dev, struct xdp_buff *xdp,
14581461
struct net_device *dev_rx);
@@ -1462,7 +1465,6 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
14621465
struct bpf_prog *xdp_prog);
14631466
bool dev_map_can_have_prog(struct bpf_map *map);
14641467

1465-
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key);
14661468
void __cpu_map_flush(void);
14671469
int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_buff *xdp,
14681470
struct net_device *dev_rx);
@@ -1593,17 +1595,6 @@ static inline int bpf_obj_get_user(const char __user *pathname, int flags)
15931595
return -EOPNOTSUPP;
15941596
}
15951597

1596-
static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map,
1597-
u32 key)
1598-
{
1599-
return NULL;
1600-
}
1601-
1602-
static inline struct net_device *__dev_map_hash_lookup_elem(struct bpf_map *map,
1603-
u32 key)
1604-
{
1605-
return NULL;
1606-
}
16071598
static inline bool dev_map_can_have_prog(struct bpf_map *map)
16081599
{
16091600
return false;
@@ -1615,6 +1606,7 @@ static inline void __dev_flush(void)
16151606

16161607
struct xdp_buff;
16171608
struct bpf_dtab_netdev;
1609+
struct bpf_cpu_map_entry;
16181610

16191611
static inline
16201612
int dev_xdp_enqueue(struct net_device *dev, struct xdp_buff *xdp,
@@ -1639,12 +1631,6 @@ static inline int dev_map_generic_redirect(struct bpf_dtab_netdev *dst,
16391631
return 0;
16401632
}
16411633

1642-
static inline
1643-
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
1644-
{
1645-
return NULL;
1646-
}
1647-
16481634
static inline void __cpu_map_flush(void)
16491635
{
16501636
}

include/linux/filter.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,4 +1472,31 @@ static inline bool bpf_sk_lookup_run_v6(struct net *net, int protocol,
14721472
}
14731473
#endif /* IS_ENABLED(CONFIG_IPV6) */
14741474

1475+
static __always_inline int __bpf_xdp_redirect_map(struct bpf_map *map, u32 ifindex, u64 flags,
1476+
void *lookup_elem(struct bpf_map *map, u32 key))
1477+
{
1478+
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
1479+
1480+
/* Lower bits of the flags are used as return code on lookup failure */
1481+
if (unlikely(flags > XDP_TX))
1482+
return XDP_ABORTED;
1483+
1484+
ri->tgt_value = lookup_elem(map, ifindex);
1485+
if (unlikely(!ri->tgt_value)) {
1486+
/* If the lookup fails we want to clear out the state in the
1487+
* redirect_info struct completely, so that if an eBPF program
1488+
* performs multiple lookups, the last one always takes
1489+
* precedence.
1490+
*/
1491+
WRITE_ONCE(ri->map, NULL);
1492+
return flags;
1493+
}
1494+
1495+
ri->flags = flags;
1496+
ri->tgt_index = ifindex;
1497+
WRITE_ONCE(ri->map, map);
1498+
1499+
return XDP_REDIRECT;
1500+
}
1501+
14751502
#endif /* __LINUX_FILTER_H__ */

include/net/xdp_sock.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,6 @@ int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp);
8080
int __xsk_map_redirect(struct xdp_sock *xs, struct xdp_buff *xdp);
8181
void __xsk_map_flush(void);
8282

83-
static inline struct xdp_sock *__xsk_map_lookup_elem(struct bpf_map *map,
84-
u32 key)
85-
{
86-
struct xsk_map *m = container_of(map, struct xsk_map, map);
87-
struct xdp_sock *xs;
88-
89-
if (key >= map->max_entries)
90-
return NULL;
91-
92-
xs = READ_ONCE(m->xsk_map[key]);
93-
return xs;
94-
}
95-
9683
#else
9784

9885
static inline int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
@@ -109,12 +96,6 @@ static inline void __xsk_map_flush(void)
10996
{
11097
}
11198

112-
static inline struct xdp_sock *__xsk_map_lookup_elem(struct bpf_map *map,
113-
u32 key)
114-
{
115-
return NULL;
116-
}
117-
11899
#endif /* CONFIG_XDP_SOCKETS */
119100

120101
#endif /* _LINUX_XDP_SOCK_H */

kernel/bpf/cpumap.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ static void cpu_map_free(struct bpf_map *map)
563563
kfree(cmap);
564564
}
565565

566-
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
566+
static void *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
567567
{
568568
struct bpf_cpu_map *cmap = container_of(map, struct bpf_cpu_map, map);
569569
struct bpf_cpu_map_entry *rcpu;
@@ -600,6 +600,11 @@ static int cpu_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
600600
return 0;
601601
}
602602

603+
static int cpu_map_redirect(struct bpf_map *map, u32 ifindex, u64 flags)
604+
{
605+
return __bpf_xdp_redirect_map(map, ifindex, flags, __cpu_map_lookup_elem);
606+
}
607+
603608
static int cpu_map_btf_id;
604609
const struct bpf_map_ops cpu_map_ops = {
605610
.map_meta_equal = bpf_map_meta_equal,
@@ -612,6 +617,7 @@ const struct bpf_map_ops cpu_map_ops = {
612617
.map_check_btf = map_check_no_btf,
613618
.map_btf_name = "bpf_cpu_map",
614619
.map_btf_id = &cpu_map_btf_id,
620+
.map_redirect = cpu_map_redirect,
615621
};
616622

617623
static void bq_flush_to_queue(struct xdp_bulk_queue *bq)

kernel/bpf/devmap.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static int dev_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
258258
return 0;
259259
}
260260

261-
struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key)
261+
static void *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key)
262262
{
263263
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
264264
struct hlist_head *head = dev_map_index_hash(dtab, key);
@@ -392,7 +392,7 @@ void __dev_flush(void)
392392
* update happens in parallel here a dev_put wont happen until after reading the
393393
* ifindex.
394394
*/
395-
struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key)
395+
static void *__dev_map_lookup_elem(struct bpf_map *map, u32 key)
396396
{
397397
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
398398
struct bpf_dtab_netdev *obj;
@@ -735,6 +735,16 @@ static int dev_map_hash_update_elem(struct bpf_map *map, void *key, void *value,
735735
map, key, value, map_flags);
736736
}
737737

738+
static int dev_map_redirect(struct bpf_map *map, u32 ifindex, u64 flags)
739+
{
740+
return __bpf_xdp_redirect_map(map, ifindex, flags, __dev_map_lookup_elem);
741+
}
742+
743+
static int dev_hash_map_redirect(struct bpf_map *map, u32 ifindex, u64 flags)
744+
{
745+
return __bpf_xdp_redirect_map(map, ifindex, flags, __dev_map_hash_lookup_elem);
746+
}
747+
738748
static int dev_map_btf_id;
739749
const struct bpf_map_ops dev_map_ops = {
740750
.map_meta_equal = bpf_map_meta_equal,
@@ -747,6 +757,7 @@ const struct bpf_map_ops dev_map_ops = {
747757
.map_check_btf = map_check_no_btf,
748758
.map_btf_name = "bpf_dtab",
749759
.map_btf_id = &dev_map_btf_id,
760+
.map_redirect = dev_map_redirect,
750761
};
751762

752763
static int dev_map_hash_map_btf_id;
@@ -761,6 +772,7 @@ const struct bpf_map_ops dev_map_hash_ops = {
761772
.map_check_btf = map_check_no_btf,
762773
.map_btf_name = "bpf_dtab",
763774
.map_btf_id = &dev_map_hash_map_btf_id,
775+
.map_redirect = dev_hash_map_redirect,
764776
};
765777

766778
static void dev_map_hash_remove_netdev(struct bpf_dtab *dtab,

kernel/bpf/verifier.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5582,7 +5582,8 @@ record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
55825582
func_id != BPF_FUNC_map_push_elem &&
55835583
func_id != BPF_FUNC_map_pop_elem &&
55845584
func_id != BPF_FUNC_map_peek_elem &&
5585-
func_id != BPF_FUNC_for_each_map_elem)
5585+
func_id != BPF_FUNC_for_each_map_elem &&
5586+
func_id != BPF_FUNC_redirect_map)
55865587
return 0;
55875588

55885589
if (map == NULL) {
@@ -12017,7 +12018,8 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1201712018
insn->imm == BPF_FUNC_map_delete_elem ||
1201812019
insn->imm == BPF_FUNC_map_push_elem ||
1201912020
insn->imm == BPF_FUNC_map_pop_elem ||
12020-
insn->imm == BPF_FUNC_map_peek_elem)) {
12021+
insn->imm == BPF_FUNC_map_peek_elem ||
12022+
insn->imm == BPF_FUNC_redirect_map)) {
1202112023
aux = &env->insn_aux_data[i + delta];
1202212024
if (bpf_map_ptr_poisoned(aux))
1202312025
goto patch_call_imm;
@@ -12059,6 +12061,9 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1205912061
(int (*)(struct bpf_map *map, void *value))NULL));
1206012062
BUILD_BUG_ON(!__same_type(ops->map_peek_elem,
1206112063
(int (*)(struct bpf_map *map, void *value))NULL));
12064+
BUILD_BUG_ON(!__same_type(ops->map_redirect,
12065+
(int (*)(struct bpf_map *map, u32 ifindex, u64 flags))NULL));
12066+
1206212067
patch_map_ops_generic:
1206312068
switch (insn->imm) {
1206412069
case BPF_FUNC_map_lookup_elem:
@@ -12085,6 +12090,10 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1208512090
insn->imm = BPF_CAST_CALL(ops->map_peek_elem) -
1208612091
__bpf_call_base;
1208712092
continue;
12093+
case BPF_FUNC_redirect_map:
12094+
insn->imm = BPF_CAST_CALL(ops->map_redirect) -
12095+
__bpf_call_base;
12096+
continue;
1208812097
}
1208912098

1209012099
goto patch_call_imm;

net/core/filter.c

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3943,22 +3943,6 @@ void xdp_do_flush(void)
39433943
}
39443944
EXPORT_SYMBOL_GPL(xdp_do_flush);
39453945

3946-
static inline void *__xdp_map_lookup_elem(struct bpf_map *map, u32 index)
3947-
{
3948-
switch (map->map_type) {
3949-
case BPF_MAP_TYPE_DEVMAP:
3950-
return __dev_map_lookup_elem(map, index);
3951-
case BPF_MAP_TYPE_DEVMAP_HASH:
3952-
return __dev_map_hash_lookup_elem(map, index);
3953-
case BPF_MAP_TYPE_CPUMAP:
3954-
return __cpu_map_lookup_elem(map, index);
3955-
case BPF_MAP_TYPE_XSKMAP:
3956-
return __xsk_map_lookup_elem(map, index);
3957-
default:
3958-
return NULL;
3959-
}
3960-
}
3961-
39623946
void bpf_clear_redirect_map(struct bpf_map *map)
39633947
{
39643948
struct bpf_redirect_info *ri;
@@ -4112,28 +4096,7 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = {
41124096
BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex,
41134097
u64, flags)
41144098
{
4115-
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
4116-
4117-
/* Lower bits of the flags are used as return code on lookup failure */
4118-
if (unlikely(flags > XDP_TX))
4119-
return XDP_ABORTED;
4120-
4121-
ri->tgt_value = __xdp_map_lookup_elem(map, ifindex);
4122-
if (unlikely(!ri->tgt_value)) {
4123-
/* If the lookup fails we want to clear out the state in the
4124-
* redirect_info struct completely, so that if an eBPF program
4125-
* performs multiple lookups, the last one always takes
4126-
* precedence.
4127-
*/
4128-
WRITE_ONCE(ri->map, NULL);
4129-
return flags;
4130-
}
4131-
4132-
ri->flags = flags;
4133-
ri->tgt_index = ifindex;
4134-
WRITE_ONCE(ri->map, map);
4135-
4136-
return XDP_REDIRECT;
4099+
return map->ops->map_redirect(map, ifindex, flags);
41374100
}
41384101

41394102
static const struct bpf_func_proto bpf_xdp_redirect_map_proto = {

net/xdp/xskmap.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ static int xsk_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
125125
return insn - insn_buf;
126126
}
127127

128+
static void *__xsk_map_lookup_elem(struct bpf_map *map, u32 key)
129+
{
130+
struct xsk_map *m = container_of(map, struct xsk_map, map);
131+
132+
if (key >= map->max_entries)
133+
return NULL;
134+
135+
return READ_ONCE(m->xsk_map[key]);
136+
}
137+
128138
static void *xsk_map_lookup_elem(struct bpf_map *map, void *key)
129139
{
130140
WARN_ON_ONCE(!rcu_read_lock_held());
@@ -215,6 +225,11 @@ static int xsk_map_delete_elem(struct bpf_map *map, void *key)
215225
return 0;
216226
}
217227

228+
static int xsk_map_redirect(struct bpf_map *map, u32 ifindex, u64 flags)
229+
{
230+
return __bpf_xdp_redirect_map(map, ifindex, flags, __xsk_map_lookup_elem);
231+
}
232+
218233
void xsk_map_try_sock_delete(struct xsk_map *map, struct xdp_sock *xs,
219234
struct xdp_sock **map_entry)
220235
{
@@ -247,4 +262,5 @@ const struct bpf_map_ops xsk_map_ops = {
247262
.map_check_btf = map_check_no_btf,
248263
.map_btf_name = "xsk_map",
249264
.map_btf_id = &xsk_map_btf_id,
265+
.map_redirect = xsk_map_redirect,
250266
};

0 commit comments

Comments
 (0)