@@ -871,6 +871,68 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
871
871
return err ;
872
872
}
873
873
874
+ static int
875
+ mlx5_tc_ct_entry_replace_rule (struct mlx5_tc_ct_priv * ct_priv ,
876
+ struct flow_rule * flow_rule ,
877
+ struct mlx5_ct_entry * entry ,
878
+ bool nat , u8 zone_restore_id )
879
+ {
880
+ struct mlx5_ct_zone_rule * zone_rule = & entry -> zone_rules [nat ];
881
+ struct mlx5_flow_attr * attr = zone_rule -> attr , * old_attr ;
882
+ struct mlx5e_mod_hdr_handle * mh ;
883
+ struct mlx5_ct_fs_rule * rule ;
884
+ struct mlx5_flow_spec * spec ;
885
+ int err ;
886
+
887
+ spec = kvzalloc (sizeof (* spec ), GFP_KERNEL );
888
+ if (!spec )
889
+ return - ENOMEM ;
890
+
891
+ old_attr = mlx5_alloc_flow_attr (ct_priv -> ns_type );
892
+ if (!old_attr ) {
893
+ err = - ENOMEM ;
894
+ goto err_attr ;
895
+ }
896
+ * old_attr = * attr ;
897
+
898
+ err = mlx5_tc_ct_entry_create_mod_hdr (ct_priv , attr , flow_rule , & mh , zone_restore_id ,
899
+ nat , mlx5_tc_ct_entry_has_nat (entry ));
900
+ if (err ) {
901
+ ct_dbg ("Failed to create ct entry mod hdr" );
902
+ goto err_mod_hdr ;
903
+ }
904
+
905
+ mlx5_tc_ct_set_tuple_match (ct_priv , spec , flow_rule );
906
+ mlx5e_tc_match_to_reg_match (spec , ZONE_TO_REG , entry -> tuple .zone , MLX5_CT_ZONE_MASK );
907
+
908
+ rule = ct_priv -> fs_ops -> ct_rule_add (ct_priv -> fs , spec , attr , flow_rule );
909
+ if (IS_ERR (rule )) {
910
+ err = PTR_ERR (rule );
911
+ ct_dbg ("Failed to add replacement ct entry rule, nat: %d" , nat );
912
+ goto err_rule ;
913
+ }
914
+
915
+ ct_priv -> fs_ops -> ct_rule_del (ct_priv -> fs , zone_rule -> rule );
916
+ zone_rule -> rule = rule ;
917
+ mlx5_tc_ct_entry_destroy_mod_hdr (ct_priv , old_attr , zone_rule -> mh );
918
+ zone_rule -> mh = mh ;
919
+
920
+ kfree (old_attr );
921
+ kvfree (spec );
922
+ ct_dbg ("Replaced ct entry rule in zone %d" , entry -> tuple .zone );
923
+
924
+ return 0 ;
925
+
926
+ err_rule :
927
+ mlx5_tc_ct_entry_destroy_mod_hdr (ct_priv , zone_rule -> attr , mh );
928
+ mlx5_put_label_mapping (ct_priv , attr -> ct_attr .ct_labels_id );
929
+ err_mod_hdr :
930
+ kfree (old_attr );
931
+ err_attr :
932
+ kvfree (spec );
933
+ return err ;
934
+ }
935
+
874
936
static bool
875
937
mlx5_tc_ct_entry_valid (struct mlx5_ct_entry * entry )
876
938
{
@@ -1065,6 +1127,52 @@ mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv,
1065
1127
return err ;
1066
1128
}
1067
1129
1130
+ static int
1131
+ mlx5_tc_ct_entry_replace_rules (struct mlx5_tc_ct_priv * ct_priv ,
1132
+ struct flow_rule * flow_rule ,
1133
+ struct mlx5_ct_entry * entry ,
1134
+ u8 zone_restore_id )
1135
+ {
1136
+ int err ;
1137
+
1138
+ err = mlx5_tc_ct_entry_replace_rule (ct_priv , flow_rule , entry , false,
1139
+ zone_restore_id );
1140
+ if (err )
1141
+ return err ;
1142
+
1143
+ err = mlx5_tc_ct_entry_replace_rule (ct_priv , flow_rule , entry , true,
1144
+ zone_restore_id );
1145
+ if (err )
1146
+ mlx5_tc_ct_entry_del_rule (ct_priv , entry , false);
1147
+ return err ;
1148
+ }
1149
+
1150
+ static int
1151
+ mlx5_tc_ct_block_flow_offload_replace (struct mlx5_ct_ft * ft , struct flow_rule * flow_rule ,
1152
+ struct mlx5_ct_entry * entry , unsigned long cookie )
1153
+ {
1154
+ struct mlx5_tc_ct_priv * ct_priv = ft -> ct_priv ;
1155
+ int err ;
1156
+
1157
+ err = mlx5_tc_ct_entry_replace_rules (ct_priv , flow_rule , entry , ft -> zone_restore_id );
1158
+ if (!err )
1159
+ return 0 ;
1160
+
1161
+ /* If failed to update the entry, then look it up again under ht_lock
1162
+ * protection and properly delete it.
1163
+ */
1164
+ spin_lock_bh (& ct_priv -> ht_lock );
1165
+ entry = rhashtable_lookup_fast (& ft -> ct_entries_ht , & cookie , cts_ht_params );
1166
+ if (entry ) {
1167
+ rhashtable_remove_fast (& ft -> ct_entries_ht , & entry -> node , cts_ht_params );
1168
+ spin_unlock_bh (& ct_priv -> ht_lock );
1169
+ mlx5_tc_ct_entry_put (entry );
1170
+ } else {
1171
+ spin_unlock_bh (& ct_priv -> ht_lock );
1172
+ }
1173
+ return err ;
1174
+ }
1175
+
1068
1176
static int
1069
1177
mlx5_tc_ct_block_flow_offload_add (struct mlx5_ct_ft * ft ,
1070
1178
struct flow_cls_offload * flow )
@@ -1087,9 +1195,17 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft,
1087
1195
spin_lock_bh (& ct_priv -> ht_lock );
1088
1196
entry = rhashtable_lookup_fast (& ft -> ct_entries_ht , & cookie , cts_ht_params );
1089
1197
if (entry && refcount_inc_not_zero (& entry -> refcnt )) {
1198
+ if (entry -> restore_cookie == meta_action -> ct_metadata .cookie ) {
1199
+ spin_unlock_bh (& ct_priv -> ht_lock );
1200
+ mlx5_tc_ct_entry_put (entry );
1201
+ return - EEXIST ;
1202
+ }
1203
+ entry -> restore_cookie = meta_action -> ct_metadata .cookie ;
1090
1204
spin_unlock_bh (& ct_priv -> ht_lock );
1205
+
1206
+ err = mlx5_tc_ct_block_flow_offload_replace (ft , flow_rule , entry , cookie );
1091
1207
mlx5_tc_ct_entry_put (entry );
1092
- return - EEXIST ;
1208
+ return err ;
1093
1209
}
1094
1210
spin_unlock_bh (& ct_priv -> ht_lock );
1095
1211
0 commit comments