OSDN Git Service

dpaa2-switch: create and assign an ACL table per port
authorIoana Ciornei <ioana.ciornei@nxp.com>
Tue, 30 Mar 2021 14:54:16 +0000 (17:54 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 31 Mar 2021 00:18:26 +0000 (17:18 -0700)
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: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
drivers/net/ethernet/freescale/dpaa2/dpsw-cmd.h
drivers/net/ethernet/freescale/dpaa2/dpsw.c
drivers/net/ethernet/freescale/dpaa2/dpsw.h

index 073316d..0683aa3 100644 (file)
@@ -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 ethsw_core *ethsw = port_priv->ethsw_data;
        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 dpaa2_switch_fdb *fdb;
+       struct dpsw_acl_cfg acl_cfg;
        u16 fdb_id;
        int err;
 
@@ -2702,6 +2704,25 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
        if (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;
 }
 
index 5492189..6559378 100644 (file)
@@ -79,6 +79,8 @@
 #define DPAA2_SWITCH_NEEDED_HEADROOM \
        (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;
 
 struct ethsw_core;
@@ -113,6 +115,8 @@ struct ethsw_port_priv {
        struct dpaa2_switch_fdb *fdb;
        bool                    bcast_flood;
        bool                    ucast_flood;
+
+       u16                     acl_tbl;
 };
 
 /* Switch data */
index 24b17d6..89f757a 100644 (file)
 #define DPSW_CMDID_FDB_REMOVE_MULTICAST     DPSW_CMD_ID(0x087)
 #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_CTRL_IF_GET_ATTR         DPSW_CMD_ID(0x0A0)
@@ -457,5 +462,26 @@ struct dpsw_cmd_if_set_learning_mode {
        /* only the first 4 bits from LSB */
        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)
 #endif /* __FSL_DPSW_CMD_H */
index 6c787d4..ad4b62b 100644 (file)
@@ -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);
 }
+
+/**
+ * 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);
+}
index 96837b1..35b4749 100644 (file)
@@ -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,
                              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 */