126d688e3SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 226d688e3SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */ 326d688e3SAlex Vesker 426d688e3SAlex Vesker #include <linux/types.h> 540416d8eSHamdan Igbaria #include <linux/crc32.h> 626d688e3SAlex Vesker #include "dr_types.h" 726d688e3SAlex Vesker 826d688e3SAlex Vesker #define DR_STE_CRC_POLY 0xEDB88320L 926d688e3SAlex Vesker #define STE_IPV4 0x1 1026d688e3SAlex Vesker #define STE_IPV6 0x2 1126d688e3SAlex Vesker #define STE_TCP 0x1 1226d688e3SAlex Vesker #define STE_UDP 0x2 1326d688e3SAlex Vesker #define STE_SPI 0x3 1426d688e3SAlex Vesker #define IP_VERSION_IPV4 0x4 1526d688e3SAlex Vesker #define IP_VERSION_IPV6 0x6 1626d688e3SAlex Vesker #define STE_SVLAN 0x1 1726d688e3SAlex Vesker #define STE_CVLAN 0x2 1826d688e3SAlex Vesker 1926d688e3SAlex Vesker #define DR_STE_ENABLE_FLOW_TAG BIT(31) 2026d688e3SAlex Vesker 2126d688e3SAlex Vesker /* Set to STE a specific value using DR_STE_SET */ 2226d688e3SAlex Vesker #define DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, value) do { \ 2326d688e3SAlex Vesker if ((spec)->s_fname) { \ 2426d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, t_fname, value); \ 2526d688e3SAlex Vesker (spec)->s_fname = 0; \ 2626d688e3SAlex Vesker } \ 2726d688e3SAlex Vesker } while (0) 2826d688e3SAlex Vesker 2926d688e3SAlex Vesker /* Set to STE spec->s_fname to tag->t_fname */ 3026d688e3SAlex Vesker #define DR_STE_SET_TAG(lookup_type, tag, t_fname, spec, s_fname) \ 3126d688e3SAlex Vesker DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, spec->s_fname) 3226d688e3SAlex Vesker 3326d688e3SAlex Vesker /* Set to STE -1 to bit_mask->bm_fname and set spec->s_fname as used */ 3426d688e3SAlex Vesker #define DR_STE_SET_MASK(lookup_type, bit_mask, bm_fname, spec, s_fname) \ 3526d688e3SAlex Vesker DR_STE_SET_VAL(lookup_type, bit_mask, bm_fname, spec, s_fname, -1) 3626d688e3SAlex Vesker 3726d688e3SAlex Vesker /* Set to STE spec->s_fname to bit_mask->bm_fname and set spec->s_fname as used */ 3826d688e3SAlex Vesker #define DR_STE_SET_MASK_V(lookup_type, bit_mask, bm_fname, spec, s_fname) \ 3926d688e3SAlex Vesker DR_STE_SET_VAL(lookup_type, bit_mask, bm_fname, spec, s_fname, (spec)->s_fname) 4026d688e3SAlex Vesker 4126d688e3SAlex Vesker #define DR_STE_SET_TCP_FLAGS(lookup_type, tag, spec) do { \ 4226d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_ns, !!((spec)->tcp_flags & (1 << 8))); \ 4326d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_cwr, !!((spec)->tcp_flags & (1 << 7))); \ 4426d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_ece, !!((spec)->tcp_flags & (1 << 6))); \ 4526d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_urg, !!((spec)->tcp_flags & (1 << 5))); \ 4626d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_ack, !!((spec)->tcp_flags & (1 << 4))); \ 4726d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_psh, !!((spec)->tcp_flags & (1 << 3))); \ 4826d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_rst, !!((spec)->tcp_flags & (1 << 2))); \ 4926d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_syn, !!((spec)->tcp_flags & (1 << 1))); \ 5026d688e3SAlex Vesker MLX5_SET(ste_##lookup_type, tag, tcp_fin, !!((spec)->tcp_flags & (1 << 0))); \ 5126d688e3SAlex Vesker } while (0) 5226d688e3SAlex Vesker 5326d688e3SAlex Vesker #define DR_STE_SET_MPLS_MASK(lookup_type, mask, in_out, bit_mask) do { \ 5426d688e3SAlex Vesker DR_STE_SET_MASK_V(lookup_type, mask, mpls0_label, mask, \ 5526d688e3SAlex Vesker in_out##_first_mpls_label);\ 5626d688e3SAlex Vesker DR_STE_SET_MASK_V(lookup_type, mask, mpls0_s_bos, mask, \ 5726d688e3SAlex Vesker in_out##_first_mpls_s_bos); \ 5826d688e3SAlex Vesker DR_STE_SET_MASK_V(lookup_type, mask, mpls0_exp, mask, \ 5926d688e3SAlex Vesker in_out##_first_mpls_exp); \ 6026d688e3SAlex Vesker DR_STE_SET_MASK_V(lookup_type, mask, mpls0_ttl, mask, \ 6126d688e3SAlex Vesker in_out##_first_mpls_ttl); \ 6226d688e3SAlex Vesker } while (0) 6326d688e3SAlex Vesker 6426d688e3SAlex Vesker #define DR_STE_SET_MPLS_TAG(lookup_type, mask, in_out, tag) do { \ 6526d688e3SAlex Vesker DR_STE_SET_TAG(lookup_type, tag, mpls0_label, mask, \ 6626d688e3SAlex Vesker in_out##_first_mpls_label);\ 6726d688e3SAlex Vesker DR_STE_SET_TAG(lookup_type, tag, mpls0_s_bos, mask, \ 6826d688e3SAlex Vesker in_out##_first_mpls_s_bos); \ 6926d688e3SAlex Vesker DR_STE_SET_TAG(lookup_type, tag, mpls0_exp, mask, \ 7026d688e3SAlex Vesker in_out##_first_mpls_exp); \ 7126d688e3SAlex Vesker DR_STE_SET_TAG(lookup_type, tag, mpls0_ttl, mask, \ 7226d688e3SAlex Vesker in_out##_first_mpls_ttl); \ 7326d688e3SAlex Vesker } while (0) 7426d688e3SAlex Vesker 7526d688e3SAlex Vesker #define DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(_misc) (\ 7626d688e3SAlex Vesker (_misc)->outer_first_mpls_over_gre_label || \ 7726d688e3SAlex Vesker (_misc)->outer_first_mpls_over_gre_exp || \ 7826d688e3SAlex Vesker (_misc)->outer_first_mpls_over_gre_s_bos || \ 7926d688e3SAlex Vesker (_misc)->outer_first_mpls_over_gre_ttl) 8026d688e3SAlex Vesker #define DR_STE_IS_OUTER_MPLS_OVER_UDP_SET(_misc) (\ 8126d688e3SAlex Vesker (_misc)->outer_first_mpls_over_udp_label || \ 8226d688e3SAlex Vesker (_misc)->outer_first_mpls_over_udp_exp || \ 8326d688e3SAlex Vesker (_misc)->outer_first_mpls_over_udp_s_bos || \ 8426d688e3SAlex Vesker (_misc)->outer_first_mpls_over_udp_ttl) 8526d688e3SAlex Vesker 8626d688e3SAlex Vesker #define DR_STE_CALC_LU_TYPE(lookup_type, rx, inner) \ 8726d688e3SAlex Vesker ((inner) ? MLX5DR_STE_LU_TYPE_##lookup_type##_I : \ 8826d688e3SAlex Vesker (rx) ? MLX5DR_STE_LU_TYPE_##lookup_type##_D : \ 8926d688e3SAlex Vesker MLX5DR_STE_LU_TYPE_##lookup_type##_O) 9026d688e3SAlex Vesker 9126d688e3SAlex Vesker enum dr_ste_tunl_action { 9226d688e3SAlex Vesker DR_STE_TUNL_ACTION_NONE = 0, 9326d688e3SAlex Vesker DR_STE_TUNL_ACTION_ENABLE = 1, 9426d688e3SAlex Vesker DR_STE_TUNL_ACTION_DECAP = 2, 9526d688e3SAlex Vesker DR_STE_TUNL_ACTION_L3_DECAP = 3, 9626d688e3SAlex Vesker DR_STE_TUNL_ACTION_POP_VLAN = 4, 9726d688e3SAlex Vesker }; 9826d688e3SAlex Vesker 9926d688e3SAlex Vesker enum dr_ste_action_type { 10026d688e3SAlex Vesker DR_STE_ACTION_TYPE_PUSH_VLAN = 1, 10126d688e3SAlex Vesker DR_STE_ACTION_TYPE_ENCAP_L3 = 3, 10226d688e3SAlex Vesker DR_STE_ACTION_TYPE_ENCAP = 4, 10326d688e3SAlex Vesker }; 10426d688e3SAlex Vesker 10526d688e3SAlex Vesker struct dr_hw_ste_format { 10626d688e3SAlex Vesker u8 ctrl[DR_STE_SIZE_CTRL]; 10726d688e3SAlex Vesker u8 tag[DR_STE_SIZE_TAG]; 10826d688e3SAlex Vesker u8 mask[DR_STE_SIZE_MASK]; 10926d688e3SAlex Vesker }; 11026d688e3SAlex Vesker 11140416d8eSHamdan Igbaria static u32 dr_ste_crc32_calc(const void *input_data, size_t length) 11240416d8eSHamdan Igbaria { 11340416d8eSHamdan Igbaria u32 crc = crc32(0, input_data, length); 11440416d8eSHamdan Igbaria 1159ff2e92cSSaeed Mahameed return (__force u32)htonl(crc); 11640416d8eSHamdan Igbaria } 11740416d8eSHamdan Igbaria 11826d688e3SAlex Vesker u32 mlx5dr_ste_calc_hash_index(u8 *hw_ste_p, struct mlx5dr_ste_htbl *htbl) 11926d688e3SAlex Vesker { 12026d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 12126d688e3SAlex Vesker u8 masked[DR_STE_SIZE_TAG] = {}; 12226d688e3SAlex Vesker u32 crc32, index; 12326d688e3SAlex Vesker u16 bit; 12426d688e3SAlex Vesker int i; 12526d688e3SAlex Vesker 12626d688e3SAlex Vesker /* Don't calculate CRC if the result is predicted */ 12726d688e3SAlex Vesker if (htbl->chunk->num_of_entries == 1 || htbl->byte_mask == 0) 12826d688e3SAlex Vesker return 0; 12926d688e3SAlex Vesker 13026d688e3SAlex Vesker /* Mask tag using byte mask, bit per byte */ 13126d688e3SAlex Vesker bit = 1 << (DR_STE_SIZE_TAG - 1); 13226d688e3SAlex Vesker for (i = 0; i < DR_STE_SIZE_TAG; i++) { 13326d688e3SAlex Vesker if (htbl->byte_mask & bit) 13426d688e3SAlex Vesker masked[i] = hw_ste->tag[i]; 13526d688e3SAlex Vesker 13626d688e3SAlex Vesker bit = bit >> 1; 13726d688e3SAlex Vesker } 13826d688e3SAlex Vesker 13940416d8eSHamdan Igbaria crc32 = dr_ste_crc32_calc(masked, DR_STE_SIZE_TAG); 14026d688e3SAlex Vesker index = crc32 & (htbl->chunk->num_of_entries - 1); 14126d688e3SAlex Vesker 14226d688e3SAlex Vesker return index; 14326d688e3SAlex Vesker } 14426d688e3SAlex Vesker 14526d688e3SAlex Vesker static u16 dr_ste_conv_bit_to_byte_mask(u8 *bit_mask) 14626d688e3SAlex Vesker { 14726d688e3SAlex Vesker u16 byte_mask = 0; 14826d688e3SAlex Vesker int i; 14926d688e3SAlex Vesker 15026d688e3SAlex Vesker for (i = 0; i < DR_STE_SIZE_MASK; i++) { 15126d688e3SAlex Vesker byte_mask = byte_mask << 1; 15226d688e3SAlex Vesker if (bit_mask[i] == 0xff) 15326d688e3SAlex Vesker byte_mask |= 1; 15426d688e3SAlex Vesker } 15526d688e3SAlex Vesker return byte_mask; 15626d688e3SAlex Vesker } 15726d688e3SAlex Vesker 15826d688e3SAlex Vesker void mlx5dr_ste_set_bit_mask(u8 *hw_ste_p, u8 *bit_mask) 15926d688e3SAlex Vesker { 16026d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 16126d688e3SAlex Vesker 16226d688e3SAlex Vesker memcpy(hw_ste->mask, bit_mask, DR_STE_SIZE_MASK); 16326d688e3SAlex Vesker } 16426d688e3SAlex Vesker 16526d688e3SAlex Vesker void mlx5dr_ste_rx_set_flow_tag(u8 *hw_ste_p, u32 flow_tag) 16626d688e3SAlex Vesker { 16726d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, qp_list_pointer, 16826d688e3SAlex Vesker DR_STE_ENABLE_FLOW_TAG | flow_tag); 16926d688e3SAlex Vesker } 17026d688e3SAlex Vesker 17126d688e3SAlex Vesker void mlx5dr_ste_set_counter_id(u8 *hw_ste_p, u32 ctr_id) 17226d688e3SAlex Vesker { 17326d688e3SAlex Vesker /* This can be used for both rx_steering_mult and for sx_transmit */ 17426d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, counter_trigger_15_0, ctr_id); 17526d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, counter_trigger_23_16, ctr_id >> 16); 17626d688e3SAlex Vesker } 17726d688e3SAlex Vesker 17826d688e3SAlex Vesker void mlx5dr_ste_set_go_back_bit(u8 *hw_ste_p) 17926d688e3SAlex Vesker { 18026d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, go_back, 1); 18126d688e3SAlex Vesker } 18226d688e3SAlex Vesker 18326d688e3SAlex Vesker void mlx5dr_ste_set_tx_push_vlan(u8 *hw_ste_p, u32 vlan_hdr, 18426d688e3SAlex Vesker bool go_back) 18526d688e3SAlex Vesker { 18626d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, action_type, 18726d688e3SAlex Vesker DR_STE_ACTION_TYPE_PUSH_VLAN); 18826d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, encap_pointer_vlan_data, vlan_hdr); 18926d688e3SAlex Vesker /* Due to HW limitation we need to set this bit, otherwise reforamt + 19026d688e3SAlex Vesker * push vlan will not work. 19126d688e3SAlex Vesker */ 19226d688e3SAlex Vesker if (go_back) 19326d688e3SAlex Vesker mlx5dr_ste_set_go_back_bit(hw_ste_p); 19426d688e3SAlex Vesker } 19526d688e3SAlex Vesker 19626d688e3SAlex Vesker void mlx5dr_ste_set_tx_encap(void *hw_ste_p, u32 reformat_id, int size, bool encap_l3) 19726d688e3SAlex Vesker { 19826d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, action_type, 19926d688e3SAlex Vesker encap_l3 ? DR_STE_ACTION_TYPE_ENCAP_L3 : DR_STE_ACTION_TYPE_ENCAP); 20026d688e3SAlex Vesker /* The hardware expects here size in words (2 byte) */ 20126d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, action_description, size / 2); 20226d688e3SAlex Vesker MLX5_SET(ste_sx_transmit, hw_ste_p, encap_pointer_vlan_data, reformat_id); 20326d688e3SAlex Vesker } 20426d688e3SAlex Vesker 20526d688e3SAlex Vesker void mlx5dr_ste_set_rx_decap(u8 *hw_ste_p) 20626d688e3SAlex Vesker { 20726d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action, 20826d688e3SAlex Vesker DR_STE_TUNL_ACTION_DECAP); 20926d688e3SAlex Vesker } 21026d688e3SAlex Vesker 21126d688e3SAlex Vesker void mlx5dr_ste_set_rx_pop_vlan(u8 *hw_ste_p) 21226d688e3SAlex Vesker { 21326d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action, 21426d688e3SAlex Vesker DR_STE_TUNL_ACTION_POP_VLAN); 21526d688e3SAlex Vesker } 21626d688e3SAlex Vesker 21726d688e3SAlex Vesker void mlx5dr_ste_set_rx_decap_l3(u8 *hw_ste_p, bool vlan) 21826d688e3SAlex Vesker { 21926d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action, 22026d688e3SAlex Vesker DR_STE_TUNL_ACTION_L3_DECAP); 22126d688e3SAlex Vesker MLX5_SET(ste_modify_packet, hw_ste_p, action_description, vlan ? 1 : 0); 22226d688e3SAlex Vesker } 22326d688e3SAlex Vesker 22426d688e3SAlex Vesker void mlx5dr_ste_set_entry_type(u8 *hw_ste_p, u8 entry_type) 22526d688e3SAlex Vesker { 22626d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste_p, entry_type, entry_type); 22726d688e3SAlex Vesker } 22826d688e3SAlex Vesker 22926d688e3SAlex Vesker u8 mlx5dr_ste_get_entry_type(u8 *hw_ste_p) 23026d688e3SAlex Vesker { 23126d688e3SAlex Vesker return MLX5_GET(ste_general, hw_ste_p, entry_type); 23226d688e3SAlex Vesker } 23326d688e3SAlex Vesker 23426d688e3SAlex Vesker void mlx5dr_ste_set_rewrite_actions(u8 *hw_ste_p, u16 num_of_actions, 23526d688e3SAlex Vesker u32 re_write_index) 23626d688e3SAlex Vesker { 23726d688e3SAlex Vesker MLX5_SET(ste_modify_packet, hw_ste_p, number_of_re_write_actions, 23826d688e3SAlex Vesker num_of_actions); 23926d688e3SAlex Vesker MLX5_SET(ste_modify_packet, hw_ste_p, header_re_write_actions_pointer, 24026d688e3SAlex Vesker re_write_index); 24126d688e3SAlex Vesker } 24226d688e3SAlex Vesker 24326d688e3SAlex Vesker void mlx5dr_ste_set_hit_gvmi(u8 *hw_ste_p, u16 gvmi) 24426d688e3SAlex Vesker { 24526d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste_p, next_table_base_63_48, gvmi); 24626d688e3SAlex Vesker } 24726d688e3SAlex Vesker 24826d688e3SAlex Vesker void mlx5dr_ste_init(u8 *hw_ste_p, u8 lu_type, u8 entry_type, 24926d688e3SAlex Vesker u16 gvmi) 25026d688e3SAlex Vesker { 25126d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste_p, entry_type, entry_type); 25226d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste_p, entry_sub_type, lu_type); 25326d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste_p, next_lu_type, MLX5DR_STE_LU_TYPE_DONT_CARE); 25426d688e3SAlex Vesker 25526d688e3SAlex Vesker /* Set GVMI once, this is the same for RX/TX 25626d688e3SAlex Vesker * bits 63_48 of next table base / miss address encode the next GVMI 25726d688e3SAlex Vesker */ 25826d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, gvmi, gvmi); 25926d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, next_table_base_63_48, gvmi); 26026d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_63_48, gvmi); 26126d688e3SAlex Vesker } 26226d688e3SAlex Vesker 26326d688e3SAlex Vesker static void dr_ste_set_always_hit(struct dr_hw_ste_format *hw_ste) 26426d688e3SAlex Vesker { 26526d688e3SAlex Vesker memset(&hw_ste->tag, 0, sizeof(hw_ste->tag)); 26626d688e3SAlex Vesker memset(&hw_ste->mask, 0, sizeof(hw_ste->mask)); 26726d688e3SAlex Vesker } 26826d688e3SAlex Vesker 26926d688e3SAlex Vesker static void dr_ste_set_always_miss(struct dr_hw_ste_format *hw_ste) 27026d688e3SAlex Vesker { 27126d688e3SAlex Vesker hw_ste->tag[0] = 0xdc; 27226d688e3SAlex Vesker hw_ste->mask[0] = 0; 27326d688e3SAlex Vesker } 27426d688e3SAlex Vesker 27526d688e3SAlex Vesker u64 mlx5dr_ste_get_miss_addr(u8 *hw_ste) 27626d688e3SAlex Vesker { 27726d688e3SAlex Vesker u64 index = 27826d688e3SAlex Vesker (MLX5_GET(ste_rx_steering_mult, hw_ste, miss_address_31_6) | 27926d688e3SAlex Vesker MLX5_GET(ste_rx_steering_mult, hw_ste, miss_address_39_32) << 26); 28026d688e3SAlex Vesker 28126d688e3SAlex Vesker return index << 6; 28226d688e3SAlex Vesker } 28326d688e3SAlex Vesker 28426d688e3SAlex Vesker void mlx5dr_ste_set_hit_addr(u8 *hw_ste, u64 icm_addr, u32 ht_size) 28526d688e3SAlex Vesker { 28626d688e3SAlex Vesker u64 index = (icm_addr >> 5) | ht_size; 28726d688e3SAlex Vesker 28826d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste, next_table_base_39_32_size, index >> 27); 28926d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste, next_table_base_31_5_size, index); 29026d688e3SAlex Vesker } 29126d688e3SAlex Vesker 29226d688e3SAlex Vesker u64 mlx5dr_ste_get_icm_addr(struct mlx5dr_ste *ste) 29326d688e3SAlex Vesker { 29426d688e3SAlex Vesker u32 index = ste - ste->htbl->ste_arr; 29526d688e3SAlex Vesker 29626d688e3SAlex Vesker return ste->htbl->chunk->icm_addr + DR_STE_SIZE * index; 29726d688e3SAlex Vesker } 29826d688e3SAlex Vesker 29926d688e3SAlex Vesker u64 mlx5dr_ste_get_mr_addr(struct mlx5dr_ste *ste) 30026d688e3SAlex Vesker { 30126d688e3SAlex Vesker u32 index = ste - ste->htbl->ste_arr; 30226d688e3SAlex Vesker 30326d688e3SAlex Vesker return ste->htbl->chunk->mr_addr + DR_STE_SIZE * index; 30426d688e3SAlex Vesker } 30526d688e3SAlex Vesker 30626d688e3SAlex Vesker struct list_head *mlx5dr_ste_get_miss_list(struct mlx5dr_ste *ste) 30726d688e3SAlex Vesker { 30826d688e3SAlex Vesker u32 index = ste - ste->htbl->ste_arr; 30926d688e3SAlex Vesker 31026d688e3SAlex Vesker return &ste->htbl->miss_list[index]; 31126d688e3SAlex Vesker } 31226d688e3SAlex Vesker 31326d688e3SAlex Vesker static void dr_ste_always_hit_htbl(struct mlx5dr_ste *ste, 31426d688e3SAlex Vesker struct mlx5dr_ste_htbl *next_htbl) 31526d688e3SAlex Vesker { 31626d688e3SAlex Vesker struct mlx5dr_icm_chunk *chunk = next_htbl->chunk; 31726d688e3SAlex Vesker u8 *hw_ste = ste->hw_ste; 31826d688e3SAlex Vesker 31926d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste, byte_mask, next_htbl->byte_mask); 32026d688e3SAlex Vesker MLX5_SET(ste_general, hw_ste, next_lu_type, next_htbl->lu_type); 32126d688e3SAlex Vesker mlx5dr_ste_set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries); 32226d688e3SAlex Vesker 32326d688e3SAlex Vesker dr_ste_set_always_hit((struct dr_hw_ste_format *)ste->hw_ste); 32426d688e3SAlex Vesker } 32526d688e3SAlex Vesker 32626d688e3SAlex Vesker bool mlx5dr_ste_is_last_in_rule(struct mlx5dr_matcher_rx_tx *nic_matcher, 32726d688e3SAlex Vesker u8 ste_location) 32826d688e3SAlex Vesker { 32926d688e3SAlex Vesker return ste_location == nic_matcher->num_of_builders; 33026d688e3SAlex Vesker } 33126d688e3SAlex Vesker 33226d688e3SAlex Vesker /* Replace relevant fields, except of: 33326d688e3SAlex Vesker * htbl - keep the origin htbl 33426d688e3SAlex Vesker * miss_list + list - already took the src from the list. 33526d688e3SAlex Vesker * icm_addr/mr_addr - depends on the hosting table. 33626d688e3SAlex Vesker * 33726d688e3SAlex Vesker * Before: 33826d688e3SAlex Vesker * | a | -> | b | -> | c | -> 33926d688e3SAlex Vesker * 34026d688e3SAlex Vesker * After: 34126d688e3SAlex Vesker * | a | -> | c | -> 34226d688e3SAlex Vesker * While the data that was in b copied to a. 34326d688e3SAlex Vesker */ 34426d688e3SAlex Vesker static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src) 34526d688e3SAlex Vesker { 34626d688e3SAlex Vesker memcpy(dst->hw_ste, src->hw_ste, DR_STE_SIZE_REDUCED); 34726d688e3SAlex Vesker dst->next_htbl = src->next_htbl; 34826d688e3SAlex Vesker if (dst->next_htbl) 34926d688e3SAlex Vesker dst->next_htbl->pointing_ste = dst; 35026d688e3SAlex Vesker 3514ce380caSYevgeny Kliteynik dst->refcount = src->refcount; 35226d688e3SAlex Vesker 35326d688e3SAlex Vesker INIT_LIST_HEAD(&dst->rule_list); 35426d688e3SAlex Vesker list_splice_tail_init(&src->rule_list, &dst->rule_list); 35526d688e3SAlex Vesker } 35626d688e3SAlex Vesker 35726d688e3SAlex Vesker /* Free ste which is the head and the only one in miss_list */ 35826d688e3SAlex Vesker static void 35926d688e3SAlex Vesker dr_ste_remove_head_ste(struct mlx5dr_ste *ste, 36026d688e3SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher, 36126d688e3SAlex Vesker struct mlx5dr_ste_send_info *ste_info_head, 36226d688e3SAlex Vesker struct list_head *send_ste_list, 36326d688e3SAlex Vesker struct mlx5dr_ste_htbl *stats_tbl) 36426d688e3SAlex Vesker { 36526d688e3SAlex Vesker u8 tmp_data_ste[DR_STE_SIZE] = {}; 36626d688e3SAlex Vesker struct mlx5dr_ste tmp_ste = {}; 36726d688e3SAlex Vesker u64 miss_addr; 36826d688e3SAlex Vesker 36926d688e3SAlex Vesker tmp_ste.hw_ste = tmp_data_ste; 37026d688e3SAlex Vesker 37126d688e3SAlex Vesker /* Use temp ste because dr_ste_always_miss_addr 37226d688e3SAlex Vesker * touches bit_mask area which doesn't exist at ste->hw_ste. 37326d688e3SAlex Vesker */ 37426d688e3SAlex Vesker memcpy(tmp_ste.hw_ste, ste->hw_ste, DR_STE_SIZE_REDUCED); 37526d688e3SAlex Vesker miss_addr = nic_matcher->e_anchor->chunk->icm_addr; 37626d688e3SAlex Vesker mlx5dr_ste_always_miss_addr(&tmp_ste, miss_addr); 37726d688e3SAlex Vesker memcpy(ste->hw_ste, tmp_ste.hw_ste, DR_STE_SIZE_REDUCED); 37826d688e3SAlex Vesker 37926d688e3SAlex Vesker list_del_init(&ste->miss_list_node); 38026d688e3SAlex Vesker 38126d688e3SAlex Vesker /* Write full STE size in order to have "always_miss" */ 38226d688e3SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE, 38326d688e3SAlex Vesker 0, tmp_data_ste, 38426d688e3SAlex Vesker ste_info_head, 38526d688e3SAlex Vesker send_ste_list, 38626d688e3SAlex Vesker true /* Copy data */); 38726d688e3SAlex Vesker 38826d688e3SAlex Vesker stats_tbl->ctrl.num_of_valid_entries--; 38926d688e3SAlex Vesker } 39026d688e3SAlex Vesker 39126d688e3SAlex Vesker /* Free ste which is the head but NOT the only one in miss_list: 39226d688e3SAlex Vesker * |_ste_| --> |_next_ste_| -->|__| -->|__| -->/0 39326d688e3SAlex Vesker */ 39426d688e3SAlex Vesker static void 39526d688e3SAlex Vesker dr_ste_replace_head_ste(struct mlx5dr_ste *ste, struct mlx5dr_ste *next_ste, 39626d688e3SAlex Vesker struct mlx5dr_ste_send_info *ste_info_head, 39726d688e3SAlex Vesker struct list_head *send_ste_list, 39826d688e3SAlex Vesker struct mlx5dr_ste_htbl *stats_tbl) 39926d688e3SAlex Vesker 40026d688e3SAlex Vesker { 40126d688e3SAlex Vesker struct mlx5dr_ste_htbl *next_miss_htbl; 40226d688e3SAlex Vesker 40326d688e3SAlex Vesker next_miss_htbl = next_ste->htbl; 40426d688e3SAlex Vesker 40526d688e3SAlex Vesker /* Remove from the miss_list the next_ste before copy */ 40626d688e3SAlex Vesker list_del_init(&next_ste->miss_list_node); 40726d688e3SAlex Vesker 40826d688e3SAlex Vesker /* All rule-members that use next_ste should know about that */ 40926d688e3SAlex Vesker mlx5dr_rule_update_rule_member(next_ste, ste); 41026d688e3SAlex Vesker 41126d688e3SAlex Vesker /* Move data from next into ste */ 41226d688e3SAlex Vesker dr_ste_replace(ste, next_ste); 41326d688e3SAlex Vesker 41426d688e3SAlex Vesker /* Del the htbl that contains the next_ste. 41526d688e3SAlex Vesker * The origin htbl stay with the same number of entries. 41626d688e3SAlex Vesker */ 41726d688e3SAlex Vesker mlx5dr_htbl_put(next_miss_htbl); 41826d688e3SAlex Vesker 41926d688e3SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE_REDUCED, 42026d688e3SAlex Vesker 0, ste->hw_ste, 42126d688e3SAlex Vesker ste_info_head, 42226d688e3SAlex Vesker send_ste_list, 42326d688e3SAlex Vesker true /* Copy data */); 42426d688e3SAlex Vesker 42526d688e3SAlex Vesker stats_tbl->ctrl.num_of_collisions--; 42626d688e3SAlex Vesker stats_tbl->ctrl.num_of_valid_entries--; 42726d688e3SAlex Vesker } 42826d688e3SAlex Vesker 42926d688e3SAlex Vesker /* Free ste that is located in the middle of the miss list: 43026d688e3SAlex Vesker * |__| -->|_prev_ste_|->|_ste_|-->|_next_ste_| 43126d688e3SAlex Vesker */ 43226d688e3SAlex Vesker static void dr_ste_remove_middle_ste(struct mlx5dr_ste *ste, 43326d688e3SAlex Vesker struct mlx5dr_ste_send_info *ste_info, 43426d688e3SAlex Vesker struct list_head *send_ste_list, 43526d688e3SAlex Vesker struct mlx5dr_ste_htbl *stats_tbl) 43626d688e3SAlex Vesker { 43726d688e3SAlex Vesker struct mlx5dr_ste *prev_ste; 43826d688e3SAlex Vesker u64 miss_addr; 43926d688e3SAlex Vesker 44048cbde4bSAlex Vesker prev_ste = list_prev_entry(ste, miss_list_node); 44148cbde4bSAlex Vesker if (WARN_ON(!prev_ste)) 44226d688e3SAlex Vesker return; 44326d688e3SAlex Vesker 44426d688e3SAlex Vesker miss_addr = mlx5dr_ste_get_miss_addr(ste->hw_ste); 44526d688e3SAlex Vesker mlx5dr_ste_set_miss_addr(prev_ste->hw_ste, miss_addr); 44626d688e3SAlex Vesker 44726d688e3SAlex Vesker mlx5dr_send_fill_and_append_ste_send_info(prev_ste, DR_STE_SIZE_REDUCED, 0, 44826d688e3SAlex Vesker prev_ste->hw_ste, ste_info, 44926d688e3SAlex Vesker send_ste_list, true /* Copy data*/); 45026d688e3SAlex Vesker 45126d688e3SAlex Vesker list_del_init(&ste->miss_list_node); 45226d688e3SAlex Vesker 45326d688e3SAlex Vesker stats_tbl->ctrl.num_of_valid_entries--; 45426d688e3SAlex Vesker stats_tbl->ctrl.num_of_collisions--; 45526d688e3SAlex Vesker } 45626d688e3SAlex Vesker 45726d688e3SAlex Vesker void mlx5dr_ste_free(struct mlx5dr_ste *ste, 45826d688e3SAlex Vesker struct mlx5dr_matcher *matcher, 45926d688e3SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher) 46026d688e3SAlex Vesker { 46126d688e3SAlex Vesker struct mlx5dr_ste_send_info *cur_ste_info, *tmp_ste_info; 46226d688e3SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn; 46326d688e3SAlex Vesker struct mlx5dr_ste_send_info ste_info_head; 46426d688e3SAlex Vesker struct mlx5dr_ste *next_ste, *first_ste; 46526d688e3SAlex Vesker bool put_on_origin_table = true; 46626d688e3SAlex Vesker struct mlx5dr_ste_htbl *stats_tbl; 46726d688e3SAlex Vesker LIST_HEAD(send_ste_list); 46826d688e3SAlex Vesker 46948cbde4bSAlex Vesker first_ste = list_first_entry(mlx5dr_ste_get_miss_list(ste), 47026d688e3SAlex Vesker struct mlx5dr_ste, miss_list_node); 47126d688e3SAlex Vesker stats_tbl = first_ste->htbl; 47226d688e3SAlex Vesker 47326d688e3SAlex Vesker /* Two options: 47426d688e3SAlex Vesker * 1. ste is head: 47526d688e3SAlex Vesker * a. head ste is the only ste in the miss list 47626d688e3SAlex Vesker * b. head ste is not the only ste in the miss-list 47726d688e3SAlex Vesker * 2. ste is not head 47826d688e3SAlex Vesker */ 47926d688e3SAlex Vesker if (first_ste == ste) { /* Ste is the head */ 48026d688e3SAlex Vesker struct mlx5dr_ste *last_ste; 48126d688e3SAlex Vesker 48226d688e3SAlex Vesker last_ste = list_last_entry(mlx5dr_ste_get_miss_list(ste), 48326d688e3SAlex Vesker struct mlx5dr_ste, miss_list_node); 48426d688e3SAlex Vesker if (last_ste == first_ste) 48526d688e3SAlex Vesker next_ste = NULL; 48626d688e3SAlex Vesker else 48748cbde4bSAlex Vesker next_ste = list_next_entry(ste, miss_list_node); 48826d688e3SAlex Vesker 48926d688e3SAlex Vesker if (!next_ste) { 49026d688e3SAlex Vesker /* One and only entry in the list */ 49126d688e3SAlex Vesker dr_ste_remove_head_ste(ste, nic_matcher, 49226d688e3SAlex Vesker &ste_info_head, 49326d688e3SAlex Vesker &send_ste_list, 49426d688e3SAlex Vesker stats_tbl); 49526d688e3SAlex Vesker } else { 49626d688e3SAlex Vesker /* First but not only entry in the list */ 49726d688e3SAlex Vesker dr_ste_replace_head_ste(ste, next_ste, &ste_info_head, 49826d688e3SAlex Vesker &send_ste_list, stats_tbl); 49926d688e3SAlex Vesker put_on_origin_table = false; 50026d688e3SAlex Vesker } 50126d688e3SAlex Vesker } else { /* Ste in the middle of the list */ 50226d688e3SAlex Vesker dr_ste_remove_middle_ste(ste, &ste_info_head, &send_ste_list, stats_tbl); 50326d688e3SAlex Vesker } 50426d688e3SAlex Vesker 50526d688e3SAlex Vesker /* Update HW */ 50626d688e3SAlex Vesker list_for_each_entry_safe(cur_ste_info, tmp_ste_info, 50726d688e3SAlex Vesker &send_ste_list, send_list) { 50826d688e3SAlex Vesker list_del(&cur_ste_info->send_list); 50926d688e3SAlex Vesker mlx5dr_send_postsend_ste(dmn, cur_ste_info->ste, 51026d688e3SAlex Vesker cur_ste_info->data, cur_ste_info->size, 51126d688e3SAlex Vesker cur_ste_info->offset); 51226d688e3SAlex Vesker } 51326d688e3SAlex Vesker 51426d688e3SAlex Vesker if (put_on_origin_table) 51526d688e3SAlex Vesker mlx5dr_htbl_put(ste->htbl); 51626d688e3SAlex Vesker } 51726d688e3SAlex Vesker 51826d688e3SAlex Vesker bool mlx5dr_ste_equal_tag(void *src, void *dst) 51926d688e3SAlex Vesker { 52026d688e3SAlex Vesker struct dr_hw_ste_format *s_hw_ste = (struct dr_hw_ste_format *)src; 52126d688e3SAlex Vesker struct dr_hw_ste_format *d_hw_ste = (struct dr_hw_ste_format *)dst; 52226d688e3SAlex Vesker 52326d688e3SAlex Vesker return !memcmp(s_hw_ste->tag, d_hw_ste->tag, DR_STE_SIZE_TAG); 52426d688e3SAlex Vesker } 52526d688e3SAlex Vesker 52626d688e3SAlex Vesker void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste, 52726d688e3SAlex Vesker struct mlx5dr_ste_htbl *next_htbl) 52826d688e3SAlex Vesker { 52926d688e3SAlex Vesker struct mlx5dr_icm_chunk *chunk = next_htbl->chunk; 53026d688e3SAlex Vesker 53126d688e3SAlex Vesker mlx5dr_ste_set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries); 53226d688e3SAlex Vesker } 53326d688e3SAlex Vesker 53426d688e3SAlex Vesker void mlx5dr_ste_set_miss_addr(u8 *hw_ste_p, u64 miss_addr) 53526d688e3SAlex Vesker { 53626d688e3SAlex Vesker u64 index = miss_addr >> 6; 53726d688e3SAlex Vesker 53826d688e3SAlex Vesker /* Miss address for TX and RX STEs located in the same offsets */ 53926d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_39_32, index >> 26); 54026d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_31_6, index); 54126d688e3SAlex Vesker } 54226d688e3SAlex Vesker 54326d688e3SAlex Vesker void mlx5dr_ste_always_miss_addr(struct mlx5dr_ste *ste, u64 miss_addr) 54426d688e3SAlex Vesker { 54526d688e3SAlex Vesker u8 *hw_ste = ste->hw_ste; 54626d688e3SAlex Vesker 54726d688e3SAlex Vesker MLX5_SET(ste_rx_steering_mult, hw_ste, next_lu_type, MLX5DR_STE_LU_TYPE_DONT_CARE); 54826d688e3SAlex Vesker mlx5dr_ste_set_miss_addr(hw_ste, miss_addr); 54926d688e3SAlex Vesker dr_ste_set_always_miss((struct dr_hw_ste_format *)ste->hw_ste); 55026d688e3SAlex Vesker } 55126d688e3SAlex Vesker 55226d688e3SAlex Vesker /* The assumption here is that we don't update the ste->hw_ste if it is not 55326d688e3SAlex Vesker * used ste, so it will be all zero, checking the next_lu_type. 55426d688e3SAlex Vesker */ 55526d688e3SAlex Vesker bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste) 55626d688e3SAlex Vesker { 55726d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)p_hw_ste; 55826d688e3SAlex Vesker 55926d688e3SAlex Vesker if (MLX5_GET(ste_general, hw_ste, next_lu_type) == 56026d688e3SAlex Vesker MLX5DR_STE_LU_TYPE_NOP) 56126d688e3SAlex Vesker return true; 56226d688e3SAlex Vesker 56326d688e3SAlex Vesker return false; 56426d688e3SAlex Vesker } 56526d688e3SAlex Vesker 56626d688e3SAlex Vesker bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste) 56726d688e3SAlex Vesker { 5684ce380caSYevgeny Kliteynik return !ste->refcount; 56926d688e3SAlex Vesker } 57026d688e3SAlex Vesker 57126d688e3SAlex Vesker /* Init one ste as a pattern for ste data array */ 57226d688e3SAlex Vesker void mlx5dr_ste_set_formatted_ste(u16 gvmi, 57326d688e3SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn, 57426d688e3SAlex Vesker struct mlx5dr_ste_htbl *htbl, 57526d688e3SAlex Vesker u8 *formatted_ste, 57626d688e3SAlex Vesker struct mlx5dr_htbl_connect_info *connect_info) 57726d688e3SAlex Vesker { 57826d688e3SAlex Vesker struct mlx5dr_ste ste = {}; 57926d688e3SAlex Vesker 58026d688e3SAlex Vesker mlx5dr_ste_init(formatted_ste, htbl->lu_type, nic_dmn->ste_type, gvmi); 58126d688e3SAlex Vesker ste.hw_ste = formatted_ste; 58226d688e3SAlex Vesker 58326d688e3SAlex Vesker if (connect_info->type == CONNECT_HIT) 58426d688e3SAlex Vesker dr_ste_always_hit_htbl(&ste, connect_info->hit_next_htbl); 58526d688e3SAlex Vesker else 58626d688e3SAlex Vesker mlx5dr_ste_always_miss_addr(&ste, connect_info->miss_icm_addr); 58726d688e3SAlex Vesker } 58826d688e3SAlex Vesker 58926d688e3SAlex Vesker int mlx5dr_ste_htbl_init_and_postsend(struct mlx5dr_domain *dmn, 59026d688e3SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn, 59126d688e3SAlex Vesker struct mlx5dr_ste_htbl *htbl, 59226d688e3SAlex Vesker struct mlx5dr_htbl_connect_info *connect_info, 59326d688e3SAlex Vesker bool update_hw_ste) 59426d688e3SAlex Vesker { 59526d688e3SAlex Vesker u8 formatted_ste[DR_STE_SIZE] = {}; 59626d688e3SAlex Vesker 59726d688e3SAlex Vesker mlx5dr_ste_set_formatted_ste(dmn->info.caps.gvmi, 59826d688e3SAlex Vesker nic_dmn, 59926d688e3SAlex Vesker htbl, 60026d688e3SAlex Vesker formatted_ste, 60126d688e3SAlex Vesker connect_info); 60226d688e3SAlex Vesker 60326d688e3SAlex Vesker return mlx5dr_send_postsend_formatted_htbl(dmn, htbl, formatted_ste, update_hw_ste); 60426d688e3SAlex Vesker } 60526d688e3SAlex Vesker 60626d688e3SAlex Vesker int mlx5dr_ste_create_next_htbl(struct mlx5dr_matcher *matcher, 60726d688e3SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher, 60826d688e3SAlex Vesker struct mlx5dr_ste *ste, 60926d688e3SAlex Vesker u8 *cur_hw_ste, 61026d688e3SAlex Vesker enum mlx5dr_icm_chunk_size log_table_size) 61126d688e3SAlex Vesker { 61226d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)cur_hw_ste; 61326d688e3SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn; 61426d688e3SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn; 61526d688e3SAlex Vesker struct mlx5dr_htbl_connect_info info; 61626d688e3SAlex Vesker struct mlx5dr_ste_htbl *next_htbl; 61726d688e3SAlex Vesker 61826d688e3SAlex Vesker if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste->ste_chain_location)) { 61926d688e3SAlex Vesker u8 next_lu_type; 62026d688e3SAlex Vesker u16 byte_mask; 62126d688e3SAlex Vesker 62226d688e3SAlex Vesker next_lu_type = MLX5_GET(ste_general, hw_ste, next_lu_type); 62326d688e3SAlex Vesker byte_mask = MLX5_GET(ste_general, hw_ste, byte_mask); 62426d688e3SAlex Vesker 62526d688e3SAlex Vesker next_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool, 62626d688e3SAlex Vesker log_table_size, 62726d688e3SAlex Vesker next_lu_type, 62826d688e3SAlex Vesker byte_mask); 62926d688e3SAlex Vesker if (!next_htbl) { 63026d688e3SAlex Vesker mlx5dr_dbg(dmn, "Failed allocating table\n"); 63126d688e3SAlex Vesker return -ENOMEM; 63226d688e3SAlex Vesker } 63326d688e3SAlex Vesker 63426d688e3SAlex Vesker /* Write new table to HW */ 63526d688e3SAlex Vesker info.type = CONNECT_MISS; 63626d688e3SAlex Vesker info.miss_icm_addr = nic_matcher->e_anchor->chunk->icm_addr; 63726d688e3SAlex Vesker if (mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, next_htbl, 63826d688e3SAlex Vesker &info, false)) { 63926d688e3SAlex Vesker mlx5dr_info(dmn, "Failed writing table to HW\n"); 64026d688e3SAlex Vesker goto free_table; 64126d688e3SAlex Vesker } 64226d688e3SAlex Vesker 64326d688e3SAlex Vesker mlx5dr_ste_set_hit_addr_by_next_htbl(cur_hw_ste, next_htbl); 64426d688e3SAlex Vesker ste->next_htbl = next_htbl; 64526d688e3SAlex Vesker next_htbl->pointing_ste = ste; 64626d688e3SAlex Vesker } 64726d688e3SAlex Vesker 64826d688e3SAlex Vesker return 0; 64926d688e3SAlex Vesker 65026d688e3SAlex Vesker free_table: 65126d688e3SAlex Vesker mlx5dr_ste_htbl_free(next_htbl); 65226d688e3SAlex Vesker return -ENOENT; 65326d688e3SAlex Vesker } 65426d688e3SAlex Vesker 65526d688e3SAlex Vesker static void dr_ste_set_ctrl(struct mlx5dr_ste_htbl *htbl) 65626d688e3SAlex Vesker { 65726d688e3SAlex Vesker struct mlx5dr_ste_htbl_ctrl *ctrl = &htbl->ctrl; 65826d688e3SAlex Vesker int num_of_entries; 65926d688e3SAlex Vesker 66026d688e3SAlex Vesker htbl->ctrl.may_grow = true; 66126d688e3SAlex Vesker 66283e79489SAlex Vesker if (htbl->chunk_size == DR_CHUNK_SIZE_MAX - 1 || !htbl->byte_mask) 66326d688e3SAlex Vesker htbl->ctrl.may_grow = false; 66426d688e3SAlex Vesker 66526d688e3SAlex Vesker /* Threshold is 50%, one is added to table of size 1 */ 66626d688e3SAlex Vesker num_of_entries = mlx5dr_icm_pool_chunk_size_to_entries(htbl->chunk_size); 66726d688e3SAlex Vesker ctrl->increase_threshold = (num_of_entries + 1) / 2; 66826d688e3SAlex Vesker } 66926d688e3SAlex Vesker 67026d688e3SAlex Vesker struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool, 67126d688e3SAlex Vesker enum mlx5dr_icm_chunk_size chunk_size, 67226d688e3SAlex Vesker u8 lu_type, u16 byte_mask) 67326d688e3SAlex Vesker { 67426d688e3SAlex Vesker struct mlx5dr_icm_chunk *chunk; 67526d688e3SAlex Vesker struct mlx5dr_ste_htbl *htbl; 67626d688e3SAlex Vesker int i; 67726d688e3SAlex Vesker 67826d688e3SAlex Vesker htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); 67926d688e3SAlex Vesker if (!htbl) 68026d688e3SAlex Vesker return NULL; 68126d688e3SAlex Vesker 68226d688e3SAlex Vesker chunk = mlx5dr_icm_alloc_chunk(pool, chunk_size); 68326d688e3SAlex Vesker if (!chunk) 68426d688e3SAlex Vesker goto out_free_htbl; 68526d688e3SAlex Vesker 68626d688e3SAlex Vesker htbl->chunk = chunk; 68726d688e3SAlex Vesker htbl->lu_type = lu_type; 68826d688e3SAlex Vesker htbl->byte_mask = byte_mask; 68926d688e3SAlex Vesker htbl->ste_arr = chunk->ste_arr; 69026d688e3SAlex Vesker htbl->hw_ste_arr = chunk->hw_ste_arr; 69126d688e3SAlex Vesker htbl->miss_list = chunk->miss_list; 6924ce380caSYevgeny Kliteynik htbl->refcount = 0; 69326d688e3SAlex Vesker 69426d688e3SAlex Vesker for (i = 0; i < chunk->num_of_entries; i++) { 69526d688e3SAlex Vesker struct mlx5dr_ste *ste = &htbl->ste_arr[i]; 69626d688e3SAlex Vesker 69726d688e3SAlex Vesker ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED; 69826d688e3SAlex Vesker ste->htbl = htbl; 6994ce380caSYevgeny Kliteynik ste->refcount = 0; 70026d688e3SAlex Vesker INIT_LIST_HEAD(&ste->miss_list_node); 70126d688e3SAlex Vesker INIT_LIST_HEAD(&htbl->miss_list[i]); 70226d688e3SAlex Vesker INIT_LIST_HEAD(&ste->rule_list); 70326d688e3SAlex Vesker } 70426d688e3SAlex Vesker 70526d688e3SAlex Vesker htbl->chunk_size = chunk_size; 70626d688e3SAlex Vesker dr_ste_set_ctrl(htbl); 70726d688e3SAlex Vesker return htbl; 70826d688e3SAlex Vesker 70926d688e3SAlex Vesker out_free_htbl: 71026d688e3SAlex Vesker kfree(htbl); 71126d688e3SAlex Vesker return NULL; 71226d688e3SAlex Vesker } 71326d688e3SAlex Vesker 71426d688e3SAlex Vesker int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl) 71526d688e3SAlex Vesker { 7164ce380caSYevgeny Kliteynik if (htbl->refcount) 71726d688e3SAlex Vesker return -EBUSY; 71826d688e3SAlex Vesker 71926d688e3SAlex Vesker mlx5dr_icm_free_chunk(htbl->chunk); 72026d688e3SAlex Vesker kfree(htbl); 72126d688e3SAlex Vesker return 0; 72226d688e3SAlex Vesker } 72326d688e3SAlex Vesker 72426d688e3SAlex Vesker int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn, 72526d688e3SAlex Vesker u8 match_criteria, 72626d688e3SAlex Vesker struct mlx5dr_match_param *mask, 72726d688e3SAlex Vesker struct mlx5dr_match_param *value) 72826d688e3SAlex Vesker { 72926d688e3SAlex Vesker if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) { 73026d688e3SAlex Vesker if (mask->misc.source_port && mask->misc.source_port != 0xffff) { 731b7d0db55SErez Shitrit mlx5dr_err(dmn, "Partial mask source_port is not supported\n"); 73226d688e3SAlex Vesker return -EINVAL; 73326d688e3SAlex Vesker } 73426d688e3SAlex Vesker } 73526d688e3SAlex Vesker 73626d688e3SAlex Vesker return 0; 73726d688e3SAlex Vesker } 73826d688e3SAlex Vesker 73926d688e3SAlex Vesker int mlx5dr_ste_build_ste_arr(struct mlx5dr_matcher *matcher, 74026d688e3SAlex Vesker struct mlx5dr_matcher_rx_tx *nic_matcher, 74126d688e3SAlex Vesker struct mlx5dr_match_param *value, 74226d688e3SAlex Vesker u8 *ste_arr) 74326d688e3SAlex Vesker { 74426d688e3SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn; 74526d688e3SAlex Vesker struct mlx5dr_domain *dmn = matcher->tbl->dmn; 74626d688e3SAlex Vesker struct mlx5dr_ste_build *sb; 74726d688e3SAlex Vesker int ret, i; 74826d688e3SAlex Vesker 74926d688e3SAlex Vesker ret = mlx5dr_ste_build_pre_check(dmn, matcher->match_criteria, 75026d688e3SAlex Vesker &matcher->mask, value); 75126d688e3SAlex Vesker if (ret) 75226d688e3SAlex Vesker return ret; 75326d688e3SAlex Vesker 75426d688e3SAlex Vesker sb = nic_matcher->ste_builder; 75526d688e3SAlex Vesker for (i = 0; i < nic_matcher->num_of_builders; i++) { 75626d688e3SAlex Vesker mlx5dr_ste_init(ste_arr, 75726d688e3SAlex Vesker sb->lu_type, 75826d688e3SAlex Vesker nic_dmn->ste_type, 75926d688e3SAlex Vesker dmn->info.caps.gvmi); 76026d688e3SAlex Vesker 76126d688e3SAlex Vesker mlx5dr_ste_set_bit_mask(ste_arr, sb->bit_mask); 76226d688e3SAlex Vesker 76326d688e3SAlex Vesker ret = sb->ste_build_tag_func(value, sb, ste_arr); 76426d688e3SAlex Vesker if (ret) 76526d688e3SAlex Vesker return ret; 76626d688e3SAlex Vesker 76726d688e3SAlex Vesker /* Connect the STEs */ 76826d688e3SAlex Vesker if (i < (nic_matcher->num_of_builders - 1)) { 76926d688e3SAlex Vesker /* Need the next builder for these fields, 77026d688e3SAlex Vesker * not relevant for the last ste in the chain. 77126d688e3SAlex Vesker */ 77226d688e3SAlex Vesker sb++; 77326d688e3SAlex Vesker MLX5_SET(ste_general, ste_arr, next_lu_type, sb->lu_type); 77426d688e3SAlex Vesker MLX5_SET(ste_general, ste_arr, byte_mask, sb->byte_mask); 77526d688e3SAlex Vesker } 77626d688e3SAlex Vesker ste_arr += DR_STE_SIZE; 77726d688e3SAlex Vesker } 77826d688e3SAlex Vesker return 0; 77926d688e3SAlex Vesker } 78026d688e3SAlex Vesker 78126d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_bit_mask(struct mlx5dr_match_param *value, 78226d688e3SAlex Vesker bool inner, u8 *bit_mask) 78326d688e3SAlex Vesker { 78426d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 78526d688e3SAlex Vesker 78626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_47_16, mask, dmac_47_16); 78726d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_15_0, mask, dmac_15_0); 78826d688e3SAlex Vesker 78926d688e3SAlex Vesker if (mask->smac_47_16 || mask->smac_15_0) { 79026d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_47_32, 79126d688e3SAlex Vesker mask->smac_47_16 >> 16); 79226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_31_0, 79326d688e3SAlex Vesker mask->smac_47_16 << 16 | mask->smac_15_0); 79426d688e3SAlex Vesker mask->smac_47_16 = 0; 79526d688e3SAlex Vesker mask->smac_15_0 = 0; 79626d688e3SAlex Vesker } 79726d688e3SAlex Vesker 79826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_vlan_id, mask, first_vid); 79926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_cfi, mask, first_cfi); 80026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_priority, mask, first_prio); 80126d688e3SAlex Vesker DR_STE_SET_MASK(eth_l2_src_dst, bit_mask, l3_type, mask, ip_version); 80226d688e3SAlex Vesker 80326d688e3SAlex Vesker if (mask->cvlan_tag) { 80426d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1); 80526d688e3SAlex Vesker mask->cvlan_tag = 0; 80626d688e3SAlex Vesker } else if (mask->svlan_tag) { 80726d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1); 80826d688e3SAlex Vesker mask->svlan_tag = 0; 80926d688e3SAlex Vesker } 81026d688e3SAlex Vesker 81126d688e3SAlex Vesker if (mask->cvlan_tag || mask->svlan_tag) { 81226d688e3SAlex Vesker pr_info("Invalid c/svlan mask configuration\n"); 81326d688e3SAlex Vesker return -EINVAL; 81426d688e3SAlex Vesker } 81526d688e3SAlex Vesker 81626d688e3SAlex Vesker return 0; 81726d688e3SAlex Vesker } 81826d688e3SAlex Vesker 81926d688e3SAlex Vesker static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec) 82026d688e3SAlex Vesker { 82126d688e3SAlex Vesker spec->gre_c_present = MLX5_GET(fte_match_set_misc, mask, gre_c_present); 82226d688e3SAlex Vesker spec->gre_k_present = MLX5_GET(fte_match_set_misc, mask, gre_k_present); 82326d688e3SAlex Vesker spec->gre_s_present = MLX5_GET(fte_match_set_misc, mask, gre_s_present); 82426d688e3SAlex Vesker spec->source_vhca_port = MLX5_GET(fte_match_set_misc, mask, source_vhca_port); 82526d688e3SAlex Vesker spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn); 82626d688e3SAlex Vesker 82726d688e3SAlex Vesker spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port); 828640bdb1fSAlaa Hleihel spec->source_eswitch_owner_vhca_id = MLX5_GET(fte_match_set_misc, mask, 829640bdb1fSAlaa Hleihel source_eswitch_owner_vhca_id); 83026d688e3SAlex Vesker 83126d688e3SAlex Vesker spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio); 83226d688e3SAlex Vesker spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi); 83326d688e3SAlex Vesker spec->outer_second_vid = MLX5_GET(fte_match_set_misc, mask, outer_second_vid); 83426d688e3SAlex Vesker spec->inner_second_prio = MLX5_GET(fte_match_set_misc, mask, inner_second_prio); 83526d688e3SAlex Vesker spec->inner_second_cfi = MLX5_GET(fte_match_set_misc, mask, inner_second_cfi); 83626d688e3SAlex Vesker spec->inner_second_vid = MLX5_GET(fte_match_set_misc, mask, inner_second_vid); 83726d688e3SAlex Vesker 83826d688e3SAlex Vesker spec->outer_second_cvlan_tag = 83926d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, outer_second_cvlan_tag); 84026d688e3SAlex Vesker spec->inner_second_cvlan_tag = 84126d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, inner_second_cvlan_tag); 84226d688e3SAlex Vesker spec->outer_second_svlan_tag = 84326d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, outer_second_svlan_tag); 84426d688e3SAlex Vesker spec->inner_second_svlan_tag = 84526d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, inner_second_svlan_tag); 84626d688e3SAlex Vesker 84726d688e3SAlex Vesker spec->gre_protocol = MLX5_GET(fte_match_set_misc, mask, gre_protocol); 84826d688e3SAlex Vesker 84926d688e3SAlex Vesker spec->gre_key_h = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi); 85026d688e3SAlex Vesker spec->gre_key_l = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo); 85126d688e3SAlex Vesker 85226d688e3SAlex Vesker spec->vxlan_vni = MLX5_GET(fte_match_set_misc, mask, vxlan_vni); 85326d688e3SAlex Vesker 85426d688e3SAlex Vesker spec->geneve_vni = MLX5_GET(fte_match_set_misc, mask, geneve_vni); 85526d688e3SAlex Vesker spec->geneve_oam = MLX5_GET(fte_match_set_misc, mask, geneve_oam); 85626d688e3SAlex Vesker 85726d688e3SAlex Vesker spec->outer_ipv6_flow_label = 85826d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, outer_ipv6_flow_label); 85926d688e3SAlex Vesker 86026d688e3SAlex Vesker spec->inner_ipv6_flow_label = 86126d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, inner_ipv6_flow_label); 86226d688e3SAlex Vesker 86326d688e3SAlex Vesker spec->geneve_opt_len = MLX5_GET(fte_match_set_misc, mask, geneve_opt_len); 86426d688e3SAlex Vesker spec->geneve_protocol_type = 86526d688e3SAlex Vesker MLX5_GET(fte_match_set_misc, mask, geneve_protocol_type); 86626d688e3SAlex Vesker 86726d688e3SAlex Vesker spec->bth_dst_qp = MLX5_GET(fte_match_set_misc, mask, bth_dst_qp); 86826d688e3SAlex Vesker } 86926d688e3SAlex Vesker 87026d688e3SAlex Vesker static void dr_ste_copy_mask_spec(char *mask, struct mlx5dr_match_spec *spec) 87126d688e3SAlex Vesker { 872c2ba2c22SSaeed Mahameed __be32 raw_ip[4]; 87326d688e3SAlex Vesker 87426d688e3SAlex Vesker spec->smac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_47_16); 87526d688e3SAlex Vesker 87626d688e3SAlex Vesker spec->smac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_15_0); 87726d688e3SAlex Vesker spec->ethertype = MLX5_GET(fte_match_set_lyr_2_4, mask, ethertype); 87826d688e3SAlex Vesker 87926d688e3SAlex Vesker spec->dmac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_47_16); 88026d688e3SAlex Vesker 88126d688e3SAlex Vesker spec->dmac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_15_0); 88226d688e3SAlex Vesker spec->first_prio = MLX5_GET(fte_match_set_lyr_2_4, mask, first_prio); 88326d688e3SAlex Vesker spec->first_cfi = MLX5_GET(fte_match_set_lyr_2_4, mask, first_cfi); 88426d688e3SAlex Vesker spec->first_vid = MLX5_GET(fte_match_set_lyr_2_4, mask, first_vid); 88526d688e3SAlex Vesker 88626d688e3SAlex Vesker spec->ip_protocol = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_protocol); 88726d688e3SAlex Vesker spec->ip_dscp = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_dscp); 88826d688e3SAlex Vesker spec->ip_ecn = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_ecn); 88926d688e3SAlex Vesker spec->cvlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, cvlan_tag); 89026d688e3SAlex Vesker spec->svlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, svlan_tag); 89126d688e3SAlex Vesker spec->frag = MLX5_GET(fte_match_set_lyr_2_4, mask, frag); 89226d688e3SAlex Vesker spec->ip_version = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_version); 89326d688e3SAlex Vesker spec->tcp_flags = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_flags); 89426d688e3SAlex Vesker spec->tcp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_sport); 89526d688e3SAlex Vesker spec->tcp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_dport); 89626d688e3SAlex Vesker 89726d688e3SAlex Vesker spec->ttl_hoplimit = MLX5_GET(fte_match_set_lyr_2_4, mask, ttl_hoplimit); 89826d688e3SAlex Vesker 89926d688e3SAlex Vesker spec->udp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_sport); 90026d688e3SAlex Vesker spec->udp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_dport); 90126d688e3SAlex Vesker 90226d688e3SAlex Vesker memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, 90326d688e3SAlex Vesker src_ipv4_src_ipv6.ipv6_layout.ipv6), 90426d688e3SAlex Vesker sizeof(raw_ip)); 90526d688e3SAlex Vesker 90626d688e3SAlex Vesker spec->src_ip_127_96 = be32_to_cpu(raw_ip[0]); 90726d688e3SAlex Vesker spec->src_ip_95_64 = be32_to_cpu(raw_ip[1]); 90826d688e3SAlex Vesker spec->src_ip_63_32 = be32_to_cpu(raw_ip[2]); 90926d688e3SAlex Vesker spec->src_ip_31_0 = be32_to_cpu(raw_ip[3]); 91026d688e3SAlex Vesker 91126d688e3SAlex Vesker memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, 91226d688e3SAlex Vesker dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 91326d688e3SAlex Vesker sizeof(raw_ip)); 91426d688e3SAlex Vesker 91526d688e3SAlex Vesker spec->dst_ip_127_96 = be32_to_cpu(raw_ip[0]); 91626d688e3SAlex Vesker spec->dst_ip_95_64 = be32_to_cpu(raw_ip[1]); 91726d688e3SAlex Vesker spec->dst_ip_63_32 = be32_to_cpu(raw_ip[2]); 91826d688e3SAlex Vesker spec->dst_ip_31_0 = be32_to_cpu(raw_ip[3]); 91926d688e3SAlex Vesker } 92026d688e3SAlex Vesker 92126d688e3SAlex Vesker static void dr_ste_copy_mask_misc2(char *mask, struct mlx5dr_match_misc2 *spec) 92226d688e3SAlex Vesker { 92326d688e3SAlex Vesker spec->outer_first_mpls_label = 92426d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_label); 92526d688e3SAlex Vesker spec->outer_first_mpls_exp = 92626d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_exp); 92726d688e3SAlex Vesker spec->outer_first_mpls_s_bos = 92826d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_s_bos); 92926d688e3SAlex Vesker spec->outer_first_mpls_ttl = 93026d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_ttl); 93126d688e3SAlex Vesker spec->inner_first_mpls_label = 93226d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_label); 93326d688e3SAlex Vesker spec->inner_first_mpls_exp = 93426d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_exp); 93526d688e3SAlex Vesker spec->inner_first_mpls_s_bos = 93626d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_s_bos); 93726d688e3SAlex Vesker spec->inner_first_mpls_ttl = 93826d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_ttl); 93926d688e3SAlex Vesker spec->outer_first_mpls_over_gre_label = 94026d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_label); 94126d688e3SAlex Vesker spec->outer_first_mpls_over_gre_exp = 94226d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_exp); 94326d688e3SAlex Vesker spec->outer_first_mpls_over_gre_s_bos = 94426d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_s_bos); 94526d688e3SAlex Vesker spec->outer_first_mpls_over_gre_ttl = 94626d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_ttl); 94726d688e3SAlex Vesker spec->outer_first_mpls_over_udp_label = 94826d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_label); 94926d688e3SAlex Vesker spec->outer_first_mpls_over_udp_exp = 95026d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_exp); 95126d688e3SAlex Vesker spec->outer_first_mpls_over_udp_s_bos = 95226d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_s_bos); 95326d688e3SAlex Vesker spec->outer_first_mpls_over_udp_ttl = 95426d688e3SAlex Vesker MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_ttl); 95526d688e3SAlex Vesker spec->metadata_reg_c_7 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_7); 95626d688e3SAlex Vesker spec->metadata_reg_c_6 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_6); 95726d688e3SAlex Vesker spec->metadata_reg_c_5 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_5); 95826d688e3SAlex Vesker spec->metadata_reg_c_4 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_4); 95926d688e3SAlex Vesker spec->metadata_reg_c_3 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_3); 96026d688e3SAlex Vesker spec->metadata_reg_c_2 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_2); 96126d688e3SAlex Vesker spec->metadata_reg_c_1 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_1); 96226d688e3SAlex Vesker spec->metadata_reg_c_0 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_0); 96326d688e3SAlex Vesker spec->metadata_reg_a = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_a); 96426d688e3SAlex Vesker } 96526d688e3SAlex Vesker 96626d688e3SAlex Vesker static void dr_ste_copy_mask_misc3(char *mask, struct mlx5dr_match_misc3 *spec) 96726d688e3SAlex Vesker { 96826d688e3SAlex Vesker spec->inner_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_seq_num); 96926d688e3SAlex Vesker spec->outer_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_seq_num); 97026d688e3SAlex Vesker spec->inner_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_ack_num); 97126d688e3SAlex Vesker spec->outer_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_ack_num); 97226d688e3SAlex Vesker spec->outer_vxlan_gpe_vni = 97326d688e3SAlex Vesker MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_vni); 97426d688e3SAlex Vesker spec->outer_vxlan_gpe_next_protocol = 97526d688e3SAlex Vesker MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_next_protocol); 97626d688e3SAlex Vesker spec->outer_vxlan_gpe_flags = 97726d688e3SAlex Vesker MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_flags); 97826d688e3SAlex Vesker spec->icmpv4_header_data = MLX5_GET(fte_match_set_misc3, mask, icmp_header_data); 97926d688e3SAlex Vesker spec->icmpv6_header_data = 98026d688e3SAlex Vesker MLX5_GET(fte_match_set_misc3, mask, icmpv6_header_data); 98126d688e3SAlex Vesker spec->icmpv4_type = MLX5_GET(fte_match_set_misc3, mask, icmp_type); 98226d688e3SAlex Vesker spec->icmpv4_code = MLX5_GET(fte_match_set_misc3, mask, icmp_code); 98326d688e3SAlex Vesker spec->icmpv6_type = MLX5_GET(fte_match_set_misc3, mask, icmpv6_type); 98426d688e3SAlex Vesker spec->icmpv6_code = MLX5_GET(fte_match_set_misc3, mask, icmpv6_code); 98526d688e3SAlex Vesker } 98626d688e3SAlex Vesker 98726d688e3SAlex Vesker void mlx5dr_ste_copy_param(u8 match_criteria, 98826d688e3SAlex Vesker struct mlx5dr_match_param *set_param, 98926d688e3SAlex Vesker struct mlx5dr_match_parameters *mask) 99026d688e3SAlex Vesker { 99126d688e3SAlex Vesker u8 tail_param[MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4)] = {}; 99226d688e3SAlex Vesker u8 *data = (u8 *)mask->match_buf; 99326d688e3SAlex Vesker size_t param_location; 99426d688e3SAlex Vesker void *buff; 99526d688e3SAlex Vesker 99626d688e3SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_OUTER) { 99726d688e3SAlex Vesker if (mask->match_sz < sizeof(struct mlx5dr_match_spec)) { 99826d688e3SAlex Vesker memcpy(tail_param, data, mask->match_sz); 99926d688e3SAlex Vesker buff = tail_param; 100026d688e3SAlex Vesker } else { 100126d688e3SAlex Vesker buff = mask->match_buf; 100226d688e3SAlex Vesker } 100326d688e3SAlex Vesker dr_ste_copy_mask_spec(buff, &set_param->outer); 100426d688e3SAlex Vesker } 100526d688e3SAlex Vesker param_location = sizeof(struct mlx5dr_match_spec); 100626d688e3SAlex Vesker 100726d688e3SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC) { 100826d688e3SAlex Vesker if (mask->match_sz < param_location + 100926d688e3SAlex Vesker sizeof(struct mlx5dr_match_misc)) { 101026d688e3SAlex Vesker memcpy(tail_param, data + param_location, 101126d688e3SAlex Vesker mask->match_sz - param_location); 101226d688e3SAlex Vesker buff = tail_param; 101326d688e3SAlex Vesker } else { 101426d688e3SAlex Vesker buff = data + param_location; 101526d688e3SAlex Vesker } 101626d688e3SAlex Vesker dr_ste_copy_mask_misc(buff, &set_param->misc); 101726d688e3SAlex Vesker } 101826d688e3SAlex Vesker param_location += sizeof(struct mlx5dr_match_misc); 101926d688e3SAlex Vesker 102026d688e3SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_INNER) { 102126d688e3SAlex Vesker if (mask->match_sz < param_location + 102226d688e3SAlex Vesker sizeof(struct mlx5dr_match_spec)) { 102326d688e3SAlex Vesker memcpy(tail_param, data + param_location, 102426d688e3SAlex Vesker mask->match_sz - param_location); 102526d688e3SAlex Vesker buff = tail_param; 102626d688e3SAlex Vesker } else { 102726d688e3SAlex Vesker buff = data + param_location; 102826d688e3SAlex Vesker } 102926d688e3SAlex Vesker dr_ste_copy_mask_spec(buff, &set_param->inner); 103026d688e3SAlex Vesker } 103126d688e3SAlex Vesker param_location += sizeof(struct mlx5dr_match_spec); 103226d688e3SAlex Vesker 103326d688e3SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC2) { 103426d688e3SAlex Vesker if (mask->match_sz < param_location + 103526d688e3SAlex Vesker sizeof(struct mlx5dr_match_misc2)) { 103626d688e3SAlex Vesker memcpy(tail_param, data + param_location, 103726d688e3SAlex Vesker mask->match_sz - param_location); 103826d688e3SAlex Vesker buff = tail_param; 103926d688e3SAlex Vesker } else { 104026d688e3SAlex Vesker buff = data + param_location; 104126d688e3SAlex Vesker } 104226d688e3SAlex Vesker dr_ste_copy_mask_misc2(buff, &set_param->misc2); 104326d688e3SAlex Vesker } 104426d688e3SAlex Vesker 104526d688e3SAlex Vesker param_location += sizeof(struct mlx5dr_match_misc2); 104626d688e3SAlex Vesker 104726d688e3SAlex Vesker if (match_criteria & DR_MATCHER_CRITERIA_MISC3) { 104826d688e3SAlex Vesker if (mask->match_sz < param_location + 104926d688e3SAlex Vesker sizeof(struct mlx5dr_match_misc3)) { 105026d688e3SAlex Vesker memcpy(tail_param, data + param_location, 105126d688e3SAlex Vesker mask->match_sz - param_location); 105226d688e3SAlex Vesker buff = tail_param; 105326d688e3SAlex Vesker } else { 105426d688e3SAlex Vesker buff = data + param_location; 105526d688e3SAlex Vesker } 105626d688e3SAlex Vesker dr_ste_copy_mask_misc3(buff, &set_param->misc3); 105726d688e3SAlex Vesker } 105826d688e3SAlex Vesker } 105926d688e3SAlex Vesker 106026d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_tag(struct mlx5dr_match_param *value, 106126d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 106226d688e3SAlex Vesker u8 *hw_ste_p) 106326d688e3SAlex Vesker { 106426d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 106526d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 106626d688e3SAlex Vesker u8 *tag = hw_ste->tag; 106726d688e3SAlex Vesker 106826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_47_16, spec, dmac_47_16); 106926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_15_0, spec, dmac_15_0); 107026d688e3SAlex Vesker 107126d688e3SAlex Vesker if (spec->smac_47_16 || spec->smac_15_0) { 107226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, smac_47_32, 107326d688e3SAlex Vesker spec->smac_47_16 >> 16); 107426d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, smac_31_0, 107526d688e3SAlex Vesker spec->smac_47_16 << 16 | spec->smac_15_0); 107626d688e3SAlex Vesker spec->smac_47_16 = 0; 107726d688e3SAlex Vesker spec->smac_15_0 = 0; 107826d688e3SAlex Vesker } 107926d688e3SAlex Vesker 108026d688e3SAlex Vesker if (spec->ip_version) { 108126d688e3SAlex Vesker if (spec->ip_version == IP_VERSION_IPV4) { 108226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV4); 108326d688e3SAlex Vesker spec->ip_version = 0; 108426d688e3SAlex Vesker } else if (spec->ip_version == IP_VERSION_IPV6) { 108526d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV6); 108626d688e3SAlex Vesker spec->ip_version = 0; 108726d688e3SAlex Vesker } else { 108826d688e3SAlex Vesker pr_info("Unsupported ip_version value\n"); 108926d688e3SAlex Vesker return -EINVAL; 109026d688e3SAlex Vesker } 109126d688e3SAlex Vesker } 109226d688e3SAlex Vesker 109326d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src_dst, tag, first_vlan_id, spec, first_vid); 109426d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src_dst, tag, first_cfi, spec, first_cfi); 109526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src_dst, tag, first_priority, spec, first_prio); 109626d688e3SAlex Vesker 109726d688e3SAlex Vesker if (spec->cvlan_tag) { 109826d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_CVLAN); 109926d688e3SAlex Vesker spec->cvlan_tag = 0; 110026d688e3SAlex Vesker } else if (spec->svlan_tag) { 110126d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_SVLAN); 110226d688e3SAlex Vesker spec->svlan_tag = 0; 110326d688e3SAlex Vesker } 110426d688e3SAlex Vesker return 0; 110526d688e3SAlex Vesker } 110626d688e3SAlex Vesker 110726d688e3SAlex Vesker int mlx5dr_ste_build_eth_l2_src_des(struct mlx5dr_ste_build *sb, 110826d688e3SAlex Vesker struct mlx5dr_match_param *mask, 110926d688e3SAlex Vesker bool inner, bool rx) 111026d688e3SAlex Vesker { 111126d688e3SAlex Vesker int ret; 111226d688e3SAlex Vesker 111326d688e3SAlex Vesker ret = dr_ste_build_eth_l2_src_des_bit_mask(mask, inner, sb->bit_mask); 111426d688e3SAlex Vesker if (ret) 111526d688e3SAlex Vesker return ret; 111626d688e3SAlex Vesker 111726d688e3SAlex Vesker sb->rx = rx; 111826d688e3SAlex Vesker sb->inner = inner; 111926d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC_DST, rx, inner); 112026d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 112126d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_des_tag; 112226d688e3SAlex Vesker 112326d688e3SAlex Vesker return 0; 112426d688e3SAlex Vesker } 112526d688e3SAlex Vesker 112626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_dst_bit_mask(struct mlx5dr_match_param *value, 112726d688e3SAlex Vesker bool inner, u8 *bit_mask) 112826d688e3SAlex Vesker { 112926d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 113026d688e3SAlex Vesker 113126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_127_96, mask, dst_ip_127_96); 113226d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_95_64, mask, dst_ip_95_64); 113326d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_63_32, mask, dst_ip_63_32); 113426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_31_0, mask, dst_ip_31_0); 113526d688e3SAlex Vesker } 113626d688e3SAlex Vesker 113726d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_dst_tag(struct mlx5dr_match_param *value, 113826d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 113926d688e3SAlex Vesker u8 *hw_ste_p) 114026d688e3SAlex Vesker { 114126d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 114226d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 114326d688e3SAlex Vesker u8 *tag = hw_ste->tag; 114426d688e3SAlex Vesker 114526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_127_96, spec, dst_ip_127_96); 114626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_95_64, spec, dst_ip_95_64); 114726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_63_32, spec, dst_ip_63_32); 114826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_31_0, spec, dst_ip_31_0); 114926d688e3SAlex Vesker 115026d688e3SAlex Vesker return 0; 115126d688e3SAlex Vesker } 115226d688e3SAlex Vesker 115326d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_dst(struct mlx5dr_ste_build *sb, 115426d688e3SAlex Vesker struct mlx5dr_match_param *mask, 115526d688e3SAlex Vesker bool inner, bool rx) 115626d688e3SAlex Vesker { 115726d688e3SAlex Vesker dr_ste_build_eth_l3_ipv6_dst_bit_mask(mask, inner, sb->bit_mask); 115826d688e3SAlex Vesker 115926d688e3SAlex Vesker sb->rx = rx; 116026d688e3SAlex Vesker sb->inner = inner; 116126d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_DST, rx, inner); 116226d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 116326d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_dst_tag; 116426d688e3SAlex Vesker } 116526d688e3SAlex Vesker 116626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_src_bit_mask(struct mlx5dr_match_param *value, 116726d688e3SAlex Vesker bool inner, u8 *bit_mask) 116826d688e3SAlex Vesker { 116926d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 117026d688e3SAlex Vesker 117126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_127_96, mask, src_ip_127_96); 117226d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_95_64, mask, src_ip_95_64); 117326d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_63_32, mask, src_ip_63_32); 117426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_31_0, mask, src_ip_31_0); 117526d688e3SAlex Vesker } 117626d688e3SAlex Vesker 117726d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_src_tag(struct mlx5dr_match_param *value, 117826d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 117926d688e3SAlex Vesker u8 *hw_ste_p) 118026d688e3SAlex Vesker { 118126d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 118226d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 118326d688e3SAlex Vesker u8 *tag = hw_ste->tag; 118426d688e3SAlex Vesker 118526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_127_96, spec, src_ip_127_96); 118626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_95_64, spec, src_ip_95_64); 118726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_63_32, spec, src_ip_63_32); 118826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_31_0, spec, src_ip_31_0); 118926d688e3SAlex Vesker 119026d688e3SAlex Vesker return 0; 119126d688e3SAlex Vesker } 119226d688e3SAlex Vesker 119326d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_src(struct mlx5dr_ste_build *sb, 119426d688e3SAlex Vesker struct mlx5dr_match_param *mask, 119526d688e3SAlex Vesker bool inner, bool rx) 119626d688e3SAlex Vesker { 119726d688e3SAlex Vesker dr_ste_build_eth_l3_ipv6_src_bit_mask(mask, inner, sb->bit_mask); 119826d688e3SAlex Vesker 119926d688e3SAlex Vesker sb->rx = rx; 120026d688e3SAlex Vesker sb->inner = inner; 120126d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_SRC, rx, inner); 120226d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 120326d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_src_tag; 120426d688e3SAlex Vesker } 120526d688e3SAlex Vesker 120626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(struct mlx5dr_match_param *value, 120726d688e3SAlex Vesker bool inner, 120826d688e3SAlex Vesker u8 *bit_mask) 120926d688e3SAlex Vesker { 121026d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 121126d688e3SAlex Vesker 121226d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 121326d688e3SAlex Vesker destination_address, mask, dst_ip_31_0); 121426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 121526d688e3SAlex Vesker source_address, mask, src_ip_31_0); 121626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 121726d688e3SAlex Vesker destination_port, mask, tcp_dport); 121826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 121926d688e3SAlex Vesker destination_port, mask, udp_dport); 122026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 122126d688e3SAlex Vesker source_port, mask, tcp_sport); 122226d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 122326d688e3SAlex Vesker source_port, mask, udp_sport); 122426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 122526d688e3SAlex Vesker protocol, mask, ip_protocol); 122626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 122726d688e3SAlex Vesker fragmented, mask, frag); 122826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 122926d688e3SAlex Vesker dscp, mask, ip_dscp); 123026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask, 123126d688e3SAlex Vesker ecn, mask, ip_ecn); 123226d688e3SAlex Vesker 123326d688e3SAlex Vesker if (mask->tcp_flags) { 123426d688e3SAlex Vesker DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, bit_mask, mask); 123526d688e3SAlex Vesker mask->tcp_flags = 0; 123626d688e3SAlex Vesker } 123726d688e3SAlex Vesker } 123826d688e3SAlex Vesker 123926d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_5_tuple_tag(struct mlx5dr_match_param *value, 124026d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 124126d688e3SAlex Vesker u8 *hw_ste_p) 124226d688e3SAlex Vesker { 124326d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 124426d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 124526d688e3SAlex Vesker u8 *tag = hw_ste->tag; 124626d688e3SAlex Vesker 124726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_address, spec, dst_ip_31_0); 124826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_address, spec, src_ip_31_0); 124926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, tcp_dport); 125026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, udp_dport); 125126d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, tcp_sport); 125226d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, udp_sport); 125326d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, protocol, spec, ip_protocol); 125426d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, fragmented, spec, frag); 125526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, dscp, spec, ip_dscp); 125626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, ecn, spec, ip_ecn); 125726d688e3SAlex Vesker 125826d688e3SAlex Vesker if (spec->tcp_flags) { 125926d688e3SAlex Vesker DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, tag, spec); 126026d688e3SAlex Vesker spec->tcp_flags = 0; 126126d688e3SAlex Vesker } 126226d688e3SAlex Vesker 126326d688e3SAlex Vesker return 0; 126426d688e3SAlex Vesker } 126526d688e3SAlex Vesker 126626d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_5_tuple(struct mlx5dr_ste_build *sb, 126726d688e3SAlex Vesker struct mlx5dr_match_param *mask, 126826d688e3SAlex Vesker bool inner, bool rx) 126926d688e3SAlex Vesker { 127026d688e3SAlex Vesker dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(mask, inner, sb->bit_mask); 127126d688e3SAlex Vesker 127226d688e3SAlex Vesker sb->rx = rx; 127326d688e3SAlex Vesker sb->inner = inner; 127426d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_5_TUPLE, rx, inner); 127526d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 127626d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_5_tuple_tag; 127726d688e3SAlex Vesker } 127826d688e3SAlex Vesker 127926d688e3SAlex Vesker static void 128026d688e3SAlex Vesker dr_ste_build_eth_l2_src_or_dst_bit_mask(struct mlx5dr_match_param *value, 128126d688e3SAlex Vesker bool inner, u8 *bit_mask) 128226d688e3SAlex Vesker { 128326d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 128426d688e3SAlex Vesker struct mlx5dr_match_misc *misc_mask = &value->misc; 128526d688e3SAlex Vesker 128626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_vlan_id, mask, first_vid); 128726d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_cfi, mask, first_cfi); 128826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_priority, mask, first_prio); 128926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, ip_fragmented, mask, frag); 129026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, l3_ethertype, mask, ethertype); 129126d688e3SAlex Vesker DR_STE_SET_MASK(eth_l2_src, bit_mask, l3_type, mask, ip_version); 129226d688e3SAlex Vesker 129326d688e3SAlex Vesker if (mask->svlan_tag || mask->cvlan_tag) { 129426d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, bit_mask, first_vlan_qualifier, -1); 129526d688e3SAlex Vesker mask->cvlan_tag = 0; 129626d688e3SAlex Vesker mask->svlan_tag = 0; 129726d688e3SAlex Vesker } 129826d688e3SAlex Vesker 129926d688e3SAlex Vesker if (inner) { 130026d688e3SAlex Vesker if (misc_mask->inner_second_cvlan_tag || 130126d688e3SAlex Vesker misc_mask->inner_second_svlan_tag) { 130226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1); 130326d688e3SAlex Vesker misc_mask->inner_second_cvlan_tag = 0; 130426d688e3SAlex Vesker misc_mask->inner_second_svlan_tag = 0; 130526d688e3SAlex Vesker } 130626d688e3SAlex Vesker 130726d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 130826d688e3SAlex Vesker second_vlan_id, misc_mask, inner_second_vid); 130926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 131026d688e3SAlex Vesker second_cfi, misc_mask, inner_second_cfi); 131126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 131226d688e3SAlex Vesker second_priority, misc_mask, inner_second_prio); 131326d688e3SAlex Vesker } else { 131426d688e3SAlex Vesker if (misc_mask->outer_second_cvlan_tag || 131526d688e3SAlex Vesker misc_mask->outer_second_svlan_tag) { 131626d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1); 131726d688e3SAlex Vesker misc_mask->outer_second_cvlan_tag = 0; 131826d688e3SAlex Vesker misc_mask->outer_second_svlan_tag = 0; 131926d688e3SAlex Vesker } 132026d688e3SAlex Vesker 132126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 132226d688e3SAlex Vesker second_vlan_id, misc_mask, outer_second_vid); 132326d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 132426d688e3SAlex Vesker second_cfi, misc_mask, outer_second_cfi); 132526d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, 132626d688e3SAlex Vesker second_priority, misc_mask, outer_second_prio); 132726d688e3SAlex Vesker } 132826d688e3SAlex Vesker } 132926d688e3SAlex Vesker 133026d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_or_dst_tag(struct mlx5dr_match_param *value, 133126d688e3SAlex Vesker bool inner, u8 *hw_ste_p) 133226d688e3SAlex Vesker { 133326d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 133426d688e3SAlex Vesker struct mlx5dr_match_spec *spec = inner ? &value->inner : &value->outer; 133526d688e3SAlex Vesker struct mlx5dr_match_misc *misc_spec = &value->misc; 133626d688e3SAlex Vesker u8 *tag = hw_ste->tag; 133726d688e3SAlex Vesker 133826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, first_vlan_id, spec, first_vid); 133926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, first_cfi, spec, first_cfi); 134026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, first_priority, spec, first_prio); 134126d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, ip_fragmented, spec, frag); 134226d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, l3_ethertype, spec, ethertype); 134326d688e3SAlex Vesker 134426d688e3SAlex Vesker if (spec->ip_version) { 134526d688e3SAlex Vesker if (spec->ip_version == IP_VERSION_IPV4) { 134626d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV4); 134726d688e3SAlex Vesker spec->ip_version = 0; 134826d688e3SAlex Vesker } else if (spec->ip_version == IP_VERSION_IPV6) { 134926d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV6); 135026d688e3SAlex Vesker spec->ip_version = 0; 135126d688e3SAlex Vesker } else { 135226d688e3SAlex Vesker pr_info("Unsupported ip_version value\n"); 135326d688e3SAlex Vesker return -EINVAL; 135426d688e3SAlex Vesker } 135526d688e3SAlex Vesker } 135626d688e3SAlex Vesker 135726d688e3SAlex Vesker if (spec->cvlan_tag) { 135826d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_CVLAN); 135926d688e3SAlex Vesker spec->cvlan_tag = 0; 136026d688e3SAlex Vesker } else if (spec->svlan_tag) { 136126d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_SVLAN); 136226d688e3SAlex Vesker spec->svlan_tag = 0; 136326d688e3SAlex Vesker } 136426d688e3SAlex Vesker 136526d688e3SAlex Vesker if (inner) { 136626d688e3SAlex Vesker if (misc_spec->inner_second_cvlan_tag) { 136726d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN); 136826d688e3SAlex Vesker misc_spec->inner_second_cvlan_tag = 0; 136926d688e3SAlex Vesker } else if (misc_spec->inner_second_svlan_tag) { 137026d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN); 137126d688e3SAlex Vesker misc_spec->inner_second_svlan_tag = 0; 137226d688e3SAlex Vesker } 137326d688e3SAlex Vesker 137426d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, inner_second_vid); 137526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, inner_second_cfi); 137626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, inner_second_prio); 137726d688e3SAlex Vesker } else { 137826d688e3SAlex Vesker if (misc_spec->outer_second_cvlan_tag) { 137926d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN); 138026d688e3SAlex Vesker misc_spec->outer_second_cvlan_tag = 0; 138126d688e3SAlex Vesker } else if (misc_spec->outer_second_svlan_tag) { 138226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN); 138326d688e3SAlex Vesker misc_spec->outer_second_svlan_tag = 0; 138426d688e3SAlex Vesker } 138526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, outer_second_vid); 138626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, outer_second_cfi); 138726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, outer_second_prio); 138826d688e3SAlex Vesker } 138926d688e3SAlex Vesker 139026d688e3SAlex Vesker return 0; 139126d688e3SAlex Vesker } 139226d688e3SAlex Vesker 139326d688e3SAlex Vesker static void dr_ste_build_eth_l2_src_bit_mask(struct mlx5dr_match_param *value, 139426d688e3SAlex Vesker bool inner, u8 *bit_mask) 139526d688e3SAlex Vesker { 139626d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 139726d688e3SAlex Vesker 139826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_47_16, mask, smac_47_16); 139926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_15_0, mask, smac_15_0); 140026d688e3SAlex Vesker 140126d688e3SAlex Vesker dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask); 140226d688e3SAlex Vesker } 140326d688e3SAlex Vesker 140426d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_tag(struct mlx5dr_match_param *value, 140526d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 140626d688e3SAlex Vesker u8 *hw_ste_p) 140726d688e3SAlex Vesker { 140826d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 140926d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 141026d688e3SAlex Vesker u8 *tag = hw_ste->tag; 141126d688e3SAlex Vesker 141226d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, smac_47_16, spec, smac_47_16); 141326d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_src, tag, smac_15_0, spec, smac_15_0); 141426d688e3SAlex Vesker 141526d688e3SAlex Vesker return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p); 141626d688e3SAlex Vesker } 141726d688e3SAlex Vesker 141826d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_src(struct mlx5dr_ste_build *sb, 141926d688e3SAlex Vesker struct mlx5dr_match_param *mask, 142026d688e3SAlex Vesker bool inner, bool rx) 142126d688e3SAlex Vesker { 142226d688e3SAlex Vesker dr_ste_build_eth_l2_src_bit_mask(mask, inner, sb->bit_mask); 142326d688e3SAlex Vesker sb->rx = rx; 142426d688e3SAlex Vesker sb->inner = inner; 142526d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC, rx, inner); 142626d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 142726d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_tag; 142826d688e3SAlex Vesker } 142926d688e3SAlex Vesker 143026d688e3SAlex Vesker static void dr_ste_build_eth_l2_dst_bit_mask(struct mlx5dr_match_param *value, 143126d688e3SAlex Vesker bool inner, u8 *bit_mask) 143226d688e3SAlex Vesker { 143326d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 143426d688e3SAlex Vesker 143526d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_47_16, mask, dmac_47_16); 143626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_15_0, mask, dmac_15_0); 143726d688e3SAlex Vesker 143826d688e3SAlex Vesker dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask); 143926d688e3SAlex Vesker } 144026d688e3SAlex Vesker 144126d688e3SAlex Vesker static int dr_ste_build_eth_l2_dst_tag(struct mlx5dr_match_param *value, 144226d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 144326d688e3SAlex Vesker u8 *hw_ste_p) 144426d688e3SAlex Vesker { 144526d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 144626d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 144726d688e3SAlex Vesker u8 *tag = hw_ste->tag; 144826d688e3SAlex Vesker 144926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_dst, tag, dmac_47_16, spec, dmac_47_16); 145026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_dst, tag, dmac_15_0, spec, dmac_15_0); 145126d688e3SAlex Vesker 145226d688e3SAlex Vesker return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p); 145326d688e3SAlex Vesker } 145426d688e3SAlex Vesker 145526d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_dst(struct mlx5dr_ste_build *sb, 145626d688e3SAlex Vesker struct mlx5dr_match_param *mask, 145726d688e3SAlex Vesker bool inner, bool rx) 145826d688e3SAlex Vesker { 145926d688e3SAlex Vesker dr_ste_build_eth_l2_dst_bit_mask(mask, inner, sb->bit_mask); 146026d688e3SAlex Vesker 146126d688e3SAlex Vesker sb->rx = rx; 146226d688e3SAlex Vesker sb->inner = inner; 146326d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_DST, rx, inner); 146426d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 146526d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l2_dst_tag; 146626d688e3SAlex Vesker } 146726d688e3SAlex Vesker 146826d688e3SAlex Vesker static void dr_ste_build_eth_l2_tnl_bit_mask(struct mlx5dr_match_param *value, 146926d688e3SAlex Vesker bool inner, u8 *bit_mask) 147026d688e3SAlex Vesker { 147126d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 147226d688e3SAlex Vesker struct mlx5dr_match_misc *misc = &value->misc; 147326d688e3SAlex Vesker 147426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_47_16, mask, dmac_47_16); 147526d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_15_0, mask, dmac_15_0); 147626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_vlan_id, mask, first_vid); 147726d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_cfi, mask, first_cfi); 147826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_priority, mask, first_prio); 147926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, ip_fragmented, mask, frag); 148026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, l3_ethertype, mask, ethertype); 148126d688e3SAlex Vesker DR_STE_SET_MASK(eth_l2_tnl, bit_mask, l3_type, mask, ip_version); 148226d688e3SAlex Vesker 148326d688e3SAlex Vesker if (misc->vxlan_vni) { 148426d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, bit_mask, 148526d688e3SAlex Vesker l2_tunneling_network_id, (misc->vxlan_vni << 8)); 148626d688e3SAlex Vesker misc->vxlan_vni = 0; 148726d688e3SAlex Vesker } 148826d688e3SAlex Vesker 148926d688e3SAlex Vesker if (mask->svlan_tag || mask->cvlan_tag) { 149026d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, bit_mask, first_vlan_qualifier, -1); 149126d688e3SAlex Vesker mask->cvlan_tag = 0; 149226d688e3SAlex Vesker mask->svlan_tag = 0; 149326d688e3SAlex Vesker } 149426d688e3SAlex Vesker } 149526d688e3SAlex Vesker 149626d688e3SAlex Vesker static int dr_ste_build_eth_l2_tnl_tag(struct mlx5dr_match_param *value, 149726d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 149826d688e3SAlex Vesker u8 *hw_ste_p) 149926d688e3SAlex Vesker { 150026d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 150126d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 150226d688e3SAlex Vesker struct mlx5dr_match_misc *misc = &value->misc; 150326d688e3SAlex Vesker u8 *tag = hw_ste->tag; 150426d688e3SAlex Vesker 150526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_47_16, spec, dmac_47_16); 150626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_15_0, spec, dmac_15_0); 150726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, first_vlan_id, spec, first_vid); 150826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, first_cfi, spec, first_cfi); 150926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, ip_fragmented, spec, frag); 151026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, first_priority, spec, first_prio); 151126d688e3SAlex Vesker DR_STE_SET_TAG(eth_l2_tnl, tag, l3_ethertype, spec, ethertype); 151226d688e3SAlex Vesker 151326d688e3SAlex Vesker if (misc->vxlan_vni) { 151426d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, tag, l2_tunneling_network_id, 151526d688e3SAlex Vesker (misc->vxlan_vni << 8)); 151626d688e3SAlex Vesker misc->vxlan_vni = 0; 151726d688e3SAlex Vesker } 151826d688e3SAlex Vesker 151926d688e3SAlex Vesker if (spec->cvlan_tag) { 152026d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_CVLAN); 152126d688e3SAlex Vesker spec->cvlan_tag = 0; 152226d688e3SAlex Vesker } else if (spec->svlan_tag) { 152326d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_SVLAN); 152426d688e3SAlex Vesker spec->svlan_tag = 0; 152526d688e3SAlex Vesker } 152626d688e3SAlex Vesker 152726d688e3SAlex Vesker if (spec->ip_version) { 152826d688e3SAlex Vesker if (spec->ip_version == IP_VERSION_IPV4) { 152926d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV4); 153026d688e3SAlex Vesker spec->ip_version = 0; 153126d688e3SAlex Vesker } else if (spec->ip_version == IP_VERSION_IPV6) { 153226d688e3SAlex Vesker MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV6); 153326d688e3SAlex Vesker spec->ip_version = 0; 153426d688e3SAlex Vesker } else { 153526d688e3SAlex Vesker return -EINVAL; 153626d688e3SAlex Vesker } 153726d688e3SAlex Vesker } 153826d688e3SAlex Vesker 153926d688e3SAlex Vesker return 0; 154026d688e3SAlex Vesker } 154126d688e3SAlex Vesker 154226d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_tnl(struct mlx5dr_ste_build *sb, 154326d688e3SAlex Vesker struct mlx5dr_match_param *mask, bool inner, bool rx) 154426d688e3SAlex Vesker { 154526d688e3SAlex Vesker dr_ste_build_eth_l2_tnl_bit_mask(mask, inner, sb->bit_mask); 154626d688e3SAlex Vesker 154726d688e3SAlex Vesker sb->rx = rx; 154826d688e3SAlex Vesker sb->inner = inner; 154926d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_ETHL2_TUNNELING_I; 155026d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 155126d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l2_tnl_tag; 155226d688e3SAlex Vesker } 155326d688e3SAlex Vesker 155426d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_misc_bit_mask(struct mlx5dr_match_param *value, 155526d688e3SAlex Vesker bool inner, u8 *bit_mask) 155626d688e3SAlex Vesker { 155726d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 155826d688e3SAlex Vesker 155926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l3_ipv4_misc, bit_mask, time_to_live, mask, ttl_hoplimit); 156026d688e3SAlex Vesker } 156126d688e3SAlex Vesker 156226d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_misc_tag(struct mlx5dr_match_param *value, 156326d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 156426d688e3SAlex Vesker u8 *hw_ste_p) 156526d688e3SAlex Vesker { 156626d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 156726d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 156826d688e3SAlex Vesker u8 *tag = hw_ste->tag; 156926d688e3SAlex Vesker 157026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l3_ipv4_misc, tag, time_to_live, spec, ttl_hoplimit); 157126d688e3SAlex Vesker 157226d688e3SAlex Vesker return 0; 157326d688e3SAlex Vesker } 157426d688e3SAlex Vesker 157526d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_misc(struct mlx5dr_ste_build *sb, 157626d688e3SAlex Vesker struct mlx5dr_match_param *mask, 157726d688e3SAlex Vesker bool inner, bool rx) 157826d688e3SAlex Vesker { 157926d688e3SAlex Vesker dr_ste_build_eth_l3_ipv4_misc_bit_mask(mask, inner, sb->bit_mask); 158026d688e3SAlex Vesker 158126d688e3SAlex Vesker sb->rx = rx; 158226d688e3SAlex Vesker sb->inner = inner; 158326d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_MISC, rx, inner); 158426d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 158526d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_misc_tag; 158626d688e3SAlex Vesker } 158726d688e3SAlex Vesker 158826d688e3SAlex Vesker static void dr_ste_build_ipv6_l3_l4_bit_mask(struct mlx5dr_match_param *value, 158926d688e3SAlex Vesker bool inner, u8 *bit_mask) 159026d688e3SAlex Vesker { 159126d688e3SAlex Vesker struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer; 159226d688e3SAlex Vesker 159326d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, tcp_dport); 159426d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, tcp_sport); 159526d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, udp_dport); 159626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, udp_sport); 159726d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, protocol, mask, ip_protocol); 159826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, fragmented, mask, frag); 159926d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, dscp, mask, ip_dscp); 160026d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, ecn, mask, ip_ecn); 160126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4, bit_mask, ipv6_hop_limit, mask, ttl_hoplimit); 160226d688e3SAlex Vesker 160326d688e3SAlex Vesker if (mask->tcp_flags) { 160426d688e3SAlex Vesker DR_STE_SET_TCP_FLAGS(eth_l4, bit_mask, mask); 160526d688e3SAlex Vesker mask->tcp_flags = 0; 160626d688e3SAlex Vesker } 160726d688e3SAlex Vesker } 160826d688e3SAlex Vesker 160926d688e3SAlex Vesker static int dr_ste_build_ipv6_l3_l4_tag(struct mlx5dr_match_param *value, 161026d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 161126d688e3SAlex Vesker u8 *hw_ste_p) 161226d688e3SAlex Vesker { 161326d688e3SAlex Vesker struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer; 161426d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 161526d688e3SAlex Vesker u8 *tag = hw_ste->tag; 161626d688e3SAlex Vesker 161726d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, tcp_dport); 161826d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, src_port, spec, tcp_sport); 161926d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, udp_dport); 162026d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, src_port, spec, udp_sport); 162126d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, protocol, spec, ip_protocol); 162226d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, fragmented, spec, frag); 162326d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, dscp, spec, ip_dscp); 162426d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, ecn, spec, ip_ecn); 162526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4, tag, ipv6_hop_limit, spec, ttl_hoplimit); 162626d688e3SAlex Vesker 162726d688e3SAlex Vesker if (spec->tcp_flags) { 162826d688e3SAlex Vesker DR_STE_SET_TCP_FLAGS(eth_l4, tag, spec); 162926d688e3SAlex Vesker spec->tcp_flags = 0; 163026d688e3SAlex Vesker } 163126d688e3SAlex Vesker 163226d688e3SAlex Vesker return 0; 163326d688e3SAlex Vesker } 163426d688e3SAlex Vesker 163526d688e3SAlex Vesker void mlx5dr_ste_build_ipv6_l3_l4(struct mlx5dr_ste_build *sb, 163626d688e3SAlex Vesker struct mlx5dr_match_param *mask, 163726d688e3SAlex Vesker bool inner, bool rx) 163826d688e3SAlex Vesker { 163926d688e3SAlex Vesker dr_ste_build_ipv6_l3_l4_bit_mask(mask, inner, sb->bit_mask); 164026d688e3SAlex Vesker 164126d688e3SAlex Vesker sb->rx = rx; 164226d688e3SAlex Vesker sb->inner = inner; 164326d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4, rx, inner); 164426d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 164526d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_ipv6_l3_l4_tag; 164626d688e3SAlex Vesker } 164726d688e3SAlex Vesker 164826d688e3SAlex Vesker static int dr_ste_build_empty_always_hit_tag(struct mlx5dr_match_param *value, 164926d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 165026d688e3SAlex Vesker u8 *hw_ste_p) 165126d688e3SAlex Vesker { 165226d688e3SAlex Vesker return 0; 165326d688e3SAlex Vesker } 165426d688e3SAlex Vesker 165526d688e3SAlex Vesker void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx) 165626d688e3SAlex Vesker { 165726d688e3SAlex Vesker sb->rx = rx; 165826d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_DONT_CARE; 165926d688e3SAlex Vesker sb->byte_mask = 0; 166026d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_empty_always_hit_tag; 166126d688e3SAlex Vesker } 166226d688e3SAlex Vesker 166326d688e3SAlex Vesker static void dr_ste_build_mpls_bit_mask(struct mlx5dr_match_param *value, 166426d688e3SAlex Vesker bool inner, u8 *bit_mask) 166526d688e3SAlex Vesker { 166626d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc2_mask = &value->misc2; 166726d688e3SAlex Vesker 166826d688e3SAlex Vesker if (inner) 166926d688e3SAlex Vesker DR_STE_SET_MPLS_MASK(mpls, misc2_mask, inner, bit_mask); 167026d688e3SAlex Vesker else 167126d688e3SAlex Vesker DR_STE_SET_MPLS_MASK(mpls, misc2_mask, outer, bit_mask); 167226d688e3SAlex Vesker } 167326d688e3SAlex Vesker 167426d688e3SAlex Vesker static int dr_ste_build_mpls_tag(struct mlx5dr_match_param *value, 167526d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 167626d688e3SAlex Vesker u8 *hw_ste_p) 167726d688e3SAlex Vesker { 167826d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 167926d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc2_mask = &value->misc2; 168026d688e3SAlex Vesker u8 *tag = hw_ste->tag; 168126d688e3SAlex Vesker 168226d688e3SAlex Vesker if (sb->inner) 168326d688e3SAlex Vesker DR_STE_SET_MPLS_TAG(mpls, misc2_mask, inner, tag); 168426d688e3SAlex Vesker else 168526d688e3SAlex Vesker DR_STE_SET_MPLS_TAG(mpls, misc2_mask, outer, tag); 168626d688e3SAlex Vesker 168726d688e3SAlex Vesker return 0; 168826d688e3SAlex Vesker } 168926d688e3SAlex Vesker 169026d688e3SAlex Vesker void mlx5dr_ste_build_mpls(struct mlx5dr_ste_build *sb, 169126d688e3SAlex Vesker struct mlx5dr_match_param *mask, 169226d688e3SAlex Vesker bool inner, bool rx) 169326d688e3SAlex Vesker { 169426d688e3SAlex Vesker dr_ste_build_mpls_bit_mask(mask, inner, sb->bit_mask); 169526d688e3SAlex Vesker 169626d688e3SAlex Vesker sb->rx = rx; 169726d688e3SAlex Vesker sb->inner = inner; 169826d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(MPLS_FIRST, rx, inner); 169926d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 170026d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_mpls_tag; 170126d688e3SAlex Vesker } 170226d688e3SAlex Vesker 170326d688e3SAlex Vesker static void dr_ste_build_gre_bit_mask(struct mlx5dr_match_param *value, 170426d688e3SAlex Vesker bool inner, u8 *bit_mask) 170526d688e3SAlex Vesker { 170626d688e3SAlex Vesker struct mlx5dr_match_misc *misc_mask = &value->misc; 170726d688e3SAlex Vesker 170826d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_protocol, misc_mask, gre_protocol); 170926d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_k_present, misc_mask, gre_k_present); 171026d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_key_h, misc_mask, gre_key_h); 171126d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_key_l, misc_mask, gre_key_l); 171226d688e3SAlex Vesker 171326d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_c_present, misc_mask, gre_c_present); 171426d688e3SAlex Vesker DR_STE_SET_MASK_V(gre, bit_mask, gre_s_present, misc_mask, gre_s_present); 171526d688e3SAlex Vesker } 171626d688e3SAlex Vesker 171726d688e3SAlex Vesker static int dr_ste_build_gre_tag(struct mlx5dr_match_param *value, 171826d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 171926d688e3SAlex Vesker u8 *hw_ste_p) 172026d688e3SAlex Vesker { 172126d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 172226d688e3SAlex Vesker struct mlx5dr_match_misc *misc = &value->misc; 172326d688e3SAlex Vesker u8 *tag = hw_ste->tag; 172426d688e3SAlex Vesker 172526d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_protocol, misc, gre_protocol); 172626d688e3SAlex Vesker 172726d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_k_present, misc, gre_k_present); 172826d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_key_h, misc, gre_key_h); 172926d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_key_l, misc, gre_key_l); 173026d688e3SAlex Vesker 173126d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_c_present, misc, gre_c_present); 173226d688e3SAlex Vesker 173326d688e3SAlex Vesker DR_STE_SET_TAG(gre, tag, gre_s_present, misc, gre_s_present); 173426d688e3SAlex Vesker 173526d688e3SAlex Vesker return 0; 173626d688e3SAlex Vesker } 173726d688e3SAlex Vesker 173826d688e3SAlex Vesker void mlx5dr_ste_build_gre(struct mlx5dr_ste_build *sb, 173926d688e3SAlex Vesker struct mlx5dr_match_param *mask, bool inner, bool rx) 174026d688e3SAlex Vesker { 174126d688e3SAlex Vesker dr_ste_build_gre_bit_mask(mask, inner, sb->bit_mask); 174226d688e3SAlex Vesker 174326d688e3SAlex Vesker sb->rx = rx; 174426d688e3SAlex Vesker sb->inner = inner; 174526d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_GRE; 174626d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 174726d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_gre_tag; 174826d688e3SAlex Vesker } 174926d688e3SAlex Vesker 175026d688e3SAlex Vesker static void dr_ste_build_flex_parser_0_bit_mask(struct mlx5dr_match_param *value, 175126d688e3SAlex Vesker bool inner, u8 *bit_mask) 175226d688e3SAlex Vesker { 175326d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 175426d688e3SAlex Vesker 175526d688e3SAlex Vesker if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) { 175626d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label, 175726d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_label); 175826d688e3SAlex Vesker 175926d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp, 176026d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_exp); 176126d688e3SAlex Vesker 176226d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos, 176326d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_s_bos); 176426d688e3SAlex Vesker 176526d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl, 176626d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_ttl); 176726d688e3SAlex Vesker } else { 176826d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label, 176926d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_label); 177026d688e3SAlex Vesker 177126d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp, 177226d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_exp); 177326d688e3SAlex Vesker 177426d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos, 177526d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_s_bos); 177626d688e3SAlex Vesker 177726d688e3SAlex Vesker DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl, 177826d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_ttl); 177926d688e3SAlex Vesker } 178026d688e3SAlex Vesker } 178126d688e3SAlex Vesker 178226d688e3SAlex Vesker static int dr_ste_build_flex_parser_0_tag(struct mlx5dr_match_param *value, 178326d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 178426d688e3SAlex Vesker u8 *hw_ste_p) 178526d688e3SAlex Vesker { 178626d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 178726d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 178826d688e3SAlex Vesker u8 *tag = hw_ste->tag; 178926d688e3SAlex Vesker 179026d688e3SAlex Vesker if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) { 179126d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label, 179226d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_label); 179326d688e3SAlex Vesker 179426d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp, 179526d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_exp); 179626d688e3SAlex Vesker 179726d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos, 179826d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_s_bos); 179926d688e3SAlex Vesker 180026d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl, 180126d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_gre_ttl); 180226d688e3SAlex Vesker } else { 180326d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label, 180426d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_label); 180526d688e3SAlex Vesker 180626d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp, 180726d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_exp); 180826d688e3SAlex Vesker 180926d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos, 181026d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_s_bos); 181126d688e3SAlex Vesker 181226d688e3SAlex Vesker DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl, 181326d688e3SAlex Vesker misc_2_mask, outer_first_mpls_over_udp_ttl); 181426d688e3SAlex Vesker } 181526d688e3SAlex Vesker return 0; 181626d688e3SAlex Vesker } 181726d688e3SAlex Vesker 181826d688e3SAlex Vesker void mlx5dr_ste_build_flex_parser_0(struct mlx5dr_ste_build *sb, 181926d688e3SAlex Vesker struct mlx5dr_match_param *mask, 182026d688e3SAlex Vesker bool inner, bool rx) 182126d688e3SAlex Vesker { 182226d688e3SAlex Vesker dr_ste_build_flex_parser_0_bit_mask(mask, inner, sb->bit_mask); 182326d688e3SAlex Vesker 182426d688e3SAlex Vesker sb->rx = rx; 182526d688e3SAlex Vesker sb->inner = inner; 182626d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_0; 182726d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 182826d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_flex_parser_0_tag; 182926d688e3SAlex Vesker } 183026d688e3SAlex Vesker 183126d688e3SAlex Vesker #define ICMP_TYPE_OFFSET_FIRST_DW 24 183226d688e3SAlex Vesker #define ICMP_CODE_OFFSET_FIRST_DW 16 183326d688e3SAlex Vesker #define ICMP_HEADER_DATA_OFFSET_SECOND_DW 0 183426d688e3SAlex Vesker 183526d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_bit_mask(struct mlx5dr_match_param *mask, 183626d688e3SAlex Vesker struct mlx5dr_cmd_caps *caps, 183726d688e3SAlex Vesker u8 *bit_mask) 183826d688e3SAlex Vesker { 183926d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc_3_mask = &mask->misc3; 184026d688e3SAlex Vesker bool is_ipv4_mask = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3_mask); 184126d688e3SAlex Vesker u32 icmp_header_data_mask; 184226d688e3SAlex Vesker u32 icmp_type_mask; 184326d688e3SAlex Vesker u32 icmp_code_mask; 184426d688e3SAlex Vesker int dw0_location; 184526d688e3SAlex Vesker int dw1_location; 184626d688e3SAlex Vesker 184726d688e3SAlex Vesker if (is_ipv4_mask) { 184826d688e3SAlex Vesker icmp_header_data_mask = misc_3_mask->icmpv4_header_data; 184926d688e3SAlex Vesker icmp_type_mask = misc_3_mask->icmpv4_type; 185026d688e3SAlex Vesker icmp_code_mask = misc_3_mask->icmpv4_code; 185126d688e3SAlex Vesker dw0_location = caps->flex_parser_id_icmp_dw0; 185226d688e3SAlex Vesker dw1_location = caps->flex_parser_id_icmp_dw1; 185326d688e3SAlex Vesker } else { 185426d688e3SAlex Vesker icmp_header_data_mask = misc_3_mask->icmpv6_header_data; 185526d688e3SAlex Vesker icmp_type_mask = misc_3_mask->icmpv6_type; 185626d688e3SAlex Vesker icmp_code_mask = misc_3_mask->icmpv6_code; 185726d688e3SAlex Vesker dw0_location = caps->flex_parser_id_icmpv6_dw0; 185826d688e3SAlex Vesker dw1_location = caps->flex_parser_id_icmpv6_dw1; 185926d688e3SAlex Vesker } 186026d688e3SAlex Vesker 186126d688e3SAlex Vesker switch (dw0_location) { 186226d688e3SAlex Vesker case 4: 186326d688e3SAlex Vesker if (icmp_type_mask) { 186426d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4, 186526d688e3SAlex Vesker (icmp_type_mask << ICMP_TYPE_OFFSET_FIRST_DW)); 186626d688e3SAlex Vesker if (is_ipv4_mask) 186726d688e3SAlex Vesker misc_3_mask->icmpv4_type = 0; 186826d688e3SAlex Vesker else 186926d688e3SAlex Vesker misc_3_mask->icmpv6_type = 0; 187026d688e3SAlex Vesker } 187126d688e3SAlex Vesker if (icmp_code_mask) { 187226d688e3SAlex Vesker u32 cur_val = MLX5_GET(ste_flex_parser_1, bit_mask, 187326d688e3SAlex Vesker flex_parser_4); 187426d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4, 187526d688e3SAlex Vesker cur_val | (icmp_code_mask << ICMP_CODE_OFFSET_FIRST_DW)); 187626d688e3SAlex Vesker if (is_ipv4_mask) 187726d688e3SAlex Vesker misc_3_mask->icmpv4_code = 0; 187826d688e3SAlex Vesker else 187926d688e3SAlex Vesker misc_3_mask->icmpv6_code = 0; 188026d688e3SAlex Vesker } 188126d688e3SAlex Vesker break; 188226d688e3SAlex Vesker default: 188326d688e3SAlex Vesker return -EINVAL; 188426d688e3SAlex Vesker } 188526d688e3SAlex Vesker 188626d688e3SAlex Vesker switch (dw1_location) { 188726d688e3SAlex Vesker case 5: 188826d688e3SAlex Vesker if (icmp_header_data_mask) { 188926d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_5, 189026d688e3SAlex Vesker (icmp_header_data_mask << ICMP_HEADER_DATA_OFFSET_SECOND_DW)); 189126d688e3SAlex Vesker if (is_ipv4_mask) 189226d688e3SAlex Vesker misc_3_mask->icmpv4_header_data = 0; 189326d688e3SAlex Vesker else 189426d688e3SAlex Vesker misc_3_mask->icmpv6_header_data = 0; 189526d688e3SAlex Vesker } 189626d688e3SAlex Vesker break; 189726d688e3SAlex Vesker default: 189826d688e3SAlex Vesker return -EINVAL; 189926d688e3SAlex Vesker } 190026d688e3SAlex Vesker 190126d688e3SAlex Vesker return 0; 190226d688e3SAlex Vesker } 190326d688e3SAlex Vesker 190426d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_tag(struct mlx5dr_match_param *value, 190526d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 190626d688e3SAlex Vesker u8 *hw_ste_p) 190726d688e3SAlex Vesker { 190826d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 190926d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc_3 = &value->misc3; 191026d688e3SAlex Vesker u8 *tag = hw_ste->tag; 191126d688e3SAlex Vesker u32 icmp_header_data; 191226d688e3SAlex Vesker int dw0_location; 191326d688e3SAlex Vesker int dw1_location; 191426d688e3SAlex Vesker u32 icmp_type; 191526d688e3SAlex Vesker u32 icmp_code; 191626d688e3SAlex Vesker bool is_ipv4; 191726d688e3SAlex Vesker 191826d688e3SAlex Vesker is_ipv4 = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3); 191926d688e3SAlex Vesker if (is_ipv4) { 192026d688e3SAlex Vesker icmp_header_data = misc_3->icmpv4_header_data; 192126d688e3SAlex Vesker icmp_type = misc_3->icmpv4_type; 192226d688e3SAlex Vesker icmp_code = misc_3->icmpv4_code; 192326d688e3SAlex Vesker dw0_location = sb->caps->flex_parser_id_icmp_dw0; 192426d688e3SAlex Vesker dw1_location = sb->caps->flex_parser_id_icmp_dw1; 192526d688e3SAlex Vesker } else { 192626d688e3SAlex Vesker icmp_header_data = misc_3->icmpv6_header_data; 192726d688e3SAlex Vesker icmp_type = misc_3->icmpv6_type; 192826d688e3SAlex Vesker icmp_code = misc_3->icmpv6_code; 192926d688e3SAlex Vesker dw0_location = sb->caps->flex_parser_id_icmpv6_dw0; 193026d688e3SAlex Vesker dw1_location = sb->caps->flex_parser_id_icmpv6_dw1; 193126d688e3SAlex Vesker } 193226d688e3SAlex Vesker 193326d688e3SAlex Vesker switch (dw0_location) { 193426d688e3SAlex Vesker case 4: 193526d688e3SAlex Vesker if (icmp_type) { 193626d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, tag, flex_parser_4, 193726d688e3SAlex Vesker (icmp_type << ICMP_TYPE_OFFSET_FIRST_DW)); 193826d688e3SAlex Vesker if (is_ipv4) 193926d688e3SAlex Vesker misc_3->icmpv4_type = 0; 194026d688e3SAlex Vesker else 194126d688e3SAlex Vesker misc_3->icmpv6_type = 0; 194226d688e3SAlex Vesker } 194326d688e3SAlex Vesker 194426d688e3SAlex Vesker if (icmp_code) { 194526d688e3SAlex Vesker u32 cur_val = MLX5_GET(ste_flex_parser_1, tag, 194626d688e3SAlex Vesker flex_parser_4); 194726d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, tag, flex_parser_4, 194826d688e3SAlex Vesker cur_val | (icmp_code << ICMP_CODE_OFFSET_FIRST_DW)); 194926d688e3SAlex Vesker if (is_ipv4) 195026d688e3SAlex Vesker misc_3->icmpv4_code = 0; 195126d688e3SAlex Vesker else 195226d688e3SAlex Vesker misc_3->icmpv6_code = 0; 195326d688e3SAlex Vesker } 195426d688e3SAlex Vesker break; 195526d688e3SAlex Vesker default: 195626d688e3SAlex Vesker return -EINVAL; 195726d688e3SAlex Vesker } 195826d688e3SAlex Vesker 195926d688e3SAlex Vesker switch (dw1_location) { 196026d688e3SAlex Vesker case 5: 196126d688e3SAlex Vesker if (icmp_header_data) { 196226d688e3SAlex Vesker MLX5_SET(ste_flex_parser_1, tag, flex_parser_5, 196326d688e3SAlex Vesker (icmp_header_data << ICMP_HEADER_DATA_OFFSET_SECOND_DW)); 196426d688e3SAlex Vesker if (is_ipv4) 196526d688e3SAlex Vesker misc_3->icmpv4_header_data = 0; 196626d688e3SAlex Vesker else 196726d688e3SAlex Vesker misc_3->icmpv6_header_data = 0; 196826d688e3SAlex Vesker } 196926d688e3SAlex Vesker break; 197026d688e3SAlex Vesker default: 197126d688e3SAlex Vesker return -EINVAL; 197226d688e3SAlex Vesker } 197326d688e3SAlex Vesker 197426d688e3SAlex Vesker return 0; 197526d688e3SAlex Vesker } 197626d688e3SAlex Vesker 197726d688e3SAlex Vesker int mlx5dr_ste_build_flex_parser_1(struct mlx5dr_ste_build *sb, 197826d688e3SAlex Vesker struct mlx5dr_match_param *mask, 197926d688e3SAlex Vesker struct mlx5dr_cmd_caps *caps, 198026d688e3SAlex Vesker bool inner, bool rx) 198126d688e3SAlex Vesker { 198226d688e3SAlex Vesker int ret; 198326d688e3SAlex Vesker 198426d688e3SAlex Vesker ret = dr_ste_build_flex_parser_1_bit_mask(mask, caps, sb->bit_mask); 198526d688e3SAlex Vesker if (ret) 198626d688e3SAlex Vesker return ret; 198726d688e3SAlex Vesker 198826d688e3SAlex Vesker sb->rx = rx; 198926d688e3SAlex Vesker sb->inner = inner; 199026d688e3SAlex Vesker sb->caps = caps; 199126d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_1; 199226d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 199326d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_flex_parser_1_tag; 199426d688e3SAlex Vesker 199526d688e3SAlex Vesker return 0; 199626d688e3SAlex Vesker } 199726d688e3SAlex Vesker 199826d688e3SAlex Vesker static void dr_ste_build_general_purpose_bit_mask(struct mlx5dr_match_param *value, 199926d688e3SAlex Vesker bool inner, u8 *bit_mask) 200026d688e3SAlex Vesker { 200126d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 200226d688e3SAlex Vesker 200326d688e3SAlex Vesker DR_STE_SET_MASK_V(general_purpose, bit_mask, 200426d688e3SAlex Vesker general_purpose_lookup_field, misc_2_mask, 200526d688e3SAlex Vesker metadata_reg_a); 200626d688e3SAlex Vesker } 200726d688e3SAlex Vesker 200826d688e3SAlex Vesker static int dr_ste_build_general_purpose_tag(struct mlx5dr_match_param *value, 200926d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 201026d688e3SAlex Vesker u8 *hw_ste_p) 201126d688e3SAlex Vesker { 201226d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 201326d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 201426d688e3SAlex Vesker u8 *tag = hw_ste->tag; 201526d688e3SAlex Vesker 201626d688e3SAlex Vesker DR_STE_SET_TAG(general_purpose, tag, general_purpose_lookup_field, 201726d688e3SAlex Vesker misc_2_mask, metadata_reg_a); 201826d688e3SAlex Vesker 201926d688e3SAlex Vesker return 0; 202026d688e3SAlex Vesker } 202126d688e3SAlex Vesker 202226d688e3SAlex Vesker void mlx5dr_ste_build_general_purpose(struct mlx5dr_ste_build *sb, 202326d688e3SAlex Vesker struct mlx5dr_match_param *mask, 202426d688e3SAlex Vesker bool inner, bool rx) 202526d688e3SAlex Vesker { 202626d688e3SAlex Vesker dr_ste_build_general_purpose_bit_mask(mask, inner, sb->bit_mask); 202726d688e3SAlex Vesker 202826d688e3SAlex Vesker sb->rx = rx; 202926d688e3SAlex Vesker sb->inner = inner; 203026d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_GENERAL_PURPOSE; 203126d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 203226d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_general_purpose_tag; 203326d688e3SAlex Vesker } 203426d688e3SAlex Vesker 203526d688e3SAlex Vesker static void dr_ste_build_eth_l4_misc_bit_mask(struct mlx5dr_match_param *value, 203626d688e3SAlex Vesker bool inner, u8 *bit_mask) 203726d688e3SAlex Vesker { 203826d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3; 203926d688e3SAlex Vesker 204026d688e3SAlex Vesker if (inner) { 204126d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask, 204226d688e3SAlex Vesker inner_tcp_seq_num); 204326d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask, 204426d688e3SAlex Vesker inner_tcp_ack_num); 204526d688e3SAlex Vesker } else { 204626d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask, 204726d688e3SAlex Vesker outer_tcp_seq_num); 204826d688e3SAlex Vesker DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask, 204926d688e3SAlex Vesker outer_tcp_ack_num); 205026d688e3SAlex Vesker } 205126d688e3SAlex Vesker } 205226d688e3SAlex Vesker 205326d688e3SAlex Vesker static int dr_ste_build_eth_l4_misc_tag(struct mlx5dr_match_param *value, 205426d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 205526d688e3SAlex Vesker u8 *hw_ste_p) 205626d688e3SAlex Vesker { 205726d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 205826d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc3 = &value->misc3; 205926d688e3SAlex Vesker u8 *tag = hw_ste->tag; 206026d688e3SAlex Vesker 206126d688e3SAlex Vesker if (sb->inner) { 206226d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, inner_tcp_seq_num); 206326d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, inner_tcp_ack_num); 206426d688e3SAlex Vesker } else { 206526d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, outer_tcp_seq_num); 206626d688e3SAlex Vesker DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, outer_tcp_ack_num); 206726d688e3SAlex Vesker } 206826d688e3SAlex Vesker 206926d688e3SAlex Vesker return 0; 207026d688e3SAlex Vesker } 207126d688e3SAlex Vesker 207226d688e3SAlex Vesker void mlx5dr_ste_build_eth_l4_misc(struct mlx5dr_ste_build *sb, 207326d688e3SAlex Vesker struct mlx5dr_match_param *mask, 207426d688e3SAlex Vesker bool inner, bool rx) 207526d688e3SAlex Vesker { 207626d688e3SAlex Vesker dr_ste_build_eth_l4_misc_bit_mask(mask, inner, sb->bit_mask); 207726d688e3SAlex Vesker 207826d688e3SAlex Vesker sb->rx = rx; 207926d688e3SAlex Vesker sb->inner = inner; 208026d688e3SAlex Vesker sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4_MISC, rx, inner); 208126d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 208226d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_eth_l4_misc_tag; 208326d688e3SAlex Vesker } 208426d688e3SAlex Vesker 20856e9e286eSYevgeny Kliteynik static void 20866e9e286eSYevgeny Kliteynik dr_ste_build_flex_parser_tnl_vxlan_gpe_bit_mask(struct mlx5dr_match_param *value, 208726d688e3SAlex Vesker bool inner, u8 *bit_mask) 208826d688e3SAlex Vesker { 208926d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3; 209026d688e3SAlex Vesker 20916e9e286eSYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask, 20926e9e286eSYevgeny Kliteynik outer_vxlan_gpe_flags, 20936e9e286eSYevgeny Kliteynik misc_3_mask, outer_vxlan_gpe_flags); 20946e9e286eSYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask, 20956e9e286eSYevgeny Kliteynik outer_vxlan_gpe_next_protocol, 20966e9e286eSYevgeny Kliteynik misc_3_mask, outer_vxlan_gpe_next_protocol); 20976e9e286eSYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask, 20986e9e286eSYevgeny Kliteynik outer_vxlan_gpe_vni, 20996e9e286eSYevgeny Kliteynik misc_3_mask, outer_vxlan_gpe_vni); 210026d688e3SAlex Vesker } 210126d688e3SAlex Vesker 21026e9e286eSYevgeny Kliteynik static int 21036e9e286eSYevgeny Kliteynik dr_ste_build_flex_parser_tnl_vxlan_gpe_tag(struct mlx5dr_match_param *value, 210426d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 210526d688e3SAlex Vesker u8 *hw_ste_p) 210626d688e3SAlex Vesker { 210726d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 210826d688e3SAlex Vesker struct mlx5dr_match_misc3 *misc3 = &value->misc3; 210926d688e3SAlex Vesker u8 *tag = hw_ste->tag; 211026d688e3SAlex Vesker 21116e9e286eSYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag, 21126e9e286eSYevgeny Kliteynik outer_vxlan_gpe_flags, misc3, 21136e9e286eSYevgeny Kliteynik outer_vxlan_gpe_flags); 21146e9e286eSYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag, 21156e9e286eSYevgeny Kliteynik outer_vxlan_gpe_next_protocol, misc3, 21166e9e286eSYevgeny Kliteynik outer_vxlan_gpe_next_protocol); 21176e9e286eSYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag, 21186e9e286eSYevgeny Kliteynik outer_vxlan_gpe_vni, misc3, 21196e9e286eSYevgeny Kliteynik outer_vxlan_gpe_vni); 212026d688e3SAlex Vesker 212126d688e3SAlex Vesker return 0; 212226d688e3SAlex Vesker } 212326d688e3SAlex Vesker 21246e9e286eSYevgeny Kliteynik void mlx5dr_ste_build_flex_parser_tnl_vxlan_gpe(struct mlx5dr_ste_build *sb, 212526d688e3SAlex Vesker struct mlx5dr_match_param *mask, 212626d688e3SAlex Vesker bool inner, bool rx) 212726d688e3SAlex Vesker { 21286e9e286eSYevgeny Kliteynik dr_ste_build_flex_parser_tnl_vxlan_gpe_bit_mask(mask, inner, 21296e9e286eSYevgeny Kliteynik sb->bit_mask); 213026d688e3SAlex Vesker 213126d688e3SAlex Vesker sb->rx = rx; 213226d688e3SAlex Vesker sb->inner = inner; 213326d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_TNL_HEADER; 213426d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 21356e9e286eSYevgeny Kliteynik sb->ste_build_tag_func = &dr_ste_build_flex_parser_tnl_vxlan_gpe_tag; 213626d688e3SAlex Vesker } 213726d688e3SAlex Vesker 2138b6d12238SYevgeny Kliteynik static void 2139b6d12238SYevgeny Kliteynik dr_ste_build_flex_parser_tnl_geneve_bit_mask(struct mlx5dr_match_param *value, 2140b6d12238SYevgeny Kliteynik u8 *bit_mask) 2141b6d12238SYevgeny Kliteynik { 2142b6d12238SYevgeny Kliteynik struct mlx5dr_match_misc *misc_mask = &value->misc; 2143b6d12238SYevgeny Kliteynik 2144b6d12238SYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask, 2145b6d12238SYevgeny Kliteynik geneve_protocol_type, 2146b6d12238SYevgeny Kliteynik misc_mask, geneve_protocol_type); 2147b6d12238SYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask, 2148b6d12238SYevgeny Kliteynik geneve_oam, 2149b6d12238SYevgeny Kliteynik misc_mask, geneve_oam); 2150b6d12238SYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask, 2151b6d12238SYevgeny Kliteynik geneve_opt_len, 2152b6d12238SYevgeny Kliteynik misc_mask, geneve_opt_len); 2153b6d12238SYevgeny Kliteynik DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask, 2154b6d12238SYevgeny Kliteynik geneve_vni, 2155b6d12238SYevgeny Kliteynik misc_mask, geneve_vni); 2156b6d12238SYevgeny Kliteynik } 2157b6d12238SYevgeny Kliteynik 2158b6d12238SYevgeny Kliteynik static int 2159b6d12238SYevgeny Kliteynik dr_ste_build_flex_parser_tnl_geneve_tag(struct mlx5dr_match_param *value, 2160b6d12238SYevgeny Kliteynik struct mlx5dr_ste_build *sb, 2161b6d12238SYevgeny Kliteynik u8 *hw_ste_p) 2162b6d12238SYevgeny Kliteynik { 2163b6d12238SYevgeny Kliteynik struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 2164b6d12238SYevgeny Kliteynik struct mlx5dr_match_misc *misc = &value->misc; 2165b6d12238SYevgeny Kliteynik u8 *tag = hw_ste->tag; 2166b6d12238SYevgeny Kliteynik 2167b6d12238SYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_geneve, tag, 2168b6d12238SYevgeny Kliteynik geneve_protocol_type, misc, geneve_protocol_type); 2169b6d12238SYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_geneve, tag, 2170b6d12238SYevgeny Kliteynik geneve_oam, misc, geneve_oam); 2171b6d12238SYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_geneve, tag, 2172b6d12238SYevgeny Kliteynik geneve_opt_len, misc, geneve_opt_len); 2173b6d12238SYevgeny Kliteynik DR_STE_SET_TAG(flex_parser_tnl_geneve, tag, 2174b6d12238SYevgeny Kliteynik geneve_vni, misc, geneve_vni); 2175b6d12238SYevgeny Kliteynik 2176b6d12238SYevgeny Kliteynik return 0; 2177b6d12238SYevgeny Kliteynik } 2178b6d12238SYevgeny Kliteynik 2179b6d12238SYevgeny Kliteynik void mlx5dr_ste_build_flex_parser_tnl_geneve(struct mlx5dr_ste_build *sb, 2180b6d12238SYevgeny Kliteynik struct mlx5dr_match_param *mask, 2181b6d12238SYevgeny Kliteynik bool inner, bool rx) 2182b6d12238SYevgeny Kliteynik { 2183b6d12238SYevgeny Kliteynik dr_ste_build_flex_parser_tnl_geneve_bit_mask(mask, sb->bit_mask); 2184b6d12238SYevgeny Kliteynik sb->rx = rx; 2185b6d12238SYevgeny Kliteynik sb->inner = inner; 2186b6d12238SYevgeny Kliteynik sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_TNL_HEADER; 2187b6d12238SYevgeny Kliteynik sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 2188b6d12238SYevgeny Kliteynik sb->ste_build_tag_func = &dr_ste_build_flex_parser_tnl_geneve_tag; 218926d688e3SAlex Vesker } 219026d688e3SAlex Vesker 219126d688e3SAlex Vesker static void dr_ste_build_register_0_bit_mask(struct mlx5dr_match_param *value, 219226d688e3SAlex Vesker u8 *bit_mask) 219326d688e3SAlex Vesker { 219426d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 219526d688e3SAlex Vesker 219626d688e3SAlex Vesker DR_STE_SET_MASK_V(register_0, bit_mask, register_0_h, 219726d688e3SAlex Vesker misc_2_mask, metadata_reg_c_0); 219826d688e3SAlex Vesker DR_STE_SET_MASK_V(register_0, bit_mask, register_0_l, 219926d688e3SAlex Vesker misc_2_mask, metadata_reg_c_1); 220026d688e3SAlex Vesker DR_STE_SET_MASK_V(register_0, bit_mask, register_1_h, 220126d688e3SAlex Vesker misc_2_mask, metadata_reg_c_2); 220226d688e3SAlex Vesker DR_STE_SET_MASK_V(register_0, bit_mask, register_1_l, 220326d688e3SAlex Vesker misc_2_mask, metadata_reg_c_3); 220426d688e3SAlex Vesker } 220526d688e3SAlex Vesker 220626d688e3SAlex Vesker static int dr_ste_build_register_0_tag(struct mlx5dr_match_param *value, 220726d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 220826d688e3SAlex Vesker u8 *hw_ste_p) 220926d688e3SAlex Vesker { 221026d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 221126d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc2 = &value->misc2; 221226d688e3SAlex Vesker u8 *tag = hw_ste->tag; 221326d688e3SAlex Vesker 221426d688e3SAlex Vesker DR_STE_SET_TAG(register_0, tag, register_0_h, misc2, metadata_reg_c_0); 221526d688e3SAlex Vesker DR_STE_SET_TAG(register_0, tag, register_0_l, misc2, metadata_reg_c_1); 221626d688e3SAlex Vesker DR_STE_SET_TAG(register_0, tag, register_1_h, misc2, metadata_reg_c_2); 221726d688e3SAlex Vesker DR_STE_SET_TAG(register_0, tag, register_1_l, misc2, metadata_reg_c_3); 221826d688e3SAlex Vesker 221926d688e3SAlex Vesker return 0; 222026d688e3SAlex Vesker } 222126d688e3SAlex Vesker 222226d688e3SAlex Vesker void mlx5dr_ste_build_register_0(struct mlx5dr_ste_build *sb, 222326d688e3SAlex Vesker struct mlx5dr_match_param *mask, 222426d688e3SAlex Vesker bool inner, bool rx) 222526d688e3SAlex Vesker { 222626d688e3SAlex Vesker dr_ste_build_register_0_bit_mask(mask, sb->bit_mask); 222726d688e3SAlex Vesker 222826d688e3SAlex Vesker sb->rx = rx; 222926d688e3SAlex Vesker sb->inner = inner; 223026d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_0; 223126d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 223226d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_register_0_tag; 223326d688e3SAlex Vesker } 223426d688e3SAlex Vesker 223526d688e3SAlex Vesker static void dr_ste_build_register_1_bit_mask(struct mlx5dr_match_param *value, 223626d688e3SAlex Vesker u8 *bit_mask) 223726d688e3SAlex Vesker { 223826d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2; 223926d688e3SAlex Vesker 224026d688e3SAlex Vesker DR_STE_SET_MASK_V(register_1, bit_mask, register_2_h, 224126d688e3SAlex Vesker misc_2_mask, metadata_reg_c_4); 224226d688e3SAlex Vesker DR_STE_SET_MASK_V(register_1, bit_mask, register_2_l, 224326d688e3SAlex Vesker misc_2_mask, metadata_reg_c_5); 224426d688e3SAlex Vesker DR_STE_SET_MASK_V(register_1, bit_mask, register_3_h, 224526d688e3SAlex Vesker misc_2_mask, metadata_reg_c_6); 224626d688e3SAlex Vesker DR_STE_SET_MASK_V(register_1, bit_mask, register_3_l, 224726d688e3SAlex Vesker misc_2_mask, metadata_reg_c_7); 224826d688e3SAlex Vesker } 224926d688e3SAlex Vesker 225026d688e3SAlex Vesker static int dr_ste_build_register_1_tag(struct mlx5dr_match_param *value, 225126d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 225226d688e3SAlex Vesker u8 *hw_ste_p) 225326d688e3SAlex Vesker { 225426d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 225526d688e3SAlex Vesker struct mlx5dr_match_misc2 *misc2 = &value->misc2; 225626d688e3SAlex Vesker u8 *tag = hw_ste->tag; 225726d688e3SAlex Vesker 225826d688e3SAlex Vesker DR_STE_SET_TAG(register_1, tag, register_2_h, misc2, metadata_reg_c_4); 225926d688e3SAlex Vesker DR_STE_SET_TAG(register_1, tag, register_2_l, misc2, metadata_reg_c_5); 226026d688e3SAlex Vesker DR_STE_SET_TAG(register_1, tag, register_3_h, misc2, metadata_reg_c_6); 226126d688e3SAlex Vesker DR_STE_SET_TAG(register_1, tag, register_3_l, misc2, metadata_reg_c_7); 226226d688e3SAlex Vesker 226326d688e3SAlex Vesker return 0; 226426d688e3SAlex Vesker } 226526d688e3SAlex Vesker 226626d688e3SAlex Vesker void mlx5dr_ste_build_register_1(struct mlx5dr_ste_build *sb, 226726d688e3SAlex Vesker struct mlx5dr_match_param *mask, 226826d688e3SAlex Vesker bool inner, bool rx) 226926d688e3SAlex Vesker { 227026d688e3SAlex Vesker dr_ste_build_register_1_bit_mask(mask, sb->bit_mask); 227126d688e3SAlex Vesker 227226d688e3SAlex Vesker sb->rx = rx; 227326d688e3SAlex Vesker sb->inner = inner; 227426d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_1; 227526d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 227626d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_register_1_tag; 227726d688e3SAlex Vesker } 227826d688e3SAlex Vesker 227926d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_bit_mask(struct mlx5dr_match_param *value, 228026d688e3SAlex Vesker u8 *bit_mask) 228126d688e3SAlex Vesker { 228226d688e3SAlex Vesker struct mlx5dr_match_misc *misc_mask = &value->misc; 228326d688e3SAlex Vesker 2284640bdb1fSAlaa Hleihel /* Partial misc source_port is not supported */ 2285640bdb1fSAlaa Hleihel if (misc_mask->source_port && misc_mask->source_port != 0xffff) 2286640bdb1fSAlaa Hleihel return -EINVAL; 2287640bdb1fSAlaa Hleihel 2288640bdb1fSAlaa Hleihel /* Partial misc source_eswitch_owner_vhca_id is not supported */ 2289640bdb1fSAlaa Hleihel if (misc_mask->source_eswitch_owner_vhca_id && 2290640bdb1fSAlaa Hleihel misc_mask->source_eswitch_owner_vhca_id != 0xffff) 229126d688e3SAlex Vesker return -EINVAL; 229226d688e3SAlex Vesker 229326d688e3SAlex Vesker DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_gvmi, misc_mask, source_port); 229426d688e3SAlex Vesker DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_qp, misc_mask, source_sqn); 2295640bdb1fSAlaa Hleihel misc_mask->source_eswitch_owner_vhca_id = 0; 229626d688e3SAlex Vesker 229726d688e3SAlex Vesker return 0; 229826d688e3SAlex Vesker } 229926d688e3SAlex Vesker 230026d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, 230126d688e3SAlex Vesker struct mlx5dr_ste_build *sb, 230226d688e3SAlex Vesker u8 *hw_ste_p) 230326d688e3SAlex Vesker { 230426d688e3SAlex Vesker struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 230526d688e3SAlex Vesker struct mlx5dr_match_misc *misc = &value->misc; 230626d688e3SAlex Vesker struct mlx5dr_cmd_vport_cap *vport_cap; 2307640bdb1fSAlaa Hleihel struct mlx5dr_domain *dmn = sb->dmn; 2308640bdb1fSAlaa Hleihel struct mlx5dr_cmd_caps *caps; 230952d21497SHamdan Igbaria u8 *bit_mask = sb->bit_mask; 231026d688e3SAlex Vesker u8 *tag = hw_ste->tag; 231152d21497SHamdan Igbaria bool source_gvmi_set; 231226d688e3SAlex Vesker 231326d688e3SAlex Vesker DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); 231426d688e3SAlex Vesker 2315640bdb1fSAlaa Hleihel if (sb->vhca_id_valid) { 2316640bdb1fSAlaa Hleihel /* Find port GVMI based on the eswitch_owner_vhca_id */ 2317640bdb1fSAlaa Hleihel if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) 2318640bdb1fSAlaa Hleihel caps = &dmn->info.caps; 2319640bdb1fSAlaa Hleihel else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == 2320640bdb1fSAlaa Hleihel dmn->peer_dmn->info.caps.gvmi)) 2321640bdb1fSAlaa Hleihel caps = &dmn->peer_dmn->info.caps; 2322640bdb1fSAlaa Hleihel else 2323640bdb1fSAlaa Hleihel return -EINVAL; 2324640bdb1fSAlaa Hleihel } else { 2325640bdb1fSAlaa Hleihel caps = &dmn->info.caps; 2326640bdb1fSAlaa Hleihel } 2327640bdb1fSAlaa Hleihel 2328640bdb1fSAlaa Hleihel vport_cap = mlx5dr_get_vport_cap(caps, misc->source_port); 232926d688e3SAlex Vesker if (!vport_cap) 233026d688e3SAlex Vesker return -EINVAL; 233126d688e3SAlex Vesker 233252d21497SHamdan Igbaria source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi); 233352d21497SHamdan Igbaria if (vport_cap->vport_gvmi && source_gvmi_set) 233426d688e3SAlex Vesker MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi); 233526d688e3SAlex Vesker 2336640bdb1fSAlaa Hleihel misc->source_eswitch_owner_vhca_id = 0; 233726d688e3SAlex Vesker misc->source_port = 0; 233826d688e3SAlex Vesker 233926d688e3SAlex Vesker return 0; 234026d688e3SAlex Vesker } 234126d688e3SAlex Vesker 234226d688e3SAlex Vesker int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb, 234326d688e3SAlex Vesker struct mlx5dr_match_param *mask, 2344640bdb1fSAlaa Hleihel struct mlx5dr_domain *dmn, 234526d688e3SAlex Vesker bool inner, bool rx) 234626d688e3SAlex Vesker { 234726d688e3SAlex Vesker int ret; 234826d688e3SAlex Vesker 2349640bdb1fSAlaa Hleihel /* Set vhca_id_valid before we reset source_eswitch_owner_vhca_id */ 2350640bdb1fSAlaa Hleihel sb->vhca_id_valid = mask->misc.source_eswitch_owner_vhca_id; 2351640bdb1fSAlaa Hleihel 235226d688e3SAlex Vesker ret = dr_ste_build_src_gvmi_qpn_bit_mask(mask, sb->bit_mask); 235326d688e3SAlex Vesker if (ret) 235426d688e3SAlex Vesker return ret; 235526d688e3SAlex Vesker 235626d688e3SAlex Vesker sb->rx = rx; 2357640bdb1fSAlaa Hleihel sb->dmn = dmn; 235826d688e3SAlex Vesker sb->inner = inner; 235926d688e3SAlex Vesker sb->lu_type = MLX5DR_STE_LU_TYPE_SRC_GVMI_AND_QP; 236026d688e3SAlex Vesker sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask); 236126d688e3SAlex Vesker sb->ste_build_tag_func = &dr_ste_build_src_gvmi_qpn_tag; 236226d688e3SAlex Vesker 236326d688e3SAlex Vesker return 0; 236426d688e3SAlex Vesker } 2365