aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/pkt_cls.h5
-rw-r--r--include/uapi/linux/pkt_cls.h6
-rw-r--r--net/sched/cls_bpf.c13
-rw-r--r--net/sched/cls_flower.c8
-rw-r--r--net/sched/cls_matchall.c15
-rw-r--r--net/sched/cls_u32.c10
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
484static inline bool tc_in_hw(u32 flags)
485{
486 return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false;
487}
488
484enum tc_fl_command { 489enum 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
166static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog, 172static 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
70static void mall_destroy_hw_filter(struct tcf_proto *tp, 75static 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))