Skip to content

Commit 332ae8e

Browse files
Jakub Kicinskidavem330
Jakub Kicinski
authored andcommitted
net: cls_bpf: add hardware offload
This patch adds hardware offload capability to cls_bpf classifier, similar to what have been done with U32 and flower. Signed-off-by: Jakub Kicinski <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2d7a892 commit 332ae8e

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

include/linux/netdevice.h

+2
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ enum {
789789
TC_SETUP_CLSU32,
790790
TC_SETUP_CLSFLOWER,
791791
TC_SETUP_MATCHALL,
792+
TC_SETUP_CLSBPF,
792793
};
793794

794795
struct tc_cls_u32_offload;
@@ -800,6 +801,7 @@ struct tc_to_netdev {
800801
struct tc_cls_u32_offload *cls_u32;
801802
struct tc_cls_flower_offload *cls_flower;
802803
struct tc_cls_matchall_offload *cls_mall;
804+
struct tc_cls_bpf_offload *cls_bpf;
803805
};
804806
};
805807

include/net/pkt_cls.h

+14
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,18 @@ struct tc_cls_matchall_offload {
486486
unsigned long cookie;
487487
};
488488

489+
enum tc_clsbpf_command {
490+
TC_CLSBPF_ADD,
491+
TC_CLSBPF_REPLACE,
492+
TC_CLSBPF_DESTROY,
493+
};
494+
495+
struct tc_cls_bpf_offload {
496+
enum tc_clsbpf_command command;
497+
struct tcf_exts *exts;
498+
struct bpf_prog *prog;
499+
const char *name;
500+
bool exts_integrated;
501+
};
502+
489503
#endif

net/sched/cls_bpf.c

+70
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct cls_bpf_prog {
3939
struct list_head link;
4040
struct tcf_result res;
4141
bool exts_integrated;
42+
bool offloaded;
4243
struct tcf_exts exts;
4344
u32 handle;
4445
union {
@@ -138,6 +139,71 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
138139
return !prog->bpf_ops;
139140
}
140141

142+
static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
143+
enum tc_clsbpf_command cmd)
144+
{
145+
struct net_device *dev = tp->q->dev_queue->dev;
146+
struct tc_cls_bpf_offload bpf_offload = {};
147+
struct tc_to_netdev offload;
148+
149+
offload.type = TC_SETUP_CLSBPF;
150+
offload.cls_bpf = &bpf_offload;
151+
152+
bpf_offload.command = cmd;
153+
bpf_offload.exts = &prog->exts;
154+
bpf_offload.prog = prog->filter;
155+
bpf_offload.name = prog->bpf_name;
156+
bpf_offload.exts_integrated = prog->exts_integrated;
157+
158+
return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
159+
tp->protocol, &offload);
160+
}
161+
162+
static void cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
163+
struct cls_bpf_prog *oldprog)
164+
{
165+
struct net_device *dev = tp->q->dev_queue->dev;
166+
struct cls_bpf_prog *obj = prog;
167+
enum tc_clsbpf_command cmd;
168+
169+
if (oldprog && oldprog->offloaded) {
170+
if (tc_should_offload(dev, tp, 0)) {
171+
cmd = TC_CLSBPF_REPLACE;
172+
} else {
173+
obj = oldprog;
174+
cmd = TC_CLSBPF_DESTROY;
175+
}
176+
} else {
177+
if (!tc_should_offload(dev, tp, 0))
178+
return;
179+
cmd = TC_CLSBPF_ADD;
180+
}
181+
182+
if (cls_bpf_offload_cmd(tp, obj, cmd))
183+
return;
184+
185+
obj->offloaded = true;
186+
if (oldprog)
187+
oldprog->offloaded = false;
188+
}
189+
190+
static void cls_bpf_stop_offload(struct tcf_proto *tp,
191+
struct cls_bpf_prog *prog)
192+
{
193+
int err;
194+
195+
if (!prog->offloaded)
196+
return;
197+
198+
err = cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY);
199+
if (err) {
200+
pr_err("Stopping hardware offload failed: %d\n", err);
201+
return;
202+
}
203+
204+
prog->offloaded = false;
205+
}
206+
141207
static int cls_bpf_init(struct tcf_proto *tp)
142208
{
143209
struct cls_bpf_head *head;
@@ -177,6 +243,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg)
177243
{
178244
struct cls_bpf_prog *prog = (struct cls_bpf_prog *) arg;
179245

246+
cls_bpf_stop_offload(tp, prog);
180247
list_del_rcu(&prog->link);
181248
tcf_unbind_filter(tp, &prog->res);
182249
call_rcu(&prog->rcu, __cls_bpf_delete_prog);
@@ -193,6 +260,7 @@ static bool cls_bpf_destroy(struct tcf_proto *tp, bool force)
193260
return false;
194261

195262
list_for_each_entry_safe(prog, tmp, &head->plist, link) {
263+
cls_bpf_stop_offload(tp, prog);
196264
list_del_rcu(&prog->link);
197265
tcf_unbind_filter(tp, &prog->res);
198266
call_rcu(&prog->rcu, __cls_bpf_delete_prog);
@@ -415,6 +483,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
415483
if (ret < 0)
416484
goto errout;
417485

486+
cls_bpf_offload(tp, prog, oldprog);
487+
418488
if (oldprog) {
419489
list_replace_rcu(&oldprog->link, &prog->link);
420490
tcf_unbind_filter(tp, &oldprog->res);

0 commit comments

Comments
 (0)