aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Vadai <amirva@mellanox.com>2016-05-13 08:55:40 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-16 13:43:51 -0400
commitbd5251dbf156b6bc0661a9409d46e47160df61dd (patch)
tree4d2fa3780ab1a0c30c6b1814245e84fe1b69e22c
parent9dc0b289c4c09bc1a92bdcc055cb37af9b72eb28 (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.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h23
-rw-r--r--include/linux/mlx5/fs.h2
-rw-r--r--include/linux/mlx5/mlx5_ifc.h2
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,
283int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, 309int 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,
62int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, 62int 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
67int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, 68int 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
1109struct 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
1124static 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
1095static bool dest_is_valid(struct mlx5_flow_destination *dest, 1136static 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
99struct mlx5_fc_cache {
100 u64 packets;
101 u64 bytes;
102 u64 lastuse;
103};
104
105struct 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 */
100struct fs_fte { 122struct 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);
125int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, 126int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
126 struct mlx5_flow_destination *dest); 127 struct mlx5_flow_destination *dest);
127 128
129struct 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
941struct mlx5_ifc_dest_format_struct_bits { 943struct mlx5_ifc_dest_format_struct_bits {