@@ -348,7 +348,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
348
348
break ;
349
349
350
350
case cpu_to_be16 (ETH_P_IPV6 ):
351
- key_layer |= NFP_FLOWER_LAYER_IPV6 ;
351
+ key_layer |= NFP_FLOWER_LAYER_IPV6 ;
352
352
key_size += sizeof (struct nfp_flower_ipv6 );
353
353
break ;
354
354
@@ -399,6 +399,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
399
399
flow_pay -> nfp_tun_ipv4_addr = 0 ;
400
400
flow_pay -> meta .flags = 0 ;
401
401
INIT_LIST_HEAD (& flow_pay -> linked_flows );
402
+ flow_pay -> in_hw = false;
402
403
403
404
return flow_pay ;
404
405
@@ -769,6 +770,8 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
769
770
struct nfp_fl_payload * sub_flow1 ,
770
771
struct nfp_fl_payload * sub_flow2 )
771
772
{
773
+ struct tc_cls_flower_offload merge_tc_off ;
774
+ struct nfp_flower_priv * priv = app -> priv ;
772
775
struct nfp_fl_payload * merge_flow ;
773
776
struct nfp_fl_key_ls merge_key_ls ;
774
777
int err ;
@@ -810,8 +813,34 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
810
813
if (err )
811
814
goto err_unlink_sub_flow1 ;
812
815
813
- err = - EOPNOTSUPP ;
816
+ merge_tc_off .cookie = merge_flow -> tc_flower_cookie ;
817
+ err = nfp_compile_flow_metadata (app , & merge_tc_off , merge_flow ,
818
+ merge_flow -> ingress_dev );
819
+ if (err )
820
+ goto err_unlink_sub_flow2 ;
814
821
822
+ err = rhashtable_insert_fast (& priv -> flow_table , & merge_flow -> fl_node ,
823
+ nfp_flower_table_params );
824
+ if (err )
825
+ goto err_release_metadata ;
826
+
827
+ err = nfp_flower_xmit_flow (app , merge_flow ,
828
+ NFP_FLOWER_CMSG_TYPE_FLOW_MOD );
829
+ if (err )
830
+ goto err_remove_rhash ;
831
+
832
+ merge_flow -> in_hw = true;
833
+ sub_flow1 -> in_hw = false;
834
+
835
+ return 0 ;
836
+
837
+ err_remove_rhash :
838
+ WARN_ON_ONCE (rhashtable_remove_fast (& priv -> flow_table ,
839
+ & merge_flow -> fl_node ,
840
+ nfp_flower_table_params ));
841
+ err_release_metadata :
842
+ nfp_modify_flow_metadata (app , merge_flow );
843
+ err_unlink_sub_flow2 :
815
844
nfp_flower_unlink_flows (merge_flow , sub_flow2 );
816
845
err_unlink_sub_flow1 :
817
846
nfp_flower_unlink_flows (merge_flow , sub_flow1 );
@@ -889,6 +918,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
889
918
if (port )
890
919
port -> tc_offload_cnt ++ ;
891
920
921
+ flow_pay -> in_hw = true;
922
+
892
923
/* Deallocate flow payload when flower rule has been destroyed. */
893
924
kfree (key_layer );
894
925
@@ -910,14 +941,83 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
910
941
return err ;
911
942
}
912
943
944
+ static void
945
+ nfp_flower_remove_merge_flow (struct nfp_app * app ,
946
+ struct nfp_fl_payload * del_sub_flow ,
947
+ struct nfp_fl_payload * merge_flow )
948
+ {
949
+ struct nfp_flower_priv * priv = app -> priv ;
950
+ struct nfp_fl_payload_link * link , * temp ;
951
+ struct nfp_fl_payload * origin ;
952
+ bool mod = false;
953
+ int err ;
954
+
955
+ link = list_first_entry (& merge_flow -> linked_flows ,
956
+ struct nfp_fl_payload_link , merge_flow .list );
957
+ origin = link -> sub_flow .flow ;
958
+
959
+ /* Re-add rule the merge had overwritten if it has not been deleted. */
960
+ if (origin != del_sub_flow )
961
+ mod = true;
962
+
963
+ err = nfp_modify_flow_metadata (app , merge_flow );
964
+ if (err ) {
965
+ nfp_flower_cmsg_warn (app , "Metadata fail for merge flow delete.\n" );
966
+ goto err_free_links ;
967
+ }
968
+
969
+ if (!mod ) {
970
+ err = nfp_flower_xmit_flow (app , merge_flow ,
971
+ NFP_FLOWER_CMSG_TYPE_FLOW_DEL );
972
+ if (err ) {
973
+ nfp_flower_cmsg_warn (app , "Failed to delete merged flow.\n" );
974
+ goto err_free_links ;
975
+ }
976
+ } else {
977
+ __nfp_modify_flow_metadata (priv , origin );
978
+ err = nfp_flower_xmit_flow (app , origin ,
979
+ NFP_FLOWER_CMSG_TYPE_FLOW_MOD );
980
+ if (err )
981
+ nfp_flower_cmsg_warn (app , "Failed to revert merge flow.\n" );
982
+ origin -> in_hw = true;
983
+ }
984
+
985
+ err_free_links :
986
+ /* Clean any links connected with the merged flow. */
987
+ list_for_each_entry_safe (link , temp , & merge_flow -> linked_flows ,
988
+ merge_flow .list )
989
+ nfp_flower_unlink_flow (link );
990
+
991
+ kfree (merge_flow -> action_data );
992
+ kfree (merge_flow -> mask_data );
993
+ kfree (merge_flow -> unmasked_data );
994
+ WARN_ON_ONCE (rhashtable_remove_fast (& priv -> flow_table ,
995
+ & merge_flow -> fl_node ,
996
+ nfp_flower_table_params ));
997
+ kfree_rcu (merge_flow , rcu );
998
+ }
999
+
1000
+ static void
1001
+ nfp_flower_del_linked_merge_flows (struct nfp_app * app ,
1002
+ struct nfp_fl_payload * sub_flow )
1003
+ {
1004
+ struct nfp_fl_payload_link * link , * temp ;
1005
+
1006
+ /* Remove any merge flow formed from the deleted sub_flow. */
1007
+ list_for_each_entry_safe (link , temp , & sub_flow -> linked_flows ,
1008
+ sub_flow .list )
1009
+ nfp_flower_remove_merge_flow (app , sub_flow ,
1010
+ link -> merge_flow .flow );
1011
+ }
1012
+
913
1013
/**
914
1014
* nfp_flower_del_offload() - Removes a flow from hardware.
915
1015
* @app: Pointer to the APP handle
916
1016
* @netdev: netdev structure.
917
1017
* @flow: TC flower classifier offload structure
918
1018
*
919
1019
* Removes a flow from the repeated hash structure and clears the
920
- * action payload.
1020
+ * action payload. Any flows merged from this are also deleted.
921
1021
*
922
1022
* Return: negative value on error, 0 if removed successfully.
923
1023
*/
@@ -939,17 +1039,22 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
939
1039
940
1040
err = nfp_modify_flow_metadata (app , nfp_flow );
941
1041
if (err )
942
- goto err_free_flow ;
1042
+ goto err_free_merge_flow ;
943
1043
944
1044
if (nfp_flow -> nfp_tun_ipv4_addr )
945
1045
nfp_tunnel_del_ipv4_off (app , nfp_flow -> nfp_tun_ipv4_addr );
946
1046
1047
+ if (!nfp_flow -> in_hw ) {
1048
+ err = 0 ;
1049
+ goto err_free_merge_flow ;
1050
+ }
1051
+
947
1052
err = nfp_flower_xmit_flow (app , nfp_flow ,
948
1053
NFP_FLOWER_CMSG_TYPE_FLOW_DEL );
949
- if (err )
950
- goto err_free_flow ;
1054
+ /* Fall through on error. */
951
1055
952
- err_free_flow :
1056
+ err_free_merge_flow :
1057
+ nfp_flower_del_linked_merge_flows (app , nfp_flow );
953
1058
if (port )
954
1059
port -> tc_offload_cnt -- ;
955
1060
kfree (nfp_flow -> action_data );
0 commit comments