@@ -371,14 +371,22 @@ struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, u32 chain_index)
371371}
372372EXPORT_SYMBOL (tcf_chain_get_by_act );
373373
374- static void tc_chain_tmplt_del (struct tcf_chain * chain );
374+ static void tc_chain_tmplt_del (const struct tcf_proto_ops * tmplt_ops ,
375+ void * tmplt_priv );
376+ static int tc_chain_notify_delete (const struct tcf_proto_ops * tmplt_ops ,
377+ void * tmplt_priv , u32 chain_index ,
378+ struct tcf_block * block , struct sk_buff * oskb ,
379+ u32 seq , u16 flags , bool unicast );
375380
376381static void __tcf_chain_put (struct tcf_chain * chain , bool by_act ,
377382 bool explicitly_created )
378383{
379384 struct tcf_block * block = chain -> block ;
385+ const struct tcf_proto_ops * tmplt_ops ;
380386 bool is_last , free_block = false;
381387 unsigned int refcnt ;
388+ void * tmplt_priv ;
389+ u32 chain_index ;
382390
383391 mutex_lock (& block -> lock );
384392 if (explicitly_created ) {
@@ -398,16 +406,21 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act,
398406 */
399407 refcnt = -- chain -> refcnt ;
400408 is_last = refcnt - chain -> action_refcnt == 0 ;
409+ tmplt_ops = chain -> tmplt_ops ;
410+ tmplt_priv = chain -> tmplt_priv ;
411+ chain_index = chain -> index ;
412+
401413 if (refcnt == 0 )
402414 free_block = tcf_chain_detach (chain );
403415 mutex_unlock (& block -> lock );
404416
405417 /* The last dropped non-action reference will trigger notification. */
406418 if (is_last && !by_act )
407- tc_chain_notify (chain , NULL , 0 , 0 , RTM_DELCHAIN , false);
419+ tc_chain_notify_delete (tmplt_ops , tmplt_priv , chain_index ,
420+ block , NULL , 0 , 0 , false);
408421
409422 if (refcnt == 0 ) {
410- tc_chain_tmplt_del (chain );
423+ tc_chain_tmplt_del (tmplt_ops , tmplt_priv );
411424 tcf_chain_destroy (chain , free_block );
412425 }
413426}
@@ -2155,8 +2168,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
21552168 return skb -> len ;
21562169}
21572170
2158- static int tc_chain_fill_node (struct tcf_chain * chain , struct net * net ,
2159- struct sk_buff * skb , struct tcf_block * block ,
2171+ static int tc_chain_fill_node (const struct tcf_proto_ops * tmplt_ops ,
2172+ void * tmplt_priv , u32 chain_index ,
2173+ struct net * net , struct sk_buff * skb ,
2174+ struct tcf_block * block ,
21602175 u32 portid , u32 seq , u16 flags , int event )
21612176{
21622177 unsigned char * b = skb_tail_pointer (skb );
@@ -2165,8 +2180,8 @@ static int tc_chain_fill_node(struct tcf_chain *chain, struct net *net,
21652180 struct tcmsg * tcm ;
21662181 void * priv ;
21672182
2168- ops = chain -> tmplt_ops ;
2169- priv = chain -> tmplt_priv ;
2183+ ops = tmplt_ops ;
2184+ priv = tmplt_priv ;
21702185
21712186 nlh = nlmsg_put (skb , portid , seq , event , sizeof (* tcm ), flags );
21722187 if (!nlh )
@@ -2184,7 +2199,7 @@ static int tc_chain_fill_node(struct tcf_chain *chain, struct net *net,
21842199 tcm -> tcm_block_index = block -> index ;
21852200 }
21862201
2187- if (nla_put_u32 (skb , TCA_CHAIN , chain -> index ))
2202+ if (nla_put_u32 (skb , TCA_CHAIN , chain_index ))
21882203 goto nla_put_failure ;
21892204
21902205 if (ops ) {
@@ -2215,7 +2230,8 @@ static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb,
22152230 if (!skb )
22162231 return - ENOBUFS ;
22172232
2218- if (tc_chain_fill_node (chain , net , skb , block , portid ,
2233+ if (tc_chain_fill_node (chain -> tmplt_ops , chain -> tmplt_priv ,
2234+ chain -> index , net , skb , block , portid ,
22192235 seq , flags , event ) <= 0 ) {
22202236 kfree_skb (skb );
22212237 return - EINVAL ;
@@ -2227,6 +2243,31 @@ static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb,
22272243 return rtnetlink_send (skb , net , portid , RTNLGRP_TC , flags & NLM_F_ECHO );
22282244}
22292245
2246+ static int tc_chain_notify_delete (const struct tcf_proto_ops * tmplt_ops ,
2247+ void * tmplt_priv , u32 chain_index ,
2248+ struct tcf_block * block , struct sk_buff * oskb ,
2249+ u32 seq , u16 flags , bool unicast )
2250+ {
2251+ u32 portid = oskb ? NETLINK_CB (oskb ).portid : 0 ;
2252+ struct net * net = block -> net ;
2253+ struct sk_buff * skb ;
2254+
2255+ skb = alloc_skb (NLMSG_GOODSIZE , GFP_KERNEL );
2256+ if (!skb )
2257+ return - ENOBUFS ;
2258+
2259+ if (tc_chain_fill_node (tmplt_ops , tmplt_priv , chain_index , net , skb ,
2260+ block , portid , seq , flags , RTM_DELCHAIN ) <= 0 ) {
2261+ kfree_skb (skb );
2262+ return - EINVAL ;
2263+ }
2264+
2265+ if (unicast )
2266+ return netlink_unicast (net -> rtnl , skb , portid , MSG_DONTWAIT );
2267+
2268+ return rtnetlink_send (skb , net , portid , RTNLGRP_TC , flags & NLM_F_ECHO );
2269+ }
2270+
22302271static int tc_chain_tmplt_add (struct tcf_chain * chain , struct net * net ,
22312272 struct nlattr * * tca ,
22322273 struct netlink_ext_ack * extack )
@@ -2256,16 +2297,15 @@ static int tc_chain_tmplt_add(struct tcf_chain *chain, struct net *net,
22562297 return 0 ;
22572298}
22582299
2259- static void tc_chain_tmplt_del (struct tcf_chain * chain )
2300+ static void tc_chain_tmplt_del (const struct tcf_proto_ops * tmplt_ops ,
2301+ void * tmplt_priv )
22602302{
2261- const struct tcf_proto_ops * ops = chain -> tmplt_ops ;
2262-
22632303 /* If template ops are set, no work to do for us. */
2264- if (!ops )
2304+ if (!tmplt_ops )
22652305 return ;
22662306
2267- ops -> tmplt_destroy (chain -> tmplt_priv );
2268- module_put (ops -> owner );
2307+ tmplt_ops -> tmplt_destroy (tmplt_priv );
2308+ module_put (tmplt_ops -> owner );
22692309}
22702310
22712311/* Add/delete/get a chain */
@@ -2486,7 +2526,8 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
24862526 index ++ ;
24872527 continue ;
24882528 }
2489- err = tc_chain_fill_node (chain , net , skb , block ,
2529+ err = tc_chain_fill_node (chain -> tmplt_ops , chain -> tmplt_priv ,
2530+ chain -> index , net , skb , block ,
24902531 NETLINK_CB (cb -> skb ).portid ,
24912532 cb -> nlh -> nlmsg_seq , NLM_F_MULTI ,
24922533 RTM_NEWCHAIN );
0 commit comments