aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-01-22 16:30:30 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-22 16:30:30 -0500
commit208e0b17329cd802088c79f399835d51b9710df8 (patch)
tree8129f3ba6e564ceaa4ac6132cb56c7e9ffd1c811
parent25a39f7f975c3c26a0052fbf9b59201c06744332 (diff)
parent52be9a7cde1fd26e43a01ac06d5c2558c563a7cb (diff)
Merge branch 'net-sched-add-extack-support-for-cls-offloads'
Jakub Kicinski says: ==================== net: sched: add extack support for cls offloads I've dropped the tests from the series because test_offloads.py changes will conflict with bpf-next patches. I will send four more patches with tests once bpf-next is merged back, hopefully still making it into 4.16 :) v4: - rebase on top of Alex's changes. --- Quentin says: This series tries to improve user experience when eBPF hardware offload hits error paths at load time. In particular, it introduces netlink extended ack support in the nfp driver. To that aim, transmission of the pointer to the extack object is piped through the `change()` operation of the existing classifiers (patch 1 to 6). Then it is used for TC offload in the nfp driver (patch 8) and in netdevsim (patch 9, selftest in patch 10). Patch 7 adds a helper to handle extack messages in the core when TC offload is disabled on the net device. For completeness extack is propagated for classifiers other than cls_bpf, but it's up to the drivers to make use of it. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.c35
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.h2
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/offload.c24
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_app.h9
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c2
-rw-r--r--include/net/pkt_cls.h16
-rw-r--r--net/sched/cls_bpf.c18
-rw-r--r--net/sched/cls_flower.c12
-rw-r--r--net/sched/cls_matchall.c10
-rw-r--r--net/sched/cls_u32.c18
10 files changed, 95 insertions, 51 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index 4ee11bf2aed7..b3206855535a 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -54,7 +54,7 @@ static bool nfp_net_ebpf_capable(struct nfp_net *nn)
54 54
55static int 55static int
56nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn, 56nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
57 struct bpf_prog *prog) 57 struct bpf_prog *prog, struct netlink_ext_ack *extack)
58{ 58{
59 bool running, xdp_running; 59 bool running, xdp_running;
60 int ret; 60 int ret;
@@ -70,10 +70,10 @@ nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
70 if (prog && running && !xdp_running) 70 if (prog && running && !xdp_running)
71 return -EBUSY; 71 return -EBUSY;
72 72
73 ret = nfp_net_bpf_offload(nn, prog, running); 73 ret = nfp_net_bpf_offload(nn, prog, running, extack);
74 /* Stop offload if replace not possible */ 74 /* Stop offload if replace not possible */
75 if (ret && prog) 75 if (ret && prog)
76 nfp_bpf_xdp_offload(app, nn, NULL); 76 nfp_bpf_xdp_offload(app, nn, NULL, extack);
77 77
78 nn->dp.bpf_offload_xdp = prog && !ret; 78 nn->dp.bpf_offload_xdp = prog && !ret;
79 return ret; 79 return ret;
@@ -125,17 +125,31 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
125 struct nfp_bpf_vnic *bv; 125 struct nfp_bpf_vnic *bv;
126 int err; 126 int err;
127 127
128 if (type != TC_SETUP_CLSBPF || 128 if (type != TC_SETUP_CLSBPF) {
129 !tc_can_offload(nn->dp.netdev) || 129 NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
130 !nfp_net_ebpf_capable(nn) || 130 "only offload of BPF classifiers supported");
131 cls_bpf->common.protocol != htons(ETH_P_ALL) || 131 return -EOPNOTSUPP;
132 cls_bpf->common.chain_index) 132 }
133 if (!tc_can_offload_extack(nn->dp.netdev, cls_bpf->common.extack))
134 return -EOPNOTSUPP;
135 if (!nfp_net_ebpf_capable(nn)) {
136 NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
137 "NFP firmware does not support eBPF offload");
138 return -EOPNOTSUPP;
139 }
140 if (cls_bpf->common.protocol != htons(ETH_P_ALL)) {
141 NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
142 "only ETH_P_ALL supported as filter protocol");
143 return -EOPNOTSUPP;
144 }
145 if (cls_bpf->common.chain_index)
133 return -EOPNOTSUPP; 146 return -EOPNOTSUPP;
134 147
135 /* Only support TC direct action */ 148 /* Only support TC direct action */
136 if (!cls_bpf->exts_integrated || 149 if (!cls_bpf->exts_integrated ||
137 tcf_exts_has_actions(cls_bpf->exts)) { 150 tcf_exts_has_actions(cls_bpf->exts)) {
138 nn_err(nn, "only direct action with no legacy actions supported\n"); 151 NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
152 "only direct action with no legacy actions supported");
139 return -EOPNOTSUPP; 153 return -EOPNOTSUPP;
140 } 154 }
141 155
@@ -152,7 +166,8 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
152 return 0; 166 return 0;
153 } 167 }
154 168
155 err = nfp_net_bpf_offload(nn, cls_bpf->prog, oldprog); 169 err = nfp_net_bpf_offload(nn, cls_bpf->prog, oldprog,
170 cls_bpf->common.extack);
156 if (err) 171 if (err)
157 return err; 172 return err;
158 173
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index c476bca15ba4..424fe8338105 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -335,7 +335,7 @@ struct nfp_net;
335int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn, 335int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn,
336 struct netdev_bpf *bpf); 336 struct netdev_bpf *bpf);
337int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog, 337int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
338 bool old_prog); 338 bool old_prog, struct netlink_ext_ack *extack);
339 339
340struct nfp_insn_meta * 340struct nfp_insn_meta *
341nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, 341nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
index 1a357aacc444..0a7732385469 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -281,7 +281,9 @@ int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn, struct netdev_bpf *bpf)
281 } 281 }
282} 282}
283 283
284static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog) 284static int
285nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog,
286 struct netlink_ext_ack *extack)
285{ 287{
286 struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv; 288 struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
287 unsigned int max_mtu; 289 unsigned int max_mtu;
@@ -291,7 +293,7 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
291 293
292 max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32; 294 max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
293 if (max_mtu < nn->dp.netdev->mtu) { 295 if (max_mtu < nn->dp.netdev->mtu) {
294 nn_info(nn, "BPF offload not supported with MTU larger than HW packet split boundary\n"); 296 NL_SET_ERR_MSG_MOD(extack, "BPF offload not supported with MTU larger than HW packet split boundary");
295 return -EOPNOTSUPP; 297 return -EOPNOTSUPP;
296 } 298 }
297 299
@@ -313,7 +315,8 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
313 /* Load up the JITed code */ 315 /* Load up the JITed code */
314 err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_BPF); 316 err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_BPF);
315 if (err) 317 if (err)
316 nn_err(nn, "FW command error while loading BPF: %d\n", err); 318 NL_SET_ERR_MSG_MOD(extack,
319 "FW command error while loading BPF");
317 320
318 dma_unmap_single(nn->dp.dev, dma_addr, nfp_prog->prog_len * sizeof(u64), 321 dma_unmap_single(nn->dp.dev, dma_addr, nfp_prog->prog_len * sizeof(u64),
319 DMA_TO_DEVICE); 322 DMA_TO_DEVICE);
@@ -322,7 +325,8 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
322 return err; 325 return err;
323} 326}
324 327
325static void nfp_net_bpf_start(struct nfp_net *nn) 328static void
329nfp_net_bpf_start(struct nfp_net *nn, struct netlink_ext_ack *extack)
326{ 330{
327 int err; 331 int err;
328 332
@@ -331,7 +335,8 @@ static void nfp_net_bpf_start(struct nfp_net *nn)
331 nn_writel(nn, NFP_NET_CFG_CTRL, nn->dp.ctrl); 335 nn_writel(nn, NFP_NET_CFG_CTRL, nn->dp.ctrl);
332 err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN); 336 err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
333 if (err) 337 if (err)
334 nn_err(nn, "FW command error while enabling BPF: %d\n", err); 338 NL_SET_ERR_MSG_MOD(extack,
339 "FW command error while enabling BPF");
335} 340}
336 341
337static int nfp_net_bpf_stop(struct nfp_net *nn) 342static int nfp_net_bpf_stop(struct nfp_net *nn)
@@ -346,7 +351,7 @@ static int nfp_net_bpf_stop(struct nfp_net *nn)
346} 351}
347 352
348int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog, 353int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
349 bool old_prog) 354 bool old_prog, struct netlink_ext_ack *extack)
350{ 355{
351 int err; 356 int err;
352 357
@@ -364,7 +369,8 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
364 369
365 cap = nn_readb(nn, NFP_NET_CFG_BPF_CAP); 370 cap = nn_readb(nn, NFP_NET_CFG_BPF_CAP);
366 if (!(cap & NFP_NET_BPF_CAP_RELO)) { 371 if (!(cap & NFP_NET_BPF_CAP_RELO)) {
367 nn_err(nn, "FW does not support live reload\n"); 372 NL_SET_ERR_MSG_MOD(extack,
373 "FW does not support live reload");
368 return -EBUSY; 374 return -EBUSY;
369 } 375 }
370 } 376 }
@@ -376,12 +382,12 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
376 if (old_prog && !prog) 382 if (old_prog && !prog)
377 return nfp_net_bpf_stop(nn); 383 return nfp_net_bpf_stop(nn);
378 384
379 err = nfp_net_bpf_load(nn, prog); 385 err = nfp_net_bpf_load(nn, prog, extack);
380 if (err) 386 if (err)
381 return err; 387 return err;
382 388
383 if (!old_prog) 389 if (!old_prog)
384 nfp_net_bpf_start(nn); 390 nfp_net_bpf_start(nn, extack);
385 391
386 return 0; 392 return 0;
387} 393}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index 7e474df90598..437964afa8ee 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -43,6 +43,7 @@
43struct bpf_prog; 43struct bpf_prog;
44struct net_device; 44struct net_device;
45struct netdev_bpf; 45struct netdev_bpf;
46struct netlink_ext_ack;
46struct pci_dev; 47struct pci_dev;
47struct sk_buff; 48struct sk_buff;
48struct sk_buff; 49struct sk_buff;
@@ -138,7 +139,8 @@ struct nfp_app_type {
138 int (*bpf)(struct nfp_app *app, struct nfp_net *nn, 139 int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
139 struct netdev_bpf *xdp); 140 struct netdev_bpf *xdp);
140 int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn, 141 int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
141 struct bpf_prog *prog); 142 struct bpf_prog *prog,
143 struct netlink_ext_ack *extack);
142 144
143 int (*sriov_enable)(struct nfp_app *app, int num_vfs); 145 int (*sriov_enable)(struct nfp_app *app, int num_vfs);
144 void (*sriov_disable)(struct nfp_app *app); 146 void (*sriov_disable)(struct nfp_app *app);
@@ -324,11 +326,12 @@ static inline int nfp_app_bpf(struct nfp_app *app, struct nfp_net *nn,
324} 326}
325 327
326static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn, 328static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
327 struct bpf_prog *prog) 329 struct bpf_prog *prog,
330 struct netlink_ext_ack *extack)
328{ 331{
329 if (!app || !app->type->xdp_offload) 332 if (!app || !app->type->xdp_offload)
330 return -EOPNOTSUPP; 333 return -EOPNOTSUPP;
331 return app->type->xdp_offload(app, nn, prog); 334 return app->type->xdp_offload(app, nn, prog, extack);
332} 335}
333 336
334static inline bool __nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb) 337static inline bool __nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index cdf52421eaca..c0fd351c86b1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3403,7 +3403,7 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
3403 if (err) 3403 if (err)
3404 return err; 3404 return err;
3405 3405
3406 err = nfp_app_xdp_offload(nn->app, nn, offload_prog); 3406 err = nfp_app_xdp_offload(nn->app, nn, offload_prog, extack);
3407 if (err && flags & XDP_FLAGS_HW_MODE) 3407 if (err && flags & XDP_FLAGS_HW_MODE)
3408 return err; 3408 return err;
3409 3409
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 2e4b8e436d25..2f8f16a4d88e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -602,15 +602,18 @@ struct tc_cls_common_offload {
602 u32 chain_index; 602 u32 chain_index;
603 __be16 protocol; 603 __be16 protocol;
604 u32 prio; 604 u32 prio;
605 struct netlink_ext_ack *extack;
605}; 606};
606 607
607static inline void 608static inline void
608tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common, 609tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common,
609 const struct tcf_proto *tp) 610 const struct tcf_proto *tp,
611 struct netlink_ext_ack *extack)
610{ 612{
611 cls_common->chain_index = tp->chain->index; 613 cls_common->chain_index = tp->chain->index;
612 cls_common->protocol = tp->protocol; 614 cls_common->protocol = tp->protocol;
613 cls_common->prio = tp->prio; 615 cls_common->prio = tp->prio;
616 cls_common->extack = extack;
614} 617}
615 618
616struct tc_cls_u32_knode { 619struct tc_cls_u32_knode {
@@ -653,6 +656,17 @@ static inline bool tc_can_offload(const struct net_device *dev)
653 return dev->features & NETIF_F_HW_TC; 656 return dev->features & NETIF_F_HW_TC;
654} 657}
655 658
659static inline bool tc_can_offload_extack(const struct net_device *dev,
660 struct netlink_ext_ack *extack)
661{
662 bool can = tc_can_offload(dev);
663
664 if (!can)
665 NL_SET_ERR_MSG(extack, "TC offload is disabled on net device");
666
667 return can;
668}
669
656static inline bool tc_skip_hw(u32 flags) 670static inline bool tc_skip_hw(u32 flags)
657{ 671{
658 return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false; 672 return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 988ad45d78b8..c11e0fe23a17 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -147,7 +147,8 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
147} 147}
148 148
149static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, 149static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
150 struct cls_bpf_prog *oldprog) 150 struct cls_bpf_prog *oldprog,
151 struct netlink_ext_ack *extack)
151{ 152{
152 struct tcf_block *block = tp->chain->block; 153 struct tcf_block *block = tp->chain->block;
153 struct tc_cls_bpf_offload cls_bpf = {}; 154 struct tc_cls_bpf_offload cls_bpf = {};
@@ -158,7 +159,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
158 skip_sw = prog && tc_skip_sw(prog->gen_flags); 159 skip_sw = prog && tc_skip_sw(prog->gen_flags);
159 obj = prog ?: oldprog; 160 obj = prog ?: oldprog;
160 161
161 tc_cls_common_offload_init(&cls_bpf.common, tp); 162 tc_cls_common_offload_init(&cls_bpf.common, tp, extack);
162 cls_bpf.command = TC_CLSBPF_OFFLOAD; 163 cls_bpf.command = TC_CLSBPF_OFFLOAD;
163 cls_bpf.exts = &obj->exts; 164 cls_bpf.exts = &obj->exts;
164 cls_bpf.prog = prog ? prog->filter : NULL; 165 cls_bpf.prog = prog ? prog->filter : NULL;
@@ -173,7 +174,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
173 err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw); 174 err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw);
174 if (prog) { 175 if (prog) {
175 if (err < 0) { 176 if (err < 0) {
176 cls_bpf_offload_cmd(tp, oldprog, prog); 177 cls_bpf_offload_cmd(tp, oldprog, prog, extack);
177 return err; 178 return err;
178 } else if (err > 0) { 179 } else if (err > 0) {
179 tcf_block_offload_inc(block, &prog->gen_flags); 180 tcf_block_offload_inc(block, &prog->gen_flags);
@@ -192,7 +193,8 @@ static u32 cls_bpf_flags(u32 flags)
192} 193}
193 194
194static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, 195static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
195 struct cls_bpf_prog *oldprog) 196 struct cls_bpf_prog *oldprog,
197 struct netlink_ext_ack *extack)
196{ 198{
197 if (prog && oldprog && 199 if (prog && oldprog &&
198 cls_bpf_flags(prog->gen_flags) != 200 cls_bpf_flags(prog->gen_flags) !=
@@ -206,7 +208,7 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
206 if (!prog && !oldprog) 208 if (!prog && !oldprog)
207 return 0; 209 return 0;
208 210
209 return cls_bpf_offload_cmd(tp, prog, oldprog); 211 return cls_bpf_offload_cmd(tp, prog, oldprog, extack);
210} 212}
211 213
212static void cls_bpf_stop_offload(struct tcf_proto *tp, 214static void cls_bpf_stop_offload(struct tcf_proto *tp,
@@ -214,7 +216,7 @@ static void cls_bpf_stop_offload(struct tcf_proto *tp,
214{ 216{
215 int err; 217 int err;
216 218
217 err = cls_bpf_offload_cmd(tp, NULL, prog); 219 err = cls_bpf_offload_cmd(tp, NULL, prog, NULL);
218 if (err) 220 if (err)
219 pr_err("Stopping hardware offload failed: %d\n", err); 221 pr_err("Stopping hardware offload failed: %d\n", err);
220} 222}
@@ -225,7 +227,7 @@ static void cls_bpf_offload_update_stats(struct tcf_proto *tp,
225 struct tcf_block *block = tp->chain->block; 227 struct tcf_block *block = tp->chain->block;
226 struct tc_cls_bpf_offload cls_bpf = {}; 228 struct tc_cls_bpf_offload cls_bpf = {};
227 229
228 tc_cls_common_offload_init(&cls_bpf.common, tp); 230 tc_cls_common_offload_init(&cls_bpf.common, tp, NULL);
229 cls_bpf.command = TC_CLSBPF_STATS; 231 cls_bpf.command = TC_CLSBPF_STATS;
230 cls_bpf.exts = &prog->exts; 232 cls_bpf.exts = &prog->exts;
231 cls_bpf.prog = prog->filter; 233 cls_bpf.prog = prog->filter;
@@ -514,7 +516,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
514 if (ret < 0) 516 if (ret < 0)
515 goto errout_idr; 517 goto errout_idr;
516 518
517 ret = cls_bpf_offload(tp, prog, oldprog); 519 ret = cls_bpf_offload(tp, prog, oldprog, extack);
518 if (ret) 520 if (ret)
519 goto errout_parms; 521 goto errout_parms;
520 522
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index c6ac4a612c4a..727c10378f37 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -223,7 +223,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
223 struct tc_cls_flower_offload cls_flower = {}; 223 struct tc_cls_flower_offload cls_flower = {};
224 struct tcf_block *block = tp->chain->block; 224 struct tcf_block *block = tp->chain->block;
225 225
226 tc_cls_common_offload_init(&cls_flower.common, tp); 226 tc_cls_common_offload_init(&cls_flower.common, tp, NULL);
227 cls_flower.command = TC_CLSFLOWER_DESTROY; 227 cls_flower.command = TC_CLSFLOWER_DESTROY;
228 cls_flower.cookie = (unsigned long) f; 228 cls_flower.cookie = (unsigned long) f;
229 229
@@ -235,14 +235,15 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
235static int fl_hw_replace_filter(struct tcf_proto *tp, 235static int fl_hw_replace_filter(struct tcf_proto *tp,
236 struct flow_dissector *dissector, 236 struct flow_dissector *dissector,
237 struct fl_flow_key *mask, 237 struct fl_flow_key *mask,
238 struct cls_fl_filter *f) 238 struct cls_fl_filter *f,
239 struct netlink_ext_ack *extack)
239{ 240{
240 struct tc_cls_flower_offload cls_flower = {}; 241 struct tc_cls_flower_offload cls_flower = {};
241 struct tcf_block *block = tp->chain->block; 242 struct tcf_block *block = tp->chain->block;
242 bool skip_sw = tc_skip_sw(f->flags); 243 bool skip_sw = tc_skip_sw(f->flags);
243 int err; 244 int err;
244 245
245 tc_cls_common_offload_init(&cls_flower.common, tp); 246 tc_cls_common_offload_init(&cls_flower.common, tp, extack);
246 cls_flower.command = TC_CLSFLOWER_REPLACE; 247 cls_flower.command = TC_CLSFLOWER_REPLACE;
247 cls_flower.cookie = (unsigned long) f; 248 cls_flower.cookie = (unsigned long) f;
248 cls_flower.dissector = dissector; 249 cls_flower.dissector = dissector;
@@ -271,7 +272,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
271 struct tc_cls_flower_offload cls_flower = {}; 272 struct tc_cls_flower_offload cls_flower = {};
272 struct tcf_block *block = tp->chain->block; 273 struct tcf_block *block = tp->chain->block;
273 274
274 tc_cls_common_offload_init(&cls_flower.common, tp); 275 tc_cls_common_offload_init(&cls_flower.common, tp, NULL);
275 cls_flower.command = TC_CLSFLOWER_STATS; 276 cls_flower.command = TC_CLSFLOWER_STATS;
276 cls_flower.cookie = (unsigned long) f; 277 cls_flower.cookie = (unsigned long) f;
277 cls_flower.exts = &f->exts; 278 cls_flower.exts = &f->exts;
@@ -943,7 +944,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
943 err = fl_hw_replace_filter(tp, 944 err = fl_hw_replace_filter(tp,
944 &head->dissector, 945 &head->dissector,
945 &mask.key, 946 &mask.key,
946 fnew); 947 fnew,
948 extack);
947 if (err) 949 if (err)
948 goto errout_idr; 950 goto errout_idr;
949 } 951 }
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index f67d3d7fcf40..d990d2a52c6d 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -76,7 +76,7 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
76 struct tc_cls_matchall_offload cls_mall = {}; 76 struct tc_cls_matchall_offload cls_mall = {};
77 struct tcf_block *block = tp->chain->block; 77 struct tcf_block *block = tp->chain->block;
78 78
79 tc_cls_common_offload_init(&cls_mall.common, tp); 79 tc_cls_common_offload_init(&cls_mall.common, tp, NULL);
80 cls_mall.command = TC_CLSMATCHALL_DESTROY; 80 cls_mall.command = TC_CLSMATCHALL_DESTROY;
81 cls_mall.cookie = cookie; 81 cls_mall.cookie = cookie;
82 82
@@ -86,14 +86,15 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
86 86
87static int mall_replace_hw_filter(struct tcf_proto *tp, 87static int mall_replace_hw_filter(struct tcf_proto *tp,
88 struct cls_mall_head *head, 88 struct cls_mall_head *head,
89 unsigned long cookie) 89 unsigned long cookie,
90 struct netlink_ext_ack *extack)
90{ 91{
91 struct tc_cls_matchall_offload cls_mall = {}; 92 struct tc_cls_matchall_offload cls_mall = {};
92 struct tcf_block *block = tp->chain->block; 93 struct tcf_block *block = tp->chain->block;
93 bool skip_sw = tc_skip_sw(head->flags); 94 bool skip_sw = tc_skip_sw(head->flags);
94 int err; 95 int err;
95 96
96 tc_cls_common_offload_init(&cls_mall.common, tp); 97 tc_cls_common_offload_init(&cls_mall.common, tp, extack);
97 cls_mall.command = TC_CLSMATCHALL_REPLACE; 98 cls_mall.command = TC_CLSMATCHALL_REPLACE;
98 cls_mall.exts = &head->exts; 99 cls_mall.exts = &head->exts;
99 cls_mall.cookie = cookie; 100 cls_mall.cookie = cookie;
@@ -205,7 +206,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
205 goto err_set_parms; 206 goto err_set_parms;
206 207
207 if (!tc_skip_hw(new->flags)) { 208 if (!tc_skip_hw(new->flags)) {
208 err = mall_replace_hw_filter(tp, new, (unsigned long)new); 209 err = mall_replace_hw_filter(tp, new, (unsigned long)new,
210 extack);
209 if (err) 211 if (err)
210 goto err_replace_hw_filter; 212 goto err_replace_hw_filter;
211 } 213 }
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 57113e936155..7030240f8826 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -491,7 +491,7 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
491 struct tcf_block *block = tp->chain->block; 491 struct tcf_block *block = tp->chain->block;
492 struct tc_cls_u32_offload cls_u32 = {}; 492 struct tc_cls_u32_offload cls_u32 = {};
493 493
494 tc_cls_common_offload_init(&cls_u32.common, tp); 494 tc_cls_common_offload_init(&cls_u32.common, tp, NULL);
495 cls_u32.command = TC_CLSU32_DELETE_HNODE; 495 cls_u32.command = TC_CLSU32_DELETE_HNODE;
496 cls_u32.hnode.divisor = h->divisor; 496 cls_u32.hnode.divisor = h->divisor;
497 cls_u32.hnode.handle = h->handle; 497 cls_u32.hnode.handle = h->handle;
@@ -501,7 +501,7 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
501} 501}
502 502
503static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h, 503static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
504 u32 flags) 504 u32 flags, struct netlink_ext_ack *extack)
505{ 505{
506 struct tcf_block *block = tp->chain->block; 506 struct tcf_block *block = tp->chain->block;
507 struct tc_cls_u32_offload cls_u32 = {}; 507 struct tc_cls_u32_offload cls_u32 = {};
@@ -509,7 +509,7 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
509 bool offloaded = false; 509 bool offloaded = false;
510 int err; 510 int err;
511 511
512 tc_cls_common_offload_init(&cls_u32.common, tp); 512 tc_cls_common_offload_init(&cls_u32.common, tp, extack);
513 cls_u32.command = TC_CLSU32_NEW_HNODE; 513 cls_u32.command = TC_CLSU32_NEW_HNODE;
514 cls_u32.hnode.divisor = h->divisor; 514 cls_u32.hnode.divisor = h->divisor;
515 cls_u32.hnode.handle = h->handle; 515 cls_u32.hnode.handle = h->handle;
@@ -534,7 +534,7 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n)
534 struct tcf_block *block = tp->chain->block; 534 struct tcf_block *block = tp->chain->block;
535 struct tc_cls_u32_offload cls_u32 = {}; 535 struct tc_cls_u32_offload cls_u32 = {};
536 536
537 tc_cls_common_offload_init(&cls_u32.common, tp); 537 tc_cls_common_offload_init(&cls_u32.common, tp, NULL);
538 cls_u32.command = TC_CLSU32_DELETE_KNODE; 538 cls_u32.command = TC_CLSU32_DELETE_KNODE;
539 cls_u32.knode.handle = n->handle; 539 cls_u32.knode.handle = n->handle;
540 540
@@ -543,14 +543,14 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n)
543} 543}
544 544
545static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n, 545static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
546 u32 flags) 546 u32 flags, struct netlink_ext_ack *extack)
547{ 547{
548 struct tcf_block *block = tp->chain->block; 548 struct tcf_block *block = tp->chain->block;
549 struct tc_cls_u32_offload cls_u32 = {}; 549 struct tc_cls_u32_offload cls_u32 = {};
550 bool skip_sw = tc_skip_sw(flags); 550 bool skip_sw = tc_skip_sw(flags);
551 int err; 551 int err;
552 552
553 tc_cls_common_offload_init(&cls_u32.common, tp); 553 tc_cls_common_offload_init(&cls_u32.common, tp, extack);
554 cls_u32.command = TC_CLSU32_REPLACE_KNODE; 554 cls_u32.command = TC_CLSU32_REPLACE_KNODE;
555 cls_u32.knode.handle = n->handle; 555 cls_u32.knode.handle = n->handle;
556 cls_u32.knode.fshift = n->fshift; 556 cls_u32.knode.fshift = n->fshift;
@@ -965,7 +965,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
965 return err; 965 return err;
966 } 966 }
967 967
968 err = u32_replace_hw_knode(tp, new, flags); 968 err = u32_replace_hw_knode(tp, new, flags, extack);
969 if (err) { 969 if (err) {
970 u32_destroy_key(tp, new, false); 970 u32_destroy_key(tp, new, false);
971 return err; 971 return err;
@@ -1016,7 +1016,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
1016 ht->prio = tp->prio; 1016 ht->prio = tp->prio;
1017 idr_init(&ht->handle_idr); 1017 idr_init(&ht->handle_idr);
1018 1018
1019 err = u32_replace_hw_hnode(tp, ht, flags); 1019 err = u32_replace_hw_hnode(tp, ht, flags, extack);
1020 if (err) { 1020 if (err) {
1021 idr_remove_ext(&tp_c->handle_idr, handle); 1021 idr_remove_ext(&tp_c->handle_idr, handle);
1022 kfree(ht); 1022 kfree(ht);
@@ -1122,7 +1122,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
1122 struct tc_u_knode __rcu **ins; 1122 struct tc_u_knode __rcu **ins;
1123 struct tc_u_knode *pins; 1123 struct tc_u_knode *pins;
1124 1124
1125 err = u32_replace_hw_knode(tp, n, flags); 1125 err = u32_replace_hw_knode(tp, n, flags, extack);
1126 if (err) 1126 if (err)
1127 goto errhw; 1127 goto errhw;
1128 1128