@@ -21,6 +21,7 @@ struct cls_mall_filter {
21
21
struct tcf_result res ;
22
22
u32 handle ;
23
23
struct rcu_head rcu ;
24
+ u32 flags ;
24
25
};
25
26
26
27
struct cls_mall_head {
@@ -34,6 +35,9 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
34
35
struct cls_mall_head * head = rcu_dereference_bh (tp -> root );
35
36
struct cls_mall_filter * f = head -> filter ;
36
37
38
+ if (tc_skip_sw (f -> flags ))
39
+ return -1 ;
40
+
37
41
return tcf_exts_exec (skb , & f -> exts , res );
38
42
}
39
43
@@ -55,18 +59,61 @@ static void mall_destroy_filter(struct rcu_head *head)
55
59
struct cls_mall_filter * f = container_of (head , struct cls_mall_filter , rcu );
56
60
57
61
tcf_exts_destroy (& f -> exts );
62
+
58
63
kfree (f );
59
64
}
60
65
66
+ static int mall_replace_hw_filter (struct tcf_proto * tp ,
67
+ struct cls_mall_filter * f ,
68
+ unsigned long cookie )
69
+ {
70
+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
71
+ struct tc_to_netdev offload ;
72
+ struct tc_cls_matchall_offload mall_offload = {0 };
73
+
74
+ offload .type = TC_SETUP_MATCHALL ;
75
+ offload .cls_mall = & mall_offload ;
76
+ offload .cls_mall -> command = TC_CLSMATCHALL_REPLACE ;
77
+ offload .cls_mall -> exts = & f -> exts ;
78
+ offload .cls_mall -> cookie = cookie ;
79
+
80
+ return dev -> netdev_ops -> ndo_setup_tc (dev , tp -> q -> handle , tp -> protocol ,
81
+ & offload );
82
+ }
83
+
84
+ static void mall_destroy_hw_filter (struct tcf_proto * tp ,
85
+ struct cls_mall_filter * f ,
86
+ unsigned long cookie )
87
+ {
88
+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
89
+ struct tc_to_netdev offload ;
90
+ struct tc_cls_matchall_offload mall_offload = {0 };
91
+
92
+ offload .type = TC_SETUP_MATCHALL ;
93
+ offload .cls_mall = & mall_offload ;
94
+ offload .cls_mall -> command = TC_CLSMATCHALL_DESTROY ;
95
+ offload .cls_mall -> exts = NULL ;
96
+ offload .cls_mall -> cookie = cookie ;
97
+
98
+ dev -> netdev_ops -> ndo_setup_tc (dev , tp -> q -> handle , tp -> protocol ,
99
+ & offload );
100
+ }
101
+
61
102
static bool mall_destroy (struct tcf_proto * tp , bool force )
62
103
{
63
104
struct cls_mall_head * head = rtnl_dereference (tp -> root );
105
+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
106
+ struct cls_mall_filter * f = head -> filter ;
64
107
65
- if (!force && head -> filter )
108
+ if (!force && f )
66
109
return false;
67
110
68
- if (head -> filter )
69
- call_rcu (& head -> filter -> rcu , mall_destroy_filter );
111
+ if (f ) {
112
+ if (tc_should_offload (dev , tp , f -> flags ))
113
+ mall_destroy_hw_filter (tp , f , (unsigned long ) f );
114
+
115
+ call_rcu (& f -> rcu , mall_destroy_filter );
116
+ }
70
117
RCU_INIT_POINTER (tp -> root , NULL );
71
118
kfree_rcu (head , rcu );
72
119
return true;
@@ -117,8 +164,10 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
117
164
{
118
165
struct cls_mall_head * head = rtnl_dereference (tp -> root );
119
166
struct cls_mall_filter * fold = (struct cls_mall_filter * ) * arg ;
167
+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
120
168
struct cls_mall_filter * f ;
121
169
struct nlattr * tb [TCA_MATCHALL_MAX + 1 ];
170
+ u32 flags = 0 ;
122
171
int err ;
123
172
124
173
if (!tca [TCA_OPTIONS ])
@@ -135,6 +184,12 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
135
184
if (err < 0 )
136
185
return err ;
137
186
187
+ if (tb [TCA_MATCHALL_FLAGS ]) {
188
+ flags = nla_get_u32 (tb [TCA_MATCHALL_FLAGS ]);
189
+ if (!tc_flags_valid (flags ))
190
+ return - EINVAL ;
191
+ }
192
+
138
193
f = kzalloc (sizeof (* f ), GFP_KERNEL );
139
194
if (!f )
140
195
return - ENOBUFS ;
@@ -144,11 +199,22 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
144
199
if (!handle )
145
200
handle = 1 ;
146
201
f -> handle = handle ;
202
+ f -> flags = flags ;
147
203
148
204
err = mall_set_parms (net , tp , f , base , tb , tca [TCA_RATE ], ovr );
149
205
if (err )
150
206
goto errout ;
151
207
208
+ if (tc_should_offload (dev , tp , flags )) {
209
+ err = mall_replace_hw_filter (tp , f , (unsigned long ) f );
210
+ if (err ) {
211
+ if (tc_skip_sw (flags ))
212
+ goto errout ;
213
+ else
214
+ err = 0 ;
215
+ }
216
+ }
217
+
152
218
* arg = (unsigned long ) f ;
153
219
rcu_assign_pointer (head -> filter , f );
154
220
@@ -163,6 +229,10 @@ static int mall_delete(struct tcf_proto *tp, unsigned long arg)
163
229
{
164
230
struct cls_mall_head * head = rtnl_dereference (tp -> root );
165
231
struct cls_mall_filter * f = (struct cls_mall_filter * ) arg ;
232
+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
233
+
234
+ if (tc_should_offload (dev , tp , f -> flags ))
235
+ mall_destroy_hw_filter (tp , f , (unsigned long ) f );
166
236
167
237
RCU_INIT_POINTER (head -> filter , NULL );
168
238
tcf_unbind_filter (tp , & f -> res );
0 commit comments