Commit 90f07102 authored by Ioana Ciornei's avatar Ioana Ciornei Committed by David S. Miller

dpaa2-switch: create and assign an ACL table per port

In order to trap frames to the CPU, the DPAA2 switch uses the ACL table.
At probe time, create an ACL table for each switch port so that in the
next patches we can use this to trap STP frames and redirect them to the
control interface.
Signed-off-by: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6aa6791d
...@@ -2659,8 +2659,10 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) ...@@ -2659,8 +2659,10 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
struct net_device *netdev = port_priv->netdev; struct net_device *netdev = port_priv->netdev;
struct ethsw_core *ethsw = port_priv->ethsw_data; struct ethsw_core *ethsw = port_priv->ethsw_data;
struct dpsw_fdb_cfg fdb_cfg = {0}; struct dpsw_fdb_cfg fdb_cfg = {0};
struct dpaa2_switch_fdb *fdb; struct dpsw_acl_if_cfg acl_if_cfg;
struct dpsw_if_attr dpsw_if_attr; struct dpsw_if_attr dpsw_if_attr;
struct dpaa2_switch_fdb *fdb;
struct dpsw_acl_cfg acl_cfg;
u16 fdb_id; u16 fdb_id;
int err; int err;
...@@ -2702,6 +2704,25 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) ...@@ -2702,6 +2704,25 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
if (err) if (err)
return err; return err;
/* Create an ACL table to be used by this switch port */
acl_cfg.max_entries = DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES;
err = dpsw_acl_add(ethsw->mc_io, 0, ethsw->dpsw_handle,
&port_priv->acl_tbl, &acl_cfg);
if (err) {
netdev_err(netdev, "dpsw_acl_add err %d\n", err);
return err;
}
acl_if_cfg.if_id[0] = port_priv->idx;
acl_if_cfg.num_ifs = 1;
err = dpsw_acl_add_if(ethsw->mc_io, 0, ethsw->dpsw_handle,
port_priv->acl_tbl, &acl_if_cfg);
if (err) {
netdev_err(netdev, "dpsw_acl_add_if err %d\n", err);
dpsw_acl_remove(ethsw->mc_io, 0, ethsw->dpsw_handle,
port_priv->acl_tbl);
}
return err; return err;
} }
......
...@@ -79,6 +79,8 @@ ...@@ -79,6 +79,8 @@
#define DPAA2_SWITCH_NEEDED_HEADROOM \ #define DPAA2_SWITCH_NEEDED_HEADROOM \
(DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN) (DPAA2_SWITCH_TX_DATA_OFFSET + DPAA2_SWITCH_TX_BUF_ALIGN)
#define DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES 16
extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops; extern const struct ethtool_ops dpaa2_switch_port_ethtool_ops;
struct ethsw_core; struct ethsw_core;
...@@ -113,6 +115,8 @@ struct ethsw_port_priv { ...@@ -113,6 +115,8 @@ struct ethsw_port_priv {
struct dpaa2_switch_fdb *fdb; struct dpaa2_switch_fdb *fdb;
bool bcast_flood; bool bcast_flood;
bool ucast_flood; bool ucast_flood;
u16 acl_tbl;
}; };
/* Switch data */ /* Switch data */
......
...@@ -74,6 +74,11 @@ ...@@ -74,6 +74,11 @@
#define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) #define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087)
#define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) #define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A)
#define DPSW_CMDID_ACL_ADD DPSW_CMD_ID(0x090)
#define DPSW_CMDID_ACL_REMOVE DPSW_CMD_ID(0x091)
#define DPSW_CMDID_ACL_ADD_IF DPSW_CMD_ID(0x094)
#define DPSW_CMDID_ACL_REMOVE_IF DPSW_CMD_ID(0x095)
#define DPSW_CMDID_IF_GET_PORT_MAC_ADDR DPSW_CMD_ID(0x0A7) #define DPSW_CMDID_IF_GET_PORT_MAC_ADDR DPSW_CMD_ID(0x0A7)
#define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0) #define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0)
...@@ -457,5 +462,26 @@ struct dpsw_cmd_if_set_learning_mode { ...@@ -457,5 +462,26 @@ struct dpsw_cmd_if_set_learning_mode {
/* only the first 4 bits from LSB */ /* only the first 4 bits from LSB */
u8 mode; u8 mode;
}; };
struct dpsw_cmd_acl_add {
__le16 pad;
__le16 max_entries;
};
struct dpsw_rsp_acl_add {
__le16 acl_id;
};
struct dpsw_cmd_acl_remove {
__le16 acl_id;
};
struct dpsw_cmd_acl_if {
__le16 acl_id;
__le16 num_ifs;
__le32 pad;
__le64 if_id;
};
#pragma pack(pop) #pragma pack(pop)
#endif /* __FSL_DPSW_CMD_H */ #endif /* __FSL_DPSW_CMD_H */
...@@ -1354,3 +1354,115 @@ int dpsw_if_set_learning_mode(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, ...@@ -1354,3 +1354,115 @@ int dpsw_if_set_learning_mode(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
return mc_send_command(mc_io, &cmd); return mc_send_command(mc_io, &cmd);
} }
/**
* dpsw_acl_add() - Create an ACL table
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPSW object
* @acl_id: Returned ACL ID, for future references
* @cfg: ACL configuration
*
* Create Access Control List table. Multiple ACLs can be created and
* co-exist in L2 switch
*
* Return: '0' on Success; Error code otherwise.
*/
int dpsw_acl_add(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u16 *acl_id,
const struct dpsw_acl_cfg *cfg)
{
struct dpsw_cmd_acl_add *cmd_params;
struct dpsw_rsp_acl_add *rsp_params;
struct fsl_mc_command cmd = { 0 };
int err;
cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD, cmd_flags, token);
cmd_params = (struct dpsw_cmd_acl_add *)cmd.params;
cmd_params->max_entries = cpu_to_le16(cfg->max_entries);
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
rsp_params = (struct dpsw_rsp_acl_add *)cmd.params;
*acl_id = le16_to_cpu(rsp_params->acl_id);
return 0;
}
/**
* dpsw_acl_remove() - Remove an ACL table from L2 switch.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPSW object
* @acl_id: ACL ID
*
* Return: '0' on Success; Error code otherwise.
*/
int dpsw_acl_remove(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id)
{
struct dpsw_cmd_acl_remove *cmd_params;
struct fsl_mc_command cmd = { 0 };
cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE, cmd_flags,
token);
cmd_params = (struct dpsw_cmd_acl_remove *)cmd.params;
cmd_params->acl_id = cpu_to_le16(acl_id);
return mc_send_command(mc_io, &cmd);
}
/**
* dpsw_acl_add_if() - Associate interface/interfaces with an ACL table.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPSW object
* @acl_id: ACL ID
* @cfg: Interfaces list
*
* Return: '0' on Success; Error code otherwise.
*/
int dpsw_acl_add_if(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id, const struct dpsw_acl_if_cfg *cfg)
{
struct dpsw_cmd_acl_if *cmd_params;
struct fsl_mc_command cmd = { 0 };
cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF, cmd_flags,
token);
cmd_params = (struct dpsw_cmd_acl_if *)cmd.params;
cmd_params->acl_id = cpu_to_le16(acl_id);
cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
build_if_id_bitmap(&cmd_params->if_id, cfg->if_id, cfg->num_ifs);
return mc_send_command(mc_io, &cmd);
}
/**
* dpsw_acl_remove_if() - De-associate interface/interfaces from an ACL table
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPSW object
* @acl_id: ACL ID
* @cfg: Interfaces list
*
* Return: '0' on Success; Error code otherwise.
*/
int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id, const struct dpsw_acl_if_cfg *cfg)
{
struct dpsw_cmd_acl_if *cmd_params;
struct fsl_mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF, cmd_flags,
token);
cmd_params = (struct dpsw_cmd_acl_if *)cmd.params;
cmd_params->acl_id = cpu_to_le16(acl_id);
cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
build_if_id_bitmap(&cmd_params->if_id, cfg->if_id, cfg->num_ifs);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
...@@ -628,4 +628,33 @@ int dpsw_set_egress_flood(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, ...@@ -628,4 +628,33 @@ int dpsw_set_egress_flood(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
int dpsw_if_set_learning_mode(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, int dpsw_if_set_learning_mode(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 if_id, enum dpsw_learning_mode mode); u16 if_id, enum dpsw_learning_mode mode);
/**
* struct dpsw_acl_cfg - ACL Configuration
* @max_entries: Number of ACL rules
*/
struct dpsw_acl_cfg {
u16 max_entries;
};
int dpsw_acl_add(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u16 *acl_id,
const struct dpsw_acl_cfg *cfg);
int dpsw_acl_remove(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id);
/**
* struct dpsw_acl_if_cfg - List of interfaces to associate with an ACL table
* @num_ifs: Number of interfaces
* @if_id: List of interfaces
*/
struct dpsw_acl_if_cfg {
u16 num_ifs;
u16 if_id[DPSW_MAX_IF];
};
int dpsw_acl_add_if(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id, const struct dpsw_acl_if_cfg *cfg);
int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
u16 acl_id, const struct dpsw_acl_if_cfg *cfg);
#endif /* __FSL_DPSW_H */ #endif /* __FSL_DPSW_H */
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