Skip to content

Commit c46646d

Browse files
borkmanndavem330
authored andcommitted
sched, bpf: add helper for retrieving routing realms
Using routing realms as part of the classifier is quite useful, it can be viewed as a tag for one or multiple routing entries (think of an analogy to net_cls cgroup for processes), set by user space routing daemons or via iproute2 as an indicator for traffic classifiers and later on processed in the eBPF program. Unlike actions, the classifier can inspect device flags and enable netif_keep_dst() if necessary. tc actions don't have that possibility, but in case people know what they are doing, it can be used from there as well (e.g. via devs that must keep dsts by design anyway). If a realm is set, the handler returns the non-zero realm. User space can set the full 32bit realm for the dst. Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a91263d commit c46646d

File tree

5 files changed

+39
-3
lines changed

5 files changed

+39
-3
lines changed

include/linux/filter.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ struct bpf_prog {
328328
u16 pages; /* Number of allocated pages */
329329
kmemcheck_bitfield_begin(meta);
330330
u16 jited:1, /* Is our filter JIT'ed? */
331-
gpl_compatible:1; /* Is filter GPL compatible? */
331+
gpl_compatible:1, /* Is filter GPL compatible? */
332+
dst_needed:1; /* Do we need dst entry? */
332333
kmemcheck_bitfield_end(meta);
333334
u32 len; /* Number of filter blocks */
334335
enum bpf_prog_type type; /* Type of BPF program */

include/uapi/linux/bpf.h

+7
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,13 @@ enum bpf_func_id {
280280
* Return: TC_ACT_REDIRECT
281281
*/
282282
BPF_FUNC_redirect,
283+
284+
/**
285+
* bpf_get_route_realm(skb) - retrieve a dst's tclassid
286+
* @skb: pointer to skb
287+
* Return: realm if != 0
288+
*/
289+
BPF_FUNC_get_route_realm,
283290
__BPF_FUNC_MAX_ID,
284291
};
285292

kernel/bpf/syscall.c

+2
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ static void fixup_bpf_calls(struct bpf_prog *prog)
402402
*/
403403
BUG_ON(!prog->aux->ops->get_func_proto);
404404

405+
if (insn->imm == BPF_FUNC_get_route_realm)
406+
prog->dst_needed = 1;
405407
if (insn->imm == BPF_FUNC_tail_call) {
406408
/* mark bpf_tail_call as different opcode
407409
* to avoid conditional branch in

net/core/filter.c

+22
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <net/sch_generic.h>
5050
#include <net/cls_cgroup.h>
5151
#include <net/dst_metadata.h>
52+
#include <net/dst.h>
5253

5354
/**
5455
* sk_filter - run a packet through a socket filter
@@ -1478,6 +1479,25 @@ static const struct bpf_func_proto bpf_get_cgroup_classid_proto = {
14781479
.arg1_type = ARG_PTR_TO_CTX,
14791480
};
14801481

1482+
static u64 bpf_get_route_realm(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
1483+
{
1484+
#ifdef CONFIG_IP_ROUTE_CLASSID
1485+
const struct dst_entry *dst;
1486+
1487+
dst = skb_dst((struct sk_buff *) (unsigned long) r1);
1488+
if (dst)
1489+
return dst->tclassid;
1490+
#endif
1491+
return 0;
1492+
}
1493+
1494+
static const struct bpf_func_proto bpf_get_route_realm_proto = {
1495+
.func = bpf_get_route_realm,
1496+
.gpl_only = false,
1497+
.ret_type = RET_INTEGER,
1498+
.arg1_type = ARG_PTR_TO_CTX,
1499+
};
1500+
14811501
static u64 bpf_skb_vlan_push(u64 r1, u64 r2, u64 vlan_tci, u64 r4, u64 r5)
14821502
{
14831503
struct sk_buff *skb = (struct sk_buff *) (long) r1;
@@ -1648,6 +1668,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
16481668
return bpf_get_skb_set_tunnel_key_proto();
16491669
case BPF_FUNC_redirect:
16501670
return &bpf_redirect_proto;
1671+
case BPF_FUNC_get_route_realm:
1672+
return &bpf_get_route_realm_proto;
16511673
default:
16521674
return sk_filter_func_proto(func_id);
16531675
}

net/sched/cls_bpf.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ static int cls_bpf_prog_from_ops(struct nlattr **tb, struct cls_bpf_prog *prog)
262262
return 0;
263263
}
264264

265-
static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog)
265+
static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
266+
const struct tcf_proto *tp)
266267
{
267268
struct bpf_prog *fp;
268269
char *name = NULL;
@@ -294,6 +295,9 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog)
294295
prog->bpf_name = name;
295296
prog->filter = fp;
296297

298+
if (fp->dst_needed)
299+
netif_keep_dst(qdisc_dev(tp->q));
300+
297301
return 0;
298302
}
299303

@@ -330,7 +334,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
330334
prog->exts_integrated = have_exts;
331335

332336
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
333-
cls_bpf_prog_from_efd(tb, prog);
337+
cls_bpf_prog_from_efd(tb, prog, tp);
334338
if (ret < 0) {
335339
tcf_exts_destroy(&exts);
336340
return ret;

0 commit comments

Comments
 (0)