1 /* 2 * drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h 3 * Copyright (c) 2017 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the names of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * Alternatively, this software may be distributed under the terms of the 19 * GNU General Public License ("GPL") version 2 as published by the Free 20 * Software Foundation. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H 36 #define _MLXSW_CORE_ACL_FLEX_KEYS_H 37 38 #include <linux/types.h> 39 #include <linux/bitmap.h> 40 41 #include "item.h" 42 43 enum mlxsw_afk_element { 44 MLXSW_AFK_ELEMENT_SRC_SYS_PORT, 45 MLXSW_AFK_ELEMENT_DMAC, 46 MLXSW_AFK_ELEMENT_SMAC, 47 MLXSW_AFK_ELEMENT_ETHERTYPE, 48 MLXSW_AFK_ELEMENT_IP_PROTO, 49 MLXSW_AFK_ELEMENT_SRC_IP4, 50 MLXSW_AFK_ELEMENT_DST_IP4, 51 MLXSW_AFK_ELEMENT_SRC_IP6_HI, 52 MLXSW_AFK_ELEMENT_SRC_IP6_LO, 53 MLXSW_AFK_ELEMENT_DST_IP6_HI, 54 MLXSW_AFK_ELEMENT_DST_IP6_LO, 55 MLXSW_AFK_ELEMENT_DST_L4_PORT, 56 MLXSW_AFK_ELEMENT_SRC_L4_PORT, 57 MLXSW_AFK_ELEMENT_VID, 58 MLXSW_AFK_ELEMENT_PCP, 59 MLXSW_AFK_ELEMENT_TCP_FLAGS, 60 MLXSW_AFK_ELEMENT_IP_TTL_, 61 MLXSW_AFK_ELEMENT_MAX, 62 }; 63 64 enum mlxsw_afk_element_type { 65 MLXSW_AFK_ELEMENT_TYPE_U32, 66 MLXSW_AFK_ELEMENT_TYPE_BUF, 67 }; 68 69 struct mlxsw_afk_element_info { 70 enum mlxsw_afk_element element; /* element ID */ 71 enum mlxsw_afk_element_type type; 72 struct mlxsw_item item; /* element geometry in internal storage */ 73 }; 74 75 #define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size) \ 76 [MLXSW_AFK_ELEMENT_##_element] = { \ 77 .element = MLXSW_AFK_ELEMENT_##_element, \ 78 .type = _type, \ 79 .item = { \ 80 .offset = _offset, \ 81 .shift = _shift, \ 82 .size = {.bits = _size}, \ 83 .name = #_element, \ 84 }, \ 85 } 86 87 #define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size) \ 88 MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32, \ 89 _element, _offset, _shift, _size) 90 91 #define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size) \ 92 MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \ 93 _element, _offset, 0, _size) 94 95 /* For the purpose of the driver, define an internal storage scratchpad 96 * that will be used to store key/mask values. For each defined element type 97 * define an internal storage geometry. 98 */ 99 static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { 100 MLXSW_AFK_ELEMENT_INFO_U32(SRC_SYS_PORT, 0x00, 16, 16), 101 MLXSW_AFK_ELEMENT_INFO_BUF(DMAC, 0x04, 6), 102 MLXSW_AFK_ELEMENT_INFO_BUF(SMAC, 0x0A, 6), 103 MLXSW_AFK_ELEMENT_INFO_U32(ETHERTYPE, 0x00, 0, 16), 104 MLXSW_AFK_ELEMENT_INFO_U32(IP_PROTO, 0x10, 0, 8), 105 MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12), 106 MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3), 107 MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9), 108 MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x14, 0, 8), 109 MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x18, 0, 32), 110 MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x1C, 0, 32), 111 MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x18, 8), 112 MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_LO, 0x20, 8), 113 MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_HI, 0x28, 8), 114 MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_LO, 0x30, 8), 115 MLXSW_AFK_ELEMENT_INFO_U32(DST_L4_PORT, 0x14, 0, 16), 116 MLXSW_AFK_ELEMENT_INFO_U32(SRC_L4_PORT, 0x14, 16, 16), 117 }; 118 119 #define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x38 120 121 struct mlxsw_afk_element_inst { /* element instance in actual block */ 122 const struct mlxsw_afk_element_info *info; 123 enum mlxsw_afk_element_type type; 124 struct mlxsw_item item; /* element geometry in block */ 125 }; 126 127 #define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset, _shift, _size) \ 128 { \ 129 .info = &mlxsw_afk_element_infos[MLXSW_AFK_ELEMENT_##_element], \ 130 .type = _type, \ 131 .item = { \ 132 .offset = _offset, \ 133 .shift = _shift, \ 134 .size = {.bits = _size}, \ 135 .name = #_element, \ 136 }, \ 137 } 138 139 #define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size) \ 140 MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \ 141 _element, _offset, _shift, _size) 142 143 #define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size) \ 144 MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF, \ 145 _element, _offset, 0, _size) 146 147 struct mlxsw_afk_block { 148 u16 encoding; /* block ID */ 149 struct mlxsw_afk_element_inst *instances; 150 unsigned int instances_count; 151 }; 152 153 #define MLXSW_AFK_BLOCK(_encoding, _instances) \ 154 { \ 155 .encoding = _encoding, \ 156 .instances = _instances, \ 157 .instances_count = ARRAY_SIZE(_instances), \ 158 } 159 160 struct mlxsw_afk_element_usage { 161 DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX); 162 }; 163 164 #define mlxsw_afk_element_usage_for_each(element, elusage) \ 165 for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX) 166 167 static inline void 168 mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage, 169 enum mlxsw_afk_element element) 170 { 171 __set_bit(element, elusage->usage); 172 } 173 174 static inline void 175 mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage) 176 { 177 bitmap_zero(elusage->usage, MLXSW_AFK_ELEMENT_MAX); 178 } 179 180 static inline void 181 mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage, 182 const enum mlxsw_afk_element *elements, 183 unsigned int elements_count) 184 { 185 int i; 186 187 mlxsw_afk_element_usage_zero(elusage); 188 for (i = 0; i < elements_count; i++) 189 mlxsw_afk_element_usage_add(elusage, elements[i]); 190 } 191 192 static inline bool 193 mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small, 194 struct mlxsw_afk_element_usage *elusage_big) 195 { 196 int i; 197 198 for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++) 199 if (test_bit(i, elusage_small->usage) && 200 !test_bit(i, elusage_big->usage)) 201 return false; 202 return true; 203 } 204 205 struct mlxsw_afk; 206 207 struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks, 208 const struct mlxsw_afk_block *blocks, 209 unsigned int blocks_count); 210 void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk); 211 212 struct mlxsw_afk_key_info; 213 214 struct mlxsw_afk_key_info * 215 mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk, 216 struct mlxsw_afk_element_usage *elusage); 217 void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info); 218 bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info, 219 struct mlxsw_afk_element_usage *elusage); 220 221 u16 222 mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info, 223 int block_index); 224 unsigned int 225 mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info); 226 227 struct mlxsw_afk_element_values { 228 struct mlxsw_afk_element_usage elusage; 229 struct { 230 char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE]; 231 char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE]; 232 } storage; 233 }; 234 235 void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values, 236 enum mlxsw_afk_element element, 237 u32 key_value, u32 mask_value); 238 void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values, 239 enum mlxsw_afk_element element, 240 const char *key_value, const char *mask_value, 241 unsigned int len); 242 void mlxsw_afk_encode(struct mlxsw_afk_key_info *key_info, 243 struct mlxsw_afk_element_values *values, 244 char *key, char *mask); 245 246 #endif 247