| /* |
| * Copyright (c) 2020, Mellanox Technologies. All rights reserved. |
| * |
| * This software is available to you under a choice of one of two |
| * licenses. You may choose to be licensed under the terms of the GNU |
| * General Public License (GPL) Version 2, available from the file |
| * COPYING in the main directory of this source tree, or the |
| * OpenIB.org BSD license below: |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials |
| * provided with the distribution. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| |
| #ifndef _DR_STE_ |
| #define _DR_STE_ |
| |
| #include <ccan/array_size.h> |
| #include "mlx5dv_dr.h" |
| |
| #define IPV4_ETHERTYPE 0x0800 |
| #define IPV6_ETHERTYPE 0x86DD |
| #define STE_IPV4 0x1 |
| #define STE_IPV6 0x2 |
| #define STE_TCP 0x1 |
| #define STE_UDP 0x2 |
| #define STE_SPI 0x3 |
| #define IP_VERSION_IPV4 0x4 |
| #define IP_VERSION_IPV6 0x6 |
| #define IP_PROTOCOL_UDP 0x11 |
| #define IP_PROTOCOL_TCP 0x06 |
| #define IP_PROTOCOL_IPSEC 0x33 |
| #define HDR_LEN_L2_MACS 0xC |
| #define HDR_LEN_L2_VLAN 0x4 |
| #define HDR_LEN_L2_ETHER 0x2 |
| #define HDR_LEN_L2 (HDR_LEN_L2_MACS + HDR_LEN_L2_ETHER) |
| #define HDR_LEN_L2_W_VLAN (HDR_LEN_L2 + HDR_LEN_L2_VLAN) |
| |
| enum { |
| HDR_MPLS_OFFSET_LABEL = 12, |
| HDR_MPLS_OFFSET_EXP = 9, |
| HDR_MPLS_OFFSET_S_BOS = 8, |
| HDR_MPLS_OFFSET_TTL = 0, |
| }; |
| |
| #define DR_DEVX_GET_CLEAR(typ, p, fld, clear) ({ \ |
| uint32_t ___t = DEVX_GET(typ, p, fld); \ |
| if (clear) \ |
| DEVX_SET(typ, p, fld, 0); \ |
| ___t; \ |
| }) |
| |
| /* Read from layout struct */ |
| #define DR_STE_GET(typ, p, fld) DEVX_GET(ste_##typ, p, fld) |
| |
| /* Write to layout a value */ |
| #define DR_STE_SET(typ, p, fld, v) DEVX_SET(ste_##typ, p, fld, v) |
| |
| #define DR_STE_SET_BOOL(typ, p, fld, v) DEVX_SET(ste_##typ, p, fld, !!(v)) |
| |
| /* Set to STE a specific value using DR_STE_SET */ |
| #define DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, value) do { \ |
| if ((spec)->s_fname) { \ |
| DR_STE_SET(lookup_type, tag, t_fname, value); \ |
| (spec)->s_fname = 0; \ |
| } \ |
| } while (0) |
| |
| /* Set to STE spec->s_fname to tag->t_fname set spec->s_fname as used */ |
| #define DR_STE_SET_TAG(lookup_type, tag, t_fname, spec, s_fname) \ |
| DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, (spec)->s_fname) |
| |
| /* Set to STE -1 to tag->t_fname and set spec->s_fname as used */ |
| #define DR_STE_SET_ONES(lookup_type, tag, t_fname, spec, s_fname) \ |
| DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, -1) |
| |
| #define DR_STE_SET_TCP_FLAGS(lookup_type, tag, spec) do { \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_ns, (spec)->tcp_flags & (1 << 8)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_cwr, (spec)->tcp_flags & (1 << 7)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_ece, (spec)->tcp_flags & (1 << 6)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_urg, (spec)->tcp_flags & (1 << 5)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_ack, (spec)->tcp_flags & (1 << 4)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_psh, (spec)->tcp_flags & (1 << 3)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_rst, (spec)->tcp_flags & (1 << 2)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_syn, (spec)->tcp_flags & (1 << 1)); \ |
| DR_STE_SET_BOOL(lookup_type, tag, tcp_fin, (spec)->tcp_flags & (1 << 0)); \ |
| } while (0) |
| |
| #define DR_STE_SET_MPLS(lookup_type, mask, in_out, tag) do { \ |
| DR_STE_SET_TAG(lookup_type, tag, mpls0_label, mask, \ |
| in_out##_first_mpls_label);\ |
| DR_STE_SET_TAG(lookup_type, tag, mpls0_s_bos, mask, \ |
| in_out##_first_mpls_s_bos); \ |
| DR_STE_SET_TAG(lookup_type, tag, mpls0_exp, mask, \ |
| in_out##_first_mpls_exp); \ |
| DR_STE_SET_TAG(lookup_type, tag, mpls0_ttl, mask, \ |
| in_out##_first_mpls_ttl); \ |
| } while (0) |
| |
| #define DR_STE_SET_FLEX_PARSER_FIELD(tag, fname, caps, spec) do { \ |
| if ((spec)->fname) { \ |
| uint8_t parser_id = caps->flex_parser_id_##fname; \ |
| uint8_t *parser_ptr = dr_ste_calc_flex_parser_offset(tag, parser_id); \ |
| *(__be32 *)parser_ptr = htobe32((spec)->fname);\ |
| (spec)->fname = 0; \ |
| } \ |
| } while (0) |
| |
| enum dr_ste_action_modify_flags { |
| DR_STE_ACTION_MODIFY_FLAG_REQ_FLEX = 1 << 0, |
| }; |
| |
| enum dr_ste_action_modify_type_l3 { |
| DR_STE_ACTION_MDFY_TYPE_L3_NONE = 0x0, |
| DR_STE_ACTION_MDFY_TYPE_L3_IPV4 = 0x1, |
| DR_STE_ACTION_MDFY_TYPE_L3_IPV6 = 0x2, |
| }; |
| |
| enum dr_ste_action_modify_type_l4 { |
| DR_STE_ACTION_MDFY_TYPE_L4_NONE = 0x0, |
| DR_STE_ACTION_MDFY_TYPE_L4_TCP = 0x1, |
| DR_STE_ACTION_MDFY_TYPE_L4_UDP = 0x2, |
| }; |
| |
| uint16_t dr_ste_conv_bit_to_byte_mask(uint8_t *bit_mask); |
| |
| static inline uint8_t * |
| dr_ste_calc_flex_parser_offset(uint8_t *tag, uint8_t parser_id) |
| { |
| /* Calculate tag byte offset based on flex parser id */ |
| return tag + 4 * (3 - (parser_id % 4)); |
| } |
| |
| typedef void (*dr_ste_builder_void_init)(struct dr_ste_build *sb, |
| struct dr_match_param *mask); |
| |
| struct dr_ste_ctx { |
| /* Builders */ |
| dr_ste_builder_void_init build_eth_l2_src_dst_init; |
| dr_ste_builder_void_init build_eth_l3_ipv6_src_init; |
| dr_ste_builder_void_init build_eth_l3_ipv6_dst_init; |
| dr_ste_builder_void_init build_eth_l3_ipv4_5_tuple_init; |
| dr_ste_builder_void_init build_eth_l2_src_init; |
| dr_ste_builder_void_init build_eth_l2_dst_init; |
| dr_ste_builder_void_init build_eth_l2_tnl_init; |
| dr_ste_builder_void_init build_eth_l3_ipv4_misc_init; |
| dr_ste_builder_void_init build_eth_ipv6_l3_l4_init; |
| dr_ste_builder_void_init build_mpls_init; |
| dr_ste_builder_void_init build_tnl_gre_init; |
| dr_ste_builder_void_init build_tnl_mpls_over_gre_init; |
| dr_ste_builder_void_init build_tnl_mpls_over_udp_init; |
| dr_ste_builder_void_init build_icmp_init; |
| dr_ste_builder_void_init build_general_purpose_init; |
| dr_ste_builder_void_init build_eth_l4_misc_init; |
| dr_ste_builder_void_init build_tnl_vxlan_gpe_init; |
| dr_ste_builder_void_init build_tnl_geneve_init; |
| dr_ste_builder_void_init build_tnl_geneve_tlv_opt_init; |
| dr_ste_builder_void_init build_tnl_geneve_tlv_opt_exist_init; |
| dr_ste_builder_void_init build_tnl_gtpu_init; |
| dr_ste_builder_void_init build_tnl_gtpu_flex_parser_0; |
| dr_ste_builder_void_init build_tnl_gtpu_flex_parser_1; |
| dr_ste_builder_void_init build_register_0_init; |
| dr_ste_builder_void_init build_register_1_init; |
| dr_ste_builder_void_init build_src_gvmi_qpn_init; |
| dr_ste_builder_void_init build_flex_parser_0_init; |
| dr_ste_builder_void_init build_flex_parser_1_init; |
| dr_ste_builder_void_init build_tunnel_header_init; |
| dr_ste_builder_void_init build_def0_init; |
| dr_ste_builder_void_init build_def2_init; |
| dr_ste_builder_void_init build_def6_init; |
| dr_ste_builder_void_init build_def16_init; |
| dr_ste_builder_void_init build_def22_init; |
| dr_ste_builder_void_init build_def24_init; |
| dr_ste_builder_void_init build_def25_init; |
| dr_ste_builder_void_init build_def26_init; |
| dr_ste_builder_void_init build_def28_init; |
| dr_ste_builder_void_init build_def33_init; |
| int (*aso_other_domain_link)(struct mlx5dv_devx_obj *devx_obj, |
| struct mlx5dv_dr_domain *peer_dmn, |
| struct mlx5dv_dr_domain *dmn, |
| uint32_t flags, |
| uint8_t return_reg_c); |
| int (*aso_other_domain_unlink)(struct mlx5dv_devx_obj *devx_obj); |
| |
| /* Getters and Setters */ |
| void (*ste_init)(uint8_t *hw_ste_p, uint16_t lu_type, |
| bool is_rx, uint16_t gvmi); |
| void (*set_next_lu_type)(uint8_t *hw_ste_p, uint16_t lu_type); |
| uint16_t (*get_next_lu_type)(uint8_t *hw_ste_p); |
| void (*set_miss_addr)(uint8_t *hw_ste_p, uint64_t miss_addr); |
| uint64_t (*get_miss_addr)(uint8_t *hw_ste_p); |
| void (*set_hit_addr)(uint8_t *hw_ste_p, uint64_t icm_addr, uint32_t ht_size); |
| void (*set_byte_mask)(uint8_t *hw_ste_p, uint16_t byte_mask); |
| uint16_t (*get_byte_mask)(uint8_t *hw_ste_p); |
| void (*set_ctrl_always_hit_htbl)(uint8_t *hw_ste, uint16_t byte_mask, |
| uint16_t lu_type, uint64_t icm_addr, |
| uint32_t num_of_entries, uint16_t gvmi); |
| void (*set_ctrl_always_miss)(uint8_t *hw_ste, |
| uint64_t miss_addr, |
| uint16_t gvmi); |
| void (*set_hit_gvmi)(uint8_t *hw_ste, uint16_t gvmi); |
| |
| /* Actions */ |
| uint32_t actions_caps; |
| const struct dr_ste_action_modify_field *action_modify_field_arr; |
| size_t action_modify_field_arr_size; |
| void (*set_actions_rx)(uint8_t *action_type_set, |
| uint32_t actions_caps, |
| uint8_t *hw_ste_arr, |
| struct dr_ste_actions_attr *attr, |
| uint32_t *added_stes); |
| void (*set_actions_tx)(uint8_t *action_type_set, |
| uint32_t actions_caps, |
| uint8_t *hw_ste_arr, |
| struct dr_ste_actions_attr *attr, |
| uint32_t *added_stes); |
| void (*set_action_set)(uint8_t *hw_action, |
| uint8_t hw_field, |
| uint8_t shifter, |
| uint8_t length, |
| uint32_t data); |
| void (*set_action_add)(uint8_t *hw_action, |
| uint8_t hw_field, |
| uint8_t shifter, |
| uint8_t length, |
| uint32_t data); |
| void (*set_action_copy)(uint8_t *hw_action, |
| uint8_t dst_hw_field, |
| uint8_t dst_shifter, |
| uint8_t dst_len, |
| uint8_t src_hw_field, |
| uint8_t src_shifter); |
| const struct dr_ste_action_modify_field * |
| (*get_action_hw_field)(struct dr_ste_ctx *ste_ctx, |
| uint16_t sw_field, |
| struct dr_devx_caps *caps); |
| int (*set_action_decap_l3_list)(void *data, uint32_t data_sz, |
| uint8_t *hw_action, uint32_t hw_action_sz, |
| uint16_t *used_hw_action_num); |
| void (*set_aso_ct_cross_dmn)(uint8_t *hw_ste, uint32_t object_id, |
| uint32_t offset, uint8_t dest_reg_id, |
| bool direction); |
| int (*alloc_modify_hdr_chunk)(struct mlx5dv_dr_action *action, |
| uint32_t chunck_size); |
| void (*dealloc_modify_hdr_chunk)(struct mlx5dv_dr_action *action); |
| |
| /* Send */ |
| void (*prepare_for_postsend)(uint8_t *hw_ste_p, uint32_t ste_size); |
| }; |
| |
| struct dr_ste_ctx *dr_ste_get_ctx_v0(void); |
| struct dr_ste_ctx *dr_ste_get_ctx_v1(void); |
| struct dr_ste_ctx *dr_ste_get_ctx_v2(void); |
| |
| #endif |