diff options
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/main.c | 12 | ||||
| -rw-r--r-- | include/net/pkt_cls.h | 5 | ||||
| -rw-r--r-- | net/sched/cls_bpf.c | 93 |
3 files changed, 43 insertions, 67 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index e379b78e86ef..a4cf62ba4604 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c | |||
| @@ -110,16 +110,10 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type, | |||
| 110 | return -EOPNOTSUPP; | 110 | return -EOPNOTSUPP; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | switch (cls_bpf->command) { | 113 | if (cls_bpf->command != TC_CLSBPF_OFFLOAD) |
| 114 | case TC_CLSBPF_REPLACE: | ||
| 115 | return nfp_net_bpf_offload(nn, cls_bpf->prog, true); | ||
| 116 | case TC_CLSBPF_ADD: | ||
| 117 | return nfp_net_bpf_offload(nn, cls_bpf->prog, false); | ||
| 118 | case TC_CLSBPF_DESTROY: | ||
| 119 | return nfp_net_bpf_offload(nn, NULL, true); | ||
| 120 | default: | ||
| 121 | return -EOPNOTSUPP; | 114 | return -EOPNOTSUPP; |
| 122 | } | 115 | |
| 116 | return nfp_net_bpf_offload(nn, cls_bpf->prog, cls_bpf->oldprog); | ||
| 123 | } | 117 | } |
| 124 | 118 | ||
| 125 | static int nfp_bpf_setup_tc_block(struct net_device *netdev, | 119 | static int nfp_bpf_setup_tc_block(struct net_device *netdev, |
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 0105445cab83..8e08b6da72f3 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h | |||
| @@ -694,9 +694,7 @@ struct tc_cls_matchall_offload { | |||
| 694 | }; | 694 | }; |
| 695 | 695 | ||
| 696 | enum tc_clsbpf_command { | 696 | enum tc_clsbpf_command { |
| 697 | TC_CLSBPF_ADD, | 697 | TC_CLSBPF_OFFLOAD, |
| 698 | TC_CLSBPF_REPLACE, | ||
| 699 | TC_CLSBPF_DESTROY, | ||
| 700 | TC_CLSBPF_STATS, | 698 | TC_CLSBPF_STATS, |
| 701 | }; | 699 | }; |
| 702 | 700 | ||
| @@ -705,6 +703,7 @@ struct tc_cls_bpf_offload { | |||
| 705 | enum tc_clsbpf_command command; | 703 | enum tc_clsbpf_command command; |
| 706 | struct tcf_exts *exts; | 704 | struct tcf_exts *exts; |
| 707 | struct bpf_prog *prog; | 705 | struct bpf_prog *prog; |
| 706 | struct bpf_prog *oldprog; | ||
| 708 | const char *name; | 707 | const char *name; |
| 709 | bool exts_integrated; | 708 | bool exts_integrated; |
| 710 | u32 gen_flags; | 709 | u32 gen_flags; |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 6fe798c2df1a..8d78e7f4ecc3 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
| @@ -42,7 +42,6 @@ struct cls_bpf_prog { | |||
| 42 | struct list_head link; | 42 | struct list_head link; |
| 43 | struct tcf_result res; | 43 | struct tcf_result res; |
| 44 | bool exts_integrated; | 44 | bool exts_integrated; |
| 45 | bool offloaded; | ||
| 46 | u32 gen_flags; | 45 | u32 gen_flags; |
| 47 | struct tcf_exts exts; | 46 | struct tcf_exts exts; |
| 48 | u32 handle; | 47 | u32 handle; |
| @@ -148,33 +147,37 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog) | |||
| 148 | } | 147 | } |
| 149 | 148 | ||
| 150 | static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, | 149 | static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, |
| 151 | enum tc_clsbpf_command cmd) | 150 | struct cls_bpf_prog *oldprog) |
| 152 | { | 151 | { |
| 153 | bool addorrep = cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE; | ||
| 154 | struct tcf_block *block = tp->chain->block; | 152 | struct tcf_block *block = tp->chain->block; |
| 155 | bool skip_sw = tc_skip_sw(prog->gen_flags); | ||
| 156 | struct tc_cls_bpf_offload cls_bpf = {}; | 153 | struct tc_cls_bpf_offload cls_bpf = {}; |
| 154 | struct cls_bpf_prog *obj; | ||
| 155 | bool skip_sw; | ||
| 157 | int err; | 156 | int err; |
| 158 | 157 | ||
| 158 | skip_sw = prog && tc_skip_sw(prog->gen_flags); | ||
| 159 | obj = prog ?: oldprog; | ||
| 160 | |||
| 159 | tc_cls_common_offload_init(&cls_bpf.common, tp); | 161 | tc_cls_common_offload_init(&cls_bpf.common, tp); |
| 160 | cls_bpf.command = cmd; | 162 | cls_bpf.command = TC_CLSBPF_OFFLOAD; |
| 161 | cls_bpf.exts = &prog->exts; | 163 | cls_bpf.exts = &obj->exts; |
| 162 | cls_bpf.prog = prog->filter; | 164 | cls_bpf.prog = prog ? prog->filter : NULL; |
| 163 | cls_bpf.name = prog->bpf_name; | 165 | cls_bpf.oldprog = oldprog ? oldprog->filter : NULL; |
| 164 | cls_bpf.exts_integrated = prog->exts_integrated; | 166 | cls_bpf.name = obj->bpf_name; |
| 165 | cls_bpf.gen_flags = prog->gen_flags; | 167 | cls_bpf.exts_integrated = obj->exts_integrated; |
| 168 | cls_bpf.gen_flags = obj->gen_flags; | ||
| 166 | 169 | ||
| 167 | err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw); | 170 | err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw); |
| 168 | if (addorrep) { | 171 | if (prog) { |
| 169 | if (err < 0) { | 172 | if (err < 0) { |
| 170 | cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY); | 173 | cls_bpf_offload_cmd(tp, oldprog, prog); |
| 171 | return err; | 174 | return err; |
| 172 | } else if (err > 0) { | 175 | } else if (err > 0) { |
| 173 | prog->gen_flags |= TCA_CLS_FLAGS_IN_HW; | 176 | prog->gen_flags |= TCA_CLS_FLAGS_IN_HW; |
| 174 | } | 177 | } |
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | if (addorrep && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW)) | 180 | if (prog && skip_sw && !(prog->gen_flags & TCA_CLS_FLAGS_IN_HW)) |
| 178 | return -EINVAL; | 181 | return -EINVAL; |
| 179 | 182 | ||
| 180 | return 0; | 183 | return 0; |
| @@ -183,38 +186,17 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, | |||
| 183 | static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, | 186 | static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, |
| 184 | struct cls_bpf_prog *oldprog) | 187 | struct cls_bpf_prog *oldprog) |
| 185 | { | 188 | { |
| 186 | struct cls_bpf_prog *obj = prog; | 189 | if (prog && oldprog && prog->gen_flags != oldprog->gen_flags) |
| 187 | enum tc_clsbpf_command cmd; | 190 | return -EINVAL; |
| 188 | bool skip_sw; | ||
| 189 | int ret; | ||
| 190 | |||
| 191 | skip_sw = tc_skip_sw(prog->gen_flags) || | ||
| 192 | (oldprog && tc_skip_sw(oldprog->gen_flags)); | ||
| 193 | |||
| 194 | if (oldprog && oldprog->offloaded) { | ||
| 195 | if (!tc_skip_hw(prog->gen_flags)) { | ||
| 196 | cmd = TC_CLSBPF_REPLACE; | ||
| 197 | } else if (!tc_skip_sw(prog->gen_flags)) { | ||
| 198 | obj = oldprog; | ||
| 199 | cmd = TC_CLSBPF_DESTROY; | ||
| 200 | } else { | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
| 203 | } else { | ||
| 204 | if (tc_skip_hw(prog->gen_flags)) | ||
| 205 | return skip_sw ? -EINVAL : 0; | ||
| 206 | cmd = TC_CLSBPF_ADD; | ||
| 207 | } | ||
| 208 | |||
| 209 | ret = cls_bpf_offload_cmd(tp, obj, cmd); | ||
| 210 | if (ret) | ||
| 211 | return ret; | ||
| 212 | 191 | ||
| 213 | obj->offloaded = true; | 192 | if (prog && tc_skip_hw(prog->gen_flags)) |
| 214 | if (oldprog) | 193 | prog = NULL; |
| 215 | oldprog->offloaded = false; | 194 | if (oldprog && tc_skip_hw(oldprog->gen_flags)) |
| 195 | oldprog = NULL; | ||
| 196 | if (!prog && !oldprog) | ||
| 197 | return 0; | ||
| 216 | 198 | ||
| 217 | return 0; | 199 | return cls_bpf_offload_cmd(tp, prog, oldprog); |
| 218 | } | 200 | } |
| 219 | 201 | ||
| 220 | static void cls_bpf_stop_offload(struct tcf_proto *tp, | 202 | static void cls_bpf_stop_offload(struct tcf_proto *tp, |
| @@ -222,25 +204,26 @@ static void cls_bpf_stop_offload(struct tcf_proto *tp, | |||
| 222 | { | 204 | { |
| 223 | int err; | 205 | int err; |
| 224 | 206 | ||
| 225 | if (!prog->offloaded) | 207 | err = cls_bpf_offload_cmd(tp, NULL, prog); |
| 226 | return; | 208 | if (err) |
| 227 | |||
| 228 | err = cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY); | ||
| 229 | if (err) { | ||
| 230 | pr_err("Stopping hardware offload failed: %d\n", err); | 209 | pr_err("Stopping hardware offload failed: %d\n", err); |
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | prog->offloaded = false; | ||
| 235 | } | 210 | } |
| 236 | 211 | ||
| 237 | static void cls_bpf_offload_update_stats(struct tcf_proto *tp, | 212 | static void cls_bpf_offload_update_stats(struct tcf_proto *tp, |
| 238 | struct cls_bpf_prog *prog) | 213 | struct cls_bpf_prog *prog) |
| 239 | { | 214 | { |
| 240 | if (!prog->offloaded) | 215 | struct tcf_block *block = tp->chain->block; |
| 241 | return; | 216 | struct tc_cls_bpf_offload cls_bpf = {}; |
| 217 | |||
| 218 | tc_cls_common_offload_init(&cls_bpf.common, tp); | ||
| 219 | cls_bpf.command = TC_CLSBPF_STATS; | ||
| 220 | cls_bpf.exts = &prog->exts; | ||
| 221 | cls_bpf.prog = prog->filter; | ||
| 222 | cls_bpf.name = prog->bpf_name; | ||
| 223 | cls_bpf.exts_integrated = prog->exts_integrated; | ||
| 224 | cls_bpf.gen_flags = prog->gen_flags; | ||
| 242 | 225 | ||
| 243 | cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_STATS); | 226 | tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, false); |
| 244 | } | 227 | } |
| 245 | 228 | ||
| 246 | static int cls_bpf_init(struct tcf_proto *tp) | 229 | static int cls_bpf_init(struct tcf_proto *tp) |
