10d9f9647SVlad Buslov /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
20d9f9647SVlad Buslov /* Copyright (c) 2021 Mellanox Technologies. */
30d9f9647SVlad Buslov 
40d9f9647SVlad Buslov #ifndef __MLX5_EN_TC_PRIV_H__
50d9f9647SVlad Buslov #define __MLX5_EN_TC_PRIV_H__
60d9f9647SVlad Buslov 
70d9f9647SVlad Buslov #include "en_tc.h"
8fad54790SRoi Dayan #include "en/tc/act/act.h"
90d9f9647SVlad Buslov 
100d9f9647SVlad Buslov #define MLX5E_TC_FLOW_BASE (MLX5E_TC_FLAG_LAST_EXPORTED_BIT + 1)
110d9f9647SVlad Buslov 
120d9f9647SVlad Buslov #define MLX5E_TC_MAX_SPLITS 1
130d9f9647SVlad Buslov 
1467d62ee7SRoi Dayan 
150d9f9647SVlad Buslov enum {
160d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_INGRESS               = MLX5E_TC_FLAG_INGRESS_BIT,
170d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_EGRESS                = MLX5E_TC_FLAG_EGRESS_BIT,
180d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_ESWITCH               = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT,
190d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_FT                    = MLX5E_TC_FLAG_FT_OFFLOAD_BIT,
200d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_NIC                   = MLX5E_TC_FLAG_NIC_OFFLOAD_BIT,
210d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_OFFLOADED             = MLX5E_TC_FLOW_BASE,
220d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_HAIRPIN               = MLX5E_TC_FLOW_BASE + 1,
230d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_HAIRPIN_RSS           = MLX5E_TC_FLOW_BASE + 2,
240d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_SLOW                  = MLX5E_TC_FLOW_BASE + 3,
250d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_DUP                   = MLX5E_TC_FLOW_BASE + 4,
260d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_NOT_READY             = MLX5E_TC_FLOW_BASE + 5,
270d9f9647SVlad Buslov 	MLX5E_TC_FLOW_FLAG_DELETED               = MLX5E_TC_FLOW_BASE + 6,
2835c8de16SPaul Blakey 	MLX5E_TC_FLOW_FLAG_L3_TO_L2_DECAP        = MLX5E_TC_FLOW_BASE + 7,
2935c8de16SPaul Blakey 	MLX5E_TC_FLOW_FLAG_TUN_RX                = MLX5E_TC_FLOW_BASE + 8,
3035c8de16SPaul Blakey 	MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 9,
3135c8de16SPaul Blakey 	MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 10,
3235c8de16SPaul Blakey 	MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 11,
330d9f9647SVlad Buslov };
340d9f9647SVlad Buslov 
350d9f9647SVlad Buslov struct mlx5e_tc_flow_parse_attr {
360d9f9647SVlad Buslov 	const struct ip_tunnel_info *tun_info[MLX5_MAX_FLOW_FWD_VPORTS];
37c63741b4SMaor Dickman 	struct mlx5e_mpls_info mpls_info[MLX5_MAX_FLOW_FWD_VPORTS];
380d9f9647SVlad Buslov 	struct net_device *filter_dev;
390d9f9647SVlad Buslov 	struct mlx5_flow_spec spec;
4009bf9792SRoi Dayan 	struct pedit_headers_action hdrs[__PEDIT_CMD_MAX];
410d9f9647SVlad Buslov 	struct mlx5e_tc_mod_hdr_acts mod_hdr_acts;
420d9f9647SVlad Buslov 	int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
43fad54790SRoi Dayan 	struct mlx5e_tc_act_parse_state parse_state;
440d9f9647SVlad Buslov };
450d9f9647SVlad Buslov 
4623bde065SLama Kayal struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc);
4723bde065SLama Kayal 
480d9f9647SVlad Buslov /* Helper struct for accessing a struct containing list_head array.
490d9f9647SVlad Buslov  * Containing struct
500d9f9647SVlad Buslov  *   |- Helper array
510d9f9647SVlad Buslov  *      [0] Helper item 0
520d9f9647SVlad Buslov  *          |- list_head item 0
530d9f9647SVlad Buslov  *          |- index (0)
540d9f9647SVlad Buslov  *      [1] Helper item 1
550d9f9647SVlad Buslov  *          |- list_head item 1
560d9f9647SVlad Buslov  *          |- index (1)
570d9f9647SVlad Buslov  * To access the containing struct from one of the list_head items:
580d9f9647SVlad Buslov  * 1. Get the helper item from the list_head item using
590d9f9647SVlad Buslov  *    helper item =
600d9f9647SVlad Buslov  *        container_of(list_head item, helper struct type, list_head field)
610d9f9647SVlad Buslov  * 2. Get the contining struct from the helper item and its index in the array:
620d9f9647SVlad Buslov  *    containing struct =
630d9f9647SVlad Buslov  *        container_of(helper item, containing struct type, helper field[index])
640d9f9647SVlad Buslov  */
650d9f9647SVlad Buslov struct encap_flow_item {
660d9f9647SVlad Buslov 	struct mlx5e_encap_entry *e; /* attached encap instance */
670d9f9647SVlad Buslov 	struct list_head list;
680d9f9647SVlad Buslov 	int index;
690d9f9647SVlad Buslov };
700d9f9647SVlad Buslov 
71777bb800SVlad Buslov struct encap_route_flow_item {
72777bb800SVlad Buslov 	struct mlx5e_route_entry *r; /* attached route instance */
73777bb800SVlad Buslov 	int index;
74777bb800SVlad Buslov };
75777bb800SVlad Buslov 
760d9f9647SVlad Buslov struct mlx5e_tc_flow {
770d9f9647SVlad Buslov 	struct rhash_head node;
780d9f9647SVlad Buslov 	struct mlx5e_priv *priv;
790d9f9647SVlad Buslov 	u64 cookie;
800d9f9647SVlad Buslov 	unsigned long flags;
810d9f9647SVlad Buslov 	struct mlx5_flow_handle *rule[MLX5E_TC_MAX_SPLITS + 1];
820d9f9647SVlad Buslov 
830d9f9647SVlad Buslov 	/* flows sharing the same reformat object - currently mpls decap */
840d9f9647SVlad Buslov 	struct list_head l3_to_l2_reformat;
850d9f9647SVlad Buslov 	struct mlx5e_decap_entry *decap_reformat;
860d9f9647SVlad Buslov 
87777bb800SVlad Buslov 	/* flows sharing same route entry */
88777bb800SVlad Buslov 	struct list_head decap_routes;
89777bb800SVlad Buslov 	struct mlx5e_route_entry *decap_route;
90777bb800SVlad Buslov 	struct encap_route_flow_item encap_routes[MLX5_MAX_FLOW_FWD_VPORTS];
91777bb800SVlad Buslov 
920d9f9647SVlad Buslov 	/* Flow can be associated with multiple encap IDs.
930d9f9647SVlad Buslov 	 * The number of encaps is bounded by the number of supported
940d9f9647SVlad Buslov 	 * destinations.
950d9f9647SVlad Buslov 	 */
960d9f9647SVlad Buslov 	struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS];
970d9f9647SVlad Buslov 	struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */
980d9f9647SVlad Buslov 	struct list_head hairpin; /* flows sharing the same hairpin */
99*9be6c21fSShay Drory 	struct list_head peer[MLX5_MAX_PORTS];    /* flows with peer flow */
1000d9f9647SVlad Buslov 	struct list_head unready; /* flows not ready to be offloaded (e.g
1010d9f9647SVlad Buslov 				   * due to missing route)
1020d9f9647SVlad Buslov 				   */
103953bb24dSMark Bloch 	struct list_head peer_flows; /* flows on peer */
1040d9f9647SVlad Buslov 	struct net_device *orig_dev; /* netdev adding flow first */
105021905f8SVlad Buslov 	int tmp_entry_index;
1060d9f9647SVlad Buslov 	struct list_head tmp_list; /* temporary flow list used by neigh update */
1070d9f9647SVlad Buslov 	refcount_t refcnt;
1080d9f9647SVlad Buslov 	struct rcu_head rcu_head;
1090d9f9647SVlad Buslov 	struct completion init_done;
110362980eaSVlad Buslov 	struct completion del_hw_done;
1110d9f9647SVlad Buslov 	struct mlx5_flow_attr *attr;
1128300f225SRoi Dayan 	struct list_head attrs;
1138dc47c05SPaul Blakey 	u32 chain_mapping;
1140d9f9647SVlad Buslov };
1150d9f9647SVlad Buslov 
11684ba8062SRoi Dayan struct mlx5_flow_handle *
11784ba8062SRoi Dayan mlx5e_tc_rule_offload(struct mlx5e_priv *priv,
11884ba8062SRoi Dayan 		      struct mlx5_flow_spec *spec,
11984ba8062SRoi Dayan 		      struct mlx5_flow_attr *attr);
12084ba8062SRoi Dayan 
12184ba8062SRoi Dayan void
12284ba8062SRoi Dayan mlx5e_tc_rule_unoffload(struct mlx5e_priv *priv,
123a572c0a7SRoi Dayan 			struct mlx5_flow_handle *rule,
12484ba8062SRoi Dayan 			struct mlx5_flow_attr *attr);
12584ba8062SRoi Dayan 
1260d9f9647SVlad Buslov u8 mlx5e_tc_get_ip_version(struct mlx5_flow_spec *spec, bool outer);
1270d9f9647SVlad Buslov 
1280d9f9647SVlad Buslov struct mlx5_flow_handle *
1290d9f9647SVlad Buslov mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw,
1300d9f9647SVlad Buslov 			   struct mlx5e_tc_flow *flow,
1310d9f9647SVlad Buslov 			   struct mlx5_flow_spec *spec,
1320d9f9647SVlad Buslov 			   struct mlx5_flow_attr *attr);
1330d9f9647SVlad Buslov 
1348300f225SRoi Dayan struct mlx5_flow_attr *
1358300f225SRoi Dayan mlx5e_tc_get_encap_attr(struct mlx5e_tc_flow *flow);
1368300f225SRoi Dayan 
1378300f225SRoi Dayan void mlx5e_tc_unoffload_flow_post_acts(struct mlx5e_tc_flow *flow);
1388300f225SRoi Dayan int mlx5e_tc_offload_flow_post_acts(struct mlx5e_tc_flow *flow);
1398300f225SRoi Dayan 
14067d62ee7SRoi Dayan bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow);
14167d62ee7SRoi Dayan bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow);
1420d9f9647SVlad Buslov bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow);
143e36db1eeSRoi Dayan int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow);
144ab3f3d5eSRoi Dayan bool mlx5e_same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv);
1450d9f9647SVlad Buslov 
__flow_flag_set(struct mlx5e_tc_flow * flow,unsigned long flag)1460d9f9647SVlad Buslov static inline void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag)
1470d9f9647SVlad Buslov {
1480d9f9647SVlad Buslov 	/* Complete all memory stores before setting bit. */
1490d9f9647SVlad Buslov 	smp_mb__before_atomic();
1500d9f9647SVlad Buslov 	set_bit(flag, &flow->flags);
1510d9f9647SVlad Buslov }
1520d9f9647SVlad Buslov 
1530d9f9647SVlad Buslov #define flow_flag_set(flow, flag) __flow_flag_set(flow, MLX5E_TC_FLOW_FLAG_##flag)
1540d9f9647SVlad Buslov 
__flow_flag_test_and_set(struct mlx5e_tc_flow * flow,unsigned long flag)1550d9f9647SVlad Buslov static inline bool __flow_flag_test_and_set(struct mlx5e_tc_flow *flow,
1560d9f9647SVlad Buslov 					    unsigned long flag)
1570d9f9647SVlad Buslov {
1580d9f9647SVlad Buslov 	/* test_and_set_bit() provides all necessary barriers */
1590d9f9647SVlad Buslov 	return test_and_set_bit(flag, &flow->flags);
1600d9f9647SVlad Buslov }
1610d9f9647SVlad Buslov 
1620d9f9647SVlad Buslov #define flow_flag_test_and_set(flow, flag)			\
1630d9f9647SVlad Buslov 	__flow_flag_test_and_set(flow,				\
1640d9f9647SVlad Buslov 				 MLX5E_TC_FLOW_FLAG_##flag)
1650d9f9647SVlad Buslov 
__flow_flag_clear(struct mlx5e_tc_flow * flow,unsigned long flag)1660d9f9647SVlad Buslov static inline void __flow_flag_clear(struct mlx5e_tc_flow *flow, unsigned long flag)
1670d9f9647SVlad Buslov {
1680d9f9647SVlad Buslov 	/* Complete all memory stores before clearing bit. */
1690d9f9647SVlad Buslov 	smp_mb__before_atomic();
1700d9f9647SVlad Buslov 	clear_bit(flag, &flow->flags);
1710d9f9647SVlad Buslov }
1720d9f9647SVlad Buslov 
1730d9f9647SVlad Buslov #define flow_flag_clear(flow, flag) __flow_flag_clear(flow,		\
1740d9f9647SVlad Buslov 						      MLX5E_TC_FLOW_FLAG_##flag)
1750d9f9647SVlad Buslov 
__flow_flag_test(struct mlx5e_tc_flow * flow,unsigned long flag)1760d9f9647SVlad Buslov static inline bool __flow_flag_test(struct mlx5e_tc_flow *flow, unsigned long flag)
1770d9f9647SVlad Buslov {
1780d9f9647SVlad Buslov 	bool ret = test_bit(flag, &flow->flags);
1790d9f9647SVlad Buslov 
1800d9f9647SVlad Buslov 	/* Read fields of flow structure only after checking flags. */
1810d9f9647SVlad Buslov 	smp_mb__after_atomic();
1820d9f9647SVlad Buslov 	return ret;
1830d9f9647SVlad Buslov }
1840d9f9647SVlad Buslov 
1850d9f9647SVlad Buslov #define flow_flag_test(flow, flag) __flow_flag_test(flow,		\
1860d9f9647SVlad Buslov 						    MLX5E_TC_FLOW_FLAG_##flag)
1870d9f9647SVlad Buslov 
1880d9f9647SVlad Buslov void mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
1890d9f9647SVlad Buslov 				       struct mlx5e_tc_flow *flow);
1900d9f9647SVlad Buslov struct mlx5_flow_handle *
1910d9f9647SVlad Buslov mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw,
1920d9f9647SVlad Buslov 			      struct mlx5e_tc_flow *flow,
1930d9f9647SVlad Buslov 			      struct mlx5_flow_spec *spec);
19484ba8062SRoi Dayan 
1950d9f9647SVlad Buslov void mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw,
1960d9f9647SVlad Buslov 				  struct mlx5e_tc_flow *flow,
1970d9f9647SVlad Buslov 				  struct mlx5_flow_attr *attr);
1980d9f9647SVlad Buslov 
1990d9f9647SVlad Buslov struct mlx5e_tc_flow *mlx5e_flow_get(struct mlx5e_tc_flow *flow);
2000d9f9647SVlad Buslov void mlx5e_flow_put(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow);
2010d9f9647SVlad Buslov 
2020d9f9647SVlad Buslov struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow);
2030d9f9647SVlad Buslov 
20427484f71SAriel Levkovich struct mlx5e_tc_int_port_priv *
20527484f71SAriel Levkovich mlx5e_get_int_port_priv(struct mlx5e_priv *priv);
2068ee72638SRoi Dayan 
20774e6b2a8SJianbo Liu struct mlx5e_flow_meters *mlx5e_get_flow_meters(struct mlx5_core_dev *dev);
20874e6b2a8SJianbo Liu 
2098ee72638SRoi Dayan void *mlx5e_get_match_headers_value(u32 flags, struct mlx5_flow_spec *spec);
2108ee72638SRoi Dayan void *mlx5e_get_match_headers_criteria(u32 flags, struct mlx5_flow_spec *spec);
2118ee72638SRoi Dayan 
2120d9f9647SVlad Buslov #endif /* __MLX5_EN_TC_PRIV_H__ */
213