From 56d2ec1c0d9c01c666b7b58193f7267aaacd54c2 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Mon, 21 Jul 2014 09:32:48 +0200
Subject: [PATCH] Fixup IPv6 iBFT interface description

The kernel iBFT implementation had an issue with IPv6 addresses,
which required the implementation of an additional 'prefix-len'
parameter.
This patch updates the open-iscsi code to use and display this
attribute if present.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Acked-by: Lee Duncan <lduncan@suse.com>
---
 include/fw_context.h               |  5 ++++-
 usr/config.h                       |  1 +
 usr/idbm.c                         |  3 +++
 usr/idbm_fields.h                  |  1 +
 usr/iface.c                        |  3 ++-
 utils/fwparam_ibft/fw_entry.c      | 14 ++++++++------
 utils/fwparam_ibft/fwparam_sysfs.c | 21 ++++++++++++++++++---
 7 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/include/fw_context.h b/include/fw_context.h
index 295b54d3d0c9..76fd14ac4ef8 100644
--- a/include/fw_context.h
+++ b/include/fw_context.h
@@ -35,6 +35,7 @@ struct boot_context {
 	char boot_target[BOOT_NAME_MAXLEN];
 
 	/* target settings */
+	int target_flags;
 	int target_port;
 	char targetname[TARGET_NAME_MAXLEN + 1];
 	char target_ipaddr[NI_MAXHOST];
@@ -48,7 +49,9 @@ struct boot_context {
 	char initiatorname[TARGET_NAME_MAXLEN + 1];
 
 	/* network settings */
-	char origin[2];
+	int nic_flags;
+	int origin;
+	int prefix;
 	char dhcp[NI_MAXHOST];
 	char iface[IF_NAMESIZE];
 	char mac[18];
diff --git a/usr/config.h b/usr/config.h
index fd31a54d0130..2e36a0a164b6 100644
--- a/usr/config.h
+++ b/usr/config.h
@@ -225,6 +225,7 @@ typedef struct iface_rec {
 	char			ipv6_autocfg[NI_MAXHOST];
 	char			linklocal_autocfg[NI_MAXHOST];
 	char			router_autocfg[NI_MAXHOST];
+	uint8_t			prefix_len;
 	uint16_t		vlan_id;
 	uint8_t			vlan_priority;
 	char			vlan_state[ISCSI_MAX_STR_LEN];
diff --git a/usr/idbm.c b/usr/idbm.c
index 9f3e5676aae4..b2ab182c4ee7 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -264,6 +264,8 @@ idbm_recinfo_node(node_rec_t *r, recinfo_t *ri)
 	__recinfo_str(IFACE_NETNAME, ri, r, iface.netdev, IDBM_SHOW, num, 1);
 	__recinfo_str(IFACE_GATEWAY, ri, r, iface.gateway, IDBM_SHOW, num, 1);
 	__recinfo_str(IFACE_SUBNET_MASK, ri, r, iface.subnet_mask, IDBM_SHOW, num, 1);
+	__recinfo_uint8(IFACE_PREFIX_LEN, ri, r, iface.prefix_len,
+			IDBM_SHOW, num, 1);
 	/*
 	 * svn 780 compat: older versions used node.transport_name and
 	 * rec->transport_name
@@ -535,6 +537,7 @@ void idbm_recinfo_iface(iface_rec_t *r, recinfo_t *ri)
 	__recinfo_str(IFACE_ISCSINAME, ri, r, name, IDBM_SHOW, num, 0);
 	__recinfo_str(IFACE_NETNAME, ri, r, netdev, IDBM_SHOW, num, 1);
 	__recinfo_str(IFACE_IPADDR, ri, r, ipaddress, IDBM_SHOW, num, 1);
+	__recinfo_uint8(IFACE_PREFIX_LEN, ri, r, prefix_len, IDBM_SHOW, num, 1);
 	__recinfo_str(IFACE_HWADDR, ri, r, hwaddress, IDBM_SHOW, num, 1);
 	__recinfo_str(IFACE_TRANSPORTNAME, ri, r, transport_name,
 		      IDBM_SHOW, num, 1);
diff --git a/usr/idbm_fields.h b/usr/idbm_fields.h
index 5790a033d241..c6af3cde2ee8 100644
--- a/usr/idbm_fields.h
+++ b/usr/idbm_fields.h
@@ -73,6 +73,7 @@
 #define IFACE_ISID		"iface.isid"
 #define IFACE_BOOT_PROTO	"iface.bootproto"
 #define IFACE_IPADDR		"iface.ipaddress"
+#define IFACE_PREFIX_LEN	"iface.prefix_len"
 #define IFACE_SUBNET_MASK	"iface.subnet_mask"
 #define IFACE_GATEWAY		"iface.gateway"
 #define IFACE_PRIMARY_DNS	"iface.primary_dns"
diff --git a/usr/iface.c b/usr/iface.c
index 870dba0a1fcc..940ee2388945 100644
--- a/usr/iface.c
+++ b/usr/iface.c
@@ -1002,7 +1002,8 @@ int iface_setup_from_boot_context(struct iface_rec *iface,
 			sizeof(iface->iname));
 
 	if (strlen(context->scsi_host_name)) {
-		if (sscanf(context->scsi_host_name, "iscsi_boot%u", &hostno) != 		    1) {
+		if (sscanf(context->scsi_host_name,
+			   "iscsi_boot%u", &hostno) != 1) {
 			log_error("Could not parse %s's host no.",
 				  context->scsi_host_name);
 			return 0;
diff --git a/utils/fwparam_ibft/fw_entry.c b/utils/fwparam_ibft/fw_entry.c
index 295e905620eb..e804061202d5 100644
--- a/utils/fwparam_ibft/fw_entry.c
+++ b/utils/fwparam_ibft/fw_entry.c
@@ -66,16 +66,16 @@ int fw_setup_nics(void)
 	 * For each target in iBFT bring up required NIC and use routing
 	 * to force iSCSI traffic through correct NIC
 	 */
-	list_for_each_entry(context, &targets, list) {			
-	        /* if it is a offload nic ignore it */
-	        if (!net_get_transport_name_from_netdev(context->iface,
+	list_for_each_entry(context, &targets, list) {
+		/* if it is a offload nic ignore it */
+		if (!net_get_transport_name_from_netdev(context->iface,
 							transport))
 			continue;
 
 		if (iface_prev == NULL || strcmp(context->iface, iface_prev)) {
 			/* Note: test above works because there is a
- 			 * maximum of two targets in the iBFT
- 			 */
+			 * maximum of two targets in the iBFT
+			 */
 			iface_prev = context->iface;
 			needs_bringup = 1;
 		}
@@ -196,13 +196,15 @@ static void dump_network(struct boot_context *context)
 	 * Otherwise evaluate the 'dhcp' field, if this has a valid
 	 * address then DHCP was used (broadcom sends 0.0.0.0).
 	 */
-	if ((strlen(context->origin) && !strcmp(context->origin, "3")) ||
+	if ((context->origin == 3) ||
 	    (strlen(context->dhcp) && strcmp(context->dhcp, "0.0.0.0")))
 		printf("%s = DHCP\n", IFACE_BOOT_PROTO);
 	else
 		printf("%s = STATIC\n", IFACE_BOOT_PROTO);
 	if (strlen(context->ipaddr))
 		printf("%s = %s\n", IFACE_IPADDR, context->ipaddr);
+	if (context->prefix)
+		printf("%s = %d\n", IFACE_PREFIX_LEN, context->prefix);
 	if (strlen(context->mask))
 		printf("%s = %s\n", IFACE_SUBNET_MASK, context->mask);
 	if (strlen(context->gateway))
diff --git a/utils/fwparam_ibft/fwparam_sysfs.c b/utils/fwparam_ibft/fwparam_sysfs.c
index 09dd9fd5cbbc..5868eaed5add 100644
--- a/utils/fwparam_ibft/fwparam_sysfs.c
+++ b/utils/fwparam_ibft/fwparam_sysfs.c
@@ -170,6 +170,13 @@ static int fill_nic_context(char *subsys, char *id,
 {
 	int rc;
 
+	rc = sysfs_get_int(id, subsys, "flags", &context->nic_flags);
+	/* Bit 1 is 'target block valid' */
+	if (!rc && !(context->nic_flags & 1))
+		rc = ENODEV;
+	if (rc)
+		return rc;
+
 	rc = sysfs_get_str(id, subsys, "mac", context->mac,
 			   sizeof(context->mac));
 	if (rc)
@@ -209,6 +216,7 @@ static int fill_nic_context(char *subsys, char *id,
 		      sizeof(context->vlan));
 	sysfs_get_str(id, subsys, "subnet-mask", context->mask,
 		      sizeof(context->mask));
+	sysfs_get_int(id, subsys, "prefix-len", &context->prefix);
 	sysfs_get_str(id, subsys, "gateway", context->gateway,
 		      sizeof(context->gateway));
 	sysfs_get_str(id, subsys, "primary-dns", context->primary_dns,
@@ -217,8 +225,7 @@ static int fill_nic_context(char *subsys, char *id,
 		      sizeof(context->secondary_dns));
 	sysfs_get_str(id, subsys, "dhcp", context->dhcp,
 		      sizeof(context->dhcp));
-	sysfs_get_str(id, subsys, "origin", context->origin,
-		      sizeof(context->origin));
+	sysfs_get_int(id, subsys, "origin", &context->origin);
 	return 0;
 }
 
@@ -232,11 +239,19 @@ static void fill_initiator_context(char *subsys, struct boot_context *context)
 
 	strlcpy(context->boot_root, subsys, sizeof(context->boot_root));
 }
+
 static int fill_tgt_context(char *subsys, char *id,
 			    struct boot_context *context)
 {
 	int rc;
 
+	rc = sysfs_get_int(id, subsys, "flags", &context->target_flags);
+	/* Bit 1 is 'target block valid' */
+	if (!rc && !(context->target_flags & 1))
+		rc = ENODEV;
+	if (rc)
+		return rc;
+
 	rc = sysfs_get_str(id, subsys, "target-name", context->targetname,
 			   sizeof(context->targetname));
 	if (rc)
@@ -401,7 +416,7 @@ static int get_targets(struct list_head *list, char *rootdir, char *subsys)
 	nic_cnt = 0;
 	tgt_cnt = 0;
 
-	/* Find the target's and the ethernet's */
+	/* Find the targets and the ethernets */
 	nftw(rootdir, find_sysfs_dirs, 20, 1);
 	for (i = 0; i < tgt_cnt; i++) {
 		context = calloc(1, sizeof(*context));
-- 
1.8.4.5

