Skip to content

Commit bb45e51

Browse files
Jakub Kicinskidavem330
authored andcommitted
nfp: move bpf offload code to the BPF app
Move bulk of the eBPF offload code out of common vNIC code into app-specific callbacks. Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d9ae7f2 commit bb45e51

File tree

6 files changed

+159
-59
lines changed

6 files changed

+159
-59
lines changed

drivers/net/ethernet/netronome/nfp/bpf/main.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,57 @@
3131
* SOFTWARE.
3232
*/
3333

34+
#include <net/pkt_cls.h>
35+
3436
#include "../nfpcore/nfp_cpp.h"
3537
#include "../nfp_app.h"
3638
#include "../nfp_main.h"
3739
#include "../nfp_net.h"
3840
#include "../nfp_port.h"
41+
#include "main.h"
42+
43+
static bool nfp_net_ebpf_capable(struct nfp_net *nn)
44+
{
45+
if (nn->cap & NFP_NET_CFG_CTRL_BPF &&
46+
nn_readb(nn, NFP_NET_CFG_BPF_ABI) == NFP_NET_BPF_ABI)
47+
return true;
48+
return false;
49+
}
50+
51+
static int
52+
nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
53+
struct bpf_prog *prog)
54+
{
55+
struct tc_cls_bpf_offload cmd = {
56+
.prog = prog,
57+
};
58+
int ret;
59+
60+
if (!nfp_net_ebpf_capable(nn))
61+
return -EINVAL;
62+
63+
if (nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF) {
64+
if (!nn->dp.bpf_offload_xdp)
65+
return prog ? -EBUSY : 0;
66+
cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY;
67+
} else {
68+
if (!prog)
69+
return 0;
70+
cmd.command = TC_CLSBPF_ADD;
71+
}
72+
73+
ret = nfp_net_bpf_offload(nn, &cmd);
74+
/* Stop offload if replace not possible */
75+
if (ret && cmd.command == TC_CLSBPF_REPLACE)
76+
nfp_bpf_xdp_offload(app, nn, NULL);
77+
nn->dp.bpf_offload_xdp = prog && !ret;
78+
return ret;
79+
}
80+
81+
static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)
82+
{
83+
return nfp_net_ebpf_capable(nn) ? "BPF" : "";
84+
}
3985

4086
static int
4187
nfp_bpf_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
@@ -51,9 +97,47 @@ nfp_bpf_vnic_init(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
5197
return nfp_app_nic_vnic_init(app, nn, id);
5298
}
5399

100+
static void nfp_bpf_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
101+
{
102+
if (nn->dp.bpf_offload_xdp)
103+
nfp_bpf_xdp_offload(app, nn, NULL);
104+
}
105+
106+
static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
107+
u32 handle, __be16 proto, struct tc_to_netdev *tc)
108+
{
109+
struct nfp_net *nn = netdev_priv(netdev);
110+
111+
if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
112+
return -EOPNOTSUPP;
113+
if (proto != htons(ETH_P_ALL))
114+
return -EOPNOTSUPP;
115+
116+
if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) {
117+
if (!nn->dp.bpf_offload_xdp)
118+
return nfp_net_bpf_offload(nn, tc->cls_bpf);
119+
else
120+
return -EBUSY;
121+
}
122+
123+
return -EINVAL;
124+
}
125+
126+
static bool nfp_bpf_tc_busy(struct nfp_app *app, struct nfp_net *nn)
127+
{
128+
return nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF;
129+
}
130+
54131
const struct nfp_app_type app_bpf = {
55132
.id = NFP_APP_BPF_NIC,
56133
.name = "ebpf",
57134

135+
.extra_cap = nfp_bpf_extra_cap,
136+
58137
.vnic_init = nfp_bpf_vnic_init,
138+
.vnic_clean = nfp_bpf_vnic_clean,
139+
140+
.setup_tc = nfp_bpf_setup_tc,
141+
.tc_busy = nfp_bpf_tc_busy,
142+
.xdp_offload = nfp_bpf_xdp_offload,
59143
};

drivers/net/ethernet/netronome/nfp/bpf/main.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,9 @@ nfp_bpf_jit(struct bpf_prog *filter, void *prog, enum nfp_bpf_action_type act,
198198

199199
int nfp_prog_verify(struct nfp_prog *nfp_prog, struct bpf_prog *prog);
200200

201+
struct nfp_net;
202+
struct tc_cls_bpf_offload;
203+
204+
int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf);
205+
201206
#endif

drivers/net/ethernet/netronome/nfp/nfp_app.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@
3434
#ifndef _NFP_APP_H
3535
#define _NFP_APP_H 1
3636

37+
struct bpf_prog;
38+
struct net_device;
3739
struct pci_dev;
40+
struct tc_to_netdev;
3841
struct nfp_app;
3942
struct nfp_cpp;
4043
struct nfp_pf;
@@ -55,16 +58,30 @@ extern const struct nfp_app_type app_bpf;
5558
*
5659
* Callbacks
5760
* @init: perform basic app checks
61+
* @extra_cap: extra capabilities string
5862
* @vnic_init: init vNICs (assign port types, etc.)
63+
* @vnic_clean: clean up app's vNIC state
64+
* @setup_tc: setup TC ndo
65+
* @tc_busy: TC HW offload busy (rules loaded)
66+
* @xdp_offload: offload an XDP program
5967
*/
6068
struct nfp_app_type {
6169
enum nfp_app_id id;
6270
const char *name;
6371

6472
int (*init)(struct nfp_app *app);
6573

74+
const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);
75+
6676
int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn,
6777
unsigned int id);
78+
void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn);
79+
80+
int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
81+
u32 handle, __be16 proto, struct tc_to_netdev *tc);
82+
bool (*tc_busy)(struct nfp_app *app, struct nfp_net *nn);
83+
int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
84+
struct bpf_prog *prog);
6885
};
6986

7087
/**
@@ -95,13 +112,57 @@ static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn,
95112
return app->type->vnic_init(app, nn, id);
96113
}
97114

115+
static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
116+
{
117+
if (app->type->vnic_clean)
118+
app->type->vnic_clean(app, nn);
119+
}
120+
98121
static inline const char *nfp_app_name(struct nfp_app *app)
99122
{
100123
if (!app)
101124
return "";
102125
return app->type->name;
103126
}
104127

128+
static inline const char *nfp_app_extra_cap(struct nfp_app *app,
129+
struct nfp_net *nn)
130+
{
131+
if (!app || !app->type->extra_cap)
132+
return "";
133+
return app->type->extra_cap(app, nn);
134+
}
135+
136+
static inline bool nfp_app_has_tc(struct nfp_app *app)
137+
{
138+
return app && app->type->setup_tc;
139+
}
140+
141+
static inline bool nfp_app_tc_busy(struct nfp_app *app, struct nfp_net *nn)
142+
{
143+
if (!app || !app->type->tc_busy)
144+
return false;
145+
return app->type->tc_busy(app, nn);
146+
}
147+
148+
static inline int nfp_app_setup_tc(struct nfp_app *app,
149+
struct net_device *netdev,
150+
u32 handle, __be16 proto,
151+
struct tc_to_netdev *tc)
152+
{
153+
if (!app || !app->type->setup_tc)
154+
return -EOPNOTSUPP;
155+
return app->type->setup_tc(app, netdev, handle, proto, tc);
156+
}
157+
158+
static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
159+
struct bpf_prog *prog)
160+
{
161+
if (!app || !app->type->xdp_offload)
162+
return -EOPNOTSUPP;
163+
return app->type->xdp_offload(app, nn, prog);
164+
}
165+
105166
struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id);
106167
void nfp_app_free(struct nfp_app *app);
107168

drivers/net/ethernet/netronome/nfp/nfp_net.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,5 @@ static inline void nfp_net_debugfs_dir_clean(struct dentry **dir)
868868
#endif /* CONFIG_NFP_DEBUG */
869869

870870
void nfp_net_filter_stats_timer(unsigned long data);
871-
int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf);
872871

873872
#endif /* _NFP_NET_H_ */

drivers/net/ethernet/netronome/nfp/nfp_net_common.c

Lines changed: 8 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@
6464

6565
#include <linux/ktime.h>
6666

67-
#include <net/pkt_cls.h>
6867
#include <net/vxlan.h>
6968

7069
#include "nfpcore/nfp_nsp.h"
70+
#include "nfp_app.h"
7171
#include "nfp_net_ctrl.h"
7272
#include "nfp_net.h"
7373
#include "nfp_port.h"
@@ -2681,33 +2681,13 @@ static void nfp_net_stat64(struct net_device *netdev,
26812681
}
26822682
}
26832683

2684-
static bool nfp_net_ebpf_capable(struct nfp_net *nn)
2685-
{
2686-
if (nn->cap & NFP_NET_CFG_CTRL_BPF &&
2687-
nn_readb(nn, NFP_NET_CFG_BPF_ABI) == NFP_NET_BPF_ABI)
2688-
return true;
2689-
return false;
2690-
}
2691-
26922684
static int
26932685
nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
26942686
struct tc_to_netdev *tc)
26952687
{
26962688
struct nfp_net *nn = netdev_priv(netdev);
26972689

2698-
if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
2699-
return -EOPNOTSUPP;
2700-
if (proto != htons(ETH_P_ALL))
2701-
return -EOPNOTSUPP;
2702-
2703-
if (tc->type == TC_SETUP_CLSBPF && nfp_net_ebpf_capable(nn)) {
2704-
if (!nn->dp.bpf_offload_xdp)
2705-
return nfp_net_bpf_offload(nn, tc->cls_bpf);
2706-
else
2707-
return -EBUSY;
2708-
}
2709-
2710-
return -EINVAL;
2690+
return nfp_app_setup_tc(nn->app, netdev, handle, proto, tc);
27112691
}
27122692

27132693
static int nfp_net_set_features(struct net_device *netdev,
@@ -2765,7 +2745,7 @@ static int nfp_net_set_features(struct net_device *netdev,
27652745
new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
27662746
}
27672747

2768-
if (changed & NETIF_F_HW_TC && nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF) {
2748+
if (changed & NETIF_F_HW_TC && nfp_app_tc_busy(nn->app, nn)) {
27692749
nn_err(nn, "Cannot disable HW TC offload while in use\n");
27702750
return -EBUSY;
27712751
}
@@ -2914,34 +2894,6 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
29142894
nfp_net_set_vxlan_port(nn, idx, 0);
29152895
}
29162896

2917-
static int nfp_net_xdp_offload(struct nfp_net *nn, struct bpf_prog *prog)
2918-
{
2919-
struct tc_cls_bpf_offload cmd = {
2920-
.prog = prog,
2921-
};
2922-
int ret;
2923-
2924-
if (!nfp_net_ebpf_capable(nn))
2925-
return -EINVAL;
2926-
2927-
if (nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF) {
2928-
if (!nn->dp.bpf_offload_xdp)
2929-
return prog ? -EBUSY : 0;
2930-
cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY;
2931-
} else {
2932-
if (!prog)
2933-
return 0;
2934-
cmd.command = TC_CLSBPF_ADD;
2935-
}
2936-
2937-
ret = nfp_net_bpf_offload(nn, &cmd);
2938-
/* Stop offload if replace not possible */
2939-
if (ret && cmd.command == TC_CLSBPF_REPLACE)
2940-
nfp_net_xdp_offload(nn, NULL);
2941-
nn->dp.bpf_offload_xdp = prog && !ret;
2942-
return ret;
2943-
}
2944-
29452897
static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
29462898
{
29472899
struct bpf_prog *old_prog = nn->dp.xdp_prog;
@@ -2954,7 +2906,7 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
29542906
if (prog && nn->dp.xdp_prog) {
29552907
prog = xchg(&nn->dp.xdp_prog, prog);
29562908
bpf_prog_put(prog);
2957-
nfp_net_xdp_offload(nn, nn->dp.xdp_prog);
2909+
nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
29582910
return 0;
29592911
}
29602912

@@ -2975,7 +2927,7 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
29752927
if (old_prog)
29762928
bpf_prog_put(old_prog);
29772929

2978-
nfp_net_xdp_offload(nn, nn->dp.xdp_prog);
2930+
nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
29792931

29802932
return 0;
29812933
}
@@ -3068,10 +3020,10 @@ void nfp_net_info(struct nfp_net *nn)
30683020
nn->cap & NFP_NET_CFG_CTRL_IRQMOD ? "IRQMOD " : "",
30693021
nn->cap & NFP_NET_CFG_CTRL_VXLAN ? "VXLAN " : "",
30703022
nn->cap & NFP_NET_CFG_CTRL_NVGRE ? "NVGRE " : "",
3071-
nfp_net_ebpf_capable(nn) ? "BPF " : "",
30723023
nn->cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ?
30733024
"RXCSUM_COMPLETE " : "",
3074-
nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "");
3025+
nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "",
3026+
nfp_app_extra_cap(nn->app, nn));
30753027
}
30763028

30773029
/**
@@ -3316,7 +3268,7 @@ int nfp_net_init(struct nfp_net *nn)
33163268

33173269
netdev->features = netdev->hw_features;
33183270

3319-
if (nfp_net_ebpf_capable(nn))
3271+
if (nfp_app_has_tc(nn->app))
33203272
netdev->hw_features |= NETIF_F_HW_TC;
33213273

33223274
/* Advertise but disable TSO by default. */
@@ -3373,6 +3325,4 @@ void nfp_net_clean(struct nfp_net *nn)
33733325

33743326
if (nn->dp.xdp_prog)
33753327
bpf_prog_put(nn->dp.xdp_prog);
3376-
if (nn->dp.bpf_offload_xdp)
3377-
nfp_net_xdp_offload(nn, NULL);
33783328
}

drivers/net/ethernet/netronome/nfp/nfp_net_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ static void nfp_net_pf_clean_vnic(struct nfp_pf *pf, struct nfp_net *nn)
427427
nfp_devlink_port_unregister(nn->port);
428428
nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
429429
nfp_net_clean(nn);
430+
nfp_app_vnic_clean(pf->app, nn);
430431
}
431432

432433
static int

0 commit comments

Comments
 (0)