@@ -673,6 +673,9 @@ static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb)
673673 kfree (indr_block_cb );
674674}
675675
676+ static int tcf_block_setup (struct tcf_block * block ,
677+ struct flow_block_offload * bo );
678+
676679static void tc_indr_block_ing_cmd (struct tc_indr_block_dev * indr_dev ,
677680 struct tc_indr_block_cb * indr_block_cb ,
678681 enum flow_block_command command )
@@ -683,12 +686,14 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
683686 .net = dev_net (indr_dev -> dev ),
684687 .block = indr_dev -> block ,
685688 };
689+ INIT_LIST_HEAD (& bo .cb_list );
686690
687691 if (!indr_dev -> block )
688692 return ;
689693
690694 indr_block_cb -> cb (indr_dev -> dev , indr_block_cb -> cb_priv , TC_SETUP_BLOCK ,
691695 & bo );
696+ tcf_block_setup (indr_dev -> block , & bo );
692697}
693698
694699int __tc_indr_block_cb_register (struct net_device * dev , void * cb_priv ,
@@ -773,6 +778,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
773778 .block = block ,
774779 .extack = extack ,
775780 };
781+ INIT_LIST_HEAD (& bo .cb_list );
776782
777783 indr_dev = tc_indr_block_dev_lookup (dev );
778784 if (!indr_dev )
@@ -783,6 +789,8 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
783789 list_for_each_entry (indr_block_cb , & indr_dev -> cb_list , list )
784790 indr_block_cb -> cb (dev , indr_block_cb -> cb_priv , TC_SETUP_BLOCK ,
785791 & bo );
792+
793+ tcf_block_setup (block , & bo );
786794}
787795
788796static bool tcf_block_offload_in_use (struct tcf_block * block )
@@ -797,13 +805,20 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
797805 struct netlink_ext_ack * extack )
798806{
799807 struct tc_block_offload bo = {};
808+ int err ;
800809
801810 bo .net = dev_net (dev );
802811 bo .command = command ;
803812 bo .binder_type = ei -> binder_type ;
804813 bo .block = block ;
805814 bo .extack = extack ;
806- return dev -> netdev_ops -> ndo_setup_tc (dev , TC_SETUP_BLOCK , & bo );
815+ INIT_LIST_HEAD (& bo .cb_list );
816+
817+ err = dev -> netdev_ops -> ndo_setup_tc (dev , TC_SETUP_BLOCK , & bo );
818+ if (err < 0 )
819+ return err ;
820+
821+ return tcf_block_setup (block , & bo );
807822}
808823
809824static int tcf_block_offload_bind (struct tcf_block * block , struct Qdisc * q ,
@@ -1637,6 +1652,77 @@ void tcf_block_cb_unregister(struct tcf_block *block,
16371652}
16381653EXPORT_SYMBOL (tcf_block_cb_unregister );
16391654
1655+ static int tcf_block_bind (struct tcf_block * block ,
1656+ struct flow_block_offload * bo )
1657+ {
1658+ struct flow_block_cb * block_cb , * next ;
1659+ int err , i = 0 ;
1660+
1661+ list_for_each_entry (block_cb , & bo -> cb_list , list ) {
1662+ err = tcf_block_playback_offloads (block , block_cb -> cb ,
1663+ block_cb -> cb_priv , true,
1664+ tcf_block_offload_in_use (block ),
1665+ bo -> extack );
1666+ if (err )
1667+ goto err_unroll ;
1668+
1669+ i ++ ;
1670+ }
1671+ list_splice (& bo -> cb_list , & block -> cb_list );
1672+
1673+ return 0 ;
1674+
1675+ err_unroll :
1676+ list_for_each_entry_safe (block_cb , next , & bo -> cb_list , list ) {
1677+ if (i -- > 0 ) {
1678+ list_del (& block_cb -> list );
1679+ tcf_block_playback_offloads (block , block_cb -> cb ,
1680+ block_cb -> cb_priv , false,
1681+ tcf_block_offload_in_use (block ),
1682+ NULL );
1683+ }
1684+ flow_block_cb_free (block_cb );
1685+ }
1686+
1687+ return err ;
1688+ }
1689+
1690+ static void tcf_block_unbind (struct tcf_block * block ,
1691+ struct flow_block_offload * bo )
1692+ {
1693+ struct flow_block_cb * block_cb , * next ;
1694+
1695+ list_for_each_entry_safe (block_cb , next , & bo -> cb_list , list ) {
1696+ tcf_block_playback_offloads (block , block_cb -> cb ,
1697+ block_cb -> cb_priv , false,
1698+ tcf_block_offload_in_use (block ),
1699+ NULL );
1700+ list_del (& block_cb -> list );
1701+ flow_block_cb_free (block_cb );
1702+ }
1703+ }
1704+
1705+ static int tcf_block_setup (struct tcf_block * block ,
1706+ struct flow_block_offload * bo )
1707+ {
1708+ int err ;
1709+
1710+ switch (bo -> command ) {
1711+ case FLOW_BLOCK_BIND :
1712+ err = tcf_block_bind (block , bo );
1713+ break ;
1714+ case FLOW_BLOCK_UNBIND :
1715+ err = 0 ;
1716+ tcf_block_unbind (block , bo );
1717+ break ;
1718+ default :
1719+ WARN_ON_ONCE (1 );
1720+ err = - EOPNOTSUPP ;
1721+ }
1722+
1723+ return err ;
1724+ }
1725+
16401726/* Main classifier routine: scans classifier chain attached
16411727 * to this qdisc, (optionally) tests for protocol and asks
16421728 * specific classifiers.
0 commit comments