linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
<<
>>
Prefs
   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
  10static 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, 16),
  16};
  17
  18static 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, 16),
  24};
  25
  26static 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
  32static 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, 16),
  36};
  37
  38static 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, 16),
  42};
  43
  44static 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
  52static 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
  59static 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
  64static 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
  70static 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
  75static 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
  80static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
  81        MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
  82};
  83
  84static 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
 101static void mlxsw_sp1_afk_encode_block(char *output, int block_index,
 102                                       char *block)
 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
 110static void mlxsw_sp1_afk_clear_block(char *output, int block_index)
 111{
 112        unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
 113        char *output_indexed = output + offset;
 114
 115        memset(output_indexed, 0, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
 116}
 117
 118const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
 119        .blocks         = mlxsw_sp1_afk_blocks,
 120        .blocks_count   = ARRAY_SIZE(mlxsw_sp1_afk_blocks),
 121        .encode_block   = mlxsw_sp1_afk_encode_block,
 122        .clear_block    = mlxsw_sp1_afk_clear_block,
 123};
 124
 125static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
 126        MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
 127};
 128
 129static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
 130        MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
 131};
 132
 133static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
 134        MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
 135        MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
 136};
 137
 138static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
 139        MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
 140        MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
 141        MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
 142};
 143
 144static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
 145        MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
 146        MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
 147        MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
 148};
 149
 150static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
 151        MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
 152        MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 8, -1, true), /* RX_ACL_SYSTEM_PORT */
 153};
 154
 155static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
 156        MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
 157};
 158
 159static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
 160        MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
 161};
 162
 163static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
 164        MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
 165        MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
 166        MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
 167        MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
 168};
 169
 170static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4[] = {
 171        MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_7, 0x04, 24, 8),
 172        MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_8_10, 0x00, 0, 3),
 173};
 174
 175static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
 176        MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
 177};
 178
 179static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
 180        MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
 181};
 182
 183static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
 184        MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
 185};
 186
 187static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
 188        MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
 189};
 190
 191static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
 192        MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
 193};
 194
 195static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
 196        MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
 197};
 198
 199static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
 200        MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
 201        MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
 202};
 203
 204static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
 205        MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
 206};
 207
 208static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
 209        MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
 210        MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
 211        MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
 212        MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
 213        MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
 214        MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5),
 215        MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
 216        MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
 217        MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
 218        MLXSW_AFK_BLOCK(0x3C, mlxsw_sp_afk_element_info_ipv4_4),
 219        MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
 220        MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
 221        MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
 222        MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
 223        MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
 224        MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
 225        MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
 226        MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
 227};
 228
 229#define MLXSW_SP2_AFK_BITS_PER_BLOCK 36
 230
 231/* A block in Spectrum-2 is of the following form:
 232 *
 233 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 234 * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |35|34|33|32|
 235 * +-----------------------------------------------------------------------------------------------+
 236 * |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|
 237 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 238 */
 239MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK);
 240
 241/* The key / mask block layout in Spectrum-2 is of the following form:
 242 *
 243 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 244 * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |                block11_high                   |
 245 * +-----------------------------------------------------------------------------------------------+
 246 * |                    block11_low                               |         block10_high           |
 247 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 248 * ...
 249 */
 250
 251struct mlxsw_sp2_afk_block_layout {
 252        unsigned short offset;
 253        struct mlxsw_item item;
 254};
 255
 256#define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift)                     \
 257        {                                                                       \
 258                .offset = _offset,                                              \
 259                {                                                               \
 260                        .shift = _shift,                                        \
 261                        .size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK},         \
 262                        .name = #_block,                                        \
 263                }                                                               \
 264        }                                                                       \
 265
 266static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
 267        MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0),
 268        MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4),
 269        MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8),
 270        MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12),
 271        MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16),
 272        MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20),
 273        MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24),
 274        MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28),
 275        MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0),
 276        MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4),
 277        MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8),
 278        MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
 279};
 280
 281static void __mlxsw_sp2_afk_block_value_set(char *output, int block_index,
 282                                            u64 block_value)
 283{
 284        const struct mlxsw_sp2_afk_block_layout *block_layout;
 285
 286        if (WARN_ON(block_index < 0 ||
 287                    block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout)))
 288                return;
 289
 290        block_layout = &mlxsw_sp2_afk_blocks_layout[block_index];
 291        __mlxsw_item_set64(output + block_layout->offset,
 292                           &block_layout->item, 0, block_value);
 293}
 294
 295static void mlxsw_sp2_afk_encode_block(char *output, int block_index,
 296                                       char *block)
 297{
 298        u64 block_value = mlxsw_sp2_afk_block_value_get(block);
 299
 300        __mlxsw_sp2_afk_block_value_set(output, block_index, block_value);
 301}
 302
 303static void mlxsw_sp2_afk_clear_block(char *output, int block_index)
 304{
 305        __mlxsw_sp2_afk_block_value_set(output, block_index, 0);
 306}
 307
 308const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
 309        .blocks         = mlxsw_sp2_afk_blocks,
 310        .blocks_count   = ARRAY_SIZE(mlxsw_sp2_afk_blocks),
 311        .encode_block   = mlxsw_sp2_afk_encode_block,
 312        .clear_block    = mlxsw_sp2_afk_clear_block,
 313};
 314