@@ -673,6 +673,9 @@ static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb)
673
673
kfree (indr_block_cb );
674
674
}
675
675
676
+ static int tcf_block_setup (struct tcf_block * block ,
677
+ struct flow_block_offload * bo );
678
+
676
679
static void tc_indr_block_ing_cmd (struct tc_indr_block_dev * indr_dev ,
677
680
struct tc_indr_block_cb * indr_block_cb ,
678
681
enum flow_block_command command )
@@ -683,12 +686,14 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
683
686
.net = dev_net (indr_dev -> dev ),
684
687
.block = indr_dev -> block ,
685
688
};
689
+ INIT_LIST_HEAD (& bo .cb_list );
686
690
687
691
if (!indr_dev -> block )
688
692
return ;
689
693
690
694
indr_block_cb -> cb (indr_dev -> dev , indr_block_cb -> cb_priv , TC_SETUP_BLOCK ,
691
695
& bo );
696
+ tcf_block_setup (indr_dev -> block , & bo );
692
697
}
693
698
694
699
int __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,
773
778
.block = block ,
774
779
.extack = extack ,
775
780
};
781
+ INIT_LIST_HEAD (& bo .cb_list );
776
782
777
783
indr_dev = tc_indr_block_dev_lookup (dev );
778
784
if (!indr_dev )
@@ -783,6 +789,8 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
783
789
list_for_each_entry (indr_block_cb , & indr_dev -> cb_list , list )
784
790
indr_block_cb -> cb (dev , indr_block_cb -> cb_priv , TC_SETUP_BLOCK ,
785
791
& bo );
792
+
793
+ tcf_block_setup (block , & bo );
786
794
}
787
795
788
796
static bool tcf_block_offload_in_use (struct tcf_block * block )
@@ -797,13 +805,20 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
797
805
struct netlink_ext_ack * extack )
798
806
{
799
807
struct tc_block_offload bo = {};
808
+ int err ;
800
809
801
810
bo .net = dev_net (dev );
802
811
bo .command = command ;
803
812
bo .binder_type = ei -> binder_type ;
804
813
bo .block = block ;
805
814
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 );
807
822
}
808
823
809
824
static 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,
1637
1652
}
1638
1653
EXPORT_SYMBOL (tcf_block_cb_unregister );
1639
1654
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
+
1640
1726
/* Main classifier routine: scans classifier chain attached
1641
1727
* to this qdisc, (optionally) tests for protocol and asks
1642
1728
* specific classifiers.
0 commit comments