Blob Blame Raw
commit ac38eee2083821eb29d098227ad044c950d115e4
Author: Mike Christie <michaelc@cs.wisc.edu>
Date:   Sun Aug 14 22:14:04 2011 -0500

    iscsi tools: fix default iface binding setup
    
    If a driver supports multiple ifaces only one is getting
    auto created. This modifies the default iface setup code
    so that it creates a iface per kernel iface or a iface per
    host if kernel ifaces are not supported.

diff --git a/usr/iface.c b/usr/iface.c
index 5d5f7bf..9c70d09 100644
--- a/usr/iface.c
+++ b/usr/iface.c
@@ -424,12 +424,61 @@ int iface_get_by_net_binding(struct iface_rec *pattern,
 	return ISCSI_ERR_NO_OBJS_FOUND;
 }
 
+static int iface_get_iptype(struct iface_rec *iface)
+{
+	if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
+		return ISCSI_IFACE_TYPE_IPV6;
+	else
+		return ISCSI_IFACE_TYPE_IPV4;
+}
+
+static int iface_setup_binding_from_kern_iface(void *data,
+					       struct iface_rec *kern_iface)
+{
+	struct host_info *hinfo = data;
+	struct iface_rec iface;
+
+	if (!strlen(hinfo->iface.hwaddress)) {
+		log_error("Invalid offload iSCSI host %u. Missing "
+			  "hwaddress. Try upgrading %s driver.\n",
+			  hinfo->host_no, hinfo->iface.transport_name);
+		return 0;
+	}
+
+	memset(&iface, 0, sizeof(struct iface_rec));
+	strcpy(iface.hwaddress, hinfo->iface.hwaddress);
+	strcpy(iface.transport_name, hinfo->iface.transport_name);
+
+	if (kern_iface) {
+		iface.iface_num = kern_iface->iface_num;
+
+		snprintf(iface.name, sizeof(iface.name), "%s.%s.%s.%u",
+			 kern_iface->transport_name,
+			 kern_iface->hwaddress,
+			 iface_get_iptype(kern_iface) == ISCSI_IFACE_TYPE_IPV4 ?
+			 "ipv4" : "ipv6", kern_iface->iface_num);
+	} else {
+		snprintf(iface.name, sizeof(iface.name), "%s.%s",
+			 hinfo->iface.transport_name, hinfo->iface.hwaddress);
+	}
+
+	if (iface_conf_read(&iface)) {
+		/* not found so create it */
+		if (iface_conf_write(&iface)) {
+			log_error("Could not create default iface conf %s.",
+				  iface.name);
+			/* fall through - will not be persistent */
+		}
+	}
+
+	return 0;
+}
+
 static int __iface_setup_host_bindings(void *data, struct host_info *hinfo)
 {
 	struct iface_rec *def_iface;
-	struct iface_rec iface;
 	struct iscsi_transport *t;
-	int i = 0;
+	int i = 0, nr_found;
 
 	t = iscsi_sysfs_get_transport_by_hba(hinfo->host_no);
 	if (!t)
@@ -441,26 +490,12 @@ static int __iface_setup_host_bindings(void *data, struct host_info *hinfo)
 			return 0;
 	}
 
-	if (iface_get_by_net_binding(&hinfo->iface, &iface) ==
-	    ISCSI_ERR_NO_OBJS_FOUND) {
-		/* Must be a new port */
-		if (!strlen(hinfo->iface.hwaddress)) {
-			log_error("Invalid offload iSCSI host %u. Missing "
-				  "hwaddress. Try upgrading %s driver.\n",
-				  hinfo->host_no, t->name);
-			return 0;
-		}
-
-		memset(&iface, 0, sizeof(struct iface_rec));
-		strcpy(iface.hwaddress, hinfo->iface.hwaddress);
-		strcpy(iface.transport_name, hinfo->iface.transport_name);
-		snprintf(iface.name, sizeof(iface.name), "%s.%s",
-			 t->name, hinfo->iface.hwaddress);
-		if (iface_conf_write(&iface))
-			log_error("Could not create default iface conf %s.",
-				  iface.name);
-			/* fall through - will not be persistent */
-	}
+	nr_found = 0;
+	iscsi_sysfs_for_each_iface_on_host(hinfo, hinfo->host_no,
+					   &nr_found,
+					   iface_setup_binding_from_kern_iface);
+	if (!nr_found)
+		iface_setup_binding_from_kern_iface(hinfo, NULL);	
 	return 0;
 }
 
@@ -843,7 +878,6 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
 	memset(iface->name, 0, sizeof(iface->name));
 	snprintf(iface->name, sizeof(iface->name), "%s.%s",
 		 iface->transport_name, context->mac);
-
 	strlcpy(iface->hwaddress, context->mac,
 		sizeof(iface->hwaddress));
 	strlcpy(iface->ipaddress, context->ipaddr,
@@ -921,9 +955,7 @@ static int __iface_get_param_count(void *data, struct iface_rec *iface)
 	if (strcmp(iface_params->primary->hwaddress, iface->hwaddress))
 		return 0;
 
-	if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
-		iptype = ISCSI_IFACE_TYPE_IPV6;
-
+	iptype = iface_get_iptype(iface);
 	if (iptype == ISCSI_IFACE_TYPE_IPV4) {
 
 		if (strcmp(iface->state, "disable")) {
@@ -1466,12 +1498,10 @@ static int __iface_build_net_config(void *data, struct iface_rec *iface)
 	if (strcmp(net_config->primary->hwaddress, iface->hwaddress))
 		return 0;
 
-	if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
-		iptype = ISCSI_IFACE_TYPE_IPV6;
-
 	/* start at 2, because 0 is for nlmsghdr and 1 for event */
 	iov = net_config->iovs + 2;
 
+	iptype = iface_get_iptype(iface);
 	if (iptype == ISCSI_IFACE_TYPE_IPV4) {
 		if (!strcmp(iface->state, "disable")) {
 			if (!iface_fill_net_state(&iov[net_config->count],
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
index 995549e..961cefd 100644
--- a/usr/iscsi_sysfs.c
+++ b/usr/iscsi_sysfs.c
@@ -425,9 +425,10 @@ uint32_t iscsi_sysfs_get_host_no_from_hwinfo(struct iface_rec *iface, int *rc)
 static int iscsi_sysfs_read_iface(struct iface_rec *iface, int host_no,
 				  char *session, char *iface_kern_id)
 {
+	uint32_t tmp_host_no, iface_num;
 	char host_id[NAME_SIZE];
 	struct iscsi_transport *t;
-	int ret;
+	int ret, iface_type;
 
 	t = iscsi_sysfs_get_transport_by_hba(host_no);
 	if (!t)
@@ -582,6 +583,10 @@ static int iscsi_sysfs_read_iface(struct iface_rec *iface, int host_no,
 			 &iface->vlan_id);
 	sysfs_get_uint8(iface_kern_id, ISCSI_IFACE_SUBSYS, "vlan_priority",
 			 &iface->vlan_priority);
+
+	if (sscanf(iface_kern_id, "ipv%d-iface-%u-%u", &iface_type,
+		   &tmp_host_no, &iface_num) == 3)
+		iface->iface_num = iface_num;
 done:
 	if (ret)
 		return ISCSI_ERR_SYSFS_LOOKUP;