mlx4_core: Add support for secure-host and SMP firewall
authorJack Morgenstein <jackm@dev.mellanox.co.il>
Sun, 1 Jun 2014 08:53:50 +0000 (11:53 +0300)
committerRoland Dreier <roland@purestorage.com>
Tue, 5 Aug 2014 14:40:22 +0000 (07:40 -0700)
Secure-host is the general term for the capability of a device
to protect itself and the subnet from malicious host software.

This is achieved by:
1. Not allowing un-trusted entities to access device configuration
   registers, directly (through pci_cr or pci_conf) and indirectly
   (through MADs).

2. Hiding M_Key from untrusted entities.

3. Preventing the modification of GUID0 by un-trusted entities

4. Not allowing drivers on untrusted hosts to receive nor to transmit
   packets over QP0 (SMP Firewall).

The secure-host capability depends on firmware handling all QP0
packets, and not passing these packets up to the driver. Any information
required by the driver for proper operation (e.g., SM lid) is passed
via events generated by the firmware while processing QP0 MADs.

Driver support mainly requires using the MAD_DEMUX FW command at startup,
where the feature is enabled/disabled through a procedure described in
the Mellanox HCA tools package.

Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
[ Fix error path in mlx4_setup_hca to go to err_mcg_table_free. - Roland ]

Signed-off-by: Roland Dreier <roland@purestorage.com>
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
include/linux/mlx4/cmd.h
include/linux/mlx4/device.h

index 5d940a26055c64ab71250f1d998b9b38418fb2ec..65a4a0f88ea0d80090bc2e604fe0f7e2b0bb2fad 100644 (file)
@@ -1310,6 +1310,15 @@ static struct mlx4_cmd_info cmd_info[] = {
                .verify = NULL,
                .wrapper = mlx4_MAD_IFC_wrapper
        },
+       {
+               .opcode = MLX4_CMD_MAD_DEMUX,
+               .has_inbox = false,
+               .has_outbox = false,
+               .out_is_imm = false,
+               .encode_slave_id = false,
+               .verify = NULL,
+               .wrapper = mlx4_CMD_EPERM_wrapper
+       },
        {
                .opcode = MLX4_CMD_QUERY_IF_STAT,
                .has_inbox = false,
index 688e1eabab29d697137477ea4a05b1dbb46a6d1f..494753e44ae3a1324fac4a269f60868766926717 100644 (file)
@@ -136,7 +136,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
                [7] = "FSM (MAC anti-spoofing) support",
                [8] = "Dynamic QP updates support",
                [9] = "Device managed flow steering IPoIB support",
-               [10] = "TCP/IP offloads/flow-steering for VXLAN support"
+               [10] = "TCP/IP offloads/flow-steering for VXLAN support",
+               [11] = "MAD DEMUX (Secure-Host) support"
        };
        int i;
 
@@ -571,6 +572,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET                0xa0
 #define QUERY_DEV_CAP_FW_REASSIGN_MAC          0x9d
 #define QUERY_DEV_CAP_VXLAN                    0x9e
+#define QUERY_DEV_CAP_MAD_DEMUX_OFFSET         0xb0
 
        dev_cap->flags2 = 0;
        mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -748,6 +750,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                MLX4_GET(dev_cap->max_counters, outbox,
                         QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
 
+       MLX4_GET(field32, outbox,
+                QUERY_DEV_CAP_MAD_DEMUX_OFFSET);
+       if (field32 & (1 << 0))
+               dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX;
+
        MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
        if (field32 & (1 << 16))
                dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
@@ -2016,3 +2023,85 @@ void mlx4_opreq_action(struct work_struct *work)
 out:
        mlx4_free_cmd_mailbox(dev, mailbox);
 }
+
+static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev,
+                                         struct mlx4_cmd_mailbox *mailbox)
+{
+#define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET             0x10
+#define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET         0x20
+#define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET            0x40
+#define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET    0x70
+
+       u32 set_attr_mask, getresp_attr_mask;
+       u32 trap_attr_mask, traprepress_attr_mask;
+
+       MLX4_GET(set_attr_mask, mailbox->buf,
+                MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET);
+       mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n",
+                set_attr_mask);
+
+       MLX4_GET(getresp_attr_mask, mailbox->buf,
+                MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET);
+       mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n",
+                getresp_attr_mask);
+
+       MLX4_GET(trap_attr_mask, mailbox->buf,
+                MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET);
+       mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n",
+                trap_attr_mask);
+
+       MLX4_GET(traprepress_attr_mask, mailbox->buf,
+                MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET);
+       mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n",
+                traprepress_attr_mask);
+
+       if (set_attr_mask && getresp_attr_mask && trap_attr_mask &&
+           traprepress_attr_mask)
+               return 1;
+
+       return 0;
+}
+
+int mlx4_config_mad_demux(struct mlx4_dev *dev)
+{
+       struct mlx4_cmd_mailbox *mailbox;
+       int secure_host_active;
+       int err;
+
+       /* Check if mad_demux is supported */
+       if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX))
+               return 0;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox)) {
+               mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX");
+               return -ENOMEM;
+       }
+
+       /* Query mad_demux to find out which MADs are handled by internal sma */
+       err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */,
+                          MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX,
+                          MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+       if (err) {
+               mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n",
+                         err);
+               goto out;
+       }
+
+       secure_host_active = mlx4_check_smp_firewall_active(dev, mailbox);
+
+       /* Config mad_demux to handle all MADs returned by the query above */
+       err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */,
+                      MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX,
+                      MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+       if (err) {
+               mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err);
+               goto out;
+       }
+
+       if (secure_host_active)
+               mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n");
+out:
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
index 82ab427290c30a8f6aaf478ea98c1a1207e5724d..f2c8e8ba23fe1052e3db3d7a3ab1018340f156db 100644 (file)
@@ -1831,6 +1831,11 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
                        mlx4_err(dev, "Failed to initialize multicast group table, aborting\n");
                        goto err_mr_table_free;
                }
+               err = mlx4_config_mad_demux(dev);
+               if (err) {
+                       mlx4_err(dev, "Failed in config_mad_demux, aborting\n");
+                       goto err_mcg_table_free;
+               }
        }
 
        err = mlx4_init_eq_table(dev);
index 1d8af7336807b649feb5a5cdb8c4c32a303d31b2..310b30b4682c0168df4f0c6e38ebe35997362503 100644 (file)
@@ -1311,5 +1311,6 @@ void mlx4_init_quotas(struct mlx4_dev *dev);
 int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port);
 /* Returns the VF index of slave */
 int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave);
+int mlx4_config_mad_demux(struct mlx4_dev *dev);
 
 #endif /* MLX4_H */
index c8450366c13019fe0ec0343487cd5ef6a8e2855f..379c02648ab3b36029ba459534416ebe224cc282 100644 (file)
@@ -116,6 +116,7 @@ enum {
        /* special QP and management commands */
        MLX4_CMD_CONF_SPECIAL_QP = 0x23,
        MLX4_CMD_MAD_IFC         = 0x24,
+       MLX4_CMD_MAD_DEMUX       = 0x203,
 
        /* multicast commands */
        MLX4_CMD_READ_MCG        = 0x25,
@@ -185,6 +186,12 @@ enum {
        MLX4_SET_PORT_VXLAN     = 0xB
 };
 
+enum {
+       MLX4_CMD_MAD_DEMUX_CONFIG       = 0,
+       MLX4_CMD_MAD_DEMUX_QUERY_STATE  = 1,
+       MLX4_CMD_MAD_DEMUX_QUERY_RESTR  = 2, /* Query mad demux restrictions */
+};
+
 enum {
        MLX4_CMD_WRAPPED,
        MLX4_CMD_NATIVE
index 35b51e7af88659f5c1f4e11ff84bc80c3420f6a1..cee9561e8ef6aab35da0ae608d4c99c92fbfac85 100644 (file)
@@ -172,6 +172,7 @@ enum {
        MLX4_DEV_CAP_FLAG2_UPDATE_QP            = 1LL <<  8,
        MLX4_DEV_CAP_FLAG2_DMFS_IPOIB           = 1LL <<  9,
        MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS       = 1LL <<  10,
+       MLX4_DEV_CAP_FLAG2_MAD_DEMUX            = 1LL <<  11,
 };
 
 enum {