Subject: [PATCH] [BZ 123849] ziomon/ziorep: fix wrong assumption of 0.0.xxxx busids
From: Martin Peschke <mpeschke@linux.vnet.ibm.com>

Description:  ziomon/ziorep: fix wrong assumption of 0.0.xxxx busids
Symptom:      The ziorep tools can't parse the ziomon configuration file.
Problem:      The ziorep tools can't handle device busids a.b.xxxx with
              a and b being non-zero.
Solution:     Fixed all occurrences of device busids in the ziorep tools
              to support full range of possible values.
Reproduction: Run ziorep tools on ziomon data that contains device
              busids not conforming to the 0.0.xxxx scheme,
              e.g. 0.1.1234.
Upstream-ID:  -
Problem-ID:   123849

Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
---
 ziomon/ziorep_cfgreader.cpp |   21 +++++++++++++--------
 ziomon/ziorep_cfgreader.hpp |    6 ++++--
 ziomon/ziorep_collapser.cpp |   13 +++++++------
 ziomon/ziorep_printers.cpp  |   10 +++++-----
 ziomon/ziorep_traffic.cpp   |   12 ++++++------
 ziomon/ziorep_utils.cpp     |    6 +++---
 ziomon/ziorep_utils.hpp     |   13 +++++++++++++
 7 files changed, 51 insertions(+), 30 deletions(-)

--- a/ziomon/ziorep_cfgreader.cpp
+++ b/ziomon/ziorep_cfgreader.cpp
@@ -35,6 +35,7 @@ ConfigReader::ConfigReader(int *rc, cons
 	int			 line_idx = 1;
 	long long unsigned int	 tmp_lun;
 	long long unsigned int	 tmp_wwpn;
+	unsigned int		 subch1, subch2, subch3, devno1, devno2, devno3;
 
 	*rc = 0;
 
@@ -64,13 +65,14 @@ ConfigReader::ConfigReader(int *rc, cons
 		new_elem.device = (char*)malloc(lrc + 1);
 		new_elem.type = (char*)malloc(lrc + 1);
 		new_elem.multipath_device = (char*)malloc(lrc + 1);
-		lrc = sscanf(line, "%x %u:%u:%u:%u 0.0.%x:0.0.%x:%Lx:%Lx %s %u %u:%u %s %u %u:%u %s",
+		lrc = sscanf(line, "%x %u:%u:%u:%u %x.%x.%x:%x.%x.%x:%Lx:%Lx %s %u %u:%u %s %u %u:%u %s",
 		       &new_elem.chpid,
 		       &new_elem.hctl_identifier.host,
 		       &new_elem.hctl_identifier.channel,
 		       &new_elem.hctl_identifier.target,
 		       &new_elem.hctl_identifier.lun,
-		       &new_elem.subchannel, &new_elem.devno,
+		       &subch1, &subch2, &subch3,
+		       &devno1, &devno2, &devno3,
 		       &tmp_wwpn,
 		       &tmp_lun,
 		       new_elem.multipath_device, &new_elem.mp_mm,
@@ -81,12 +83,15 @@ ConfigReader::ConfigReader(int *rc, cons
 		       new_elem.type);
 		free(line);
 		line = NULL;
-		if (lrc != 18) {
+		if (lrc != 22) {
 			fprintf(stderr, "%s: Could not parse line %d"
 				" - configuration file broken?\n", toolname, line_idx);
 			*rc = -1;
 			goto out;
 		}
+		/* complete bus-IDs packed in u32 to avoid filter code changes */
+		new_elem.subchannel = ZIOREP_BUSID_PACKED(subch1, subch2, subch3);
+		new_elem.devno = ZIOREP_BUSID_PACKED(devno1, devno2, devno3);
 		new_elem.wwpn = tmp_wwpn;
 		new_elem.lun = tmp_lun;
 
@@ -364,13 +369,12 @@ void ConfigReader::host_id_not_found_err
 		" again\n", toolname, h);
 }
 
-
 void ConfigReader::devno_not_found_error(__u32 devno, int *rc) const
 {
 	*rc = -1;
-	fprintf(stderr, "%s: Could not find bus id 0.0.%x in configuration"
+	fprintf(stderr, "%s: Could not find bus id %x.%x.%04x in configuration"
 		" file. Please check if you have the right .cfg file and try"
-		" again\n", toolname, devno);
+		" again\n", toolname, ZIOREP_BUSID_UNPACKED(devno));
 }
 
 
@@ -855,13 +859,14 @@ void ConfigReader::dump(FILE *fp) const
 	fprintf(fp, "dumping cfg....\n");
 	for (list<struct device_info>::const_iterator i = m_devices.begin();
 	      i != m_devices.end(); ++i) {
-		fprintf(fp, "%x %u %u:%u:%u:%u 0.0.%04x:0.0.%x:%016Lx:%016Lx %s %u:%u %s %u:%u %s\n",
+		fprintf(fp, "%x %u %u:%u:%u:%u %x.%x.%04x:%x.%x.%04x:%016Lx:%016Lx %s %u:%u %s %u:%u %s\n",
 		       (*i).chpid, (*i).mm_internal,
 		       (*i).hctl_identifier.host,
 		       (*i).hctl_identifier.channel,
 		       (*i).hctl_identifier.target,
 		       (*i).hctl_identifier.lun,
-		       (*i).subchannel, (*i).devno,
+		       ZIOREP_BUSID_UNPACKED((*i).subchannel),
+		       ZIOREP_BUSID_UNPACKED((*i).devno),
 		       (long long unsigned int)(*i).wwpn,
 		       (long long unsigned int)(*i).lun,
 		       ((*i).multipath_device ? (*i).multipath_device : "n/a"), (*i).mp_major,
--- a/ziomon/ziorep_cfgreader.hpp
+++ b/ziomon/ziorep_cfgreader.hpp
@@ -160,8 +160,10 @@ private:
 		// fcp device identifier, e.g. 0:0:17:1075920929
 		struct hctl_ident	hctl_identifier;
 
-		//
-		// e.g. 0.0.0010:0.0.5b1d:0x50050763030b0104:0x4021402100000000
+		// subchannel bus-ID and device bus-ID are packed into 32 bits:
+		// channel subsystem (1 byte), subchannel set (1 byte),
+		// subchannel or device number (2 bytes)
+		// use accessors ZIOREP_BUSID_PACKED and ZIOREP_BUSID_UNPACKED
 		__u32	subchannel;
 		__u32	devno;
 		__u64	wwpn;
--- a/ziomon/ziorep_collapser.cpp
+++ b/ziomon/ziorep_collapser.cpp
@@ -351,8 +351,8 @@ void AggregationCollapser::setup_by_devn
 		dev_mapping.idx = get_index_u32(m_reference_values_u32, devno);
 		assert(dev_mapping.idx >= 0);
 		add_to_index(&dev_mapping);
-		vverbose_msg("    map mm %d to bus id 0.0.%x (index %d)\n", *i,
-			     devno, dev_mapping.idx);
+		vverbose_msg("    map mm %d to bus id %x.%x.%04x (index %d)\n", *i,
+			     ZIOREP_BUSID_UNPACKED(devno), dev_mapping.idx);
 	}
 
 	cfg.get_unique_host_ids(host_ids);
@@ -368,8 +368,9 @@ void AggregationCollapser::setup_by_devn
 						    devno);
 		assert(host_id_mapping.idx >= 0);
 		add_to_index(&host_id_mapping);
-		vverbose_msg("    map host id %d to bus id 0.0.%x"
-			     " (index %d)\n", *i, devno, host_id_mapping.idx);
+		vverbose_msg("    map host id %d to bus id %x.%x.%04x"
+			     " (index %d)\n", *i, ZIOREP_BUSID_UNPACKED(devno),
+			     host_id_mapping.idx);
 	}
 
 	cfg.get_unique_devices(idents);
@@ -384,10 +385,10 @@ void AggregationCollapser::setup_by_devn
 		ide_mapping.idx = get_index_u32(m_reference_values_u32, devno);
 		assert(ide_mapping.idx >= 0);
 		add_to_index(&ide_mapping);
-		vverbose_msg("    map device [%d:%d:%d:%d] to bus id 0.0.%x"
+		vverbose_msg("    map device [%d:%d:%d:%d] to bus id %x.%x.%04x"
 			     " (index %d)\n",
 			    (*i).host, (*i).channel, (*i).target, (*i).lun,
-			    devno, ide_mapping.idx);
+			    ZIOREP_BUSID_UNPACKED(devno), ide_mapping.idx);
 	}
 }
 
--- a/ziomon/ziorep_printers.cpp
+++ b/ziomon/ziorep_printers.cpp
@@ -418,13 +418,13 @@ void VirtAdapterPrinter::print_virt_adpt
 					int *rc)
 {
 	if (m_csv)
-		fprintf(fp, "%x,0.0.%04x,",
+		fprintf(fp, "%x,%x.%x.%04x,",
 			       m_cfg->get_chpid_by_devno(devno, rc),
-			       devno);
+			       ZIOREP_BUSID_UNPACKED(devno));
 	else
-		fprintf(fp, "%3x/0.0.%04x",
+		fprintf(fp, "%3x/%x.%x.%04x",
 			       m_cfg->get_chpid_by_devno(devno, rc),
-			       devno);
+			       ZIOREP_BUSID_UNPACKED(devno));
 }
 
 void VirtAdapterPrinter::print_queue_fill(FILE *fp,
@@ -764,7 +764,7 @@ void TrafficPrinter::print_device_chpid(
 
 void TrafficPrinter::print_device_devno(FILE *fp, __u32 devno)
 {
-	fprintf(fp, "0.0.%04x", devno);
+	fprintf(fp, "%x.%x.%04x", ZIOREP_BUSID_UNPACKED(devno));
 }
 
 void TrafficPrinter::print_device_mp_mm(FILE *fp, __u32 mp_mm,
--- a/ziomon/ziorep_traffic.cpp
+++ b/ziomon/ziorep_traffic.cpp
@@ -118,7 +118,7 @@ static int parse_params(int argc, char *
 	int c;
 	int index;
 	int rc;
-	__u32 tmp32;
+	__u32 tmp32, tmp32a, tmp32b;
 	long long unsigned int tmp64;
 	long tmpl;
 	char mychar;
@@ -220,13 +220,13 @@ static int parse_params(int argc, char *
 			opts->luns.push_back(tmp64);
 			break;
 		case 'u':
-			rc = sscanf(optarg, "0.0.%x", &tmp32);
-			if (rc != 1) {
+			rc = sscanf(optarg, "%x.%x.%x", &tmp32, &tmp32a, &tmp32b);
+			if (rc != 3) {
 				fprintf(stderr, "%s: Could not read bus-ID"
 					" %s\n", toolname, optarg);
 				return -1;
 			}
-			opts->devnos.push_back(tmp32);
+			opts->devnos.push_back(ZIOREP_BUSID_PACKED(tmp32, tmp32a, tmp32b));
 			break;
 		case 'd':
 			opts->devices.push_back(optarg);
@@ -326,8 +326,8 @@ static int check_opts(struct options *op
 	for (list<__u32>::const_iterator i = opts->devnos.begin();
 	      i != opts->devnos.end(); ++i) {
 		if (!(*cfg)->verify_devno(*i)) {
-			fprintf(stderr, "Error: Could not find bus-ID 0.0.%04x in"
-				" configuration.\n", *i);
+			fprintf(stderr, "Error: Could not find bus-ID %x.%x.%04x in"
+				" configuration.\n", ZIOREP_BUSID_UNPACKED(*i));
 			rc = -3;
 		}
 	}
--- a/ziomon/ziorep_utils.cpp
+++ b/ziomon/ziorep_utils.cpp
@@ -425,12 +425,12 @@ int print_summary_report(FILE *fp, char
 	for (list<__u32>::const_iterator i = host_ids.begin();
 	      i != host_ids.end(); ++i) {
 		if (first) {
-			frmt = "HBA/CHPID:        0.0.%04x/%x\n";
+			frmt = "HBA/CHPID:        %x.%x.%04x/%x\n";
 			first = 0;
 		}
 		else
-			frmt = "                  0.0.%04x/%x\n";
-		rc += fprintf(fp, frmt, cfg.get_devno_by_host_id(*i, &lrc),
+			frmt = "                  %x.%x.%04x/%x\n";
+		rc += fprintf(fp, frmt, ZIOREP_BUSID_UNPACKED(cfg.get_devno_by_host_id(*i, &lrc)),
 			      cfg.get_chpid_by_host_id(*i, &lrc));
 		if (lrc)
 			return -1;
--- a/ziomon/ziorep_utils.hpp
+++ b/ziomon/ziorep_utils.hpp
@@ -81,5 +81,18 @@ int parse_topline_arg(char *str, __u64 *
 FILE* open_csv_output_file(const char *filename, const char *extension,
 			   int *rc);
 
+/**
+ * accessors for internal representation of device and subchannel bus-IDs
+ * packed:   takes channel subsystem, subchannel set, device number/subchannel
+ *           returns 32 bit integer
+ * unpacked: takes 32 bit integer
+ *           returns channel subsystem, subchannel set, device number/subchannel
+ *           as a comma seperated list
+ */
+#define ZIOREP_BUSID_PACKED(busid_part1, busid_part2, busid_part3) \
+	(((busid_part1) << 24) | ((busid_part2) << 16) | (busid_part3))
+#define ZIOREP_BUSID_UNPACKED(busid) \
+	((busid) >> 24) & 0xFF, ((busid) >> 16) & 0xFF, (busid) & 0xFFFF
+
 #endif
 
