/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
|
/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
|
|
#ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H
|
#define _MLXSW_CORE_ACL_FLEX_KEYS_H
|
|
#include <linux/types.h>
|
#include <linux/bitmap.h>
|
|
#include "item.h"
|
|
enum mlxsw_afk_element {
|
MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
|
MLXSW_AFK_ELEMENT_DMAC_32_47,
|
MLXSW_AFK_ELEMENT_DMAC_0_31,
|
MLXSW_AFK_ELEMENT_SMAC_32_47,
|
MLXSW_AFK_ELEMENT_SMAC_0_31,
|
MLXSW_AFK_ELEMENT_ETHERTYPE,
|
MLXSW_AFK_ELEMENT_IP_PROTO,
|
MLXSW_AFK_ELEMENT_SRC_IP_96_127,
|
MLXSW_AFK_ELEMENT_SRC_IP_64_95,
|
MLXSW_AFK_ELEMENT_SRC_IP_32_63,
|
MLXSW_AFK_ELEMENT_SRC_IP_0_31,
|
MLXSW_AFK_ELEMENT_DST_IP_96_127,
|
MLXSW_AFK_ELEMENT_DST_IP_64_95,
|
MLXSW_AFK_ELEMENT_DST_IP_32_63,
|
MLXSW_AFK_ELEMENT_DST_IP_0_31,
|
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_VIRT_ROUTER_8_10,
|
MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_7,
|
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)
|
|
#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40
|
|
struct mlxsw_afk_element_inst { /* element instance in actual block */
|
enum mlxsw_afk_element element;
|
enum mlxsw_afk_element_type type;
|
struct mlxsw_item item; /* element geometry in block */
|
int u32_key_diff; /* in case value needs to be adjusted before write
|
* this diff is here to handle that
|
*/
|
bool avoid_size_check;
|
};
|
|
#define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset, \
|
_shift, _size, _u32_key_diff, _avoid_size_check) \
|
{ \
|
.element = MLXSW_AFK_ELEMENT_##_element, \
|
.type = _type, \
|
.item = { \
|
.offset = _offset, \
|
.shift = _shift, \
|
.size = {.bits = _size}, \
|
.name = #_element, \
|
}, \
|
.u32_key_diff = _u32_key_diff, \
|
.avoid_size_check = _avoid_size_check, \
|
}
|
|
#define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size) \
|
MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \
|
_element, _offset, _shift, _size, 0, false)
|
|
#define MLXSW_AFK_ELEMENT_INST_EXT_U32(_element, _offset, \
|
_shift, _size, _key_diff, \
|
_avoid_size_check) \
|
MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32, \
|
_element, _offset, _shift, _size, \
|
_key_diff, _avoid_size_check)
|
|
#define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size) \
|
MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF, \
|
_element, _offset, 0, _size, 0, false)
|
|
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_ops {
|
const struct mlxsw_afk_block *blocks;
|
unsigned int blocks_count;
|
void (*encode_block)(char *output, int block_index, char *block);
|
void (*clear_block)(char *output, int block_index);
|
};
|
|
struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
|
const struct mlxsw_afk_ops *ops);
|
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 *mlxsw_afk,
|
struct mlxsw_afk_key_info *key_info,
|
struct mlxsw_afk_element_values *values,
|
char *key, char *mask);
|
void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
|
int block_start, int block_end);
|
|
#endif
|