1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ 3 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include "spectrum.h" 7 #include "item.h" 8 #include "core_acl_flex_keys.h" 9 10 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = { 11 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2), 12 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4), 13 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3), 14 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12), 15 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8), 16 }; 17 18 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = { 19 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2), 20 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4), 21 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3), 22 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12), 23 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8), 24 }; 25 26 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = { 27 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2), 28 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4), 29 MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16), 30 }; 31 32 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = { 33 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4), 34 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8), 35 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8), 36 }; 37 38 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = { 39 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4), 40 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8), 41 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8), 42 }; 43 44 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = { 45 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4), 46 MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2), 47 MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8), 48 MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6), 49 MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */ 50 }; 51 52 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = { 53 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12), 54 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3), 55 MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16), 56 MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16), 57 }; 58 59 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = { 60 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4), 61 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4), 62 }; 63 64 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = { 65 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4), 66 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4), 67 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8), 68 }; 69 70 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = { 71 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4), 72 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4), 73 }; 74 75 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = { 76 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4), 77 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4), 78 }; 79 80 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = { 81 MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16), 82 }; 83 84 static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = { 85 MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_l2_dmac), 86 MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_l2_smac), 87 MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_l2_smac_ex), 88 MLXSW_AFK_BLOCK(0x30, mlxsw_sp_afk_element_info_ipv4_sip), 89 MLXSW_AFK_BLOCK(0x31, mlxsw_sp_afk_element_info_ipv4_dip), 90 MLXSW_AFK_BLOCK(0x32, mlxsw_sp_afk_element_info_ipv4), 91 MLXSW_AFK_BLOCK(0x33, mlxsw_sp_afk_element_info_ipv4_ex), 92 MLXSW_AFK_BLOCK(0x60, mlxsw_sp_afk_element_info_ipv6_dip), 93 MLXSW_AFK_BLOCK(0x65, mlxsw_sp_afk_element_info_ipv6_ex1), 94 MLXSW_AFK_BLOCK(0x62, mlxsw_sp_afk_element_info_ipv6_sip), 95 MLXSW_AFK_BLOCK(0x63, mlxsw_sp_afk_element_info_ipv6_sip_ex), 96 MLXSW_AFK_BLOCK(0xB0, mlxsw_sp_afk_element_info_packet_type), 97 }; 98 99 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16 100 101 static void mlxsw_sp1_afk_encode_block(char *block, int block_index, 102 char *output) 103 { 104 unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE; 105 char *output_indexed = output + offset; 106 107 memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE); 108 } 109 110 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = { 111 .blocks = mlxsw_sp1_afk_blocks, 112 .blocks_count = ARRAY_SIZE(mlxsw_sp1_afk_blocks), 113 .encode_block = mlxsw_sp1_afk_encode_block, 114 }; 115 116 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = { 117 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4), 118 }; 119 120 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = { 121 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4), 122 }; 123 124 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = { 125 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2), 126 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2), 127 }; 128 129 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = { 130 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3), 131 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12), 132 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2), 133 }; 134 135 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = { 136 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3), 137 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12), 138 MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16), 139 }; 140 141 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = { 142 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12), 143 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x04, 0, 8), /* RX_ACL_SYSTEM_PORT */ 144 }; 145 146 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = { 147 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4), 148 }; 149 150 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = { 151 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4), 152 }; 153 154 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = { 155 MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6), 156 MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2), 157 MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8), 158 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8), 159 }; 160 161 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = { 162 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4), 163 }; 164 165 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = { 166 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4), 167 }; 168 169 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = { 170 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4), 171 }; 172 173 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = { 174 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4), 175 }; 176 177 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = { 178 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4), 179 }; 180 181 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = { 182 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4), 183 }; 184 185 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = { 186 MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16), 187 MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16), 188 }; 189 190 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = { 191 MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */ 192 }; 193 194 static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = { 195 MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0), 196 MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1), 197 MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2), 198 MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3), 199 MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4), 200 MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5), 201 MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0), 202 MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1), 203 MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2), 204 MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0), 205 MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1), 206 MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2), 207 MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3), 208 MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4), 209 MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5), 210 MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0), 211 MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2), 212 }; 213 214 #define MLXSW_SP2_AFK_BITS_PER_BLOCK 36 215 216 /* A block in Spectrum-2 is of the following form: 217 * 218 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 219 * | | | | | | | | | | | | | | | | | | | | | | | | | | | | |35|34|33|32| 220 * +-----------------------------------------------------------------------------------------------+ 221 * |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| 222 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 223 */ 224 MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK); 225 226 /* The key / mask block layout in Spectrum-2 is of the following form: 227 * 228 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 229 * | | | | | | | | | | | | | | | | | block11_high | 230 * +-----------------------------------------------------------------------------------------------+ 231 * | block11_low | block10_high | 232 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 233 * ... 234 */ 235 236 struct mlxsw_sp2_afk_block_layout { 237 unsigned short offset; 238 struct mlxsw_item item; 239 }; 240 241 #define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift) \ 242 { \ 243 .offset = _offset, \ 244 { \ 245 .shift = _shift, \ 246 .size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK}, \ 247 .name = #_block, \ 248 } \ 249 } \ 250 251 static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = { 252 MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0), 253 MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4), 254 MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8), 255 MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12), 256 MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16), 257 MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20), 258 MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24), 259 MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28), 260 MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0), 261 MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4), 262 MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8), 263 MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12), 264 }; 265 266 static void mlxsw_sp2_afk_encode_block(char *block, int block_index, 267 char *output) 268 { 269 u64 block_value = mlxsw_sp2_afk_block_value_get(block); 270 const struct mlxsw_sp2_afk_block_layout *block_layout; 271 272 if (WARN_ON(block_index < 0 || 273 block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout))) 274 return; 275 276 block_layout = &mlxsw_sp2_afk_blocks_layout[block_index]; 277 __mlxsw_item_set64(output + block_layout->offset, 278 &block_layout->item, 0, block_value); 279 } 280 281 const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = { 282 .blocks = mlxsw_sp2_afk_blocks, 283 .blocks_count = ARRAY_SIZE(mlxsw_sp2_afk_blocks), 284 .encode_block = mlxsw_sp2_afk_encode_block, 285 }; 286