Blame IbaTools/opareport/verify.c

Packit Service 3470d1
/* BEGIN_ICS_COPYRIGHT7 ****************************************
Packit Service 3470d1
Packit Service 3470d1
Copyright (c) 2015-2017, Intel Corporation
Packit Service 3470d1
Packit Service 3470d1
Redistribution and use in source and binary forms, with or without
Packit Service 3470d1
modification, are permitted provided that the following conditions are met:
Packit Service 3470d1
Packit Service 3470d1
    * Redistributions of source code must retain the above copyright notice,
Packit Service 3470d1
      this list of conditions and the following disclaimer.
Packit Service 3470d1
    * Redistributions in binary form must reproduce the above copyright
Packit Service 3470d1
      notice, this list of conditions and the following disclaimer in the
Packit Service 3470d1
      documentation and/or other materials provided with the distribution.
Packit Service 3470d1
    * Neither the name of Intel Corporation nor the names of its contributors
Packit Service 3470d1
      may be used to endorse or promote products derived from this software
Packit Service 3470d1
      without specific prior written permission.
Packit Service 3470d1
Packit Service 3470d1
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit Service 3470d1
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 3470d1
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit Service 3470d1
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit Service 3470d1
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 3470d1
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit Service 3470d1
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit Service 3470d1
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit Service 3470d1
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 3470d1
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 3470d1
Packit Service 3470d1
** END_ICS_COPYRIGHT7   ****************************************/
Packit Service 3470d1
Packit Service 3470d1
/* [ICS VERSION STRING: unknown] */
Packit Service 3470d1
Packit Service 3470d1
#include "opareport.h"
Packit Service 3470d1
#include <iba/stl_helper.h>
Packit Service 3470d1
#include <limits.h>
Packit Service 3470d1
Packit Service 3470d1
// Fabric Topology Verification and related reports
Packit Service 3470d1
Packit Service 3470d1
void ShowProblem(Format_t format, int indent, int detail, const char* pformat, ...)
Packit Service 3470d1
{
Packit Service 3470d1
	va_list args;
Packit Service 3470d1
	static char buffer[100];
Packit Service 3470d1
	int cnt;
Packit Service 3470d1
Packit Service 3470d1
	if (detail >= 0) {
Packit Service 3470d1
		va_start(args, pformat);
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*s", indent, "");
Packit Service 3470d1
			vprintf(pformat, args);
Packit Service 3470d1
			printf("\n");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			cnt = vsnprintf(buffer, sizeof(buffer), pformat, args);
Packit Service 3470d1
			ASSERT(cnt <= sizeof(buffer)-1);	/* make sure message fits */
Packit Service 3470d1
			XmlPrintStr("Problem", buffer, indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		va_end(args);
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// verify a port against its corresponding ExpectedLink->PortSelector
Packit Service 3470d1
// Only valid to be called for ports with ExpectedLink
Packit Service 3470d1
// returns FALSE if any discrepencies
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
boolean PortVerify(PortData *portp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ExpectedLink *elinkp = portp->elinkp;
Packit Service 3470d1
	PortSelector *portselp = NULL;
Packit Service 3470d1
	boolean ret=TRUE;
Packit Service 3470d1
Packit Service 3470d1
	if (elinkp->portp1 == portp) {
Packit Service 3470d1
		portselp = elinkp->portselp1;
Packit Service 3470d1
	} else if (elinkp->portp2 == portp) {
Packit Service 3470d1
		portselp = elinkp->portselp2;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (portselp) { // not specified in input topology xml file; accept any port on the other end of the link
Packit Service 3470d1
		if (portselp->NodeGUID && portselp->NodeGUID != portp->nodep->NodeInfo.NodeGUID) {
Packit Service 3470d1
			ret = FALSE;
Packit Service 3470d1
			ShowProblem(format, indent, detail,
Packit Service 3470d1
				"NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64,
Packit Service 3470d1
				portselp->NodeGUID, portp->nodep->NodeInfo.NodeGUID);
Packit Service 3470d1
		}
Packit Service 3470d1
		if (portselp->NodeDesc
Packit Service 3470d1
			&& 0 != strncmp(portselp->NodeDesc,
Packit Service 3470d1
							(char*)portp->nodep->NodeDesc.NodeString,
Packit Service 3470d1
							NODE_DESCRIPTION_ARRAY_SIZE)) {
Packit Service 3470d1
			ret = FALSE;
Packit Service 3470d1
			ShowProblem(format, indent, detail,
Packit Service 3470d1
				"NodeDesc mismatch: expected: '%s' found: '%.*s'",
Packit Service 3470d1
				portselp->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE,
Packit Service 3470d1
				(char*)portp->nodep->NodeDesc.NodeString);
Packit Service 3470d1
		}
Packit Service 3470d1
		if (portselp->gotPortNum && portselp->PortNum != portp->PortNum) {
Packit Service 3470d1
			ret = FALSE;
Packit Service 3470d1
			ShowProblem(format, indent, detail,
Packit Service 3470d1
				"PortNum mismatch: expected: %3u found: %3u",
Packit Service 3470d1
				portselp->PortNum, portp->PortNum);
Packit Service 3470d1
		}
Packit Service 3470d1
		if (portselp->PortGUID && portselp->PortGUID != portp->PortGUID) {
Packit Service 3470d1
			ret = FALSE;
Packit Service 3470d1
			ShowProblem(format, indent, detail, 
Packit Service 3470d1
				"PortGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64,
Packit Service 3470d1
				portselp->PortGUID, portp->PortGUID);
Packit Service 3470d1
		}
Packit Service 3470d1
		if (portselp->NodeType && portselp->NodeType != portp->nodep->NodeInfo.NodeType) {
Packit Service 3470d1
			ret = FALSE;
Packit Service 3470d1
			ShowProblem(format, indent, detail, 
Packit Service 3470d1
				"NodeType mismatch: expected: %s found: %s",
Packit Service 3470d1
				StlNodeTypeToText(portselp->NodeType),
Packit Service 3470d1
				StlNodeTypeToText(portp->nodep->NodeInfo.NodeType));
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	/* to get here the port must have a neighbor and hence should be linkup
Packit Service 3470d1
	 * but it could be quarantined or failing to move to Active
Packit Service 3470d1
	 */
Packit Service 3470d1
	if (portp->PortInfo.PortStates.s.PortState != IB_PORT_ACTIVE) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"Port not Active: PortState: %s",
Packit Service 3470d1
			StlPortStateToText(portp->PortInfo.PortStates.s.PortState));
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// check attributes of link against input topology
Packit Service 3470d1
// Only valid to be called for ports with ExpectedLink
Packit Service 3470d1
// returns FALSE if link fails to verify
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
boolean LinkAttrVerify(ExpectedLink *elinkp, PortData *portp1, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	PortData *portp2 = portp1->neighbor;
Packit Service 3470d1
	boolean ret = TRUE;
Packit Service 3470d1
Packit Service 3470d1
	if (elinkp->expected_rate && elinkp->expected_rate != portp1->rate) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"Link Rate mismatch: expected: %4s found: %4s",
Packit Service 3470d1
			StlStaticRateToText(elinkp->expected_rate),
Packit Service 3470d1
			StlStaticRateToText(portp1->rate));
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	if (elinkp->expected_mtu && elinkp->expected_mtu != MIN(portp1->PortInfo.MTU.Cap, portp2->PortInfo.MTU.Cap)) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"Link MTU mismatch: expected minimum MTU: %5s found MTU: %5s",
Packit Service 3470d1
			IbMTUToText(elinkp->expected_mtu),
Packit Service 3470d1
			IbMTUToText(MIN(portp1->PortInfo.MTU.Cap, portp2->PortInfo.MTU.Cap)));
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
typedef enum {
Packit Service 3470d1
	LINK_VERIFY_OK = 0,	// link matches input topology
Packit Service 3470d1
	LINK_VERIFY_DIFF = 1, // link fully resolved but diff from input topology
Packit Service 3470d1
	LINK_VERIFY_UNEXPECTED = 2, // link not found in input topology
Packit Service 3470d1
	LINK_VERIFY_MISSING = 3, // link not found in fabric, but in input topology
Packit Service 3470d1
	LINK_VERIFY_DUP = 4, // possible duplicate in input topology
Packit Service 3470d1
	LINK_VERIFY_CONN = 5, // link partially resolved, wrong cabling
Packit Service 3470d1
	LINK_VERIFY_MAX=5	// maximum value of the above
Packit Service 3470d1
} LinkVerifyResult_t;
Packit Service 3470d1
Packit Service 3470d1
// check both fabric ports and link attributes against input topology
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
LinkVerifyResult_t LinkFabricVerify(PortData *portp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	LinkVerifyResult_t ret = LINK_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	// all checks which are based off of found ports/links in fabric
Packit Service 3470d1
	if (portp->elinkp && portp->neighbor->elinkp) {
Packit Service 3470d1
		ExpectedLink *elinkp = portp->elinkp;
Packit Service 3470d1
		DEBUG_ASSERT(portp->elinkp == portp->neighbor->elinkp);
Packit Service 3470d1
		// check both sides for expected characteristics
Packit Service 3470d1
		if (! PortVerify(portp, format, indent, detail))
Packit Service 3470d1
			ret = LINK_VERIFY_DIFF;
Packit Service 3470d1
		if (! PortVerify(portp->neighbor, format, indent, detail))
Packit Service 3470d1
			ret = LINK_VERIFY_DIFF;
Packit Service 3470d1
		// check expected link characteristics
Packit Service 3470d1
		if (! LinkAttrVerify(elinkp, portp, format, indent, detail))
Packit Service 3470d1
			ret = LINK_VERIFY_DIFF;
Packit Service 3470d1
	} else if (! portp->elinkp && ! portp->neighbor->elinkp) {
Packit Service 3470d1
		ret = LINK_VERIFY_UNEXPECTED; // extra link
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected Link");
Packit Service 3470d1
	} else {
Packit Service 3470d1
		// only one side resolved
Packit Service 3470d1
		DEBUG_ASSERT(0);	// we only set elinkp if both sides resolved
Packit Service 3470d1
		ret = LINK_VERIFY_UNEXPECTED; // internal error
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// compare ExpectedLink against fabric
Packit Service 3470d1
// LinkFabricVerify will have caught links which are different or extra
Packit Service 3470d1
// this is focused on duplicate ExpectedLink or missing links
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
// side controls message output:
Packit Service 3470d1
// 	0 - both ports and link info - for initial checks
Packit Service 3470d1
// 	1 - elinkp->port 1 - when in process of outputting port 1 info
Packit Service 3470d1
// 	2 - elinkp->port 2 - when in process of outputting port 2 info
Packit Service 3470d1
// 	3 - link info only - when in process of outputting summary link info
Packit Service 3470d1
LinkVerifyResult_t ExpectedLinkVerify(ExpectedLink *elinkp, uint8 side, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	LinkVerifyResult_t ret = LINK_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	if (! elinkp->portp1 && ! elinkp->portp2) {
Packit Service 3470d1
		if (side == 0 || side == 3)
Packit Service 3470d1
			ShowProblem(format, indent, detail, "Missing Link");
Packit Service 3470d1
		ret = LINK_VERIFY_MISSING;	// missing link
Packit Service 3470d1
	} else if (elinkp->portp1 && elinkp->portp2) {
Packit Service 3470d1
		if (elinkp->portp1->elinkp != elinkp) {
Packit Service 3470d1
			// duplicate port, or incomplete/duplicate link in input topology
Packit Service 3470d1
			ret = LINK_VERIFY_DUP;
Packit Service 3470d1
			if (side == 0 || side == 1)
Packit Service 3470d1
				ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled");
Packit Service 3470d1
		}
Packit Service 3470d1
		if (elinkp->portp2->elinkp != elinkp) {
Packit Service 3470d1
			// duplicate port, or incomplete/duplicate link in input topology
Packit Service 3470d1
			ret = LINK_VERIFY_DUP;
Packit Service 3470d1
			if (side == 0 || side == 2)
Packit Service 3470d1
				ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled");
Packit Service 3470d1
		}
Packit Service 3470d1
		if (ret == LINK_VERIFY_DUP && side == 3) {
Packit Service 3470d1
			ShowProblem(format, indent, detail, "Duplicate Port in input or incorrectly cabled");
Packit Service 3470d1
		}
Packit Service 3470d1
	} else { /* elinkp->portp1 || elinkp->portp2 */
Packit Service 3470d1
		// only 1 side resolved -> incorrectly cabled
Packit Service 3470d1
		ret = LINK_VERIFY_CONN;
Packit Service 3470d1
		if (detail >= 0 && (side == 0 || side == 3)) {
Packit Service 3470d1
			if (elinkp->portp1) {
Packit Service 3470d1
				if (elinkp->portp1->neighbor) {
Packit Service 3470d1
					ShowProblem(format, indent, detail, "Incorrect Link, 2nd port found to be:");
Packit Service 3470d1
					ShowLinkPortBriefSummary(elinkp->portp1->neighbor, "    ", 
Packit Service 3470d1
							0, NULL, format, indent, 0);
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowProblem(format, indent, detail, "Incorrect Link, 2nd port not found");
Packit Service 3470d1
				}
Packit Service 3470d1
			} else /* elinkp->portp2 */ {
Packit Service 3470d1
				if (elinkp->portp2->neighbor) {
Packit Service 3470d1
					ShowProblem(format, indent, detail, "Incorrect Link, 1st port found to be:");
Packit Service 3470d1
					ShowLinkPortBriefSummary(elinkp->portp2->neighbor, "    ", 
Packit Service 3470d1
							0, NULL, format, indent, 0);
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowProblem(format, indent, detail, "Incorrect Link, 1st port not found");
Packit Service 3470d1
				}
Packit Service 3470d1
			}
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
void ShowLinkPortVerifySummaryCallback(uint64 context, PortData *portp,
Packit Service 3470d1
									Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	if (portp->elinkp && portp->neighbor->elinkp) {
Packit Service 3470d1
		(void)PortVerify(portp, format, indent, detail);
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show fabric link verify errors from portp to its neighbor
Packit Service 3470d1
void ShowLinkVerifySummary(PortData *portp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ShowLinkFromBriefSummary(portp, 0, ShowLinkPortVerifySummaryCallback, format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	ShowLinkToBriefSummary(portp->neighbor, "<-> ", FALSE, 0, ShowLinkPortVerifySummaryCallback, format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		indent +=4;
Packit Service 3470d1
	if (portp->elinkp && portp->neighbor->elinkp
Packit Service 3470d1
		&& (! PortVerify(portp, format, indent, -1)
Packit Service 3470d1
			|| ! PortVerify(portp->neighbor, format, indent, -1)))
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Port Attributes Inconsistent");
Packit Service 3470d1
	if (portp->elinkp && portp->neighbor->elinkp) {
Packit Service 3470d1
		(void)LinkAttrVerify(portp->elinkp, portp, format, indent, detail);
Packit Service 3470d1
	} else if (! portp->elinkp && ! portp->neighbor->elinkp) {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected Link");
Packit Service 3470d1
	}
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</Link>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// header used before a series of links
Packit Service 3470d1
void ShowExpectedLinkBriefSummaryHeader(Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*sRate MTU   NodeGUID          Port or PortGUID    Type Name\n", indent, "");
Packit Service 3470d1
		if (detail && (g_Fabric.flags & FF_CABLEDATA)) {
Packit Service 3470d1
			//printf("%*sPortDetails\n", indent+4, "");
Packit Service 3470d1
			//printf("%*sLinkDetails\n", indent+4, "");
Packit Service 3470d1
			printf("%*sCable: %-*s %-*s\n", indent+4, "",
Packit Service 3470d1
							CABLE_LABEL_STRLEN, "CableLabel",
Packit Service 3470d1
							CABLE_LENGTH_STRLEN, "CableLen");
Packit Service 3470d1
			printf("%*s%s\n", indent+4, "", "CableDetails");
Packit Service 3470d1
		}
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
void ShowExpectedLinkPortVerifySummaryCallback(ExpectedLink *elinkp, uint8 side,
Packit Service 3470d1
									Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	(void)ExpectedLinkVerify(elinkp, side, format, indent, detail);
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show input link verify errors
Packit Service 3470d1
void ShowExpectedLinkVerifySummary(ExpectedLink *elinkp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	// top level information about link
Packit Service 3470d1
	if (format == FORMAT_XML) {
Packit Service 3470d1
		printf("%*s<Link id=\"0x%016"PRIx64"\">\n", indent, "", (uint64)(uintn)elinkp);
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
		if (elinkp->expected_rate)
Packit Service 3470d1
			XmlPrintRate(elinkp->expected_rate, indent);
Packit Service 3470d1
		if (elinkp->expected_mtu)
Packit Service 3470d1
			XmlPrintDec("MTU",
Packit Service 3470d1
				GetBytesFromMtu(elinkp->expected_mtu), indent);
Packit Service 3470d1
		XmlPrintDec("Internal", elinkp->internal, indent);
Packit Service 3470d1
		if (detail)
Packit Service 3470d1
			ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// From Side (Port 1)
Packit Service 3470d1
	ShowExpectedLinkPortSelBriefSummary("", elinkp, elinkp->portselp1,
Packit Service 3470d1
					1, ShowExpectedLinkPortVerifySummaryCallback,
Packit Service 3470d1
					format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	// To Side (Port 2)
Packit Service 3470d1
	ShowExpectedLinkPortSelBriefSummary("", elinkp, elinkp->portselp2,
Packit Service 3470d1
					2, ShowExpectedLinkPortVerifySummaryCallback,
Packit Service 3470d1
					format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	// Summary information about Link itself
Packit Service 3470d1
	if (detail && format != FORMAT_XML)
Packit Service 3470d1
		ShowExpectedLinkBriefSummary(elinkp, format, indent+4, detail-1);
Packit Service 3470d1
	(void)ExpectedLinkVerify(elinkp, 3, format, indent, detail);
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</Link>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Verify links in fabric against specified topology
Packit Service 3470d1
void ShowVerifyLinksReport(Point *focus, report_t report, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	LIST_ITEM *p;
Packit Service 3470d1
	uint32 counts[LINK_VERIFY_MAX+1] = {0};
Packit Service 3470d1
	uint32 port_errors = 0;
Packit Service 3470d1
	uint32 link_errors = 0;
Packit Service 3470d1
	uint32 fabric_checked = 0;
Packit Service 3470d1
	uint32 input_checked = 0;
Packit Service 3470d1
	char *xml_prefix = "";
Packit Service 3470d1
	char *prefix = "";
Packit Service 3470d1
	char *report_name = "";
Packit Service 3470d1
	LinkVerifyResult_t res;
Packit Service 3470d1
Packit Service 3470d1
	switch (report) {
Packit Service 3470d1
	default:	// should not happen, but just in case
Packit Service 3470d1
		ASSERT(0);
Packit Service 3470d1
	case REPORT_VERIFYLINKS:
Packit Service 3470d1
		report_name = "verifylinks";
Packit Service 3470d1
		xml_prefix = "";
Packit Service 3470d1
		prefix = "";
Packit Service 3470d1
		break;
Packit Service 3470d1
	case REPORT_VERIFYEXTLINKS:
Packit Service 3470d1
		report_name = "verifyextlinks";
Packit Service 3470d1
		xml_prefix = "Ext";
Packit Service 3470d1
		prefix = "External ";
Packit Service 3470d1
		break;
Packit Service 3470d1
	case REPORT_VERIFYFILINKS:
Packit Service 3470d1
		report_name = "verifyfilinks";
Packit Service 3470d1
		xml_prefix = "FI";
Packit Service 3470d1
		prefix = "FI ";
Packit Service 3470d1
		break;
Packit Service 3470d1
	case REPORT_VERIFYISLINKS:
Packit Service 3470d1
		report_name = "verifyislinks";
Packit Service 3470d1
		xml_prefix = "IS";
Packit Service 3470d1
		prefix = "Inter-Switch ";
Packit Service 3470d1
		break;
Packit Service 3470d1
	case REPORT_VERIFYEXTISLINKS:
Packit Service 3470d1
		report_name = "verifyextislinks";
Packit Service 3470d1
		xml_prefix = "ExtIS";
Packit Service 3470d1
		prefix = "External Inter-Switch ";
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	// intro for report
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*s%sLinks Topology Verification\n", indent, "", prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s<Verify%sLinks> \n", indent, "", xml_prefix, prefix);
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! g_topology_in_file) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: -T option not specified\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! (g_Fabric.flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS))) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: no LinkSummary nor ExternalLinkSummary information provided\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (0 == (report & (REPORT_VERIFYEXTLINKS|REPORT_VERIFYEXTISLINKS))
Packit Service 3470d1
		&& ((g_Fabric.flags & (FF_EXPECTED_LINKS|FF_EXPECTED_EXTLINKS)) == FF_EXPECTED_EXTLINKS)) {
Packit Service 3470d1
		fprintf(stderr, "opareport: Warning: %s requested, but only ExternalLinkSummary information provided\n", report_name);
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ELINK), format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	// First we look at all the fabric links
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*s%sLinks Found with incorrect configuration:\n", indent, "", prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "", prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (p=QListHead(&g_Fabric.AllPorts); p != NULL; p = QListNext(&g_Fabric.AllPorts, p)) {
Packit Service 3470d1
		PortData *portp1, *portp2;
Packit Service 3470d1
Packit Service 3470d1
		portp1 = (PortData *)QListObj(p);
Packit Service 3470d1
		// to avoid duplicated processing, only process "from" ports in link
Packit Service 3470d1
		if (! portp1->from)
Packit Service 3470d1
			continue;
Packit Service 3470d1
Packit Service 3470d1
		switch (report) {
Packit Service 3470d1
		default:	// should not happen, but just in case
Packit Service 3470d1
		case REPORT_VERIFYLINKS:
Packit Service 3470d1
			// process all links
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYEXTLINKS:
Packit Service 3470d1
			if (isInternalLink(portp1))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYFILINKS:
Packit Service 3470d1
			if (! isFILink(portp1))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYISLINKS:
Packit Service 3470d1
			if (! isISLink(portp1))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYEXTISLINKS:
Packit Service 3470d1
			if (isInternalLink(portp1))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			if (! isISLink(portp1))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
Packit Service 3470d1
		portp2 = portp1->neighbor;
Packit Service 3470d1
		// We process only links whose PortData or resolved ExpectedLink
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( ComparePortPoint(portp1, focus)
Packit Service 3470d1
				|| ComparePortPoint(portp2, focus)
Packit Service 3470d1
				|| (portp1->elinkp && CompareExpectedLinkPoint(portp1->elinkp, focus))
Packit Service 3470d1
				|| (portp2->elinkp && CompareExpectedLinkPoint(portp2->elinkp, focus))))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		fabric_checked++;
Packit Service 3470d1
		// detail=-1 in LinkFabricVerify will suppress its output
Packit Service 3470d1
		res = LinkFabricVerify(portp1, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != LINK_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (port_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowLinkBriefSummaryHeader(format, indent, detail-1);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowLinkVerifySummary(portp1, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			port_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && port_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Fabric Links Checked\n", indent, "",
Packit Service 3470d1
					fabric_checked, g_Fabric.LinkCount);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("FabricLinksChecked", fabric_checked, indent);
Packit Service 3470d1
		XmlPrintDec("TotalFabricLinks", g_Fabric.LinkCount, indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// now look at all the expected Links from the input topology
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*s%sLinks Expected but Missing, Duplicate in input or Incorrect:\n", indent, "", prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "", prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (p=QListHead(&g_Fabric.ExpectedLinks); p != NULL; p = QListNext(&g_Fabric.ExpectedLinks, p)) {
Packit Service 3470d1
		ExpectedLink *elinkp = (ExpectedLink *)QListObj(p);
Packit Service 3470d1
Packit Service 3470d1
		// do our best to filter expected links
Packit Service 3470d1
		// the is*ExpectedLink functions are purposely generously inclusive
Packit Service 3470d1
		switch (report) {
Packit Service 3470d1
		default:	// should not happen, but just in case
Packit Service 3470d1
		case REPORT_VERIFYLINKS:
Packit Service 3470d1
			// process all links
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYEXTLINKS:
Packit Service 3470d1
			if (! isExternalExpectedLink(elinkp))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYFILINKS:
Packit Service 3470d1
			if (! isFIExpectedLink(elinkp))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYISLINKS:
Packit Service 3470d1
			if (! isISExpectedLink(elinkp))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		case REPORT_VERIFYEXTISLINKS:
Packit Service 3470d1
			if (! isExternalExpectedLink(elinkp))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			if (! isISExpectedLink(elinkp))
Packit Service 3470d1
				continue;
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
Packit Service 3470d1
		// We process only elinks whose resolved ports or ExpectedLink
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( (elinkp->portp1 && ComparePortPoint(elinkp->portp1, focus))
Packit Service 3470d1
				|| (elinkp->portp2 && ComparePortPoint(elinkp->portp2, focus))
Packit Service 3470d1
				|| CompareExpectedLinkPoint(elinkp, focus)))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		input_checked++;
Packit Service 3470d1
		// detail=-1 in ExpectedLinkVerify will suppress its output
Packit Service 3470d1
		res = ExpectedLinkVerify(elinkp, 0, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != LINK_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (link_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowExpectedLinkBriefSummaryHeader(format, indent, detail-1);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowExpectedLinkVerifySummary(elinkp, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			link_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && link_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Input Links Checked\n", indent, "",
Packit Service 3470d1
					input_checked, QListCount(&g_Fabric.ExpectedLinks));
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("InputLinksChecked", input_checked, indent);
Packit Service 3470d1
		XmlPrintDec("TotalInputLinks", QListCount(&g_Fabric.ExpectedLinks), indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// final summary information
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*sTotal of %u Incorrect Links found\n", indent, "", port_errors+link_errors);
Packit Service 3470d1
		printf("%*s%u Missing, %u Unexpected, %u Misconnected, %u Duplicate, %u Different\n", indent, "",
Packit Service 3470d1
				counts[LINK_VERIFY_MISSING], counts[LINK_VERIFY_UNEXPECTED],
Packit Service 3470d1
				counts[LINK_VERIFY_CONN], counts[LINK_VERIFY_DUP],
Packit Service 3470d1
				counts[LINK_VERIFY_DIFF]);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("TotalLinksIncorrect", port_errors+link_errors, indent);
Packit Service 3470d1
		XmlPrintDec("Missing", counts[LINK_VERIFY_MISSING], indent);
Packit Service 3470d1
		XmlPrintDec("Unexpected", counts[LINK_VERIFY_UNEXPECTED], indent);
Packit Service 3470d1
		XmlPrintDec("Misconnected", counts[LINK_VERIFY_CONN], indent);
Packit Service 3470d1
		XmlPrintDec("Duplicate", counts[LINK_VERIFY_DUP], indent);
Packit Service 3470d1
		XmlPrintDec("Different", counts[LINK_VERIFY_DIFF], indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		DisplaySeparator();
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		indent-=4;
Packit Service 3470d1
		printf("%*s</Verify%sLinks>\n", indent, "", xml_prefix);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// verify a node against its corresponding ExpectedNode
Packit Service 3470d1
// Only valid to be called for SMs with ExpectedNode
Packit Service 3470d1
// returns FALSE if any discrepencies
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
boolean NodeVerify(NodeData *nodep, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ExpectedNode *enodep = nodep->enodep;
Packit Service 3470d1
	boolean ret=TRUE;
Packit Service 3470d1
Packit Service 3470d1
	ASSERT(enodep);
Packit Service 3470d1
	if (enodep->NodeGUID && enodep->NodeGUID != nodep->NodeInfo.NodeGUID) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64,
Packit Service 3470d1
			enodep->NodeGUID, nodep->NodeInfo.NodeGUID);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (enodep->NodeDesc
Packit Service 3470d1
		&& 0 != strncmp(enodep->NodeDesc,
Packit Service 3470d1
						(char*)nodep->NodeDesc.NodeString,
Packit Service 3470d1
						NODE_DESCRIPTION_ARRAY_SIZE)) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeDesc mismatch: expected: '%s' found: '%.*s'",
Packit Service 3470d1
			enodep->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE,
Packit Service 3470d1
			(char*)nodep->NodeDesc.NodeString);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (enodep->NodeType && enodep->NodeType != nodep->NodeInfo.NodeType) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeType mismatch: expected: %s found: %s",
Packit Service 3470d1
			StlNodeTypeToText(enodep->NodeType),
Packit Service 3470d1
			StlNodeTypeToText(nodep->NodeInfo.NodeType));
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
typedef enum {
Packit Service 3470d1
	NODE_VERIFY_OK = 0,	// node matches input topology
Packit Service 3470d1
	NODE_VERIFY_DIFF = 1, // node fully resolved but diff from input topology
Packit Service 3470d1
	NODE_VERIFY_UNEXPECTED = 2, // node not found in input topology
Packit Service 3470d1
	NODE_VERIFY_MISSING = 3, // node not found in fabric, but in input topology
Packit Service 3470d1
	NODE_VERIFY_DUP = 4, // possible duplicate in input topology
Packit Service 3470d1
	NODE_VERIFY_MAX=4	// maximum value of the above
Packit Service 3470d1
} NodeVerifyResult_t;
Packit Service 3470d1
Packit Service 3470d1
// check both fabric node against input topology
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
NodeVerifyResult_t NodeFabricVerify(NodeData *nodep, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	NodeVerifyResult_t ret = NODE_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	// all checks which are based off of found node in fabric
Packit Service 3470d1
	if (nodep->enodep) {
Packit Service 3470d1
		if (! NodeVerify(nodep, format, indent, detail))
Packit Service 3470d1
			ret = NODE_VERIFY_DIFF;
Packit Service 3470d1
	} else {
Packit Service 3470d1
		ret = NODE_VERIFY_UNEXPECTED; // extra node
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected %s",
Packit Service 3470d1
			StlNodeTypeToText(nodep->NodeInfo.NodeType));
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// compare ExpectedNode against fabric
Packit Service 3470d1
// NodeFabricVerify will have caught nodes which are different or extra
Packit Service 3470d1
// this is focused on duplicate ExpectedNodes or missing nodes
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
NodeVerifyResult_t ExpectedNodeVerify(ExpectedNode *enodep, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	NodeVerifyResult_t ret = NODE_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	if (! enodep->nodep) {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Missing %s",
Packit Service 3470d1
					StlNodeTypeToText(enodep->NodeType));
Packit Service 3470d1
		ret = NODE_VERIFY_MISSING;	// missing link
Packit Service 3470d1
	} else {
Packit Service 3470d1
		if (enodep->nodep->enodep != enodep) {
Packit Service 3470d1
			// duplicate node in input topology
Packit Service 3470d1
			ret = NODE_VERIFY_DUP;
Packit Service 3470d1
			ShowProblem(format, indent, detail, "Duplicate %s in input",
Packit Service 3470d1
					StlNodeTypeToText(enodep->NodeType));
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show fabric node verify errors
Packit Service 3470d1
void ShowNodeVerifySummary(NodeData *nodep, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ShowNodeBriefSummary(nodep, NULL, FALSE, format, indent, 0);
Packit Service 3470d1
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		indent +=4;
Packit Service 3470d1
	if (nodep->enodep && ! NodeVerify(nodep, format, indent, detail-1)) {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Node Attributes Inconsistent");
Packit Service 3470d1
	} else {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected %s",
Packit Service 3470d1
			StlNodeTypeToText(nodep->NodeInfo.NodeType));
Packit Service 3470d1
	}
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</Node>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show input node verify errors
Packit Service 3470d1
void ShowExpectedNodeVerifySummary(ExpectedNode *enodep, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ShowExpectedNodeBriefSummary("", enodep, "Node", FALSE, format, indent, detail-1);
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
	(void)ExpectedNodeVerify(enodep, format, indent, detail);
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</Node>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Verify nodes in fabric against specified topology
Packit Service 3470d1
void ShowVerifyNodesReport(Point *focus, uint8 NodeType, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	LIST_ITEM *p;
Packit Service 3470d1
	uint32 counts[NODE_VERIFY_MAX+1] = {0};
Packit Service 3470d1
	uint32 fabric_errors = 0;
Packit Service 3470d1
	uint32 input_errors = 0;
Packit Service 3470d1
	uint32 fabric_checked = 0;
Packit Service 3470d1
	uint32 input_checked = 0;
Packit Service 3470d1
	NodeVerifyResult_t res;
Packit Service 3470d1
	const char *NodeTypeText = StlNodeTypeToText(NodeType);
Packit Service 3470d1
	QUICK_LIST *fabric_listp;
Packit Service 3470d1
	QUICK_LIST *input_listp;
Packit Service 3470d1
Packit Service 3470d1
	switch (NodeType) {
Packit Service 3470d1
	case STL_NODE_FI:
Packit Service 3470d1
			fabric_listp = &g_Fabric.AllFIs;
Packit Service 3470d1
			input_listp = &g_Fabric.ExpectedFIs;
Packit Service 3470d1
			break;
Packit Service 3470d1
	case STL_NODE_SW:
Packit Service 3470d1
			fabric_listp = &g_Fabric.AllSWs;
Packit Service 3470d1
			input_listp = &g_Fabric.ExpectedSWs;
Packit Service 3470d1
			break;
Packit Service 3470d1
	default:
Packit Service 3470d1
			ASSERT(0);
Packit Service 3470d1
			break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// intro for report
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*s%ss Topology Verification\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s<Verify%ss> \n", indent, "", NodeTypeText, NodeTypeText);
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! g_topology_in_file) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: -T option not specified\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! (g_Fabric.flags & FF_EXPECTED_NODES)) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: no Nodes information provided\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ENODE), format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	// First we look at all the fabric nodes
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*s%ss Found with incorrect configuration:\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (p=QListHead(fabric_listp); p != NULL; p = QListNext(fabric_listp, p)) {
Packit Service 3470d1
		NodeData *nodep = (NodeData *)QListObj(p);
Packit Service 3470d1
Packit Service 3470d1
		// We process only nodes whose NodeData or resolved ExpectedNode
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( CompareNodePoint(nodep, focus)
Packit Service 3470d1
				|| (nodep->enodep && CompareExpectedNodePoint(nodep->enodep, focus))))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		fabric_checked++;
Packit Service 3470d1
		// detail=-1 in NodeFabricVerify will suppress its output
Packit Service 3470d1
		res = NodeFabricVerify(nodep, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != NODE_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (fabric_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					// use detail 0 so don't show Port stuff
Packit Service 3470d1
					ShowNodeBriefSummaryHeadings(format, indent, 0 /*detail-1*/);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowNodeVerifySummary(nodep, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			fabric_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && fabric_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Fabric %ss Checked\n", indent, "",
Packit Service 3470d1
					fabric_checked, QListCount(fabric_listp), NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		switch (NodeType) {
Packit Service 3470d1
		case STL_NODE_FI:
Packit Service 3470d1
			XmlPrintDec("FabricFIsChecked", fabric_checked, indent);
Packit Service 3470d1
			XmlPrintDec("TotalFabricFIs", QListCount(fabric_listp), indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		case STL_NODE_SW:
Packit Service 3470d1
			XmlPrintDec("FabricSWsChecked", fabric_checked, indent);
Packit Service 3470d1
			XmlPrintDec("TotalFabricSWs", QListCount(fabric_listp), indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// now look at all the expected Nodes from the input topology
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*s%ss Expected but Missing or Duplicate in input:\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (p=QListHead(input_listp); p != NULL; p = QListNext(input_listp, p)) {
Packit Service 3470d1
		ExpectedNode *enodep = (ExpectedNode *)QListObj(p);
Packit Service 3470d1
Packit Service 3470d1
		// We process only enodes whose resolved node or ExpectedNode
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( (enodep->nodep && CompareNodePoint(enodep->nodep, focus))
Packit Service 3470d1
				|| CompareExpectedNodePoint(enodep, focus)))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		input_checked++;
Packit Service 3470d1
		// detail=-1 in ExpectedNodeVerify will suppress its output
Packit Service 3470d1
		res = ExpectedNodeVerify(enodep, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != NODE_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (input_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					// use detail 0 so don't show Port stuff
Packit Service 3470d1
					ShowNodeBriefSummaryHeadings(format, indent, 0 /*detail-1*/);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowExpectedNodeVerifySummary(enodep, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			input_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && input_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Input %ss Checked\n", indent, "",
Packit Service 3470d1
					input_checked, QListCount(input_listp), NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		switch (NodeType) {
Packit Service 3470d1
		case STL_NODE_FI:
Packit Service 3470d1
			XmlPrintDec("InputFIsChecked", input_checked, indent);
Packit Service 3470d1
			XmlPrintDec("TotalInputFIs", QListCount(input_listp), indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		case STL_NODE_SW:
Packit Service 3470d1
			XmlPrintDec("InputSWsChecked", input_checked, indent);
Packit Service 3470d1
			XmlPrintDec("TotalInputSWs", QListCount(input_listp), indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// final summary information
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*sTotal of %u Incorrect %ss found\n", indent, "", fabric_errors+input_errors, NodeTypeText);
Packit Service 3470d1
		printf("%*s%u Missing, %u Unexpected, %u Duplicate, %u Different\n", indent, "",
Packit Service 3470d1
				counts[NODE_VERIFY_MISSING], counts[NODE_VERIFY_UNEXPECTED],
Packit Service 3470d1
				counts[NODE_VERIFY_DUP],
Packit Service 3470d1
				counts[NODE_VERIFY_DIFF]);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		switch (NodeType) {
Packit Service 3470d1
		case STL_NODE_FI:
Packit Service 3470d1
			XmlPrintDec("TotalFIsIncorrect", fabric_errors+input_errors, indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		case STL_NODE_SW:
Packit Service 3470d1
			XmlPrintDec("TotalSWsIncorrect", fabric_errors+input_errors, indent);
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		XmlPrintDec("Missing", counts[NODE_VERIFY_MISSING], indent);
Packit Service 3470d1
		XmlPrintDec("Unexpected", counts[NODE_VERIFY_UNEXPECTED], indent);
Packit Service 3470d1
		XmlPrintDec("Duplicate", counts[NODE_VERIFY_DUP], indent);
Packit Service 3470d1
		XmlPrintDec("Different", counts[NODE_VERIFY_DIFF], indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		DisplaySeparator();
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		indent-=4;
Packit Service 3470d1
		printf("%*s</Verify%ss>\n", indent, "", NodeTypeText);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// verify a SM against its corresponding ExpectedSM
Packit Service 3470d1
// Only valid to be called for nodes with ExpectedSM
Packit Service 3470d1
// returns FALSE if any discrepencies
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
boolean SMVerify(SMData *smp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ExpectedSM *esmp = smp->esmp;
Packit Service 3470d1
	boolean ret=TRUE;
Packit Service 3470d1
Packit Service 3470d1
	ASSERT(esmp);
Packit Service 3470d1
	if (esmp->NodeGUID && esmp->NodeGUID != smp->portp->nodep->NodeInfo.NodeGUID) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64,
Packit Service 3470d1
			esmp->NodeGUID, smp->portp->nodep->NodeInfo.NodeGUID);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (esmp->NodeDesc
Packit Service 3470d1
		&& 0 != strncmp(esmp->NodeDesc,
Packit Service 3470d1
						(char*)smp->portp->nodep->NodeDesc.NodeString,
Packit Service 3470d1
						NODE_DESCRIPTION_ARRAY_SIZE)) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeDesc mismatch: expected: '%s' found: '%.*s'",
Packit Service 3470d1
			esmp->NodeDesc, NODE_DESCRIPTION_ARRAY_SIZE,
Packit Service 3470d1
			(char*)smp->portp->nodep->NodeDesc.NodeString);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (esmp->gotPortNum && esmp->PortNum != smp->portp->PortNum) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"PortNum mismatch: expected: %3u found: %3u",
Packit Service 3470d1
			esmp->PortNum, smp->portp->PortNum);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (esmp->PortGUID && esmp->PortGUID != smp->portp->PortGUID) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"PortGuid mismatch: expected: 0x%016"PRIx64" found: 0x%016"PRIx64,
Packit Service 3470d1
			esmp->PortGUID, smp->portp->PortGUID);
Packit Service 3470d1
	}
Packit Service 3470d1
	if (esmp->NodeType && esmp->NodeType != smp->portp->nodep->NodeInfo.NodeType) {
Packit Service 3470d1
		ret = FALSE;
Packit Service 3470d1
		ShowProblem(format, indent, detail, 
Packit Service 3470d1
			"NodeType mismatch: expected: %s found: %s",
Packit Service 3470d1
			StlNodeTypeToText(esmp->NodeType),
Packit Service 3470d1
			StlNodeTypeToText(smp->portp->nodep->NodeInfo.NodeType));
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
typedef enum {
Packit Service 3470d1
	SM_VERIFY_OK = 0,	// SM matches input topology
Packit Service 3470d1
	SM_VERIFY_DIFF = 1, // SM fully resolved but diff from input topology
Packit Service 3470d1
	SM_VERIFY_UNEXPECTED = 2, // SM not found in input topology
Packit Service 3470d1
	SM_VERIFY_MISSING = 3, // SM not found in fabric, but in input topology
Packit Service 3470d1
	SM_VERIFY_DUP = 4, // possible duplicate in input topology
Packit Service 3470d1
	SM_VERIFY_MAX=4	// maximum value of the above
Packit Service 3470d1
} SMVerifyResult_t;
Packit Service 3470d1
Packit Service 3470d1
// check both fabric node against input topology
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
SMVerifyResult_t SMFabricVerify(SMData *smp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	SMVerifyResult_t ret = SM_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	// all checks which are based off of found SM in fabric
Packit Service 3470d1
	if (smp->esmp) {
Packit Service 3470d1
		if (! SMVerify(smp, format, indent, detail))
Packit Service 3470d1
			ret = SM_VERIFY_DIFF;
Packit Service 3470d1
	} else {
Packit Service 3470d1
		ret = SM_VERIFY_UNEXPECTED; // extra node
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected SM");
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// compare ExpectedSM against fabric
Packit Service 3470d1
// SMFabricVerify will have caught nodes which are different or extra
Packit Service 3470d1
// this is focused on duplicate ExpectedSMs or missing SMs
Packit Service 3470d1
// only does output if detail >= 0
Packit Service 3470d1
SMVerifyResult_t ExpectedSMVerify(ExpectedSM *esmp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	SMVerifyResult_t ret = SM_VERIFY_OK;
Packit Service 3470d1
Packit Service 3470d1
	if (! esmp->smp) {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Missing SM");
Packit Service 3470d1
		ret = SM_VERIFY_MISSING;	// missing link
Packit Service 3470d1
	} else {
Packit Service 3470d1
		if (esmp->smp->esmp != esmp) {
Packit Service 3470d1
			// duplicate node in input topology
Packit Service 3470d1
			ret = SM_VERIFY_DUP;
Packit Service 3470d1
			ShowProblem(format, indent, detail, "Duplicate SM in input");
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	return ret;
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show fabric SM verify errors
Packit Service 3470d1
void ShowSMVerifySummary(SMData *smp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ShowVerifySMBriefSummary(smp, FALSE, format, indent, 0);
Packit Service 3470d1
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		indent +=4;
Packit Service 3470d1
	if (smp->esmp && ! SMVerify(smp, format, indent, detail-1)) {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "SM Attributes Inconsistent");
Packit Service 3470d1
	} else {
Packit Service 3470d1
		ShowProblem(format, indent, detail, "Unexpected SM");
Packit Service 3470d1
	}
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</SM>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// show input SM verify errors
Packit Service 3470d1
void ShowExpectedSMVerifySummary(ExpectedSM *esmp, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	ShowExpectedSMBriefSummary("", esmp, "SM", FALSE, format, indent, detail-1);
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
	(void)ExpectedSMVerify(esmp, format, indent, detail);
Packit Service 3470d1
	if (format == FORMAT_XML)
Packit Service 3470d1
		printf("%*s</SM>\n", indent-4, "");
Packit Service 3470d1
}
Packit Service 3470d1
Packit Service 3470d1
// Verify SMs in fabric against specified topology
Packit Service 3470d1
void ShowVerifySMsReport(Point *focus, Format_t format, int indent, int detail)
Packit Service 3470d1
{
Packit Service 3470d1
	LIST_ITEM *p;
Packit Service 3470d1
	cl_map_item_t *ip;
Packit Service 3470d1
	uint32 counts[SM_VERIFY_MAX+1] = {0};
Packit Service 3470d1
	uint32 fabric_errors = 0;
Packit Service 3470d1
	uint32 input_errors = 0;
Packit Service 3470d1
	uint32 fabric_checked = 0;
Packit Service 3470d1
	uint32 input_checked = 0;
Packit Service 3470d1
	SMVerifyResult_t res;
Packit Service 3470d1
Packit Service 3470d1
	// intro for report
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*sSMs Topology Verification\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s<VerifySMs> \n", indent, "");
Packit Service 3470d1
		indent+=4;
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! g_topology_in_file) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: -T option not specified\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
	if (! (g_Fabric.flags & FF_EXPECTED_NODES)) {
Packit Service 3470d1
		switch (format) {
Packit Service 3470d1
		case FORMAT_TEXT:
Packit Service 3470d1
			printf("%*sReport skipped: no Nodes information provided\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		case FORMAT_XML:
Packit Service 3470d1
			printf("%*s\n", indent, "");
Packit Service 3470d1
			break;
Packit Service 3470d1
		default:
Packit Service 3470d1
			break;
Packit Service 3470d1
		}
Packit Service 3470d1
		goto done;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	ShowPointFocus(focus, (FIND_FLAG_FABRIC|FIND_FLAG_ESM), format, indent, detail);
Packit Service 3470d1
Packit Service 3470d1
	// First we look at all the fabric SMs
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("%*sSMs Found with incorrect configuration:\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (ip=cl_qmap_head(&g_Fabric.AllSMs); ip != cl_qmap_end(&g_Fabric.AllSMs); ip = cl_qmap_next(ip)) {
Packit Service 3470d1
		SMData *smp = PARENT_STRUCT(ip, SMData, AllSMsEntry);
Packit Service 3470d1
Packit Service 3470d1
		// We process only SMs whose SMData or resolved ExpectedSM
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( CompareSmPoint(smp, focus)
Packit Service 3470d1
				|| (smp->esmp && CompareExpectedSMPoint(smp->esmp, focus))))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		fabric_checked++;
Packit Service 3470d1
		// detail=-1 in SMFabricVerify will suppress its output
Packit Service 3470d1
		res = SMFabricVerify(smp, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != SM_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (fabric_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowVerifySMBriefSummaryHeadings(format, indent, detail-1);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowSMVerifySummary(smp, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			fabric_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && fabric_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Fabric SMs Checked\n", indent, "",
Packit Service 3470d1
					fabric_checked, (unsigned)cl_qmap_count(&g_Fabric.AllSMs));
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("FabricSMsChecked", fabric_checked, indent);
Packit Service 3470d1
		XmlPrintDec("TotalFabricSMs", (unsigned)cl_qmap_count(&g_Fabric.AllSMs), indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// now look at all the expected Nodes from the input topology
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*sSMs Expected but Missing or Duplicate in input:\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		printf("%*s\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
	for (p=QListHead(&g_Fabric.ExpectedSMs); p != NULL; p = QListNext(&g_Fabric.ExpectedSMs, p)) {
Packit Service 3470d1
		ExpectedSM *esmp = (ExpectedSM *)QListObj(p);
Packit Service 3470d1
Packit Service 3470d1
		// We process only ExpectedSMs whose resolved SMData or ExpectedSM
Packit Service 3470d1
		// match the focus
Packit Service 3470d1
		if (! ( (esmp->smp && CompareSmPoint(esmp->smp, focus))
Packit Service 3470d1
				|| CompareExpectedSMPoint(esmp, focus)))
Packit Service 3470d1
			continue;
Packit Service 3470d1
		input_checked++;
Packit Service 3470d1
		// detail=-1 in ExpectedSMVerify will suppress its output
Packit Service 3470d1
		res = ExpectedSMVerify(esmp, format, indent, -1);
Packit Service 3470d1
		counts[res]++;
Packit Service 3470d1
		if (res != SM_VERIFY_OK) {
Packit Service 3470d1
			if (detail) {
Packit Service 3470d1
				if (input_errors) {
Packit Service 3470d1
					if (format == FORMAT_TEXT) {
Packit Service 3470d1
						printf("\n");	// blank line between links
Packit Service 3470d1
					}
Packit Service 3470d1
				} else {
Packit Service 3470d1
					ShowVerifySMBriefSummaryHeadings(format, indent, detail-1);
Packit Service 3470d1
				}
Packit Service 3470d1
				ShowExpectedSMVerifySummary(esmp, format, indent, detail-1);
Packit Service 3470d1
			}
Packit Service 3470d1
			input_errors++;
Packit Service 3470d1
		}
Packit Service 3470d1
	}
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		if (detail && input_errors)
Packit Service 3470d1
			printf("\n");	// blank line between links
Packit Service 3470d1
		printf("%*s%u of %u Input SMs Checked\n", indent, "",
Packit Service 3470d1
					input_checked, QListCount(&g_Fabric.ExpectedSMs));
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("InputSMsChecked", input_checked, indent);
Packit Service 3470d1
		XmlPrintDec("TotalInputSMs", QListCount(&g_Fabric.ExpectedSMs), indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
	// final summary information
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		printf("\n%*sTotal of %u Incorrect SMs found\n", indent, "", fabric_errors+input_errors);
Packit Service 3470d1
		printf("%*s%u Missing, %u Unexpected, %u Duplicate, %u Different\n", indent, "",
Packit Service 3470d1
				counts[SM_VERIFY_MISSING], counts[SM_VERIFY_UNEXPECTED],
Packit Service 3470d1
				counts[SM_VERIFY_DUP],
Packit Service 3470d1
				counts[SM_VERIFY_DIFF]);
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		XmlPrintDec("TotalSMsIncorrect", fabric_errors+input_errors, indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
		XmlPrintDec("Missing", counts[SM_VERIFY_MISSING], indent);
Packit Service 3470d1
		XmlPrintDec("Unexpected", counts[SM_VERIFY_UNEXPECTED], indent);
Packit Service 3470d1
		XmlPrintDec("Duplicate", counts[SM_VERIFY_DUP], indent);
Packit Service 3470d1
		XmlPrintDec("Different", counts[SM_VERIFY_DIFF], indent);
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
Packit Service 3470d1
done:
Packit Service 3470d1
	switch (format) {
Packit Service 3470d1
	case FORMAT_TEXT:
Packit Service 3470d1
		DisplaySeparator();
Packit Service 3470d1
		break;
Packit Service 3470d1
	case FORMAT_XML:
Packit Service 3470d1
		indent-=4;
Packit Service 3470d1
		printf("%*s</VerifySMs>\n", indent, "");
Packit Service 3470d1
		break;
Packit Service 3470d1
	default:
Packit Service 3470d1
		break;
Packit Service 3470d1
	}
Packit Service 3470d1
}
Packit Service 3470d1