Commit 22a67766 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

mlxsw: spectrum: Introduce ACL core with simple TCAM implementation

Add ACL core infrastructure for Spectrum ASIC. This infra provides an
abstraction layer over specific HW implementations. There are two basic
objects used. One is "rule" and the second is "ruleset" which serves as a
container of multiple rules. In general, within one ruleset the rules are
allowed to have multiple priorities and masks. Each ruleset is bound to
either ingress or egress a of port netdevice.

The initial TCAM implementation is very simple and limited. It utilizes
parman lsort manager to take care of TCAM region layout.
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44091d29
...@@ -73,6 +73,7 @@ config MLXSW_SWITCHX2 ...@@ -73,6 +73,7 @@ config MLXSW_SWITCHX2
config MLXSW_SPECTRUM config MLXSW_SPECTRUM
tristate "Mellanox Technologies Spectrum support" tristate "Mellanox Technologies Spectrum support"
depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q
select PARMAN
default m default m
---help--- ---help---
This driver supports Mellanox Technologies Spectrum Ethernet This driver supports Mellanox Technologies Spectrum Ethernet
......
...@@ -14,7 +14,8 @@ mlxsw_switchx2-objs := switchx2.o ...@@ -14,7 +14,8 @@ mlxsw_switchx2-objs := switchx2.o
obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o
mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
spectrum_switchdev.o spectrum_router.o \ spectrum_switchdev.o spectrum_router.o \
spectrum_kvdl.o spectrum_kvdl.o spectrum_acl.o \
spectrum_acl_tcam.o
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB) += spectrum_dcb.o
obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o obj-$(CONFIG_MLXSW_MINIMAL) += mlxsw_minimal.o
mlxsw_minimal-objs := minimal.o mlxsw_minimal-objs := minimal.o
/* /*
* drivers/net/ethernet/mellanox/mlxsw/spectrum.c * drivers/net/ethernet/mellanox/mlxsw/spectrum.c
* Copyright (c) 2015 Mellanox Technologies. All rights reserved. * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
* Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com> * Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com> * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
* Copyright (c) 2015 Elad Raz <eladr@mellanox.com> * Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
* *
...@@ -138,8 +138,6 @@ MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16); ...@@ -138,8 +138,6 @@ MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16);
*/ */
MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4); MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
static bool mlxsw_sp_port_dev_check(const struct net_device *dev);
static void mlxsw_sp_txhdr_construct(struct sk_buff *skb, static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info) const struct mlxsw_tx_info *tx_info)
{ {
...@@ -3203,6 +3201,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3203,6 +3201,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_span_init; goto err_span_init;
} }
err = mlxsw_sp_acl_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n");
goto err_acl_init;
}
err = mlxsw_sp_ports_create(mlxsw_sp); err = mlxsw_sp_ports_create(mlxsw_sp);
if (err) { if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n"); dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n");
...@@ -3212,6 +3216,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, ...@@ -3212,6 +3216,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
return 0; return 0;
err_ports_create: err_ports_create:
mlxsw_sp_acl_fini(mlxsw_sp);
err_acl_init:
mlxsw_sp_span_fini(mlxsw_sp); mlxsw_sp_span_fini(mlxsw_sp);
err_span_init: err_span_init:
mlxsw_sp_router_fini(mlxsw_sp); mlxsw_sp_router_fini(mlxsw_sp);
...@@ -3232,6 +3238,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) ...@@ -3232,6 +3238,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sp_ports_remove(mlxsw_sp); mlxsw_sp_ports_remove(mlxsw_sp);
mlxsw_sp_acl_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp); mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_router_fini(mlxsw_sp); mlxsw_sp_router_fini(mlxsw_sp);
mlxsw_sp_switchdev_fini(mlxsw_sp); mlxsw_sp_switchdev_fini(mlxsw_sp);
...@@ -3297,7 +3304,7 @@ static struct mlxsw_driver mlxsw_sp_driver = { ...@@ -3297,7 +3304,7 @@ static struct mlxsw_driver mlxsw_sp_driver = {
.profile = &mlxsw_sp_config_profile, .profile = &mlxsw_sp_config_profile,
}; };
static bool mlxsw_sp_port_dev_check(const struct net_device *dev) bool mlxsw_sp_port_dev_check(const struct net_device *dev)
{ {
return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
} }
......
/* /*
* drivers/net/ethernet/mellanox/mlxsw/spectrum.h * drivers/net/ethernet/mellanox/mlxsw/spectrum.h
* Copyright (c) 2015 Mellanox Technologies. All rights reserved. * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
* Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com> * Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com> * Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
* Copyright (c) 2015 Elad Raz <eladr@mellanox.com> * Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
* *
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
#include "port.h" #include "port.h"
#include "core.h" #include "core.h"
#include "core_acl_flex_keys.h"
#include "core_acl_flex_actions.h"
#define MLXSW_SP_VFID_BASE VLAN_N_VID #define MLXSW_SP_VFID_BASE VLAN_N_VID
#define MLXSW_SP_VFID_MAX 6656 /* Bridged VLAN interfaces */ #define MLXSW_SP_VFID_MAX 6656 /* Bridged VLAN interfaces */
...@@ -262,6 +264,8 @@ struct mlxsw_sp_router { ...@@ -262,6 +264,8 @@ struct mlxsw_sp_router {
bool aborted; bool aborted;
}; };
struct mlxsw_sp_acl;
struct mlxsw_sp { struct mlxsw_sp {
struct { struct {
struct list_head list; struct list_head list;
...@@ -291,6 +295,7 @@ struct mlxsw_sp { ...@@ -291,6 +295,7 @@ struct mlxsw_sp {
u8 port_to_module[MLXSW_PORT_MAX_PORTS]; u8 port_to_module[MLXSW_PORT_MAX_PORTS];
struct mlxsw_sp_sb sb; struct mlxsw_sp_sb sb;
struct mlxsw_sp_router router; struct mlxsw_sp_router router;
struct mlxsw_sp_acl *acl;
struct { struct {
DECLARE_BITMAP(usage, MLXSW_SP_KVD_LINEAR_SIZE); DECLARE_BITMAP(usage, MLXSW_SP_KVD_LINEAR_SIZE);
} kvdl; } kvdl;
...@@ -373,6 +378,7 @@ struct mlxsw_sp_port { ...@@ -373,6 +378,7 @@ struct mlxsw_sp_port {
struct mlxsw_sp_port_sample *sample; struct mlxsw_sp_port_sample *sample;
}; };
bool mlxsw_sp_port_dev_check(const struct net_device *dev);
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev); struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port); void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
...@@ -602,4 +608,94 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused, ...@@ -602,4 +608,94 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count); int mlxsw_sp_kvdl_alloc(struct mlxsw_sp *mlxsw_sp, unsigned int entry_count);
void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index); void mlxsw_sp_kvdl_free(struct mlxsw_sp *mlxsw_sp, int entry_index);
struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl);
struct mlxsw_sp_acl_rule_info {
unsigned int priority;
struct mlxsw_afk_element_values values;
struct mlxsw_afa_block *act_block;
};
enum mlxsw_sp_acl_profile {
MLXSW_SP_ACL_PROFILE_FLOWER,
};
struct mlxsw_sp_acl_profile_ops {
size_t ruleset_priv_size;
int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
void *priv, void *ruleset_priv);
void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
struct net_device *dev, bool ingress);
void (*ruleset_unbind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
size_t rule_priv_size;
int (*rule_add)(struct mlxsw_sp *mlxsw_sp,
void *ruleset_priv, void *rule_priv,
struct mlxsw_sp_acl_rule_info *rulei);
void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
};
struct mlxsw_sp_acl_ops {
size_t priv_size;
int (*init)(struct mlxsw_sp *mlxsw_sp, void *priv);
void (*fini)(struct mlxsw_sp *mlxsw_sp, void *priv);
const struct mlxsw_sp_acl_profile_ops *
(*profile_ops)(struct mlxsw_sp *mlxsw_sp,
enum mlxsw_sp_acl_profile profile);
};
struct mlxsw_sp_acl_ruleset;
struct mlxsw_sp_acl_ruleset *
mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp,
struct net_device *dev, bool ingress,
enum mlxsw_sp_acl_profile profile);
void mlxsw_sp_acl_ruleset_put(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset);
struct mlxsw_sp_acl_rule_info *
mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl);
void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei);
void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
unsigned int priority);
void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
enum mlxsw_afk_element element,
u32 key_value, u32 mask_value);
void mlxsw_sp_acl_rulei_keymask_buf(struct mlxsw_sp_acl_rule_info *rulei,
enum mlxsw_afk_element element,
const char *key_value,
const char *mask_value, unsigned int len);
void mlxsw_sp_acl_rulei_act_continue(struct mlxsw_sp_acl_rule_info *rulei);
void mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
u16 group_id);
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct net_device *out_dev);
struct mlxsw_sp_acl_rule;
struct mlxsw_sp_acl_rule *
mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset,
unsigned long cookie);
void mlxsw_sp_acl_rule_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule *rule);
int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule *rule);
void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule *rule);
struct mlxsw_sp_acl_rule *
mlxsw_sp_acl_rule_lookup(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset,
unsigned long cookie);
struct mlxsw_sp_acl_rule_info *
mlxsw_sp_acl_rule_rulei(struct mlxsw_sp_acl_rule *rule);
int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp);
extern const struct mlxsw_sp_acl_ops mlxsw_sp_acl_tcam_ops;
#endif #endif
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment