diff options
author | Amir Vadai <amirva@mellanox.com> | 2016-05-13 08:55:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-16 13:43:51 -0400 |
commit | bd5251dbf156b6bc0661a9409d46e47160df61dd (patch) | |
tree | 4d2fa3780ab1a0c30c6b1814245e84fe1b69e22c | |
parent | 9dc0b289c4c09bc1a92bdcc055cb37af9b72eb28 (diff) |
net/mlx5_core: Introduce flow steering destination of type counter
When adding a flow steering rule with a counter, need to supply a
destination of type MLX5_FLOW_DESTINATION_TYPE_COUNTER, with a pointer
to a struct mlx5_fc.
Also, MLX5_FLOW_CONTEXT_ACTION_COUNT bit should be set in the action.
Signed-off-by: Amir Vadai <amirva@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 52 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | 23 | ||||
-rw-r--r-- | include/linux/mlx5/fs.h | 2 | ||||
-rw-r--r-- | include/linux/mlx5/mlx5_ifc.h | 2 |
6 files changed, 106 insertions, 10 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index ccb63a0bb54a..a5bb6b695242 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | |||
@@ -241,17 +241,20 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, | |||
241 | MLX5_SET(flow_context, in_flow_context, group_id, group_id); | 241 | MLX5_SET(flow_context, in_flow_context, group_id, group_id); |
242 | MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag); | 242 | MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag); |
243 | MLX5_SET(flow_context, in_flow_context, action, fte->action); | 243 | MLX5_SET(flow_context, in_flow_context, action, fte->action); |
244 | MLX5_SET(flow_context, in_flow_context, destination_list_size, | ||
245 | fte->dests_size); | ||
246 | in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, | 244 | in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, |
247 | match_value); | 245 | match_value); |
248 | memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param)); | 246 | memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param)); |
249 | 247 | ||
248 | in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); | ||
250 | if (fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { | 249 | if (fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { |
251 | in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); | 250 | int list_size = 0; |
251 | |||
252 | list_for_each_entry(dst, &fte->node.children, node.list) { | 252 | list_for_each_entry(dst, &fte->node.children, node.list) { |
253 | unsigned int id; | 253 | unsigned int id; |
254 | 254 | ||
255 | if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) | ||
256 | continue; | ||
257 | |||
255 | MLX5_SET(dest_format_struct, in_dests, destination_type, | 258 | MLX5_SET(dest_format_struct, in_dests, destination_type, |
256 | dst->dest_attr.type); | 259 | dst->dest_attr.type); |
257 | if (dst->dest_attr.type == | 260 | if (dst->dest_attr.type == |
@@ -262,8 +265,31 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, | |||
262 | } | 265 | } |
263 | MLX5_SET(dest_format_struct, in_dests, destination_id, id); | 266 | MLX5_SET(dest_format_struct, in_dests, destination_id, id); |
264 | in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); | 267 | in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); |
268 | list_size++; | ||
269 | } | ||
270 | |||
271 | MLX5_SET(flow_context, in_flow_context, destination_list_size, | ||
272 | list_size); | ||
273 | } | ||
274 | |||
275 | if (fte->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { | ||
276 | int list_size = 0; | ||
277 | |||
278 | list_for_each_entry(dst, &fte->node.children, node.list) { | ||
279 | if (dst->dest_attr.type != | ||
280 | MLX5_FLOW_DESTINATION_TYPE_COUNTER) | ||
281 | continue; | ||
282 | |||
283 | MLX5_SET(flow_counter_list, in_dests, flow_counter_id, | ||
284 | dst->dest_attr.counter->id); | ||
285 | in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); | ||
286 | list_size++; | ||
265 | } | 287 | } |
288 | |||
289 | MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, | ||
290 | list_size); | ||
266 | } | 291 | } |
292 | |||
267 | memset(out, 0, sizeof(out)); | 293 | memset(out, 0, sizeof(out)); |
268 | err = mlx5_cmd_exec_check_status(dev, in, inlen, out, | 294 | err = mlx5_cmd_exec_check_status(dev, in, inlen, out, |
269 | sizeof(out)); | 295 | sizeof(out)); |
@@ -283,18 +309,16 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev, | |||
283 | int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, | 309 | int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, |
284 | struct mlx5_flow_table *ft, | 310 | struct mlx5_flow_table *ft, |
285 | unsigned group_id, | 311 | unsigned group_id, |
312 | int modify_mask, | ||
286 | struct fs_fte *fte) | 313 | struct fs_fte *fte) |
287 | { | 314 | { |
288 | int opmod; | 315 | int opmod; |
289 | int modify_mask; | ||
290 | int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, | 316 | int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, |
291 | flow_table_properties_nic_receive. | 317 | flow_table_properties_nic_receive. |
292 | flow_modify_en); | 318 | flow_modify_en); |
293 | if (!atomic_mod_cap) | 319 | if (!atomic_mod_cap) |
294 | return -ENOTSUPP; | 320 | return -ENOTSUPP; |
295 | opmod = 1; | 321 | opmod = 1; |
296 | modify_mask = 1 << | ||
297 | MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST; | ||
298 | 322 | ||
299 | return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte); | 323 | return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte); |
300 | } | 324 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 18c111a4691f..fc4f7b83fe0a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h | |||
@@ -62,6 +62,7 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev, | |||
62 | int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, | 62 | int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, |
63 | struct mlx5_flow_table *ft, | 63 | struct mlx5_flow_table *ft, |
64 | unsigned group_id, | 64 | unsigned group_id, |
65 | int modify_mask, | ||
65 | struct fs_fte *fte); | 66 | struct fs_fte *fte); |
66 | 67 | ||
67 | int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, | 68 | int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 659a6980cda2..9420def3a2fe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | |||
@@ -344,6 +344,7 @@ static void del_rule(struct fs_node *node) | |||
344 | struct mlx5_flow_group *fg; | 344 | struct mlx5_flow_group *fg; |
345 | struct fs_fte *fte; | 345 | struct fs_fte *fte; |
346 | u32 *match_value; | 346 | u32 *match_value; |
347 | int modify_mask; | ||
347 | struct mlx5_core_dev *dev = get_dev(node); | 348 | struct mlx5_core_dev *dev = get_dev(node); |
348 | int match_len = MLX5_ST_SZ_BYTES(fte_match_param); | 349 | int match_len = MLX5_ST_SZ_BYTES(fte_match_param); |
349 | int err; | 350 | int err; |
@@ -367,8 +368,11 @@ static void del_rule(struct fs_node *node) | |||
367 | } | 368 | } |
368 | if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && | 369 | if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && |
369 | --fte->dests_size) { | 370 | --fte->dests_size) { |
371 | modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST), | ||
370 | err = mlx5_cmd_update_fte(dev, ft, | 372 | err = mlx5_cmd_update_fte(dev, ft, |
371 | fg->id, fte); | 373 | fg->id, |
374 | modify_mask, | ||
375 | fte); | ||
372 | if (err) | 376 | if (err) |
373 | pr_warn("%s can't del rule fg id=%d fte_index=%d\n", | 377 | pr_warn("%s can't del rule fg id=%d fte_index=%d\n", |
374 | __func__, fg->id, fte->index); | 378 | __func__, fg->id, fte->index); |
@@ -615,6 +619,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, | |||
615 | struct mlx5_flow_table *ft; | 619 | struct mlx5_flow_table *ft; |
616 | struct mlx5_flow_group *fg; | 620 | struct mlx5_flow_group *fg; |
617 | struct fs_fte *fte; | 621 | struct fs_fte *fte; |
622 | int modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST); | ||
618 | int err = 0; | 623 | int err = 0; |
619 | 624 | ||
620 | fs_get_obj(fte, rule->node.parent); | 625 | fs_get_obj(fte, rule->node.parent); |
@@ -626,7 +631,9 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, | |||
626 | 631 | ||
627 | memcpy(&rule->dest_attr, dest, sizeof(*dest)); | 632 | memcpy(&rule->dest_attr, dest, sizeof(*dest)); |
628 | err = mlx5_cmd_update_fte(get_dev(&ft->node), | 633 | err = mlx5_cmd_update_fte(get_dev(&ft->node), |
629 | ft, fg->id, fte); | 634 | ft, fg->id, |
635 | modify_mask, | ||
636 | fte); | ||
630 | unlock_ref_node(&fte->node); | 637 | unlock_ref_node(&fte->node); |
631 | 638 | ||
632 | return err; | 639 | return err; |
@@ -877,6 +884,7 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, | |||
877 | { | 884 | { |
878 | struct mlx5_flow_table *ft; | 885 | struct mlx5_flow_table *ft; |
879 | struct mlx5_flow_rule *rule; | 886 | struct mlx5_flow_rule *rule; |
887 | int modify_mask = 0; | ||
880 | int err; | 888 | int err; |
881 | 889 | ||
882 | rule = alloc_rule(dest); | 890 | rule = alloc_rule(dest); |
@@ -892,14 +900,20 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, | |||
892 | list_add(&rule->node.list, &fte->node.children); | 900 | list_add(&rule->node.list, &fte->node.children); |
893 | else | 901 | else |
894 | list_add_tail(&rule->node.list, &fte->node.children); | 902 | list_add_tail(&rule->node.list, &fte->node.children); |
895 | if (dest) | 903 | if (dest) { |
896 | fte->dests_size++; | 904 | fte->dests_size++; |
905 | |||
906 | modify_mask |= dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ? | ||
907 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS) : | ||
908 | BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST); | ||
909 | } | ||
910 | |||
897 | if (fte->dests_size == 1 || !dest) | 911 | if (fte->dests_size == 1 || !dest) |
898 | err = mlx5_cmd_create_fte(get_dev(&ft->node), | 912 | err = mlx5_cmd_create_fte(get_dev(&ft->node), |
899 | ft, fg->id, fte); | 913 | ft, fg->id, fte); |
900 | else | 914 | else |
901 | err = mlx5_cmd_update_fte(get_dev(&ft->node), | 915 | err = mlx5_cmd_update_fte(get_dev(&ft->node), |
902 | ft, fg->id, fte); | 916 | ft, fg->id, modify_mask, fte); |
903 | if (err) | 917 | if (err) |
904 | goto free_rule; | 918 | goto free_rule; |
905 | 919 | ||
@@ -1092,10 +1106,40 @@ unlock_fg: | |||
1092 | return rule; | 1106 | return rule; |
1093 | } | 1107 | } |
1094 | 1108 | ||
1109 | struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule) | ||
1110 | { | ||
1111 | struct mlx5_flow_rule *dst; | ||
1112 | struct fs_fte *fte; | ||
1113 | |||
1114 | fs_get_obj(fte, rule->node.parent); | ||
1115 | |||
1116 | fs_for_each_dst(dst, fte) { | ||
1117 | if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) | ||
1118 | return dst->dest_attr.counter; | ||
1119 | } | ||
1120 | |||
1121 | return NULL; | ||
1122 | } | ||
1123 | |||
1124 | static bool counter_is_valid(struct mlx5_fc *counter, u32 action) | ||
1125 | { | ||
1126 | if (!(action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) | ||
1127 | return !counter; | ||
1128 | |||
1129 | if (!counter) | ||
1130 | return false; | ||
1131 | |||
1132 | /* Hardware support counter for a drop action only */ | ||
1133 | return action == (MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT); | ||
1134 | } | ||
1135 | |||
1095 | static bool dest_is_valid(struct mlx5_flow_destination *dest, | 1136 | static bool dest_is_valid(struct mlx5_flow_destination *dest, |
1096 | u32 action, | 1137 | u32 action, |
1097 | struct mlx5_flow_table *ft) | 1138 | struct mlx5_flow_table *ft) |
1098 | { | 1139 | { |
1140 | if (dest && (dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)) | ||
1141 | return counter_is_valid(dest->counter, action); | ||
1142 | |||
1099 | if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) | 1143 | if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) |
1100 | return true; | 1144 | return true; |
1101 | 1145 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 8e76cc505f5a..1989048ebdfd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h | |||
@@ -96,6 +96,28 @@ struct mlx5_flow_table { | |||
96 | struct list_head fwd_rules; | 96 | struct list_head fwd_rules; |
97 | }; | 97 | }; |
98 | 98 | ||
99 | struct mlx5_fc_cache { | ||
100 | u64 packets; | ||
101 | u64 bytes; | ||
102 | u64 lastuse; | ||
103 | }; | ||
104 | |||
105 | struct mlx5_fc { | ||
106 | struct list_head list; | ||
107 | |||
108 | /* last{packets,bytes} members are used when calculating the delta since | ||
109 | * last reading | ||
110 | */ | ||
111 | u64 lastpackets; | ||
112 | u64 lastbytes; | ||
113 | |||
114 | u16 id; | ||
115 | bool deleted; | ||
116 | bool aging; | ||
117 | |||
118 | struct mlx5_fc_cache cache ____cacheline_aligned_in_smp; | ||
119 | }; | ||
120 | |||
99 | /* Type of children is mlx5_flow_rule */ | 121 | /* Type of children is mlx5_flow_rule */ |
100 | struct fs_fte { | 122 | struct fs_fte { |
101 | struct fs_node node; | 123 | struct fs_node node; |
@@ -105,6 +127,7 @@ struct fs_fte { | |||
105 | u32 index; | 127 | u32 index; |
106 | u32 action; | 128 | u32 action; |
107 | enum fs_fte_status status; | 129 | enum fs_fte_status status; |
130 | struct mlx5_fc *counter; | ||
108 | }; | 131 | }; |
109 | 132 | ||
110 | /* Type of children is mlx5_flow_table/namespace */ | 133 | /* Type of children is mlx5_flow_table/namespace */ |
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index 6467569ad76e..c8b9ede1c20a 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h | |||
@@ -73,6 +73,7 @@ struct mlx5_flow_destination { | |||
73 | u32 tir_num; | 73 | u32 tir_num; |
74 | struct mlx5_flow_table *ft; | 74 | struct mlx5_flow_table *ft; |
75 | u32 vport_num; | 75 | u32 vport_num; |
76 | struct mlx5_fc *counter; | ||
76 | }; | 77 | }; |
77 | }; | 78 | }; |
78 | 79 | ||
@@ -125,4 +126,5 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *fr); | |||
125 | int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, | 126 | int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, |
126 | struct mlx5_flow_destination *dest); | 127 | struct mlx5_flow_destination *dest); |
127 | 128 | ||
129 | struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule); | ||
128 | #endif | 130 | #endif |
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 614c795eadea..9a05cd7e5890 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h | |||
@@ -936,6 +936,8 @@ enum mlx5_flow_destination_type { | |||
936 | MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0, | 936 | MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0, |
937 | MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1, | 937 | MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1, |
938 | MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2, | 938 | MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2, |
939 | |||
940 | MLX5_FLOW_DESTINATION_TYPE_COUNTER = 0x100, | ||
939 | }; | 941 | }; |
940 | 942 | ||
941 | struct mlx5_ifc_dest_format_struct_bits { | 943 | struct mlx5_ifc_dest_format_struct_bits { |