Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdf25218 authored by Neerav Parikh's avatar Neerav Parikh Committed by James Bottomley
Browse files

[SCSI] fcoe: Prevent creation of an NPIV port with duplicate WWPN



This patch adds a validation step before allowing creation of a new NPIV port.
It checks whether the WWPN passed for the new NPIV port to be created is unique
for the given physical port.

Signed-off-by: default avatarNeerav Parikh <Neerav.Parikh@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <jbottomley@parallels.com>
parent c051ad2e
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled);
static int fcoe_vport_disable(struct fc_vport *, bool disable);
static void fcoe_set_vport_symbolic_name(struct fc_vport *);
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
static int fcoe_validate_vport_create(struct fc_vport *);

static struct libfc_function_template fcoe_libfc_fcn_templ = {
	.frame_send = fcoe_xmit,
@@ -2351,6 +2352,17 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
	struct fcoe_interface *fcoe = port->priv;
	struct net_device *netdev = fcoe->netdev;
	struct fc_lport *vn_port;
	int rc;
	char buf[32];

	rc = fcoe_validate_vport_create(vport);
	if (rc) {
		wwn_to_str(vport->port_name, buf, sizeof(buf));
		printk(KERN_ERR "fcoe: Failed to create vport, "
			"WWPN (0x%s) already exists\n",
			buf);
		return rc;
	}

	mutex_lock(&fcoe_config_mutex);
	vn_port = fcoe_if_create(fcoe, &vport->dev, 1);
@@ -2497,3 +2509,49 @@ static void fcoe_set_port_id(struct fc_lport *lport,
	if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
		fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
}

/**
 * fcoe_validate_vport_create() - Validate a vport before creating it
 * @vport: NPIV port to be created
 *
 * This routine is meant to add validation for a vport before creating it
 * via fcoe_vport_create().
 * Current validations are:
 *      - WWPN supplied is unique for given lport
 *
 *
*/
static int fcoe_validate_vport_create(struct fc_vport *vport)
{
	struct Scsi_Host *shost = vport_to_shost(vport);
	struct fc_lport *n_port = shost_priv(shost);
	struct fc_lport *vn_port;
	int rc = 0;
	char buf[32];

	mutex_lock(&n_port->lp_mutex);

	wwn_to_str(vport->port_name, buf, sizeof(buf));
	/* Check if the wwpn is not same as that of the lport */
	if (!memcmp(&n_port->wwpn, &vport->port_name, sizeof(u64))) {
		FCOE_DBG("vport WWPN 0x%s is same as that of the "
			"base port WWPN\n", buf);
		rc = -EINVAL;
		goto out;
	}

	/* Check if there is any existing vport with same wwpn */
	list_for_each_entry(vn_port, &n_port->vports, list) {
		if (!memcmp(&vn_port->wwpn, &vport->port_name, sizeof(u64))) {
			FCOE_DBG("vport with given WWPN 0x%s already "
			"exists\n", buf);
			rc = -EINVAL;
			break;
		}
	}

out:
	mutex_unlock(&n_port->lp_mutex);

	return rc;
}
+10 −0
Original line number Diff line number Diff line
@@ -99,4 +99,14 @@ static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
			((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
}

static inline void wwn_to_str(u64 wwn, char *buf, int len)
{
	u8 wwpn[8];

	u64_to_wwn(wwn, wwpn);
	snprintf(buf, len, "%02x%02x%02x%02x%02x%02x%02x%02x",
		wwpn[0], wwpn[1], wwpn[2], wwpn[3],
		wwpn[4], wwpn[5], wwpn[6], wwpn[7]);
}

#endif /* _FCOE_H_ */