diff options
| -rw-r--r-- | include/net/pkt_cls.h | 5 | ||||
| -rw-r--r-- | include/uapi/linux/pkt_cls.h | 6 | ||||
| -rw-r--r-- | net/sched/cls_bpf.c | 13 | ||||
| -rw-r--r-- | net/sched/cls_flower.c | 8 | ||||
| -rw-r--r-- | net/sched/cls_matchall.c | 15 | ||||
| -rw-r--r-- | net/sched/cls_u32.c | 10 |
6 files changed, 50 insertions, 7 deletions
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index be5c12a5c375..269fd78bb0ae 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h | |||
| @@ -481,6 +481,11 @@ static inline bool tc_flags_valid(u32 flags) | |||
| 481 | return true; | 481 | return true; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | static inline bool tc_in_hw(u32 flags) | ||
| 485 | { | ||
| 486 | return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false; | ||
| 487 | } | ||
| 488 | |||
| 484 | enum tc_fl_command { | 489 | enum tc_fl_command { |
| 485 | TC_CLSFLOWER_REPLACE, | 490 | TC_CLSFLOWER_REPLACE, |
| 486 | TC_CLSFLOWER_DESTROY, | 491 | TC_CLSFLOWER_DESTROY, |
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 345551e71410..7a69f2a4ca0c 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h | |||
| @@ -103,8 +103,10 @@ enum { | |||
| 103 | #define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1) | 103 | #define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1) |
| 104 | 104 | ||
| 105 | /* tca flags definitions */ | 105 | /* tca flags definitions */ |
| 106 | #define TCA_CLS_FLAGS_SKIP_HW (1 << 0) | 106 | #define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */ |
| 107 | #define TCA_CLS_FLAGS_SKIP_SW (1 << 1) | 107 | #define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */ |
| 108 | #define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */ | ||
| 109 | #define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */ | ||
| 108 | 110 | ||
| 109 | /* U32 filters */ | 111 | /* U32 filters */ |
| 110 | 112 | ||
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index d9c97018317d..80f688436dd7 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
| @@ -148,6 +148,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, | |||
| 148 | struct net_device *dev = tp->q->dev_queue->dev; | 148 | struct net_device *dev = tp->q->dev_queue->dev; |
| 149 | struct tc_cls_bpf_offload bpf_offload = {}; | 149 | struct tc_cls_bpf_offload bpf_offload = {}; |
| 150 | struct tc_to_netdev offload; | 150 | struct tc_to_netdev offload; |
| 151 | int err; | ||
| 151 | 152 | ||
| 152 | offload.type = TC_SETUP_CLSBPF; | 153 | offload.type = TC_SETUP_CLSBPF; |
| 153 | offload.cls_bpf = &bpf_offload; | 154 | offload.cls_bpf = &bpf_offload; |
| @@ -159,8 +160,13 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, | |||
| 159 | bpf_offload.exts_integrated = prog->exts_integrated; | 160 | bpf_offload.exts_integrated = prog->exts_integrated; |
| 160 | bpf_offload.gen_flags = prog->gen_flags; | 161 | bpf_offload.gen_flags = prog->gen_flags; |
| 161 | 162 | ||
| 162 | return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, | 163 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, |
| 163 | tp->protocol, &offload); | 164 | tp->protocol, &offload); |
| 165 | |||
| 166 | if (!err && (cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE)) | ||
| 167 | prog->gen_flags |= TCA_CLS_FLAGS_IN_HW; | ||
| 168 | |||
| 169 | return err; | ||
| 164 | } | 170 | } |
| 165 | 171 | ||
| 166 | static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, | 172 | static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, |
| @@ -511,6 +517,9 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | |||
| 511 | return ret; | 517 | return ret; |
| 512 | } | 518 | } |
| 513 | 519 | ||
| 520 | if (!tc_in_hw(prog->gen_flags)) | ||
| 521 | prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW; | ||
| 522 | |||
| 514 | if (oldprog) { | 523 | if (oldprog) { |
| 515 | list_replace_rcu(&oldprog->link, &prog->link); | 524 | list_replace_rcu(&oldprog->link, &prog->link); |
| 516 | tcf_unbind_filter(tp, &oldprog->res); | 525 | tcf_unbind_filter(tp, &oldprog->res); |
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 0826c8ec3a76..9d0c99d2e9fb 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
| @@ -273,6 +273,8 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, | |||
| 273 | 273 | ||
| 274 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, | 274 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, |
| 275 | tc); | 275 | tc); |
| 276 | if (!err) | ||
| 277 | f->flags |= TCA_CLS_FLAGS_IN_HW; | ||
| 276 | 278 | ||
| 277 | if (tc_skip_sw(f->flags)) | 279 | if (tc_skip_sw(f->flags)) |
| 278 | return err; | 280 | return err; |
| @@ -912,6 +914,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 912 | goto errout; | 914 | goto errout; |
| 913 | } | 915 | } |
| 914 | 916 | ||
| 917 | if (!tc_in_hw(fnew->flags)) | ||
| 918 | fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW; | ||
| 919 | |||
| 915 | if (fold) { | 920 | if (fold) { |
| 916 | if (!tc_skip_sw(fold->flags)) | 921 | if (!tc_skip_sw(fold->flags)) |
| 917 | rhashtable_remove_fast(&head->ht, &fold->ht_node, | 922 | rhashtable_remove_fast(&head->ht, &fold->ht_node, |
| @@ -1229,7 +1234,8 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, | |||
| 1229 | if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags)) | 1234 | if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags)) |
| 1230 | goto nla_put_failure; | 1235 | goto nla_put_failure; |
| 1231 | 1236 | ||
| 1232 | nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags); | 1237 | if (f->flags && nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags)) |
| 1238 | goto nla_put_failure; | ||
| 1233 | 1239 | ||
| 1234 | if (tcf_exts_dump(skb, &f->exts)) | 1240 | if (tcf_exts_dump(skb, &f->exts)) |
| 1235 | goto nla_put_failure; | 1241 | goto nla_put_failure; |
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index f2141cb55562..224eb2c14346 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c | |||
| @@ -56,6 +56,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp, | |||
| 56 | struct net_device *dev = tp->q->dev_queue->dev; | 56 | struct net_device *dev = tp->q->dev_queue->dev; |
| 57 | struct tc_to_netdev offload; | 57 | struct tc_to_netdev offload; |
| 58 | struct tc_cls_matchall_offload mall_offload = {0}; | 58 | struct tc_cls_matchall_offload mall_offload = {0}; |
| 59 | int err; | ||
| 59 | 60 | ||
| 60 | offload.type = TC_SETUP_MATCHALL; | 61 | offload.type = TC_SETUP_MATCHALL; |
| 61 | offload.cls_mall = &mall_offload; | 62 | offload.cls_mall = &mall_offload; |
| @@ -63,8 +64,12 @@ static int mall_replace_hw_filter(struct tcf_proto *tp, | |||
| 63 | offload.cls_mall->exts = &head->exts; | 64 | offload.cls_mall->exts = &head->exts; |
| 64 | offload.cls_mall->cookie = cookie; | 65 | offload.cls_mall->cookie = cookie; |
| 65 | 66 | ||
| 66 | return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, | 67 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, |
| 67 | &offload); | 68 | &offload); |
| 69 | if (!err) | ||
| 70 | head->flags |= TCA_CLS_FLAGS_IN_HW; | ||
| 71 | |||
| 72 | return err; | ||
| 68 | } | 73 | } |
| 69 | 74 | ||
| 70 | static void mall_destroy_hw_filter(struct tcf_proto *tp, | 75 | static void mall_destroy_hw_filter(struct tcf_proto *tp, |
| @@ -194,6 +199,9 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, | |||
| 194 | } | 199 | } |
| 195 | } | 200 | } |
| 196 | 201 | ||
| 202 | if (!tc_in_hw(new->flags)) | ||
| 203 | new->flags |= TCA_CLS_FLAGS_NOT_IN_HW; | ||
| 204 | |||
| 197 | *arg = (unsigned long) head; | 205 | *arg = (unsigned long) head; |
| 198 | rcu_assign_pointer(tp->root, new); | 206 | rcu_assign_pointer(tp->root, new); |
| 199 | if (head) | 207 | if (head) |
| @@ -244,6 +252,9 @@ static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, | |||
| 244 | nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid)) | 252 | nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid)) |
| 245 | goto nla_put_failure; | 253 | goto nla_put_failure; |
| 246 | 254 | ||
| 255 | if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags)) | ||
| 256 | goto nla_put_failure; | ||
| 257 | |||
| 247 | if (tcf_exts_dump(skb, &head->exts)) | 258 | if (tcf_exts_dump(skb, &head->exts)) |
| 248 | goto nla_put_failure; | 259 | goto nla_put_failure; |
| 249 | 260 | ||
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index a6ec3e4b57ab..4dbe0c680fe6 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
| @@ -523,6 +523,10 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n, | |||
| 523 | 523 | ||
| 524 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, | 524 | err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, |
| 525 | tp->protocol, &offload); | 525 | tp->protocol, &offload); |
| 526 | |||
| 527 | if (!err) | ||
| 528 | n->flags |= TCA_CLS_FLAGS_IN_HW; | ||
| 529 | |||
| 526 | if (tc_skip_sw(flags)) | 530 | if (tc_skip_sw(flags)) |
| 527 | return err; | 531 | return err; |
| 528 | 532 | ||
| @@ -895,6 +899,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, | |||
| 895 | return err; | 899 | return err; |
| 896 | } | 900 | } |
| 897 | 901 | ||
| 902 | if (!tc_in_hw(new->flags)) | ||
| 903 | new->flags |= TCA_CLS_FLAGS_NOT_IN_HW; | ||
| 904 | |||
| 898 | u32_replace_knode(tp, tp_c, new); | 905 | u32_replace_knode(tp, tp_c, new); |
| 899 | tcf_unbind_filter(tp, &n->res); | 906 | tcf_unbind_filter(tp, &n->res); |
| 900 | call_rcu(&n->rcu, u32_delete_key_rcu); | 907 | call_rcu(&n->rcu, u32_delete_key_rcu); |
| @@ -1014,6 +1021,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, | |||
| 1014 | if (err) | 1021 | if (err) |
| 1015 | goto errhw; | 1022 | goto errhw; |
| 1016 | 1023 | ||
| 1024 | if (!tc_in_hw(n->flags)) | ||
| 1025 | n->flags |= TCA_CLS_FLAGS_NOT_IN_HW; | ||
| 1026 | |||
| 1017 | ins = &ht->ht[TC_U32_HASH(handle)]; | 1027 | ins = &ht->ht[TC_U32_HASH(handle)]; |
| 1018 | for (pins = rtnl_dereference(*ins); pins; | 1028 | for (pins = rtnl_dereference(*ins); pins; |
| 1019 | ins = &pins->next, pins = rtnl_dereference(*ins)) | 1029 | ins = &pins->next, pins = rtnl_dereference(*ins)) |
