@@ -21,6 +21,7 @@ struct cls_mall_filter {
2121 struct tcf_result res ;
2222 u32 handle ;
2323 struct rcu_head rcu ;
24+ u32 flags ;
2425};
2526
2627struct cls_mall_head {
@@ -34,6 +35,9 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
3435 struct cls_mall_head * head = rcu_dereference_bh (tp -> root );
3536 struct cls_mall_filter * f = head -> filter ;
3637
38+ if (tc_skip_sw (f -> flags ))
39+ return -1 ;
40+
3741 return tcf_exts_exec (skb , & f -> exts , res );
3842}
3943
@@ -55,18 +59,61 @@ static void mall_destroy_filter(struct rcu_head *head)
5559 struct cls_mall_filter * f = container_of (head , struct cls_mall_filter , rcu );
5660
5761 tcf_exts_destroy (& f -> exts );
62+
5863 kfree (f );
5964}
6065
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+
61102static bool mall_destroy (struct tcf_proto * tp , bool force )
62103{
63104 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 ;
64107
65- if (!force && head -> filter )
108+ if (!force && f )
66109 return false;
67110
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+ }
70117 RCU_INIT_POINTER (tp -> root , NULL );
71118 kfree_rcu (head , rcu );
72119 return true;
@@ -117,8 +164,10 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
117164{
118165 struct cls_mall_head * head = rtnl_dereference (tp -> root );
119166 struct cls_mall_filter * fold = (struct cls_mall_filter * ) * arg ;
167+ struct net_device * dev = tp -> q -> dev_queue -> dev ;
120168 struct cls_mall_filter * f ;
121169 struct nlattr * tb [TCA_MATCHALL_MAX + 1 ];
170+ u32 flags = 0 ;
122171 int err ;
123172
124173 if (!tca [TCA_OPTIONS ])
@@ -135,6 +184,12 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
135184 if (err < 0 )
136185 return err ;
137186
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+
138193 f = kzalloc (sizeof (* f ), GFP_KERNEL );
139194 if (!f )
140195 return - ENOBUFS ;
@@ -144,11 +199,22 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
144199 if (!handle )
145200 handle = 1 ;
146201 f -> handle = handle ;
202+ f -> flags = flags ;
147203
148204 err = mall_set_parms (net , tp , f , base , tb , tca [TCA_RATE ], ovr );
149205 if (err )
150206 goto errout ;
151207
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+
152218 * arg = (unsigned long ) f ;
153219 rcu_assign_pointer (head -> filter , f );
154220
@@ -163,6 +229,10 @@ static int mall_delete(struct tcf_proto *tp, unsigned long arg)
163229{
164230 struct cls_mall_head * head = rtnl_dereference (tp -> root );
165231 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 );
166236
167237 RCU_INIT_POINTER (head -> filter , NULL );
168238 tcf_unbind_filter (tp , & f -> res );
0 commit comments