/* * drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h * Copyright (c) 2017 Mellanox Technologies. All rights reserved. * Copyright (c) 2017 Jiri Pirko * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H #define _MLXSW_CORE_ACL_FLEX_KEYS_H #include #include #include "item.h" enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_SRC_SYS_PORT, MLXSW_AFK_ELEMENT_DMAC, MLXSW_AFK_ELEMENT_SMAC, MLXSW_AFK_ELEMENT_ETHERTYPE, MLXSW_AFK_ELEMENT_IP_PROTO, MLXSW_AFK_ELEMENT_SRC_IP4, MLXSW_AFK_ELEMENT_DST_IP4, MLXSW_AFK_ELEMENT_SRC_IP6_HI, MLXSW_AFK_ELEMENT_SRC_IP6_LO, MLXSW_AFK_ELEMENT_DST_IP6_HI, MLXSW_AFK_ELEMENT_DST_IP6_LO, MLXSW_AFK_ELEMENT_DST_L4_PORT, MLXSW_AFK_ELEMENT_SRC_L4_PORT, MLXSW_AFK_ELEMENT_VID, MLXSW_AFK_ELEMENT_PCP, MLXSW_AFK_ELEMENT_TCP_FLAGS, MLXSW_AFK_ELEMENT_IP_TTL_, MLXSW_AFK_ELEMENT_IP_ECN, MLXSW_AFK_ELEMENT_IP_DSCP, MLXSW_AFK_ELEMENT_MAX, }; enum mlxsw_afk_element_type { MLXSW_AFK_ELEMENT_TYPE_U32, MLXSW_AFK_ELEMENT_TYPE_BUF, }; struct mlxsw_afk_element_info { enum mlxsw_afk_element element; /* element ID */ enum mlxsw_afk_element_type type; struct mlxsw_item item; /* element geometry in internal storage */ }; #define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size) \ [MLXSW_AFK_ELEMENT_##_element] = { \ .element = MLXSW_AFK_ELEMENT_##_element, \ .type = _type, \ .item = { \ .offset = _offset, \ .shift = _shift, \ .size = {.bits = _size}, \ .name = #_element, \ }, \ } #define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size) \ MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32, \ _element, _offset, _shift, _size) #define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size) \ MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \ _element, _offset, 0, _size) /* For the purpose of the driver, define an internal storage scratchpad * that will be used to store key/mask values. For each defined element type * define an internal storage geometry. */ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_U32(SRC_SYS_PORT, 0x00, 16, 16), MLXSW_AFK_ELEMENT_INFO_BUF(DMAC, 0x04, 6), MLXSW_AFK_ELEMENT_INFO_BUF(SMAC, 0x0A, 6), MLXSW_AFK_ELEMENT_INFO_U32(ETHERTYPE, 0x00, 0, 16), MLXSW_AFK_ELEMENT_INFO_U32(IP_PROTO, 0x10, 0, 8), MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12), MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3), MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9), MLXSW_AFK_ELEMENT_INFO_U32(DST_L4_PORT, 0x14, 0, 16), MLXSW_AFK_ELEMENT_INFO_U32(SRC_L4_PORT, 0x14, 16, 16), MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x18, 0, 8), MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x18, 9, 2), MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x18, 11, 6), MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x20, 0, 32), MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x24, 0, 32), MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x20, 8), MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_LO, 0x28, 8), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_HI, 0x30, 8), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_LO, 0x38, 8), }; #define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40 struct mlxsw_afk_element_inst { /* element instance in actual block */ const struct mlxsw_afk_element_info *info; enum mlxsw_afk_element_type type; struct mlxsw_item item; /* element geometry in block */ }; #define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset, _shift, _size) \ { \ .info = &mlxsw_afk_element_infos[MLXSW_AFK_ELEMENT_##_element], \ .type = _type, \ .item = { \ .offset = _offset, \ .shift = _shift, \ .size = {.bits = _size}, \ .name = #_element, \ }, \ } #define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size) \ MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \ _element, _offset, _shift, _size) #define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size) \ MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF, \ _element, _offset, 0, _size) struct mlxsw_afk_block { u16 encoding; /* block ID */ struct mlxsw_afk_element_inst *instances; unsigned int instances_count; }; #define MLXSW_AFK_BLOCK(_encoding, _instances) \ { \ .encoding = _encoding, \ .instances = _instances, \ .instances_count = ARRAY_SIZE(_instances), \ } struct mlxsw_afk_element_usage { DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX); }; #define mlxsw_afk_element_usage_for_each(element, elusage) \ for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX) static inline void mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage, enum mlxsw_afk_element element) { __set_bit(element, elusage->usage); } static inline void mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage) { bitmap_zero(elusage->usage, MLXSW_AFK_ELEMENT_MAX); } static inline void mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage, const enum mlxsw_afk_element *elements, unsigned int elements_count) { int i; mlxsw_afk_element_usage_zero(elusage); for (i = 0; i < elements_count; i++) mlxsw_afk_element_usage_add(elusage, elements[i]); } static inline bool mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small, struct mlxsw_afk_element_usage *elusage_big) { int i; for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++) if (test_bit(i, elusage_small->usage) && !test_bit(i, elusage_big->usage)) return false; return true; } struct mlxsw_afk; struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks, const struct mlxsw_afk_block *blocks, unsigned int blocks_count); void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk); struct mlxsw_afk_key_info; struct mlxsw_afk_key_info * mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk, struct mlxsw_afk_element_usage *elusage); void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info); bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info, struct mlxsw_afk_element_usage *elusage); u16 mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info, int block_index); unsigned int mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info); struct mlxsw_afk_element_values { struct mlxsw_afk_element_usage elusage; struct { char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE]; char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE]; } storage; }; void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values, enum mlxsw_afk_element element, u32 key_value, u32 mask_value); void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values, enum mlxsw_afk_element element, const char *key_value, const char *mask_value, unsigned int len); void mlxsw_afk_encode(struct mlxsw_afk_key_info *key_info, struct mlxsw_afk_element_values *values, char *key, char *mask); #endif