/* * 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 #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_ib_l4_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