/* BEGIN_ICS_COPYRIGHT7 ****************************************
Copyright (c) 2015-2020, Intel Corporation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** END_ICS_COPYRIGHT7 ****************************************/
/* [ICS VERSION STRING: unknown] */
#include "topology.h"
#include "topology_internal.h"
#include <stl_helper.h>
/* this file supports fabric snapshot generation and parsing */
/****************************************************************************/
/* PortStatusData Input/Output functions */
/* bitfields needs special handling: LinkQualityIndicator */
static void PortStatusDataXmlOutputLinkQualityIndicator(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((STL_PORT_COUNTERS_DATA *)data)->lq.s.linkQualityIndicator);
}
static void PortStatusDataXmlParserEndLinkQualityIndicator(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_PORT_COUNTERS_DATA *)object)->lq.s.linkQualityIndicator = value;
}
IXML_FIELD PortStatusDataFields[] = {
{ tag:"XmitData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitData) },
{ tag:"RcvData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvData) },
{ tag:"XmitPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitPkts) },
{ tag:"RcvPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvPkts) },
{ tag:"MulticastXmitPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMulticastXmitPkts) },
{ tag:"MulticastRcvPkts", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMulticastRcvPkts) },
{ tag:"XmitWait", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWait) },
{ tag:"CongDiscards", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, swPortCongestion) },
{ tag:"RcvFECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvFECN) },
{ tag:"RcvBECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvBECN) },
{ tag:"XmitTimeCong", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitTimeCong) },
{ tag:"XmitWastedBW", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWastedBW) },
{ tag:"XmitWaitData", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitWaitData) },
{ tag:"RcvBubble", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvBubble) },
{ tag:"MarkFECN", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portMarkFECN) },
{ tag:"RcvConstraintErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvConstraintErrors) },
{ tag:"RcvSwitchRelayErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvSwitchRelayErrors) },
{ tag:"XmitDiscards", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitDiscards) },
{ tag:"XmitConstraintErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portXmitConstraintErrors) },
{ tag:"RcvRemotePhysicalErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvRemotePhysicalErrors) },
{ tag:"LocalLinkIntegrityErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, localLinkIntegrityErrors) },
{ tag:"RcvErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, portRcvErrors) },
{ tag:"ExcessiveBufferOverruns", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, excessiveBufferOverruns) },
{ tag:"FMConfigErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, fmConfigErrors) },
{ tag:"LinkErrorRecovery", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, linkErrorRecovery) },
{ tag:"LinkDowned", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, linkDowned) },
{ tag:"UncorrectableErrors", format:'U', IXML_FIELD_INFO(STL_PORT_COUNTERS_DATA, uncorrectableErrors) },
{ tag:"LinkQualityIndicator", format:'K', format_func:PortStatusDataXmlOutputLinkQualityIndicator, end_func:PortStatusDataXmlParserEndLinkQualityIndicator }, // bitfield
{ NULL }
};
void PortStatusDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (STL_PORT_COUNTERS_DATA *)data, NULL, PortStatusDataFields);
}
// only output if value != NULL
void PortStatusDataXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputOptionalStruct(state, tag, (STL_PORT_COUNTERS_DATA *)data, NULL, PortStatusDataFields);
}
static void PortStatusDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_PORT_COUNTERS_DATA *pPortCountersData = (STL_PORT_COUNTERS_DATA *)object;
PortData *portp = (PortData*)parent;
if (! valid) // missing mandatory fields
goto failvalidate;
if (portp->pPortCounters) {
IXmlParserPrintError(state, "More than 1 PortStatus for Port");
goto failinsert;
}
portp->pPortCounters = pPortCountersData;
// NumLanesDown is set in PortDataXmlParserEnd()
return;
failinsert:
failvalidate:
MemoryDeallocate(pPortCountersData);
}
/****************************************************************************/
/* QOS (SL2SCMap, SC2SLMap, SC2SCMap, VLArb Table) and PKey Table
* Input/Output functions
*/
uint8 ixVLArb; // Index for VLArb entry being parsed
uint8 vlVLArb; // VL for VLArb entry being parsed
uint8 ixPKey; // Index for P_Key entry being parsed
/****************************************************************************/
/* PortData SLtoSC Input/Output functions */
static void *SLtoSCMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW
&& portp->PortNum != 0) {
IXmlParserPrintError(state, "SLtoSCMap not valid for switch external ports");
return (NULL);
}
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
if (pQOS->SL2SCMap) {
IXmlParserPrintError(state, "SLtoSCMap improperly allocated");
return (NULL);
}
if ( !( pQOS->SL2SCMap = (STL_SLSCMAP *)MemoryAllocate2(
sizeof(STL_SLSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
memset(pQOS->SL2SCMap, 0xff, sizeof(STL_SLSCMAP));
return (pQOS->SL2SCMap);
} // End of SLtoSCMapXmlParserStart
static void SLtoSCMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of SLtoSCMapXmlParserEnd
static void *SLtoSCMapXmlParserStartSC(IXmlParserState_t *state, void *parent, const char **attr)
{
STL_SLSCMAP *pSLSC = (STL_SLSCMAP *)parent; // parent points to STL_SLSCMAP
uint8 sl;
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SL"))) {
IXmlParserPrintError(state, "Missing SL attribute for SLtoSCMap.SC");
return (NULL);
}
if (FSUCCESS != StringToUint8(&sl, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SL attribute in SLtoSCMap.SC SL: %s", attr[1]);
return (NULL);
}
if (sl >= STL_MAX_SLS) {
IXmlParserPrintError(state, "SL attribute Out-of-Range in SLtoSCMap.SC SL: %s", attr[1]);
return (NULL);
}
return &(pSLSC->SLSCMap[sl]);
} // End of SLtoSCMapXmlParserStartSC
static void SLtoSCMapXmlParserEndSC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_SLSCMAP *pSLSC = (STL_SLSCMAP *)parent; // parent points to STL_SLSCMAP
STL_SC *pSC = (STL_SC*)object; // object points to specific SLs entry
uint8 sl = pSC - pSLSC->SLSCMap;
uint8 sc;
if (! valid)
goto failvalidate;
if (!content || !len) {
IXmlParserPrintError(state, "No SC Value in SLtoSCMap.SC for SL %u", sl);
return;
}
if (FSUCCESS != StringToUint8(&sc, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SC Value in SLtoSCMap.SC for SL %u SC: %s", sl, content);
return;
}
if (sc >= STL_MAX_SCS) {
IXmlParserPrintError(state, "SC Out-of-range in SLtoSCMap.SC for SL:%u SC:%u", sl, sc);
return;
}
*((uint8 *)pSC) = sc;
return;
failvalidate:
// SLtoSCMapXmlParserEnd will free as needed
return;
} // End of SLtoSCMapXmlParserEndSC
IXML_FIELD SLtoSCMapSCFields[] = {
{ tag:"SC", format:'k', start_func:SLtoSCMapXmlParserStartSC, end_func:SLtoSCMapXmlParserEndSC },
{ NULL }
};
static void SLtoSCMapXmlOutputSLAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " SL=\"%u\"", *(uint8 *)data);
}
void SLtoSCMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
NodeData *nodep = portp->nodep;
STL_SLSCMAP *pSLSC = portp->pQOS->SL2SCMap;
uint8 sl;
// SL2SC only applicable to HFIs and switch port 0
ASSERT(nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum == 0);
IXmlOutputStartTag(state, tag);
for(sl = 0; sl < STL_MAX_SLS; sl++)
{
IXmlOutputStartAttrTag(state, "SC", &sl, SLtoSCMapXmlOutputSLAttr);
IXmlOutputPrint(state, "%u", pSLSC->SLSCMap[sl].SC);
IXmlOutputEndTag(state, "SC");
}
IXmlOutputEndTag(state, tag);
} // End of SLtoSCMapXmlOutput
/****************************************************************************/
/* PortData SCtoSL Input/Output functions */
static void *SCtoSLMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (portp->nodep->NodeInfo.NodeType == STL_NODE_SW
&& portp->PortNum != 0) {
IXmlParserPrintError(state, "SCtoSLMap not valid for switch external ports");
return (NULL);
}
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
if (pQOS->SC2SLMap) {
IXmlParserPrintError(state, "SCtoSLMap improperly allocated");
return (NULL);
}
if ( !( pQOS->SC2SLMap = (STL_SCSLMAP *)MemoryAllocate2AndClear(
sizeof(STL_SCSLMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
return (pQOS->SC2SLMap);
} // End of SCtoSLMapXmlParserStart
static void SCtoSLMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of SCtoSLMapXmlParserEnd
static void *SCtoSLMapXmlParserStartSL(IXmlParserState_t *state, void *parent, const char **attr)
{
STL_SCSLMAP *pSCSL = (STL_SCSLMAP *)parent; // parent points to STL_SCSLMAP
uint8 sc;
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) {
IXmlParserPrintError(state, "Missing SC attribute for SCtoSLMap.SL");
return (NULL);
}
if (FSUCCESS != StringToUint8(&sc, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SC attribute in SCtoSLMap.SL SC: %s", attr[1]);
return (NULL);
}
if (sc >= STL_MAX_SCS) {
IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoSLMap.SL SC: %s", attr[1]);
return (NULL);
}
return &(pSCSL->SCSLMap[sc]);
} // End of SCtoSLMapXmlParserStartSL
static void SCtoSLMapXmlParserEndSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_SCSLMAP *pSCSL = (STL_SCSLMAP *)parent; // parent points to STL_SCSLMAP
STL_SL *pSL = (STL_SL*)object; // object points to specific SCs entry
uint8 sc = pSL - pSCSL->SCSLMap;
uint8 sl;
if (! valid)
goto failvalidate;
if (!content || !len) {
IXmlParserPrintError(state, "No SL Value in SCtoSLMap.SL for SC %u", sc);
return;
}
if (FSUCCESS != StringToUint8(&sl, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SL Value in SCtoSLMap.SL for SC %u SL: %s", sc, content);
return;
}
if (sl >= STL_MAX_SLS) {
IXmlParserPrintError(state, "SL Out-of-range in SCtoSLMap.SL for SC:%u SL:%u", sc, sl);
return;
}
pSL->SL = sl;
return;
failvalidate:
// SCtoSLMapXmlParserEnd will free as needed
return;
} // End of SCtoSLMapXmlParserEndSL
IXML_FIELD SCtoSLMapSLFields[] = {
{ tag:"SL", format:'k', start_func:SCtoSLMapXmlParserStartSL, end_func:SCtoSLMapXmlParserEndSL },
{ NULL }
};
static void SCtoSLMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data);
}
void SCtoSLMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
NodeData *nodep = portp->nodep;
STL_SCSLMAP *pSCSL = portp->pQOS->SC2SLMap;
uint8 sc;
// SC2SL only applicable to HFIs and switch port 0
ASSERT(nodep->NodeInfo.NodeType != STL_NODE_SW || portp->PortNum == 0);
IXmlOutputStartTag(state, tag);
for(sc = 0; sc < STL_MAX_SCS; sc++)
{
IXmlOutputStartAttrTag(state, "SL", &sc, SCtoSLMapXmlOutputSCAttr);
IXmlOutputPrint(state, "%u", pSCSL->SCSLMap[sc].SL);
IXmlOutputEndTag(state, "SL");
}
IXmlOutputEndTag(state, tag);
} // End of SCtoSLMapXmlOutput
/****************************************************************************/
/* PortData SCtoSC Input/Output functions */
static void *SCtoSCMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
NodeData *nodep = portp->nodep;
QOSData *pQOS = portp->pQOS;
if (nodep->NodeInfo.NodeType != STL_NODE_SW) {
IXmlParserPrintError(state, "SCtoSCMap only valid for switches");
return (NULL);
}
if (portp->PortNum == 0) {
IXmlParserPrintError(state, "SCtoSCMap only valid for switch external ports");
return (NULL);
}
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
QListInitState(&pQOS->SC2SCMapList[0]);
if (!QListInit(&pQOS->SC2SCMapList[0])) {
IXmlParserPrintError(state, "Unable to initialize SC2SCMaps list");
MemoryDeallocate(pQOS);
return (NULL);
}
return (parent);
} // End of SCtoSCMapXmlParserStart
static void SCtoSCMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of SCtoSCMapXmlParserEnd
static void *SCtoSCMapXmlParserStartOutPort(IXmlParserState_t *state, void *parent, const char **attr)
{
PortMaskSC2SCMap *pSC2SC;
uint8_t outport;
if ( !attr || !attr[0] || ((0 != strcmp(attr[0], "ports")) && (0 != strcmp(attr[0], "port")))) {
IXmlParserPrintError(state, "Missing port attribute for SCtoSCMap.OutputPort");
return (NULL);
}
if (!(pSC2SC = (PortMaskSC2SCMap *)MemoryAllocate2AndClear(sizeof(PortMaskSC2SCMap), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
if (!(pSC2SC->SC2SCMap = (STL_SCSCMAP *)MemoryAllocate2AndClear(sizeof(STL_SCSCMAP), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) {
IXmlParserPrintError(state, "Unable to allocate memory");
MemoryDeallocate(pSC2SC);
return (NULL);
}
if (0 == strcmp(attr[0], "ports")) { // new format, parse the ports
if (FSUCCESS != StringToStlPortMask(pSC2SC->outports, attr[1])) {
IXmlParserPrintError(state, "Invalid ports list attribute in SCtoSCMap.OutputPorts: %s", attr[1]);
MemoryDeallocate(pSC2SC->SC2SCMap);
pSC2SC->SC2SCMap = NULL;
MemoryDeallocate(pSC2SC);
return NULL;
}
} else { // old format
if (FSUCCESS != StringToUint8(&outport, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid port list attribute in SCtoSCMap.OutputPort: %s", attr[1]);
MemoryDeallocate(pSC2SC->SC2SCMap);
pSC2SC->SC2SCMap = NULL;
MemoryDeallocate(pSC2SC);
return (NULL);
} // parser end function will combine single ports with the same tables
StlAddPortToPortMask(pSC2SC->outports, outport);
}
// Initialize the list entry
ListItemInitState(&pSC2SC->SC2SCMapListEntry);
QListSetObj(&pSC2SC->SC2SCMapListEntry, pSC2SC);
// Initialize all SCs to 15
memset(&pSC2SC->SC2SCMap->SCSCMap, 15, STL_MAX_SCS);
return (pSC2SC);
} // End of SCtoSCMapXmlParserStartOutPort
static void SCtoSCMapXmlParserEndOutPort(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
PortData *portp = (PortData *)parent; // parent points to PortData
PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)object; // object points to PortMaskSCSCMap
uint8_t numports, outport;
numports = StlNumPortsSetInPortMask(pSC2SC->outports, portp->nodep->NodeInfo.NumPorts);
// Insert into the maps list
if (numports == 1) {
// only one port
outport = StlGetFirstPortInPortMask(pSC2SC->outports);
QOSDataAddSCSCMap(portp, outport, 0, pSC2SC->SC2SCMap);
// clear out the unneeded stuff created in parser start
MemoryDeallocate(pSC2SC->SC2SCMap);
pSC2SC->SC2SCMap = NULL;
MemoryDeallocate(pSC2SC);
} else {
QListInsertTail(&portp->pQOS->SC2SCMapList[0], &pSC2SC->SC2SCMapListEntry);
}
if (! valid)
goto failvalidate;
return;
failvalidate:
// SCtoSCMapXmlParserEnd will free as needed
return;
} // End of SCtoSCMapXmlParserEndOutPort
static void *SCtoSCMapXmlParserStartOutPortSC(IXmlParserState_t *state, void *parent, const char **attr)
{
PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)parent; // parent points to PortMaskSCSCMap for given port mask
uint8 sc;
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) {
IXmlParserPrintError(state, "Missing SC attribute for SCtoSCMap.OutputPort.SC");
return (NULL);
}
if (FSUCCESS != StringToUint8(&sc, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SC attribute in SCtoSCMap.OutputPort.SC SC: %s", attr[1]);
return (NULL);
}
if (sc >= STL_MAX_SCS) {
IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoSCMap.outputPort.SC SC: %s", attr[1]);
return (NULL);
}
return &(pSC2SC->SC2SCMap->SCSCMap[sc]);
} // End of SCtoSCMapXmlParserStartOutPortSC
static void SCtoSCMapXmlParserEndOutPortSC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to STL_SCSCMAP for given output port
PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)parent; // parent points to PortMaskSCSCMap for given port mask
STL_SC *pSC = (STL_SC*)object; // object points to specific SCs entry
uint8 isc = pSC - pSC2SC->SC2SCMap->SCSCMap; // input SC
uint8 sc; // output SC
if (! valid)
goto failvalidate;
if (!content || !len) {
IXmlParserPrintError(state, "No SC Value in SCtoSCMap.OutputPort.SC for SC %u", isc);
return;
}
if (FSUCCESS != StringToUint8(&sc, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid SC' Value in SCtoSCMap.OutputPort.SC for SC %u SC': %s", isc, content);
return;
}
if (sc >= STL_MAX_SCS) {
IXmlParserPrintError(state, "SC Out-of-range in SCtoSCMap.OutputPort.SC for SC %u SC':%u", isc, sc);
return;
}
pSC->SC = sc;
return;
failvalidate:
// SCtoSCMapXmlParserEnd will free as needed
return;
} // End of SCtoSCMapXmlParserEndOutPortSC
IXML_FIELD SCtoSCMapOutPortSCFields[] = {
{ tag:"SC", format:'k', start_func:SCtoSCMapXmlParserStartOutPortSC, end_func:SCtoSCMapXmlParserEndOutPortSC },
{ NULL }
};
IXML_FIELD SCtoSCMapOutPortFields[] = {
{ tag:"OutputPort", format:'C', subfields:SCtoSCMapOutPortSCFields, start_func:SCtoSCMapXmlParserStartOutPort, end_func:SCtoSCMapXmlParserEndOutPort},
{ NULL }
};
static void SCtoSCMapXmlOutputPortAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " ports=\"%s\"", (char *)data);
}
static void SCtoSCMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data);
}
void SCtoSCMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
NodeData *nodep = portp->nodep;
LIST_ITEM *p;
uint8 sc;
// SC2SC only applicable to switch external ports
ASSERT(nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum != 0);
if (QListHead(&portp->pQOS->SC2SCMapList[0]) != NULL) {
IXmlOutputStartTag(state, tag);
for (p = QListHead(&portp->pQOS->SC2SCMapList[0]); p != NULL; p = QListNext(&portp->pQOS->SC2SCMapList[0], p)) {
PortMaskSC2SCMap *pSC2SC = (PortMaskSC2SCMap *)QListObj(p);
int buflen = portp->nodep->NodeInfo.NumPorts*3;
char buf[buflen];
FormatStlPortMask(buf, pSC2SC->outports, portp->nodep->NodeInfo.NumPorts, buflen);
IXmlOutputStartAttrTag(state, "OutputPort", &buf[7],
SCtoSCMapXmlOutputPortAttr);
for (sc = 0; sc < STL_MAX_SCS; sc++) {
// don't output mappings to SC15
if (sc == 0 || pSC2SC->SC2SCMap->SCSCMap[sc].SC != 15) {
IXmlOutputStartAttrTag(state, "SC", &sc, SCtoSCMapXmlOutputSCAttr);
IXmlOutputPrint(state, "%u", pSC2SC->SC2SCMap->SCSCMap[sc].SC);
IXmlOutputEndTag(state, "SC");
}
}
IXmlOutputEndTag(state, "OutputPort");
}
IXmlOutputEndTag(state, tag);
}
} // End of SCtoSCMapXmlOutput
/****************************************************************************/
/* PortData SCtoVLx Input/Output functions */
static void *SCtoVLxMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr, ScvlEnum_t scvlx)
{
PortData *portp = (PortData *)parent; // parent points to PortData
NodeData *nodep = (NodeData *)portp->nodep;
QOSData *pQOS = portp->pQOS;
if (scvlx == Enum_SCVLnt && nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum == 0) {
IXmlParserPrintError(state, "SCtoVLtMap not valid for Switch port 0");
return (NULL);
}
if (scvlx == Enum_SCVLr && !getIsVLrSupported(nodep, portp)) {
IXmlParserPrintError(state, "SCtoVLrMap not supported");
return (NULL);
}
if (!pQOS) {
if (!(pQOS = portp->pQOS = (QOSData*)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ))) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
return (&pQOS->SC2VLMaps[scvlx]);
} // End of SCtoVLxMapXmlParserStart
static void *SCtoVLrMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLr);
}
static void *SCtoVLtMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLt);
}
static void *SCtoVLntMapXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
return SCtoVLxMapXmlParserStart(state, parent, attr, Enum_SCVLnt);
}
static void SCtoVLxMapXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (!valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of SCtoVLxMapXmlParserEnd
static void *SCtoVLxMapXmlParserStartVLx(IXmlParserState_t *state, void *parent, const char **attr)
{
STL_SCVLMAP *pSCVL = (STL_SCVLMAP *)parent; // parent points to STL_SCVLMAP
uint8 sc;
if (!attr || !attr[0] || (0 != strcmp(attr[0], "SC"))) {
IXmlParserPrintError(state, "Missing SC attribute for SCtoVLMAp.VL");
return (NULL);
}
if (StringToUint8(&sc, attr[1], NULL, 0, TRUE) != FSUCCESS) {
IXmlParserPrintError(state, "Invalid SC attribute in SCtoVLMap.VL SC: %s", attr[1]);
return (NULL);
}
if (sc >= STL_MAX_SCS) {
IXmlParserPrintError(state, "SC attribute Out-of-Range in SCtoVLMap.VL SC: %s", attr[1]);
return (NULL);
}
return &(pSCVL->SCVLMap[sc]);
} // End of SCtoVLxMapXmlParserStartVLx
static void SCtoVLxMapXmlParserEndVLx(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_SCVLMAP *pSCVL = (STL_SCVLMAP *)parent; // parent points to STL_SCVLMAP
STL_VL *pVL = (STL_VL*)object; // object points to specific VLs entry
uint8 sc = pVL - pSCVL->SCVLMap;
uint8 vl;
if (!valid)
goto failvalidate;
if (!content || !len) {
IXmlParserPrintError(state, "No VL Value in SCtoVLMap.VL for SC %u", sc);
return;
}
if (StringToUint8(&vl, content, NULL, 0, TRUE) != FSUCCESS) {
IXmlParserPrintError(state, "Invalid VL Value in SCtoVLMap.VL for SC: %u VL: %s", sc, content);
return;
}
if (vl >= STL_MAX_VLS) {
IXmlParserPrintError(state, "VL Out-of-range in SCtoVLMap.VL for SC: %u VL: %u", sc, vl);
return;
}
pVL->VL = vl;
return;
failvalidate:
// SCtoVLMapXmlParserEnd will free as needed
return;
}
IXML_FIELD SCtoVLrMapVLrFields[] = {
{ tag:"VLr", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx },
{ NULL }
};
IXML_FIELD SCtoVLtMapVLtFields[] = {
{ tag:"VLt", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx },
{ NULL }
};
IXML_FIELD SCtoVLntMapVLntFields[] = {
{ tag:"VLnt", format:'k', start_func:SCtoVLxMapXmlParserStartVLx, end_func:SCtoVLxMapXmlParserEndVLx },
{ NULL }
};
static void SCtoVLxMapXmlOutputSCAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " SC=\"%u\"", *(uint8 *)data);
}
void SCtoVLxMapXmlOutput(IXmlOutputState_t *state, const char *tag, void *data, ScvlEnum_t scvlx)
{
PortData *portp = (PortData *)data; // data points to PortData
NodeData *nodep = portp->nodep;
STL_SCVLMAP *pSCVL = &(portp->pQOS->SC2VLMaps[scvlx]);
uint8 sc;
char *vlname = "VL";
switch (scvlx) {
case Enum_SCVLr: vlname = "VLr";
break;
case Enum_SCVLt: vlname = "VLt";
break;
case Enum_SCVLnt: vlname = "VLnt";
break;
}
// SC2VLnt doesn't apply to switch port 0
ASSERT(!(scvlx == Enum_SCVLnt && nodep->NodeInfo.NodeType == STL_NODE_SW && portp->PortNum == 0));
ASSERT(!(scvlx == Enum_SCVLr && !getIsVLrSupported(nodep, portp)));
IXmlOutputStartTag(state, tag);
for(sc = 0; sc < STL_MAX_SCS; sc++)
{
IXmlOutputStartAttrTag(state, vlname, &sc, SCtoVLxMapXmlOutputSCAttr);
IXmlOutputPrint(state, "%u", pSCVL->SCVLMap[sc].VL);
IXmlOutputEndTag(state, vlname);
}
IXmlOutputEndTag(state, tag);
} // End of SCtoVLxMapXmlOutput
/****************************************************************************/
/* PortData VLArbitration Weight Input/Output functions */
static void *VLArbXmlParserStartWeight(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to STL_VLARB_TABLE
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute for VLArbitration Weight");
return (NULL);
}
if (FSUCCESS != StringToUint8(&vlVLArb, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in VLArbitration Weight VL: %s", attr[1]);
return (NULL);
}
if (vlVLArb >= STL_MAX_VLS) {
IXmlParserPrintError( state,
"VL attribute Out-of-range in VLArbitration Weight VL: %s", attr[1] );
return (NULL);
}
// ideally we could return &pVLArbTable->Elements[ixVLArb]
// and even save vVLArb in the entry here.
// but we need to keep ixVLArb so we can increment it
// so we simply keep ixVLArb and vlVLArb in globals and don't really use
// "object" as our return
return (parent);
} // End of VLArbXmlParserStartWeight
static void VLArbXmlParserEndWeight(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to STL_VLARB_TABLE
STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent;
uint8 weight;
if (! valid)
goto failvalidate;
// Assign VLArbTable->ArbTable[ixVLArb] = vl,weight
if (!content || !len) {
IXmlParserPrintError(state, "No Weight Value in VLArbitration Weight for VL %u", vlVLArb);
return;
}
if (FSUCCESS != StringToUint8(&weight, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid Weight Value in VLArbitration Weight for VL %u Weight: %s", vlVLArb, content);
return;
}
pVLArb->Elements[ixVLArb].s.VL = vlVLArb;
pVLArb->Elements[ixVLArb].Weight = weight;
ixVLArb++;
return;
failvalidate:
// VLArb*XmlParserEnd will free as needed
return;
} // End of VLArbXmlParserEndWeight
IXML_FIELD VLArbFields[] = {
{ tag:"Weight", format:'k', start_func:VLArbXmlParserStartWeight, end_func:VLArbXmlParserEndWeight},
{ NULL }
};
static void VLArbXmlOutputVLAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " VL=\"%u\"", *(uint8 *)data);
}
void VLArbXmlOutput(IXmlOutputState_t *state, const char *tag, void *data, int capacity)
{
int ix;
uint8 vl;
STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE*)data;
IXmlOutputStartTag(state, tag);
for(ix = 0; ix < capacity; ix++)
{
vl = pVLArb->Elements[ix].s.VL;
IXmlOutputStartAttrTag(state, "Weight", &vl, VLArbXmlOutputVLAttr);
IXmlOutputPrint(state, "%u", pVLArb->Elements[ix].Weight);
IXmlOutputEndTag(state, "Weight");
}
IXmlOutputEndTag(state, tag);
} // End of VLArbXmlOutput
/****************************************************************************/
/* PortData VLArbitrationLow Input/Output functions */
static void *VLArbLowXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
ixVLArb = 0;
return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_LOW_ELEMENTS]));
} // End of VLArbLowXmlParserStart
static void VLArbLowXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of VLArbLowXmlParserEnd
void VLArbLowXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable;
VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_LOW_ELEMENTS],
portp->PortInfo.VL.ArbitrationLowCap);
} // End of VLArbLowXmlOutput
/****************************************************************************/
/* PortData VLArbitrationHigh Input/Output functions */
static void *VLArbHighXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
ixVLArb = 0;
return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_HIGH_ELEMENTS]));
} // End of VLArbHighXmlParserStart
static void VLArbHighXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of VLArbHighXmlParserEnd
void VLArbHighXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable;
VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_HIGH_ELEMENTS],
portp->PortInfo.VL.ArbitrationHighCap);
} // End of VLArbHighXmlOutput
/****************************************************************************/
/* PortData VLArbitrationPreemptElements Input/Output functions */
static void *VLArbPreemptElementsXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
ixVLArb = 0;
return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_PREEMPT_ELEMENTS]));
} // End of VLArbPreemptElementsXmlParserStart
static void VLArbPreemptElementsXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of VLArbPreemptElementsXmlParserEnd
void VLArbPreemptElementsXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable;
VLArbXmlOutput(state, tag, &pVLArb[STL_VLARB_PREEMPT_ELEMENTS],
STL_MAX_PREEMPT_CAP);
} // End of VLArbPreemptElementsXmlOutput
/****************************************************************************/
/* PortData VLArbitrationPreemptMatrix Input/Output functions */
static void *VLArbPreemptMatrixXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
QOSData *pQOS = portp->pQOS;
if (!pQOS) {
if ( !( pQOS = portp->pQOS = (QOSData *)MemoryAllocate2AndClear(
sizeof(QOSData), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
}
return ((void *)&(pQOS->u.VLArbTable[STL_VLARB_PREEMPT_MATRIX]));
} // End of VLArbPreemptMatrixXmlParserStart
static void VLArbPreemptMatrixXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreeQOSData(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of VLArbPreemptMatrixXmlParserEnd
static void *VLArbPreemptMatrixXmlParserStartEntry(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to VLARBTABLE for PreemptMatrix
STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent;
uint8 vl;
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute for VLArbitrationPreemptMatrix.MatrixEntry");
return (NULL);
}
if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in VLArbitrationPreemptMatrix.MatrixEntry VL: %s", attr[1]);
return (NULL);
}
if (vl >= STL_MAX_VLS) {
IXmlParserPrintError( state,
"VL attribute Out-of-range in VLArbitrationPreemptMatrix.MatrixEntry VL:%u", vl );
return (NULL);
}
return &(pVLArb->Matrix[vl]);
} // End of VLArbPreemptMatrixXmlParserStartEntry
static void VLArbPreemptMatrixXmlParserEndEntry(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to VLARBTABLE for PreemptMatrix
STL_VLARB_TABLE *pVLArb = (STL_VLARB_TABLE *)parent;
// object points to PreemptMatrix entry for specific VL
uint32 *pEntry = (uint32 *)object;
uint32 vl = pEntry - pVLArb->Matrix;
uint32 value;
if (! valid)
goto failvalidate;
if (!content || !len) {
IXmlParserPrintError(state, "No entry in VLArbitrationPreemptMatrix.MatrixEntry for VL %u", vl);
return;
}
if (FSUCCESS != StringToUint32(&value, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid entry in VLArbitrationPreemptMatrix.MatrixEntry for VL %u MatrixEntry: %s", vl, content);
return;
}
*pEntry = value;
return;
failvalidate:
// VLArbPreemptMatrixXmlParserEnd will free as needed
return;
}
IXML_FIELD VLArbPreemptMatrixFields[] = {
{ tag:"MatrixEntry", format:'k', start_func:VLArbPreemptMatrixXmlParserStartEntry, end_func:VLArbPreemptMatrixXmlParserEndEntry },
{ NULL }
};
void VLArbPreemptMatrixXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
uint8 ix;
PortData *portp = (PortData *)data; // data points to PortData
STL_VLARB_TABLE *pVLArb = portp->pQOS->u.VLArbTable;
IXmlOutputStartTag(state, tag);
for(ix = 0; ix < STL_MAX_VLS; ix++)
{
IXmlOutputStartAttrTag(state, "MatrixEntry", &ix, VLArbXmlOutputVLAttr);
IXmlOutputPrint(state, "%u", pVLArb[STL_VLARB_PREEMPT_MATRIX].Matrix[ix]);
IXmlOutputEndTag(state, "MatrixEntry");
}
IXmlOutputEndTag(state, tag);
} // end of VLArbPreemptMatrixXmlOutput
/****************************************************************************/
/* PortData PKeyTable Input/Output functions */
static void *PKeyTableXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
STL_PKEY_ELEMENT *pPartitionTable;
uint32 num_pkeys;
if (portp->pPartitionTable) {
IXmlParserPrintError(state, "PKeyTable improperly allocated");
return (NULL);
}
num_pkeys = PortPartitionTableSize(portp);
if ( !( pPartitionTable = portp->pPartitionTable = (STL_PKEY_ELEMENT *)MemoryAllocate2AndClear(
sizeof(STL_PKEY_ELEMENT) * num_pkeys, IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
ixPKey = 0;
return ((void *)pPartitionTable);
} // End of PKeyTableXmlParserStart
static void PKeyTableXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData
if (! valid)
goto failvalidate;
return;
failvalidate:
PortDataFreePartitionTable(IXmlParserGetContext(state), (PortData *)parent);
return;
} // End of PKeyTableXmlParserEnd
static void *PKeyTableXmlParserStartPKey(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to PKeyTable
return (parent);
} // End of PKeyTableXmlParserStartPKey
static void PKeyTableXmlParserEndPKey(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PKeyTable
STL_PKEY_ELEMENT *pPartitionTable = (STL_PKEY_ELEMENT *)parent;
uint16 pkey;
if (! valid)
goto failvalidate;
// Assign pPartitionTable[ixPKey] = pkey
if (!content || !len) {
IXmlParserPrintError(state, "No PKey Value in PKeyTable.PKey");
return;
}
if (FSUCCESS != StringToUint16(&pkey, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid PKey Value in PKeyTable.PKey: %s", content);
return;
}
pPartitionTable[ixPKey].AsReg16 = pkey;
ixPKey++;
return;
failvalidate:
// PKeyTableXmlParserEnd will free as needed
return;
} // End of PKeyTableXmlParserEndPKey
IXML_FIELD PKeyTableFields[] = {
{ tag:"PKey", format:'k', start_func:PKeyTableXmlParserStartPKey, end_func:PKeyTableXmlParserEndPKey },
{ NULL }
};
void PKeyTableXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
int ix, last=0;
PortData *portp = (PortData *)data; // data points to PortData
STL_PKEY_ELEMENT *pPKey = portp->pPartitionTable;
int ix_capacity = PortPartitionTableSize(portp);
IXmlOutputStartTag(state, tag);
// find the last non-zero pkey in the table
// we will output all pkeys, even if zero, up to the last
// so that we properly retain the pkey indexes
for (ix = 0; ix < ix_capacity; ix++)
{
if (pPKey[ix].AsReg16 & 0x7FFF)
last = ix;
}
for (ix = 0; ix <= last; ix++)
{
IXmlOutputHexPad16(state, "PKey", pPKey[ix].AsReg16);
}
IXmlOutputEndTag(state, tag);
} // End of PKeyTableXmlOutput
/****************************************************************************/
/* PortData Input/Output functions */
static void PortDataXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
PortData *portp = (PortData *)data;
IXmlOutputPrint(state, " id=\"0x%016"PRIx64":%u\"", portp->nodep->NodeInfo.NodeGUID, portp->PortNum);
}
/* bitfields needs special handling: LID */
static void PortDataXmlOutputEndPortLID(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLIDValue(state, tag, ((PortData *)data)->EndPortLID);
}
static void PortDataXmlParserEndEndPortLID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((PortData *)object)->EndPortLID = value;
}
/* bitfields needs special handling: PortState */
static void PortDataXmlOutputPortState(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputPortStateValue(state, tag, ((PortData *)data)->PortInfo.PortStates.s.PortState);
}
static void PortDataXmlParserEndPortState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData *)object)->PortInfo.PortStates.s.PortState = value;
}
/* bitfields needs special handling: InitReason */
static void PortDataXmlOutputInitReason(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputInitReasonValue(state, tag, ((PortData *)data)->PortInfo.s3.LinkInitReason);
}
static void PortDataXmlParserEndInitReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData *)object)->PortInfo.s3.LinkInitReason = value;
}
/* bitfields needs special handling: PortPhysicalState */
static void PortDataXmlOutputPhysState(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputPortPhysStateValue(state, tag, ((PortData *)data)->PortInfo.PortStates.s.PortPhysicalState);
}
static void PortDataXmlOutputPortPhysConfig(IXmlOutputState_t *state, const char *tag, void *data)
{
const uint8_t pt = ((PortData *)data)->PortInfo.PortPhysConfig.s.PortType;
IXmlOutputStr(state, tag, StlPortTypeToText(pt));
}
static void PortDataXmlParserEndPhysState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData *)object)->PortInfo.PortStates.s.PortPhysicalState = value;
}
/* bitfields needs special handling: LMC */
static void PortDataXmlOutputLMC(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((PortData *)data)->PortInfo.s1.LMC);
}
static void PortDataXmlParserEndLMC(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData *)object)->PortInfo.s1.LMC = value;
}
/* bitfields needs special handling: M_KeyProtectBits */
static void PortDataXmlOutputMKeyProtect(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputMKeyProtectValue(state, tag, ((PortData *)data)->PortInfo.s1.M_KeyProtectBits);
}
static void PortDataXmlParserEndMKeyProtect(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData *)object)->PortInfo.s1.M_KeyProtectBits = value;
}
/* special handling: LinkWidthEnabled */
static void PortDataXmlOutputLinkWidthEnabled(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidth.Enabled);
}
/* special handling: LinkWidthSupportedd */
static void PortDataXmlOutputLinkWidthSupported(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidth.Supported);
}
/* special handling: LinkWidthActive */
static void PortDataXmlOutputLinkWidthActive(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidth.Active);
}
/* special handling: LinkWidthEnabled */
static void PortDataXmlOutputLinkWidthDowngradeEnabled(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidthDowngrade.Enabled);
}
/* special handling: LinkWidthSupportedd */
static void PortDataXmlOutputLinkWidthDowngradeSupported(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidthDowngrade.Supported);
}
/* special handling: LinkWidthTxActive */
static void PortDataXmlOutputLinkWidthDowngradeTxActive(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidthDowngrade.TxActive);
}
/* special handling: LinkWidthRxActive */
static void PortDataXmlOutputLinkWidthDowngradeRxActive(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkWidthValue(state, tag,
((PortData*)data)->PortInfo.LinkWidthDowngrade.RxActive);
}
/* bitfields needs special handling: LinkSpeedSupported */
static void PortDataXmlOutputLinkSpeedSupported(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Supported);
}
static void PortDataXmlParserEndLinkSpeedSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
if (IXmlParseUint16(state, content, len, &value))
((PortData*)object)->PortInfo.LinkSpeed.Supported = value;
}
/* bitfields needs special handling: LinkSpeedEnabled */
static void PortDataXmlOutputLinkSpeedEnabled(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Enabled);
}
static void PortDataXmlParserEndLinkSpeedEnabled(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
if (IXmlParseUint16(state, content, len, &value))
((PortData*)object)->PortInfo.LinkSpeed.Enabled = value;
}
/* bitfields needs special handling: LinkSpeedActive */
static void PortDataXmlOutputLinkSpeedActive(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLinkSpeedValue( state, tag, ((PortData*)data)->PortInfo.LinkSpeed.Active);
}
static void PortDataXmlParserEndLinkSpeedActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
if (IXmlParseUint16(state, content, len, &value))
((PortData*)object)->PortInfo.LinkSpeed.Active = value;
}
static void PortDataXmlOutputMTUActiveVLAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data);
}
static void PortDataXmlOutputMTUs(IXmlOutputState_t *state, const char *tag, void *data)
{
int outputVL;
IXmlOutputStartTag(state, tag);
for(outputVL = 0; outputVL < STL_MAX_VLS; outputVL++)
{
IXmlOutputStartAttrTag(state, "MTUActive", &outputVL, PortDataXmlOutputMTUActiveVLAttr);
IXmlOutputPrint(state, "%04u", GetBytesFromMtu(GET_STL_PORT_INFO_NeighborMTU(&(((PortData*)data)->PortInfo), outputVL)));
IXmlOutputEndTag(state, "MTUActive");
}
IXmlOutputEndTag(state, tag);
} // End of PortDataXmlOutputMTUs
static void *PortDataXmlParserStartMTUActive(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to PortData
/* since MTUActives don't nest, we can get away with a single static */
/* since VL is selector for a packed array of 4 bits fields, can't return
* pointer to actual field
*/
static uint8 mtuVL;
if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute for MTUActive");
return NULL;
}
if (FSUCCESS != StringToUint8(&mtuVL, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in MTUActive: %s", attr[1]);
return NULL;
}
if (mtuVL >= STL_MAX_VLS) {
IXmlParserPrintError(state, "VL attribute Out-of-Range in MTUActive: %s", attr[1]);
return (NULL);
}
return &mtuVL;
} // End of PortDataXmlParserStartMTUActive
static void PortDataXmlParserEndMTUActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
PortData *portp = (PortData *)parent; // parent points to PortData
uint8 mtuVL = *(uint8*)object;
uint16 value;
if(IXmlParseUint16(state, content, len, &value))
PUT_STL_PORT_INFO_NeighborMTU(&(portp->PortInfo), mtuVL, GetMtuFromBytes(value));
} // End of PortDataXmlParserEndMTUActive
IXML_FIELD PortDataMTUActiveXmlFields[] = {
{ tag:"MTUActive", format:'k', start_func:PortDataXmlParserStartMTUActive, end_func:PortDataXmlParserEndMTUActive },
{ NULL }
};
/* bitfields needs special handling: MTUSupported */
static void PortDataXmlOutputMTUSupported(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputMtuValue(state, tag,
((PortData*)data)->PortInfo.MTU.Cap);
}
static void PortDataXmlParserEndMTUSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
if (IXmlParseUint16(state, content, len, &value))
((PortData*)object)->PortInfo.MTU.Cap = GetMtuFromBytes(value);
}
/* bitfields needs special handling: SMSL */
static void PortDataXmlOutputSMSL(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag,
((PortData*)data)->PortInfo.s2.MasterSMSL);
}
static void PortDataXmlParserEndSMSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.s2.MasterSMSL = value;
}
/* bitfields needs special handling: VLsActive */
static void PortDataXmlOutputVLsActive(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputVLsValue(state, tag,
((PortData*)data)->PortInfo.s4.OperationalVL);
}
static void PortDataXmlParserEndVLsActive(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.s4.OperationalVL = value;
}
/* bitfields needs special handling: VLsSupported */
static void PortDataXmlOutputVLsSupported(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputVLsValue(state, tag,
((PortData*)data)->PortInfo.VL.s2.Cap);
}
static void PortDataXmlParserEndVLsSupported(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.VL.s2.Cap = value;
}
/* VLStall */
static void PortDataXmlOutputVLStallVLAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data);
}
static void PortDataXmlOutputVLStalls(IXmlOutputState_t *state, const char *tag, void *data)
{
uint8 vl;
IXmlOutputStartTag(state, tag);
for(vl = 0; vl < STL_MAX_VLS; vl++)
{
IXmlOutputStartAttrTag(state, "VLStall", &vl, PortDataXmlOutputVLStallVLAttr);
IXmlOutputPrint(state, "%u", ((PortData*)data)->PortInfo.XmitQ[vl].VLStallCount);
IXmlOutputEndTag(state, "VLStall");
}
IXmlOutputEndTag(state, tag);
}
static void *PortDataXmlParserStartVLStall(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to PortData
uint8 vl;
if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute for VLStall");
return NULL;
}
if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in VLStall: %s", attr[1]);
return NULL;
}
if (vl >= STL_MAX_VLS) {
IXmlParserPrintError(state, "VL attribute Out-of-Range in VLStall: %s", attr[1]);
return (NULL);
}
return &((PortData *)parent)->PortInfo.XmitQ[vl];
} // End of PortDataXmlParserStartVLStall
static void PortDataXmlParserEndVLStall(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData, object points to VL specific XmitQ_s
struct XmitQ_s *xmitQ = (struct XmitQ_s*)object;
uint8 value;
if(IXmlParseUint8(state, content, len, &value))
xmitQ->VLStallCount = value;
} // End of PortDataXmlParserEndVLStall
IXML_FIELD PortDataVLStallXmlFields[] = {
{ tag:"VLStall", format:'k', start_func:PortDataXmlParserStartVLStall, end_func:PortDataXmlParserEndVLStall },
{ NULL }
};
/* bitfields needs special handling: MulticastMask */
static void PortDataXmlOutputMulticastMask(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHex(state, tag,
((PortData*)data)->PortInfo.MultiCollectMask.MulticastMask);
}
static void PortDataXmlParserEndMulticastMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.MultiCollectMask.MulticastMask = value;
}
/* bitfields needs special handling: CollectiveMask */
static void PortDataXmlOutputCollectiveMask(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHex(state, tag,
((PortData*)data)->PortInfo.MultiCollectMask.CollectiveMask);
}
static void PortDataXmlParserEndCollectiveMask(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.MultiCollectMask.CollectiveMask = value;
}
/* HoQLife */
static void PortDataXmlOutputHoQLifeVLAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " VL=\"%02u\"", *(uint8 *) data);
}
static void PortDataXmlOutputHoQLifes(IXmlOutputState_t *state, const char *tag, void *data)
{
uint8 vl;
IXmlOutputStartTag(state, tag);
for(vl = 0; vl < STL_MAX_VLS; vl++)
{
IXmlOutputStartAttrTag(state, "HoQLife_Int", &vl, PortDataXmlOutputHoQLifeVLAttr);
IXmlOutputPrint(state, "%u", ((PortData*)data)->PortInfo.XmitQ[vl].HOQLife);
IXmlOutputEndTag(state, "HoQLife_Int");
}
IXmlOutputEndTag(state, tag);
}
static void *PortDataXmlParserStartHoQLife(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to PortData
uint8 vl;
if( !attr | !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute for HoQLife");
return NULL;
}
if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in HoQLife: %s", attr[1]);
return NULL;
}
if (vl >= STL_MAX_VLS) {
IXmlParserPrintError(state, "VL attribute Out-of-Range in HoQLife: %s", attr[1]);
return (NULL);
}
return &((PortData *)parent)->PortInfo.XmitQ[vl];
} // End of PortDataXmlParserStartHoQLife
static void PortDataXmlParserEndHoQLife(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to PortData, object points to VL specific XmitQ_s
struct XmitQ_s *xmitQ = (struct XmitQ_s*)object;
uint8 value;
if(IXmlParseUint8(state, content, len, &value))
xmitQ->HOQLife = value;
} // End of PortDataXmlParserEndHoQLife
IXML_FIELD PortDataHoQLifeXmlFields[] = {
//{ tag:"HoQLife", format:'k', format_func: PortDataXmlOutputHoQLife, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"HoQLife_Int", format:'K', format_func: IXmlOutputNoop, start_func:PortDataXmlParserStartHoQLife, end_func:PortDataXmlParserEndHoQLife }, // input only bitfield
{ NULL }
};
static void PortDataXmlOutputNeighborMTU(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData * portp = (PortData *)data;
STL_VL_TO_MTU * table = portp->PortInfo.NeighborMTU;
uint8_t len = sizeof(portp->PortInfo.NeighborMTU) / sizeof(portp->PortInfo.NeighborMTU[0]);
uint8_t i;
for(i = 0; i < len; i++)
{
IXmlOutputStartTag(state, "NeighborMTU");
IXmlOutputAttrFmt(state, "VL", "%u", i);
IXmlOutputPrint(state, "0x%02x", table[i].AsReg8);
IXmlOutputEndTag( state, "NeighborMTU");
}
}
static void * PortDataXmlParserStartNeighborMtu(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData * portp = (PortData *)parent;
uint8_t len = sizeof(portp->PortInfo.NeighborMTU) / sizeof(portp->PortInfo.NeighborMTU[0]);
uint8_t i = 0;
if (!attr || !attr[0] || 0 != strcmp(attr[0], "VL")) {
IXmlParserPrintError(state, "Missing VL attribute for delay element");
return NULL;
}
if (FSUCCESS != StringToUint8(&i, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL in Neighbor MTU element: index:%s", attr[1]);
return NULL;
}
if (i >= len) {
IXmlParserPrintError(state, "VL value is out of range: index:%u len:%u", i, len);
return NULL;
}
return (void *)(portp->PortInfo.NeighborMTU + i);
}
static void PortDataXmlParserEndNeighborMtu(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8_t value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VL_TO_MTU *)object)->AsReg8 = value;
}
IXML_FIELD FlitControlPreemptionXmlFields[] = {
{ tag:"MinInitial", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MinInitial) },
{ tag:"MinTail", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MinTail) },
{ tag:"LargePktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.LargePktLimit) },
{ tag:"SmallPktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.SmallPktLimit) },
{ tag:"MaxSmallPktLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.MaxSmallPktLimit) },
{ tag:"PreemptionLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Preemption.PreemptionLimit) },
{ NULL }
};
static void FlitControlXmlOutputPreemption(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, data, NULL, FlitControlPreemptionXmlFields);
}
static void * FlitControlXmlParserStartPreemption(IXmlParserState_t *state, void *parent, const char **attr)
{
return parent;
}
IXML_FIELD PortDataFlitControlXmlFields[] = {
{ tag:"Interleave", format:'H', IXML_FIELD_INFO(PortData, PortInfo.FlitControl.Interleave.AsReg16) },
{ tag:"Preemption", format:'K', format_func:FlitControlXmlOutputPreemption, subfields:FlitControlPreemptionXmlFields, start_func:FlitControlXmlParserStartPreemption, end_func:IXmlParserEndNoop },
{ NULL }
};
static void PortDataXmlOutputFlitControl(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, data, NULL, PortDataFlitControlXmlFields);
}
static void * PortDataXmlParserStartFlitControl(IXmlParserState_t *state, void *parent, const char **attr)
{
return parent;
}
/* bitfields needs special handling: P_KeyEnforcementInbound */
static void PortDataXmlOutputP_KeyEnforcementInbound(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputOnOffValue(state, tag,
((PortData*)data)->PortInfo.s3.PartitionEnforcementInbound);
}
static void PortDataXmlParserEndP_KeyEnforcementInbound(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.s3.PartitionEnforcementInbound = value;
}
/* bitfields needs special handling: P_KeyEnforcementOutbound */
static void PortDataXmlOutputP_KeyEnforcementOutbound(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputOnOffValue(state, tag,
((PortData*)data)->PortInfo.s3.PartitionEnforcementOutbound);
}
static void PortDataXmlParserEndP_KeyEnforcementOutbound(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.s3.PartitionEnforcementOutbound = value;
}
/* bitfields needs special handling: SubnetTimeout */
static void PortDataXmlOutputSubnetTimeout(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputTimeoutMultValue(state, tag,
((PortData*)data)->PortInfo.Subnet.Timeout);
}
static void PortDataXmlParserEndSubnetTimeout(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.Subnet.Timeout = value;
}
/* bitfields needs special handling: RespTimeout */
static void PortDataXmlOutputRespTimeout(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputTimeoutMultValue(state, tag,
((PortData*)data)->PortInfo.Resp.TimeValue);
}
static void PortDataXmlParserEndRespTimeout(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.Resp.TimeValue = value;
}
static void PortDataXmlOutputSLtoSCMap(IXmlOutputState_t *state, const char *tag, void *data)
{
if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS &&
((PortData*)data)->pQOS->SL2SCMap )
SLtoSCMapXmlOutput(state, tag, data);
} // End of PortDataXmlOutputSLtoSCMap
static void PortDataXmlOutputSCtoSLMap(IXmlOutputState_t *state, const char *tag, void *data)
{
if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS &&
((PortData*)data)->pQOS->SC2SLMap )
SCtoSLMapXmlOutput(state, tag, data);
} // End of PortDataXmlOutputSCtoSLMap
static void PortDataXmlOutputSCtoSCMap(IXmlOutputState_t *state, const char *tag, void *data)
{
if ( ((PortData*)data)->nodep && ((PortData*)data)->pQOS &&
((PortData*)data)->nodep->NodeInfo.NodeType == STL_NODE_SW &&
((PortData*)data)->PortNum != 0)
SCtoSCMapXmlOutput(state, tag, data);
} // End of PortDataXmlOutputSCtoSLMap
static void PortDataXmlOutputSCtoVLxMap(IXmlOutputState_t *state, const char *tag, void *data, ScvlEnum_t scvlx)
{
if( ((PortData*)data)->nodep && ((PortData*)data)->pQOS)
SCtoVLxMapXmlOutput(state, tag, data, scvlx);
}
static void PortDataXmlOutputSCtoVLrMap(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data;
NodeData *nodep = portp->nodep;
if(getIsVLrSupported(nodep, portp))
PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLr);
}
static void PortDataXmlOutputSCtoVLtMap(IXmlOutputState_t *state, const char *tag, void *data)
{
PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLt);
}
static void PortDataXmlOutputSCtoVLntMap(IXmlOutputState_t *state, const char *tag, void *data)
{
if( !(((PortData*)data)->nodep->NodeInfo.NodeType == STL_NODE_SW &&
((PortData*)data)->PortNum == 0))
PortDataXmlOutputSCtoVLxMap(state, tag, data, Enum_SCVLnt);
}
/** =========================================================================
* Buffer Control Table I/O functions
*/
void BCTXmlOutputVLLimitAttr(struct IXmlOutputState *state, void *data)
{
IXmlOutputPrint(state, " VL=\"%u\"", *(uint8 *)data);
}
static void *BCTXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
if (portp->pBufCtrlTable) {
IXmlParserPrintError(state, "BufCtrlTable improperly allocated");
return (NULL);
}
if ( !( portp->pBufCtrlTable = (STL_BUFFER_CONTROL_TABLE*)MemoryAllocate2AndClear(
sizeof(STL_BUFFER_CONTROL_TABLE), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
return ((void *)portp->pBufCtrlTable);
}
static void PortDataXmlOutputBCT(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
STL_BUFFER_CONTROL_TABLE *bct = portp->pBufCtrlTable;
uint8_t vl;
if (! bct)
return;
IXmlOutputStartTag(state, tag);
IXmlOutputStartTag(state, "TxOverallSharedLimit");
IXmlOutputPrint(state, "%u", bct->TxOverallSharedLimit);
IXmlOutputEndTag(state, "TxOverallSharedLimit");
for (vl = 0; vl < STL_MAX_VLS; vl++)
{
IXmlOutputStartAttrTag( state, "VLLimit", &vl, BCTXmlOutputVLLimitAttr );
IXmlOutputStartTag(state, "TxDedicatedLimit");
IXmlOutputPrint(state, "%u", bct->VL[vl].TxDedicatedLimit);
IXmlOutputEndTag(state, "TxDedicatedLimit");
IXmlOutputStartTag(state, "TxSharedLimit");
IXmlOutputPrint(state, "%u", bct->VL[vl].TxSharedLimit);
IXmlOutputEndTag(state, "TxSharedLimit");
IXmlOutputEndTag( state, "VLLimit");
}
IXmlOutputEndTag(state, tag);
}
static void *BCTVLLimitStartFunc(IXmlParserState_t *state, void *parent, const char **attr)
{
STL_BUFFER_CONTROL_TABLE *bct = (STL_BUFFER_CONTROL_TABLE *)parent; // parent points to BufCtrlTable
uint8_t vl;
if ( !attr || !attr[0] || (0 != strcmp(attr[0], "VL"))) {
IXmlParserPrintError(state, "Missing VL attribute in BufferControlTable.VLLimit");
return (NULL);
}
if (FSUCCESS != StringToUint8(&vl, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid VL attribute in BufferControlTable.VLLimit VL %s", attr[1]);
return (NULL);
}
if (vl >= STL_MAX_VLS) {
IXmlParserPrintError(state, "VL attribute Out-of-Range in BufferControlTable.VLLimit VL: %s", attr[1]);
return (NULL);
}
return ((void *)&bct->VL[vl]);
}
/** =========================================================================
* Buffer Control Table Feild Definitions
*/
// parent is STL_BUFFER_CONTROL_TABLE_VL_s
static IXML_FIELD BCTVLLimitFields[] = {
{ tag:"TxDedicatedLimit", format:'U', IXML_FIELD_INFO(struct STL_BUFFER_CONTROL_TABLE_VL_s, TxDedicatedLimit) },
{ tag:"TxSharedLimit", format:'U', IXML_FIELD_INFO(struct STL_BUFFER_CONTROL_TABLE_VL_s, TxSharedLimit) },
{ NULL }
};
// parent is BufCtrlTable
static IXML_FIELD BufferControlTableFields[] = {
{ tag:"TxOverallSharedLimit", format:'U', IXML_FIELD_INFO(STL_BUFFER_CONTROL_TABLE, TxOverallSharedLimit) },
{ tag:"VLLimit", format:'k', subfields:BCTVLLimitFields, start_func:BCTVLLimitStartFunc },
{ NULL }
};
/* End Buffer Control Table Definitions */
/* ========================================================================= */
static void PortDataXmlOutputVLArbLow(IXmlOutputState_t *state, const char *tag, void *data)
{
int vlarb;
int res = getVLArb((PortData*)data, &vlarb);
DEBUG_ASSERT(!res);
if (res) {
fprintf(stderr, "Error-%s: failed to determine "
"Failed to determine if vlarb is supported. Not outputting VLArbLow\n", __func__);
return;
}
if (((PortData*)data)->pQOS && vlarb)
VLArbLowXmlOutput(state, tag, data);
} // End of PortDataXmlOutputVLArbLow
static void PortDataXmlOutputVLArbHigh(IXmlOutputState_t *state, const char *tag, void *data)
{
int vlarb;
int res = getVLArb((PortData*)data, &vlarb);
DEBUG_ASSERT(!res);
if (res) {
fprintf(stderr, "Error-%s: failed to determine "
"Failed to determine if vlarb is supported. Not outputting VLArbHigh\n", __func__);
return;
}
if (((PortData*)data)->pQOS && vlarb)
VLArbHighXmlOutput(state, tag, data);
} // End of PortDataXmlOutputVLArbHigh
static void PortDataXmlOutputVLArbPreemptElements(IXmlOutputState_t *state, const char *tag, void *data)
{
int vlarb;
int res = getVLArb((PortData*)data, &vlarb);
DEBUG_ASSERT(!res);
if (res) {
fprintf(stderr, "Error-%s: failed to determine "
"Failed to determine if vlarb is supported. Not outputting VLArbPreempt\n", __func__);
return;
}
if (((PortData*)data)->pQOS && vlarb)
VLArbPreemptElementsXmlOutput(state, tag, data);
} // End of PortDataXmlOutputVLArbPreemptElements
static void PortDataXmlOutputVLArbPreemptMatrix(IXmlOutputState_t *state, const char *tag, void *data)
{
int vlarb;
int res = getVLArb((PortData*)data, &vlarb);
DEBUG_ASSERT(!res);
if (res) {
fprintf(stderr, "Error-%s: failed to determine "
"Failed to determine if vlarb is supported. Not outputting VLArbPreemptMatrix\n", __func__);
return;
}
if (((PortData*)data)->pQOS && vlarb)
VLArbPreemptMatrixXmlOutput(state, tag, data);
}
static void PortDataXmlOutputPKeyTable(IXmlOutputState_t *state, const char *tag, void *data)
{
if (((PortData*)data)->nodep && ((PortData*)data)->pPartitionTable)
PKeyTableXmlOutput(state, tag, data);
} // End of PortDataXmlOutputPKeyTable
static void PortDataXmlOutputPortStatusData(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData*)data;
PortStatusDataXmlOutputOptional(state, "PortStatus", portp->pPortCounters);
}
/* bitfields needs special handling: PassThroughControlDRControl */
static void PortDataXmlOutputPassThroughControlDRControl(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.PassThroughControl.DRControl);
}
static void PortDataXmlParserEndPassThroughControlDRControl(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.PassThroughControl.DRControl = value;
}
/* bitfields needs special handling: SubnetMulticastPKeyTrapSuppressionEnabled */
static void PortDataXmlOutputSubnetMulticastPKeyTrapSuppressionEnabled(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.Subnet.MulticastPKeyTrapSuppressionEnabled);
}
static void PortDataXmlParserEndSubnetMulticastPKeyTrapSuppressionEnabled(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.Subnet.MulticastPKeyTrapSuppressionEnabled = value;
}
/* bitfields needs special handling: Subnet.ClientReregister */
static void PortDataXmlOutputSubnetClientReregister(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((PortData*)data)->PortInfo.Subnet.ClientReregister);
}
static void PortDataXmlParserEndSubnetClientReregister(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((PortData*)object)->PortInfo.Subnet.ClientReregister = value;
}
/** =========================================================================
* CableInfo definitions
*/
static void *CableInfoXmlParserStartSegValue(IXmlParserState_t *state, void *parent, const char **attr)
{
// parent points to CableInfoData
uint32 seg;
if ( !attr || !attr[0] || 0 != strcmp(attr[0], "Seg")) {
IXmlParserPrintError(state, "Missing Seg attribute for CableInfo.Value");
return NULL;
}
if (FSUCCESS != StringToUint32(&seg, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid Seg attribute for CableInfo.Value Seg: %s", attr[1]);
return NULL;
}
if (seg >= STL_CIB_STD_LEN / sizeof(uint64) ) {
IXmlParserPrintError(state, "Seg attribute Out-of-Range in CableInfo: %s", attr[1]);
return NULL;
}
return (&((uint8 *)parent)[seg * sizeof(uint64)]);
} // End of CableInfoXmlParserStartSegValue()
static void CableInfoXmlParserEndSegValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to CableInfoData; object points to segment-specific CableInfoData
uint8 *pCableInfoData = (uint8 *)parent;
uint8 *pCableInfoSegData = (uint8 *)object;
uint64 value;
if (! valid)
return;
if ( !pCableInfoData || !pCableInfoSegData || !content || !len ||
(pCableInfoSegData < pCableInfoData) ||
(pCableInfoSegData > pCableInfoData + STL_CIB_STD_LEN) ) {
IXmlParserPrintError(state, "CableInfo improperly allocated");
return;
}
if(IXmlParseUint64(state, content, len, &value)) {
#if CPU_LE
value = ntoh64(value);
#endif
*(uint64*)pCableInfoSegData = value;
}
} // End of CableInfoXmlParserEndSegValue()
const IXML_FIELD CableInfoFields[] = {
{ tag:"Value", start_func:CableInfoXmlParserStartSegValue, end_func:CableInfoXmlParserEndSegValue },
{ NULL }
};
static void *CableInfoXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
if (portp->pCableInfoData) {
IXmlParserPrintError(state, "CableInfo improperly allocated");
return (NULL);
}
if ( !( portp->pCableInfoData = MemoryAllocate2AndClear(
STL_CABLE_INFO_PAGESZ, IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
return ((void *)portp->pCableInfoData);
}
static void CableInfoOutputSegAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " Seg=\"0x%x\"", *(unsigned int *)data);
}
static void PortDataXmlOutputCableInfo(IXmlOutputState_t *state, const char *tag, void *data)
{
unsigned int ix_seg;
PortData *portp = (PortData*)data;
uint64 *pData = (uint64 *)portp->pCableInfoData;
uint64 temp;
if (! pData)
return;
IXmlOutputStartTag(state, tag);
for ( ix_seg = 0; ix_seg < STL_CABLE_INFO_PAGESZ / sizeof(uint64);
pData++, ix_seg++ ) {
temp = *pData;
#if CPU_LE
temp = ntoh64(temp);
#endif
IXmlOutputStartAttrTag(state, "Value", &ix_seg, CableInfoOutputSegAttr);
IXmlOutputPrint(state, "0x%016lx", temp);
IXmlOutputEndTag(state, "Value");
}
IXmlOutputEndTag(state, tag);
}
/** =========================================================================
* HFI Congestion Control Table definitions
*/
static void *HFICCTXmlParserStartSegValue(IXmlParserState_t *state, void *parent, const char **attr)
{
uint32 seg = 0;
if (parent == NULL)
return NULL;
const uint32 seg_max = ((STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY)) /
sizeof(uint64));
if ( !attr || !attr[0] || 0 != strcmp(attr[0], "Seg")) {
IXmlParserPrintError(state, "Missing Seg attribute for HFICCT.Value");
return NULL;
}
if (FSUCCESS != StringToUint32(&seg, attr[1], NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid Seg attribute for HFICCT.Value Seg: %s", attr[1]);
return NULL;
}
if (seg >= seg_max) {
IXmlParserPrintError(state, "Seg attribute Out-of-Range in HFICCT: %s", attr[1]);
return NULL;
}
return &(((uint8 *)parent)[seg * sizeof(uint64)]);
}
static void HFICCTXmlParserEndSegValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
// parent points to HFICCTData; object points to segment-specific HFICCTData
uint8 *pHFICCTData = (uint8 *)parent;
uint8 *pHFICCTSegData = (uint8 *)object;
uint64 value;
const uint32 seg_max = ((STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY)) /
sizeof(uint64));
if (!valid)
return;
if (!pHFICCTData)
return;
if (!pHFICCTSegData || !content || !len ||
(pHFICCTSegData < pHFICCTData) ||
(pHFICCTSegData > pHFICCTData + seg_max)) {
IXmlParserPrintError(state, "HFICCT improperly allocated");
return;
}
if(IXmlParseUint64(state, content, len, &value)) {
#if CPU_LE
value = ntoh64(value);
#endif
*(uint64*)pHFICCTSegData = value;
}
} // End of HFICCTXmlParserEndSegValue()
static void *HFICCTXmlParserStart(IXmlParserState_t *state, void *parent, const char **atr)
{
PortData *portp = (PortData *)parent; // parent points to PortData
unsigned int adjust = 0;
if (portp->CCTI_Limit == 0)
return (NULL);
if (portp->CCTI_Limit >= STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE) {
IXmlParserPrintError(state, "HFI Congestion Control Table Limit Index (CCTI_Limit) is invalid");
return (NULL);
}
if (portp->pCongestionControlTableEntries) {
IXmlParserPrintError(state, "HFI Congestion Control Table improperly allocated");
return (NULL);
}
// Minimum allocation is 128 entries
if (portp->CCTI_Limit < (STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES * 2))
adjust = STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES * 2;
else
adjust = portp->CCTI_Limit + 1;
// allocation must be adjusted to a multiple of blocks entries
if (adjust % STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) {
adjust = ((adjust/STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES) + 1) *
STL_NUM_CONGESTION_CONTROL_ELEMENTS_BLOCK_ENTRIES;
}
if (!(portp->pCongestionControlTableEntries = MemoryAllocate2AndClear(
adjust * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY),
IBA_MEM_FLAG_PREMPTABLE, MYTAG))) {
IXmlParserPrintError(state, "Unable to allocate memory");
return (NULL);
}
return ((void *)portp->pCongestionControlTableEntries);
}
static void HFICCTOutputSegAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " Seg=\"0x%x\"", *(unsigned int *)data);
}
static void PortDataXmlOutputHFICCT(IXmlOutputState_t *state, const char *tag, void *data)
{
unsigned int ix_seg;
PortData *portp = (PortData*)data;
uint64 *pData = (uint64 *)portp->pCongestionControlTableEntries;
uint64 temp;
uint32 len = 0;
if (!pData)
return;
if (portp->CCTI_Limit == 0 || portp->CCTI_Limit >= STL_CONGESTION_CONTROL_ENTRY_MAX_VALUE)
return;
len = (portp->CCTI_Limit + 1) * sizeof(STL_HFI_CONGESTION_CONTROL_TABLE_ENTRY);
IXmlOutputStartTag(state, tag);
for (ix_seg = 0; ix_seg < len / sizeof(uint64); pData++, ix_seg++) {
temp = *pData;
#if CPU_LE
temp = ntoh64(temp);
#endif
IXmlOutputStartAttrTag(state, "Value", &ix_seg, HFICCTOutputSegAttr);
IXmlOutputPrint(state, "0x%016lx", temp);
IXmlOutputEndTag(state, "Value");
}
IXmlOutputEndTag(state, tag);
}
const IXML_FIELD HFICCTFields[] = {
{ tag:"Value", start_func:HFICCTXmlParserStartSegValue, end_func:HFICCTXmlParserEndSegValue },
{ NULL }
};
// parse Rate_Int into a uint8 field and validate value
void McgMCRateXmlParserEnd_Int(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
McGroupData *mcgmemberp = (McGroupData*) object;
if (IXmlParseUint16(state, content, len, &value)) {
if (value <= IB_STATIC_RATE_LAST)
mcgmemberp->GroupInfo.Rate = value;
else
IXmlParserPrintError(state, "Invalid Rate: %u\n", value);
}
else
IXmlParserPrintError(state, "Invalid Rate: %s\n", content);
}
static void McgMLIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
McGroupData *mcgmemberp = (McGroupData *)object;
if (IXmlParseUint32(state, content, len, &value)) {
// MLID must be either 16-bit format (0xCXXX) or 32-bit format (0xFXXXXXXX)
if (IS_MCAST16(value))
mcgmemberp->MLID = MCAST16_TO_MCAST32(value);
else if (IS_MCAST32(value))
mcgmemberp->MLID = value;
else IXmlParserPrintError(state, "Invalid MLID value: 0x%04x\n", value);
}
else
IXmlParserPrintError(state, "Cannot parse \"%s\" as MLID\n", content);
}
static void McgMGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
McGroupData *mcgmemberp = (McGroupData *)object;
uint64 mgid[2];
if (FSUCCESS != StringToGid(&mgid[0], &mgid[1], content, NULL, TRUE)) {
IXmlParserPrintError(state, "Cannot parse \"%s\" as MGID\n", content);
return;
}
mcgmemberp->MGID.AsReg64s.H=mgid[0];
mcgmemberp->MGID.AsReg64s.L=mgid[1];
return;
}
static void McgMtuXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint16 value;
if (IXmlParseUint16(state, content, len, &value))
((McGroupData *)object)->GroupInfo.Mtu = GetMtuFromBytes(value);
else IXmlParserPrintError(state, "Invalid Mtu: %s\n", content);
}
static void McgPktLifeTimeXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((McGroupData *)object)->GroupInfo.PktLifeTime = value;
else IXmlParserPrintError(state, "Invalid PktLifeTime: %s\n", content);
}
static void McgSLXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((McGroupData *)object)->GroupInfo.u1.s.SL = value;
else IXmlParserPrintError(state, "Invalid SL: %s\n", content);
}
static void McgHopLimitXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid){
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((McGroupData *)object)->GroupInfo.u1.s.HopLimit = value;
else IXmlParserPrintError(state, "Invalid HopLimit: %s\n", content);
}
static void McgFlowLabelXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((McGroupData *)object)->GroupInfo.u1.s.FlowLabel = value;
else IXmlParserPrintError(state, "Invalid Flow Level: %s\n", content);
}
static void *McPortGIDXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
McMemberData *mcmemberp = (McMemberData*)MemoryAllocate2AndClear(sizeof(McMemberData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (!mcmemberp) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
if ( (!attr | !attr[0]) || (0 != strcmp(attr[0], "id"))) {
IXmlParserPrintError(state, "Missing PortGID id");
MemoryDeallocate(mcmemberp);
return NULL;
}
// basic initialization of the MCG structure
ListItemInitState(&mcmemberp->McMembersEntry);
QListSetObj(&mcmemberp->McMembersEntry,mcmemberp);
// no preexisting membership info
mcmemberp->MemberInfo.JoinFullMember=0;
mcmemberp->MemberInfo.JoinNonMember=0;
mcmemberp->MemberInfo.JoinSendOnlyMember=0;
return mcmemberp;
}
static void McPortGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
FabricData_t *fabricp = IXmlParserGetContext(state);
McMemberData *mcmemberp = (McMemberData *)object;
McGroupData *mcgmemberp = (McGroupData*)parent;
if (!valid) {
MemoryDeallocate(mcmemberp);
return;
}
mcmemberp->MemberInfo.RID.MGID = mcgmemberp->MGID;
mcmemberp->MemberInfo.MLID = mcgmemberp->MLID;
mcmemberp->MemberInfo.P_Key = mcgmemberp->GroupInfo.P_Key;
mcmemberp->MemberInfo.Q_Key = mcgmemberp->GroupInfo.Q_Key;
mcmemberp->MemberInfo.Mtu = mcgmemberp->GroupInfo.Mtu;
mcmemberp->MemberInfo.Rate = mcgmemberp->GroupInfo.Rate;
mcmemberp->MemberInfo.PktLifeTime = mcgmemberp->GroupInfo.PktLifeTime;
mcmemberp->MemberInfo.u1.s.SL = mcgmemberp->GroupInfo.u1.s.SL;
mcmemberp->MemberInfo.u1.s.HopLimit = mcgmemberp->GroupInfo.u1.s.HopLimit;
mcmemberp->MemberInfo.u1.s.FlowLabel = mcgmemberp->GroupInfo.u1.s.FlowLabel;
mcmemberp->MemberInfo.TClass = mcgmemberp->GroupInfo.TClass;
// inset mcmember in the groups structure
QListInsertTail(&mcgmemberp->AllMcGroupMembers, &mcmemberp->McMembersEntry);
mcmemberp->pPort = NULL;
if ((mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H != 0) && (mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L != 0)) {
// attach port to the PortGID
mcmemberp->pPort = FindPortGuid(fabricp, mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L);
//verify there is a port and that there is a neighbor
if (mcmemberp->pPort && mcmemberp->pPort->neighbor) {
// add switches that belong to this group
if (mcmemberp->pPort->neighbor->nodep->NodeInfo.NodeType == STL_NODE_SW) {
NodeData *groupswitch = mcmemberp->pPort->neighbor->nodep;
uint8 switchentryport = mcmemberp->pPort->neighbor->PortNum;
if (FSUCCESS != AddEdgeSwitchToGroup(fabricp, mcgmemberp, groupswitch, switchentryport)) {
IXmlParserPrintError(state, "No switch found for MC Group\n");
return;
}
}
}
mcgmemberp->NumOfMembers++;
}
return;
}
static void McPGIDXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
McMemberData *mcmemberp = (McMemberData*)object;
uint64 pgid[2];
if (! valid) //missing mandatory fields
return;
if (FSUCCESS != StringToGid(&pgid[0], &pgid[1], content, NULL, TRUE)) {
IXmlParserPrintError(state, "Invalid PortGID found in hex string %s\n", content);
return;
}
mcmemberp->MemberInfo.RID.PortGID.AsReg64s.H=pgid[0];
mcmemberp->MemberInfo.RID.PortGID.AsReg64s.L=pgid[1];
return;
}
static void McMembershipXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
McMemberData *mcmemberp = (McMemberData*)object;
uint8 value;
if (! IXmlParseUint8(state, content, len, &value)) {
IXmlParserPrintError(state, "Illegal Member type found: (%s)\n", content);
return;
}
if (value != 0) {
mcmemberp->MemberInfo.JoinFullMember = value & 1;
value = value >> 1;
mcmemberp->MemberInfo.JoinNonMember = value & 1;
value = value >> 1;
mcmemberp->MemberInfo.JoinSendOnlyMember = value & 1;
}
return;
}
static void *McgXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
McGroupData *mcgmemberp = (McGroupData*)MemoryAllocate2AndClear(sizeof(McGroupData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (! mcgmemberp) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
if ( (!attr | !attr[0]) || (0 != strcmp(attr[0], "id"))) {
IXmlParserPrintError(state, "Missing MGID id");
MemoryDeallocate(mcgmemberp);
return NULL;
}
ListItemInitState(&mcgmemberp->AllMcGMembersEntry);
QListSetObj(&mcgmemberp->AllMcGMembersEntry, mcgmemberp);
// init LIST of Group members to NULL
QListInitState(&mcgmemberp->AllMcGroupMembers);
if ( !QListInit(&mcgmemberp->AllMcGroupMembers)) {
IXmlParserPrintError(state, "Unable to initialize MCGroup member list");
MemoryDeallocate(mcgmemberp);
return NULL;
}
//init list of switches in a group
QListInitState(&mcgmemberp->EdgeSwitchesInGroup);
if ( !QListInit(&mcgmemberp->EdgeSwitchesInGroup)) {
IXmlParserPrintError(state, "Unable to initialize list of switches for the current MC group");
MemoryDeallocate(mcgmemberp);
return NULL;
}
//init number of member counters for groups and group members
mcgmemberp->NumOfMembers = 0;
return mcgmemberp;
}
static void McgXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field,
void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
McGroupData *mcgmemberp = (McGroupData*)object;
FabricData_t *fabricp = IXmlParserGetContext(state);
if (!valid) { // missing mandatory fields
MemoryDeallocate(mcgmemberp);
return;
}
// TODO is this correct? Should NumOfMcGroups be incremented only if the head McMemberData
// object GID != 0? Should NumOfMcGroups be incremented if there's at least one McMemberData
// object whose GID != 0 in AllMcGroupMembers?
McMemberData *pMCH = (McMemberData *)QListObj(QListHead(&mcgmemberp->AllMcGroupMembers));
if ((pMCH->MemberInfo.RID.PortGID.AsReg64s.H !=0) || (pMCH->MemberInfo.RID.PortGID.AsReg64s.L != 0))
fabricp->NumOfMcGroups++;
// insert mcmember in the fabric structure
QListInsertTail(&fabricp->AllMcGroups, &mcgmemberp->AllMcGMembersEntry);
return;
}
static void GIDXmlOutput(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " id=\"0x%016"PRIx64":0x%016"PRIx64"\"",
((IB_GID*)data)->AsReg64s.H,
((IB_GID*)data)->AsReg64s.L);
}
static void McMembershipXmlOutput(IXmlOutputState_t *state, const char* tag, void *data)
{
McMemberData *pMcMemberRecord = (McMemberData *)data;
uint8 Memberstatus;
Memberstatus = (pMcMemberRecord->MemberInfo.JoinSendOnlyMember<<2 |
pMcMemberRecord->MemberInfo.JoinNonMember<<1 |
pMcMemberRecord->MemberInfo.JoinFullMember);
IXmlOutputUint(state, tag, Memberstatus);
}
static void McGroupDataXmlOutput(IXmlOutputState_t *state, McGroupData *pMcGroupRecord)
{
IXmlOutputGID(state, "MGID", &pMcGroupRecord->MGID );
IXmlOutputLIDValue(state, "MLID", pMcGroupRecord->MLID);
IXmlOutputPKey(state, "P_Key", &pMcGroupRecord->GroupInfo.P_Key);
IXmlOutputUint(state, "Mtu", GetBytesFromMtu(pMcGroupRecord->GroupInfo.Mtu));
IXmlOutputRateValue(state, "Rate", pMcGroupRecord->GroupInfo.Rate);
IXmlOutputTimeoutMultValue(state, "PktLifeTime", pMcGroupRecord->GroupInfo.PktLifeTime);
IXmlOutputHexPad32(state, "Q_Key", pMcGroupRecord->GroupInfo.Q_Key);
IXmlOutputHex(state, "SL", pMcGroupRecord->GroupInfo.u1.s.SL);
IXmlOutputHex(state, "HopLimit", pMcGroupRecord->GroupInfo.u1.s.HopLimit);
IXmlOutputHex(state, "FlowLabel", pMcGroupRecord->GroupInfo.u1.s.FlowLabel);
IXmlOutputHexPad8(state, "TClass", pMcGroupRecord->GroupInfo.TClass);
}
static void McGroupMemberXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
McGroupData *pMcGroupRecord = (McGroupData *)data;
McMemberData *mcmemberp;
LIST_ITEM *p;
IXmlOutputStartAttrTag(state, tag, &pMcGroupRecord->MGID, GIDXmlOutput);
p=QListHead(&pMcGroupRecord->AllMcGroupMembers);
McGroupDataXmlOutput(state, pMcGroupRecord);
for (p=QListHead(&pMcGroupRecord->AllMcGroupMembers); p != NULL; p = QListNext(&pMcGroupRecord->AllMcGroupMembers, p)) {
mcmemberp = (McMemberData *)QListObj(p);
IXmlOutputStartAttrTag(state, "PortGID", &mcmemberp->MemberInfo.RID.PortGID, GIDXmlOutput);
IXmlOutputGID(state,"GID",&mcmemberp->MemberInfo.RID.PortGID );
McMembershipXmlOutput(state, "Membership_Int", mcmemberp);
IXmlOutputEndTag(state,"PortGID");
}
IXmlOutputEndTag(state,tag);
}
static IXML_FIELD McPortGIDFields[] = {
{ tag:"GID", format:'k', end_func:McPGIDXmlParserEnd },
{ tag:"Membership_Int", format:'k', end_func:McMembershipXmlParserEnd},
{ NULL},
};
static IXML_FIELD McgFields[] = {
{ tag:"MGID", format:'k', end_func: McgMGIDXmlParserEnd },
{ tag:"MLID", format:'h', end_func: McgMLIDXmlParserEnd },
{ tag:"P_Key", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.P_Key), format_func:IXmlOutputPKey},
{ tag:"Rate_Int", format:'k', end_func: McgMCRateXmlParserEnd_Int },
{ tag:"Mtu", format: 'h', end_func:McgMtuXmlParserEnd },
{ tag:"PktLifeTime_Int", format:'h', end_func:McgPktLifeTimeXmlParserEnd },
{ tag:"Q_Key", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.Q_Key) },
{ tag:"SL", format:'h', end_func: McgSLXmlParserEnd },
{ tag:"HopLimit", format:'h', end_func: McgHopLimitXmlParserEnd },
{ tag:"FlowLabel", format:'h', end_func: McgFlowLabelXmlParserEnd },
{ tag:"TClass", format:'h', IXML_FIELD_INFO(McGroupData, GroupInfo.TClass) },
{ tag:"PortGID", format:'k', subfields:McPortGIDFields, start_func:McPortGIDXmlParserStart, end_func:McPortGIDXmlParserEnd },
{ NULL }
};
static IXML_FIELD MulticastFields[] = {
{ tag:"MulticastGroup", format:'k', subfields:McgFields, start_func:McgXmlParserStart, end_func:McgXmlParserEnd }, // structure
{ NULL }
};
static void PortDataXmlOutputDownReason(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputDownReasonValue(state, tag, ((STL_LINKDOWN_REASON *)data)->LinkDownReason);
}
static void PortDataXmlParserEndDownReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_LINKDOWN_REASON *)object)->LinkDownReason = value;
}
static void PortDataXmlOutputNeighborDownReason(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputDownReasonValue(state, tag, ((STL_LINKDOWN_REASON *)data)->NeighborLinkDownReason);
}
static void PortDataXmlParserEndNeighborDownReason(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_LINKDOWN_REASON *)object)->NeighborLinkDownReason = value;
}
// LinkDownReasonLog
static IXML_FIELD LDRLogFields[] = {
{ tag:"LinkDownReason", format:'k', format_func:PortDataXmlOutputDownReason, end_func:IXmlParserEndNoop },
{ tag:"LinkDownReason_Int", format:'K', format_func:IXmlOutputNoop, end_func:PortDataXmlParserEndDownReason },
{ tag:"NeighborLinkDownReason", format:'k', format_func:PortDataXmlOutputNeighborDownReason, end_func:IXmlParserEndNoop },
{ tag:"NeighborLinkDownReason_Int", format:'K', format_func:IXmlOutputNoop, end_func:PortDataXmlParserEndNeighborDownReason },
{ tag:"Timestamp", format:'U', IXML_FIELD_INFO(STL_LINKDOWN_REASON, Timestamp) },
{ NULL }
};
static void LDRLogEntryXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " idx=\"%d\"", *(int *)data);
}
static void PortDataXmlOutputLDRLog(IXmlOutputState_t *state, const char *tag, void *data)
{
PortData *portp = (PortData *)data; // data points to PortData
int i;
for (i = 0; i < STL_NUM_LINKDOWN_REASONS; ++i) {
STL_LINKDOWN_REASON *ldr = &portp->LinkDownReasons[i];
if (ldr->Timestamp) {
IXmlOutputStartAttrTag(state, tag, &i, LDRLogEntryXmlFormatAttr);
IXmlOutputStrUint(state, "LinkDownReason",
StlLinkDownReasonToText(ldr->LinkDownReason), ldr->LinkDownReason);
IXmlOutputStrUint(state, "NeighborLinkDownReason",
StlLinkDownReasonToText(ldr->NeighborLinkDownReason), ldr->NeighborLinkDownReason);
IXmlOutputUint64(state, "Timestamp", ldr->Timestamp);
IXmlOutputEndTag(state, tag);
}
}
}
static void *LDRLogXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *pdata = (PortData *)parent;
int idx = -1;
if (attr == NULL) {
IXmlParserPrintError(state, "Failed to parse idx Attribute");
return NULL;
}
int i = 0;
while (attr[i]) {
if (!strcmp("idx", attr[i]) && attr[i+1] != NULL) {
if (attr[i + 1][1] == '\0') {
idx = attr[i + 1][0] - '0';
if (idx >= 0 && idx < STL_NUM_LINKDOWN_REASONS) {
return &pdata->LinkDownReasons[idx];
}
}
}
i++;
}
IXmlParserPrintError(state, "Failed to parse idx Attribute: %d", idx);
return NULL;
}
static void LDRLogXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
return;
}
/** =========================================================================
* PortData definitions
*/
static IXML_FIELD PortDataFields[] = {
{ tag:"PortNum", format:'U', IXML_FIELD_INFO(PortData, PortNum) },
{ tag:"GUID", format:'H', IXML_FIELD_INFO(PortData, PortGUID) },
{ tag:"EndPortLID", format:'K', format_func:PortDataXmlOutputEndPortLID, end_func:PortDataXmlParserEndEndPortLID }, // bitfield
{ tag:"M_Key", format:'H', IXML_FIELD_INFO(PortData, PortInfo.M_Key) },
{ tag:"SubnetPrefix", format:'H', IXML_FIELD_INFO(PortData, PortInfo.SubnetPrefix) },
{ tag:"LID", format:'H', IXML_FIELD_INFO(PortData, PortInfo.LID) },
{ tag:"SMLID", format:'H', IXML_FIELD_INFO(PortData, PortInfo.MasterSMLID) },
{ tag:"IPAddrIPV6", format:'k', format_func:IXmlOutputIPAddrIPV6, IXML_FIELD_INFO(PortData, PortInfo.IPAddrIPV6.addr), end_func:IXmlParserEndIPAddrIPV6},
{ tag:"IPAddrIPV4", format:'k', format_func:IXmlOutputIPAddrIPV4, IXML_FIELD_INFO(PortData, PortInfo.IPAddrIPV4.addr), end_func:IXmlParserEndIPAddrIPV4},
{ tag:"CapabilityMask", format:'H', IXML_FIELD_INFO(PortData, PortInfo.CapabilityMask.AsReg32) },
{ tag:"CapabilityMask3", format:'H', IXML_FIELD_INFO(PortData, PortInfo.CapabilityMask3.AsReg16) },
{ tag:"DiagCode", format:'H', IXML_FIELD_INFO(PortData, PortInfo.DiagCode.AsReg16) },
{ tag:"Lease", format:'U', IXML_FIELD_INFO(PortData, PortInfo.M_KeyLeasePeriod) },
{ tag:"PortState", format:'k', format_func: PortDataXmlOutputPortState, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"PortState_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndPortState }, // input only bitfield
{ tag:"InitReason", format:'k', format_func: PortDataXmlOutputInitReason, end_func:IXmlParserEndNoop },
{ tag:"InitReason_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndInitReason },
{ tag:"PhysState", format:'k', format_func: PortDataXmlOutputPhysState, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"PhysState_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndPhysState }, // input only bitfield
{ tag:"PortType", format:'k', format_func:PortDataXmlOutputPortPhysConfig, end_func:IXmlParserEndNoop },
{ tag:"PortType_Int", format:'H', IXML_FIELD_INFO(PortData, PortInfo.PortPhysConfig.AsReg8)},
{ tag:"LMC", format:'K', format_func:PortDataXmlOutputLMC, end_func:PortDataXmlParserEndLMC }, // bitfield
{ tag:"Protect", format:'k', format_func: PortDataXmlOutputMKeyProtect, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"Protect_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndMKeyProtect }, // input only bitfield
{ tag:"LinkWidthEnabled", format:'k', format_func: PortDataXmlOutputLinkWidthEnabled, end_func:IXmlParserEndNoop }, // output only
{ tag:"LinkWidthEnabled_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Enabled) }, // input only
{ tag:"LinkWidthSupported", format:'k', format_func: PortDataXmlOutputLinkWidthSupported, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkWidthSupported_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Supported) }, // input only
{ tag:"LinkWidthActive", format:'k', format_func: PortDataXmlOutputLinkWidthActive, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkWidthActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidth.Active) }, // input only
{ tag:"LinkWidthDowngradeEnabled", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeEnabled, end_func:IXmlParserEndNoop }, // output only
{ tag:"LinkWidthDowngradeEnabled_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.Enabled) }, // input only
{ tag:"LinkWidthDowngradeSupported", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeSupported, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkWidthDowngradeSupported_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.Supported) }, // input only
{ tag:"LinkWidthDowngradeTxActive", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeTxActive, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkWidthDowngradeTxActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.TxActive) }, // input only
{ tag:"LinkWidthDowngradeRxActive", format:'k', format_func: PortDataXmlOutputLinkWidthDowngradeRxActive, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkWidthDowngradeRxActive_Int", format:'U', format_func: IXmlOutputNoop, IXML_FIELD_INFO(PortData, PortInfo.LinkWidthDowngrade.RxActive) }, // input only
{ tag:"PortPacketFormatsSupported", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortPacketFormats.Supported) },
{ tag:"PortPacketFormatsEnabled", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortPacketFormats.Enabled) },
// PortLinkMode is a union of sub-byte fields; if more than one way of inputting PortLinkMode is provided, code should check that only one is used
{ tag:"PortLinkMode_Int", format:'U', IXML_FIELD_INFO(PortData, PortInfo.PortLinkMode.AsReg16) },
{ tag:"LinkSpeedEnabled", format:'k', format_func: PortDataXmlOutputLinkSpeedEnabled, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkSpeedEnabled_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedEnabled }, // input only bitfield
{ tag:"LinkSpeedSupported", format:'k', format_func: PortDataXmlOutputLinkSpeedSupported, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkSpeedSupported_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedSupported }, // input only bitfield
{ tag:"LinkSpeedActive", format:'k', format_func: PortDataXmlOutputLinkSpeedActive, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"LinkSpeedActive_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndLinkSpeedActive }, // input only bitfield
{ tag:"MTUs", format:'K', format_func:PortDataXmlOutputMTUs, subfields:PortDataMTUActiveXmlFields }, // bitfield(s)
{ tag:"MTUSupported", format:'K', format_func:PortDataXmlOutputMTUSupported, end_func:PortDataXmlParserEndMTUSupported }, // bitfield
{ tag:"SMSL", format:'K', format_func:PortDataXmlOutputSMSL, end_func:PortDataXmlParserEndSMSL }, // bitfield
{ tag:"VLsActive", format:'k', format_func: PortDataXmlOutputVLsActive, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"VLsActive_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndVLsActive }, // input only bitfield
{ tag:"VLsSupported", format:'k', format_func: PortDataXmlOutputVLsSupported, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"VLsSupported_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndVLsSupported }, // input only bitfield
{ tag:"VLArbHighLimit", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.HighLimit) },
{ tag:"VLArbHighCap", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationHighCap) },
{ tag:"VLArbLowCap", format:'U', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationLowCap) },
{ tag:"VLPreemptingLimit", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.PreemptingLimit) },
{ tag:"VLPreemptCap", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.PreemptCap) },
{ tag:"VLStalls", format:'K', format_func:PortDataXmlOutputVLStalls, subfields:PortDataVLStallXmlFields },
{ tag:"VLFlowControlDisabledMask", format:'H', IXML_FIELD_INFO(PortData,PortInfo.FlowControlMask) },
{ tag:"MulticastMask", format:'k', format_func:PortDataXmlOutputMulticastMask, end_func:PortDataXmlParserEndMulticastMask }, // bitfield
{ tag:"CollectiveMask", format:'k', format_func:PortDataXmlOutputCollectiveMask, end_func:PortDataXmlParserEndCollectiveMask }, // bitfield
{ tag:"HoQLifes", format:'K', format_func:PortDataXmlOutputHoQLifes, subfields:PortDataHoQLifeXmlFields },
{ tag:"P_KeyEnforcementInbound", format:'k', format_func: PortDataXmlOutputP_KeyEnforcementInbound, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"P_KeyEnforcementInbound_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndP_KeyEnforcementInbound }, // input only bitfield
{ tag:"P_KeyEnforcementOutbound", format:'k', format_func: PortDataXmlOutputP_KeyEnforcementOutbound, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"P_KeyEnforcementOutbound_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndP_KeyEnforcementOutbound }, // input only bitfield
{ tag:"ViolationsM_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.M_Key) },
{ tag:"ViolationsP_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.P_Key) },
{ tag:"ViolationsQ_Key", format:'U', IXML_FIELD_INFO(PortData, PortInfo.Violations.Q_Key) },
{ tag:"BufferUnits", format:'x', IXML_FIELD_INFO(PortData, PortInfo.BufferUnits.AsReg32) }, // bitfield
{ tag:"OverallBufferSpace", format:'U', IXML_FIELD_INFO(PortData, PortInfo.OverallBufferSpace) },
{ tag:"ReplayDepthBufferH", format:'u', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepthH.BufferDepthH) },
{ tag:"ReplayDepthWireH", format:'u', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepthH.WireDepthH) },
{ tag:"ReplayDepthBuffer", format:'U', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepth.BufferDepth) },
{ tag:"ReplayDepthWire", format:'U', IXML_FIELD_INFO(PortData, PortInfo.ReplayDepth.WireDepth) },
{ tag:"SubnetTimeout", format:'k', format_func: PortDataXmlOutputSubnetTimeout, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"SubnetTimeout_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndSubnetTimeout }, // input only bitfield
{ tag:"RespTimeout", format:'k', format_func: PortDataXmlOutputRespTimeout, end_func:IXmlParserEndNoop }, // output only bitfield
{ tag:"RespTimeout_Int", format:'K', format_func: IXmlOutputNoop, end_func:PortDataXmlParserEndRespTimeout }, // input only bitfield
{ tag:"SLtoSCMap", format:'k', format_func:PortDataXmlOutputSLtoSCMap, subfields:SLtoSCMapSCFields, start_func:SLtoSCMapXmlParserStart, end_func:SLtoSCMapXmlParserEnd }, // structure
{ tag:"SCtoSLMap", format:'k', format_func:PortDataXmlOutputSCtoSLMap, subfields:SCtoSLMapSLFields, start_func:SCtoSLMapXmlParserStart, end_func:SCtoSLMapXmlParserEnd }, // structure
{ tag:"SCtoSCMap", format:'k', format_func:PortDataXmlOutputSCtoSCMap, subfields:SCtoSCMapOutPortFields, start_func:SCtoSCMapXmlParserStart, end_func:SCtoSCMapXmlParserEnd }, // structure
{ tag:"SCtoVLrMap", format:'k', format_func:PortDataXmlOutputSCtoVLrMap, subfields:SCtoVLrMapVLrFields, start_func:SCtoVLrMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure
{ tag:"SCtoVLtMap", format:'k', format_func:PortDataXmlOutputSCtoVLtMap, subfields:SCtoVLtMapVLtFields, start_func:SCtoVLtMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure
{ tag:"SCtoVLntMap", format:'k', format_func:PortDataXmlOutputSCtoVLntMap, subfields:SCtoVLntMapVLntFields, start_func:SCtoVLntMapXmlParserStart, end_func:SCtoVLxMapXmlParserEnd }, // structure
{ tag:"BufferControlTable", format:'k', format_func:PortDataXmlOutputBCT, subfields:BufferControlTableFields, start_func:BCTXmlParserStart }, // structure
{ tag:"VLArbitrationLow", format:'k', format_func:PortDataXmlOutputVLArbLow, subfields:VLArbFields, start_func:VLArbLowXmlParserStart, end_func:VLArbLowXmlParserEnd }, // structure
{ tag:"VLArbitrationHigh", format:'k', format_func:PortDataXmlOutputVLArbHigh, subfields:VLArbFields, start_func:VLArbHighXmlParserStart, end_func:VLArbHighXmlParserEnd }, // structure
{ tag:"VLArbitrationPreemptElements", format:'k', format_func:PortDataXmlOutputVLArbPreemptElements, subfields:VLArbFields, start_func:VLArbPreemptElementsXmlParserStart, end_func:VLArbPreemptElementsXmlParserEnd },
{ tag:"VLArbitrationPreemptMatrix", format:'k', format_func:PortDataXmlOutputVLArbPreemptMatrix, subfields:VLArbPreemptMatrixFields, start_func:VLArbPreemptMatrixXmlParserStart, end_func:VLArbPreemptMatrixXmlParserEnd },
{ tag:"PKeyTable", format:'k', format_func:PortDataXmlOutputPKeyTable, subfields:PKeyTableFields, start_func:PKeyTableXmlParserStart, end_func:PKeyTableXmlParserEnd }, // structure
{ tag:"PortStatus", format:'k', size:sizeof(STL_PORT_COUNTERS_DATA), format_func:PortDataXmlOutputPortStatusData, subfields:PortStatusDataFields, start_func:IXmlParserStartStruct, end_func:PortStatusDataXmlParserEnd }, // structure
{ tag:"CableInfo", format:'k', size:128, format_func:PortDataXmlOutputCableInfo, subfields:(IXML_FIELD*)CableInfoFields, start_func:CableInfoXmlParserStart},
{ tag:"LocalPortNum", format:'u', IXML_FIELD_INFO(PortData, PortInfo.LocalPortNum) },
{ tag:"PortStates", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortStates.AsReg32) },
{ tag:"SMTrapQP", format:'h', IXML_FIELD_INFO(PortData, PortInfo.SM_TrapQP.AsReg32) },
{ tag:"SAQP", format:'h', IXML_FIELD_INFO(PortData, PortInfo.SA_QP.AsReg32) },
{ tag:"PortNeighborMode", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortNeighborMode) },
{ tag:"PortMode", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortMode.AsReg16) },
{ tag:"PortErrorAction", format:'h', IXML_FIELD_INFO(PortData, PortInfo.PortErrorAction.AsReg32) },
{ tag:"FlitControl", format:'k', format_func:PortDataXmlOutputFlitControl, subfields:PortDataFlitControlXmlFields, start_func:PortDataXmlParserStartFlitControl, end_func:IXmlParserEndNoop },
{ tag:"NeighborNodeGUID", format:'h', IXML_FIELD_INFO(PortData, PortInfo.NeighborNodeGUID) },
{ tag:"NeighborMTU", format:'k', format_func:PortDataXmlOutputNeighborMTU, start_func:PortDataXmlParserStartNeighborMtu, end_func:PortDataXmlParserEndNeighborMtu },
{ tag:"PKey_8B", format:'h', IXML_FIELD_INFO(PortData, PortInfo.P_Keys.P_Key_8B) },
{ tag:"PKey_10B", format:'h', IXML_FIELD_INFO(PortData, PortInfo.P_Keys.P_Key_10B) },
{ tag:"PortLTPCRCMode_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PortLTPCRCMode.AsReg16) },
{ tag:"VLArbCap_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.VL.ArbitrationHighCap) },
{ tag:"NeighborPortNum", format:'u', IXML_FIELD_INFO(PortData, PortInfo.NeighborPortNum) },
{ tag:"LinkDownReason_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.LinkDownReason) },
{ tag:"NeighborLinkDownReason_Int", format:'u', IXML_FIELD_INFO(PortData, PortInfo.NeighborLinkDownReason) },
{ tag:"PassThroughControlEgressPort", format:'u', IXML_FIELD_INFO(PortData, PortInfo.PassThroughControl.EgressPort) },
{ tag:"SubnetClientReregister_Int", format:'k', format_func:PortDataXmlOutputSubnetClientReregister, end_func:PortDataXmlParserEndSubnetClientReregister },
{ tag:"SubnetMulticastPKeyTrapSuppressionEnabled_Int", format:'u', format_func:PortDataXmlOutputSubnetMulticastPKeyTrapSuppressionEnabled, end_func:PortDataXmlParserEndSubnetMulticastPKeyTrapSuppressionEnabled },
{ tag:"PassThroughControlDRControl_Int", format:'k', format_func:PortDataXmlOutputPassThroughControlDRControl, end_func:PortDataXmlParserEndPassThroughControlDRControl },
{ tag:"HFICongestionControlTableIndexLimit", format:'h', IXML_FIELD_INFO(PortData, CCTI_Limit) },
{ tag:"HFICongestionControlTable", format:'k', format_func:PortDataXmlOutputHFICCT, subfields:(IXML_FIELD*)HFICCTFields, start_func:HFICCTXmlParserStart},
{ tag:"BundleNextPort", format:'u', IXML_FIELD_INFO(PortData, PortInfo.BundleNextPort) },
{ tag:"BundleLane", format:'u', IXML_FIELD_INFO(PortData, PortInfo.BundleLane) },
{ tag:"LinkDownReasonLog", format:'k', format_func:PortDataXmlOutputLDRLog, subfields:LDRLogFields, start_func:LDRLogXmlParserStart, end_func:LDRLogXmlParserEnd }, // structure
{ NULL }
};
static void PortDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (PortData*)data, PortDataXmlFormatAttr, PortDataFields);
}
static void *PortDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
PortData *portp = (PortData*)MemoryAllocate2AndClear(sizeof(PortData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (! portp) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
ListItemInitState(&portp->AllPortsEntry);
QListSetObj(&portp->AllPortsEntry, portp);
portp->nodep = (NodeData *)parent;
//printf("portp=%p, nodep=%p\n", portp, portp->nodep);
return portp;
}
static int Snapshot_PortDataComplete(IXmlParserState_t * state, void * object, void * parent);
static ParseCompleteFn portDataCompleteFn = Snapshot_PortDataComplete;
void SetPortDataComplete(ParseCompleteFn fn)
{
portDataCompleteFn = fn;
}
static ParseCompleteFn GetPortDataComplete()
{
return portDataCompleteFn;
}
/**
"Destructors" for some topology structs.
They do not free the targets, only their members.
*/
void Snapshot_PortDataFree(PortData * portp, FabricData_t * fabricp);
void Snapshot_NodeDataFree(NodeData * nodep, FabricData_t * fabricp);
/**
Completion handler for PortData inside a snapshot.
*/
static int Snapshot_PortDataComplete(IXmlParserState_t * state, void * object, void * parent)
{
const IXML_FIELD *p;
unsigned int i;
PortData *portp = (PortData*)object;
NodeData *nodep = portp->nodep;
FabricData_t *fabricp = IXmlParserGetContext(state);
ASSERT(nodep == (NodeData*)parent);
// technically <Port> could preceed <NodeType> within <Node>
if (nodep->NodeInfo.NodeType == STL_NODE_SW) {
// a switch only gets 1 port Guid, we save it for switch
// port 0 (the "virtual management port")
// should not have PortGUID if PortNum != 0
if (portp->PortGUID && portp->PortNum != 0) {
IXmlParserPrintError(state, "Invalid fields in Port: PortGUID not allowed for Switch port!=0");
return FERROR;
}
} else {
portp->PortInfo.LocalPortNum = portp->PortNum ;
// should have PortGUID
if (portp->PortGUID == 0 || portp->PortNum == 0) {
IXmlParserPrintError(state, "Invalid/missing fields in Port, PortGUID required for non-Switch");
return FERROR;
}
}
if (cl_qmap_insert(&nodep->Ports, portp->PortNum, &portp->NodePortsEntry) != &portp->NodePortsEntry)
{
IXmlParserPrintError(state, "Duplicate PortNum: %u", portp->PortNum);
goto failinsert2;
}
if (FSUCCESS != AllLidsAdd(fabricp, portp, FALSE))
{
IXmlParserPrintError(state, "Duplicate LIDs found in portRecords: LID 0x%x Port %u Node: %.*s\n",
portp->EndPortLID,
portp->PortNum, STL_NODE_DESCRIPTION_ARRAY_SIZE,
(char*)nodep->NodeDesc.NodeString);
goto failinsert2;
}
// Handling to deal with fields not defined in STL Gen 1, but required in Gen 2. Allows forward compatability
// of snapshots.
for (p=state->current.subfields,i=0; p->tag != NULL; ++i,++p) {
if (strcmp(p->tag, "PortPacketFormatsSupported") == 0) {
if (! (state->current.fields_found & ((uint64_t)1)<<i) ) {
portp->PortInfo.PortPacketFormats.Supported = STL_PORT_PACKET_FORMAT_9B;
portp->PortInfo.PortPacketFormats.Enabled = STL_PORT_PACKET_FORMAT_9B;
}
} else if (strcmp(p->tag, "MaxLID") == 0) {
if (! (state->current.fields_found & ((uint64_t)1)<<i) )
if (portp->PortInfo.CapabilityMask3.s.IsMAXLIDSupported) {
IXmlParserPrintError(state, "Missing fields in Port, MaxLID required for Gen2 HFI");
return FERROR;
}
}
}
return FSUCCESS;
failinsert2:
cl_qmap_remove_item(&nodep->Ports, &portp->NodePortsEntry);
return FERROR;
}
static void PortDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
PortData *portp = (PortData*)object;
FabricData_t *fabricp = IXmlParserGetContext(state);
ParseCompleteFn parseCompleteFn = GetPortDataComplete();
if (! valid) // missing mandatory fields
goto failvalidate;
portp->rate = StlLinkSpeedWidthToStaticRate(
portp->PortInfo.LinkSpeed.Active,
portp->PortInfo.LinkWidth.Active);
if (portp->pPortCounters) {
portp->pPortCounters->lq.s.numLanesDown = StlGetNumLanesDown(&portp->PortInfo);
}
if (parseCompleteFn) {
if (parseCompleteFn(state, object, parent) != FSUCCESS) {
goto failvalidate;
}
}
QListInsertTail(&fabricp->AllPorts, &portp->AllPortsEntry);
return;
failvalidate:
Snapshot_PortDataFree(portp, fabricp);
MemoryDeallocate(portp);
}
/**
Destructor for @c PortData inside parser.
Frees members but not port data itself.
*/
void Snapshot_PortDataFree(PortData * portp, FabricData_t * fabricp)
{
if (portp->pPortCounters)
MemoryDeallocate(portp->pPortCounters);
PortDataFreeQOSData(fabricp, portp);
PortDataFreePartitionTable(fabricp, portp);
}
#if !defined(VXWORKS) || defined(BUILD_DMC)
/****************************************************************************/
/* IocService Input/Output functions */
/* most are in ixml_ib */
// a better approach would be to allocate a "super structure which includes
// IocData and an extra field after it to count service entries as they
// arrive
static unsigned g_service_index = 0; // this is a hack, not Thread safe
static void *IocServiceXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
IocData *iocp = (IocData*)parent;
if (! iocp->Services) {
IXmlParserPrintError(state, "Services must follow ServicesCount");
return NULL;
}
if (g_service_index >= iocp->IocProfile.ServiceEntries) {
IXmlParserPrintError(state, "Number of Services inconsistent with ServicesCount");
return NULL;
}
return (&iocp->Services[g_service_index]);
}
static void IocServiceXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
if (! valid) // missing mandatory fields
goto failvalidate;
g_service_index++;
return;
failvalidate:
/* nothing to free, Iocp will take care of Services array */
return;
}
/****************************************************************************/
/* IocData Input/Output functions */
static void IocDataXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((IocData*)data)->IocProfile.IocGUID);
}
/* bitfields needs special handling: VendorId */
static void IocDataXmlOutputVendorId(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHex(state, tag, ((IocData *)data)->IocProfile.ven.v.VendorId);
}
static void IocDataXmlParserEndVendorId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((IocData *)object)->IocProfile.ven.v.VendorId = value;
}
/* bitfields needs special handling: SubSystemVendorId */
static void IocDataXmlOutputSubSystemVendorId(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHex(state, tag, ((IocData *)data)->IocProfile.sub.s.SubSystemVendorID);
}
static void IocDataXmlParserEndSubSystemVendorId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((IocData *)object)->IocProfile.sub.s.SubSystemVendorID = value;
}
/* this is a cheat, we need to allocate IocData.Services array.
* we depend on ServicesCount preceeding 1st Service entry in XML input
*/
static void IocDataXmlParserEndServicesCount(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
IocData * iocp = (IocData *)object;
if (IXmlParseUint8(state, content, len, &iocp->IocProfile.ServiceEntries)) {
iocp->Services = (IOC_SERVICE*)MemoryAllocate2AndClear(sizeof(IOC_SERVICE)*iocp->IocProfile.ServiceEntries, IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (! iocp->Services) {
IXmlParserPrintError(state, "Unable to allocate memory");
}
}
}
static void IocDataXmlOutputServices(IXmlOutputState_t *state, const char *tag, void *data)
{
IocData *iocp = (IocData*)data;
unsigned i;
IXmlOutputStartAttrTag(state, "Services", NULL, NULL);
for (i=0; i < iocp->IocProfile.ServiceEntries; i++)
IocServiceXmlOutput(state, "Service", &iocp->Services[i]);
IXmlOutputEndTag(state, "Services");
}
static IXML_FIELD ServicesFields[] = {
{ tag:"Service", format:'k', subfields:IocServiceFields, start_func:IocServiceXmlParserStart, end_func:IocServiceXmlParserEnd }, // structure, only used on input
{ NULL }
};
static IXML_FIELD IocDataFields[] = {
{ tag:"IocSlot", format:'U', IXML_FIELD_INFO(IocData, IocSlot) },
{ tag:"IocGUID", format:'H', IXML_FIELD_INFO(IocData, IocProfile.IocGUID) },
{ tag:"VendorId", format:'K', format_func:IocDataXmlOutputVendorId, end_func:IocDataXmlParserEndVendorId }, // bitfield
{ tag:"DeviceId", format:'X', IXML_FIELD_INFO(IocData, IocProfile.DeviceId) },
{ tag:"DeviceVersion", format:'X', IXML_FIELD_INFO(IocData, IocProfile.DeviceVersion) },
{ tag:"SubSystemVendorID", format:'K', format_func:IocDataXmlOutputSubSystemVendorId, end_func:IocDataXmlParserEndSubSystemVendorId }, // bitfield
{ tag:"SubSystemID", format:'X', IXML_FIELD_INFO(IocData, IocProfile.SubSystemID) },
{ tag:"IOClass", format:'X', IXML_FIELD_INFO(IocData, IocProfile.IOClass) },
{ tag:"IOSubClass", format:'X', IXML_FIELD_INFO(IocData, IocProfile.IOSubClass) },
{ tag:"Protocol", format:'X', IXML_FIELD_INFO(IocData, IocProfile.Protocol) },
{ tag:"ProtocolVer", format:'X', IXML_FIELD_INFO(IocData, IocProfile.ProtocolVer) },
{ tag:"SendMsgDepth", format:'U', IXML_FIELD_INFO(IocData, IocProfile.SendMsgDepth) },
{ tag:"SendMsgSize", format:'U', IXML_FIELD_INFO(IocData, IocProfile.SendMsgSize) },
{ tag:"RDMAReadDepth", format:'U', IXML_FIELD_INFO(IocData, IocProfile.RDMAReadDepth) },
{ tag:"RDMASize", format:'U', IXML_FIELD_INFO(IocData, IocProfile.RDMASize) },
{ tag:"CapabilityMask", format:'X', IXML_FIELD_INFO(IocData, IocProfile.ccm.CntlCapMask) },
{ tag:"ServicesCount", format:'U', IXML_FIELD_INFO(IocData, IocProfile.ServiceEntries), end_func:IocDataXmlParserEndServicesCount },
{ tag:"IDString", format:'C', IXML_FIELD_INFO(IocData, IocProfile.IDString) },
{ tag:"Services", format:'k', format_func:IocDataXmlOutputServices, subfields:ServicesFields }, // list
{ NULL }
};
static void IocDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (IocData*)data, IocDataXmlFormatAttr, IocDataFields);
}
static void *IocDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
IocData *iocp = (IocData*)MemoryAllocate2AndClear(sizeof(IocData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (! iocp) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
iocp->ioup = (IouData *)parent;
ListItemInitState(&iocp->IouIocsEntry);
QListSetObj(&iocp->IouIocsEntry, iocp);
g_service_index = 0;
return iocp;
}
static void IocDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
IocData *iocp = (IocData*)object;
IouData *ioup = iocp->ioup;
FabricData_t *fabricp = IXmlParserGetContext(state);
ASSERT(ioup == (IouData*)parent);
if (! valid) // missing mandatory fields
goto failvalidate;
if (cl_qmap_insert(&fabricp->AllIOCs, (uint64_t)iocp, &iocp->AllIOCsEntry) != &iocp->AllIOCsEntry)
{
IXmlParserPrintError(state, "Duplicate IOC Guids found: 0x%016"PRIx64, iocp->IocProfile.IocGUID);
goto failinsert;
}
QListInsertTail(&ioup->Iocs, &iocp->IouIocsEntry);
return;
failinsert:
failvalidate:
if (iocp->Services)
MemoryDeallocate(iocp->Services);
MemoryDeallocate(iocp);
}
/****************************************************************************/
/* IouData Input/Output functions */
static void IouDataXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((IouData*)data)->nodep->NodeInfo.NodeGUID);
}
/* bitfields needs special handling: DiagDeviceId */
static void IouDataXmlOutputDiagDeviceId(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((IouData *)data)->IouInfo.DiagDeviceId);
}
static void IouDataXmlParserEndDiagDeviceId(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((IouData *)object)->IouInfo.DiagDeviceId = value;
}
/* bitfields needs special handling: OptionRom */
static void IouDataXmlOutputOptionRom(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((IouData *)data)->IouInfo.OptionRom);
}
static void IouDataXmlParserEndOptionRom(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((IouData *)object)->IouInfo.OptionRom = value;
}
static void IouDataXmlOutputIocs(IXmlOutputState_t *state, const char *tag, void *data)
{
IouData *ioup = (IouData*)data;
LIST_ITEM *p;
for (p=QListHead(&ioup->Iocs); p != NULL; p = QListNext(&ioup->Iocs, p)) {
IocDataXmlOutput(state, "Ioc", QListObj(p));
}
}
static IXML_FIELD IouDataFields[] = {
{ tag:"ChangeID", format:'U', IXML_FIELD_INFO(IouData, IouInfo.Change_ID) },
{ tag:"MaxControllers", format:'U', IXML_FIELD_INFO(IouData, IouInfo.MaxControllers) },
{ tag:"DiagDeviceId", format:'K', format_func:IouDataXmlOutputDiagDeviceId, end_func:IouDataXmlParserEndDiagDeviceId }, // bitfield
{ tag:"OptionRom", format:'K', format_func:IouDataXmlOutputOptionRom, end_func:IouDataXmlParserEndOptionRom }, // bitfield
{ tag:"Ioc", format:'k', format_func:IouDataXmlOutputIocs, subfields:IocDataFields, start_func:IocDataXmlParserStart, end_func:IocDataXmlParserEnd }, // structures
{ NULL }
};
static void IouDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (IouData*)data, IouDataXmlFormatAttr, IouDataFields);
}
static void *IouDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
IouData *ioup = (IouData*)MemoryAllocate2AndClear(sizeof(IouData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (! ioup) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
ListItemInitState(&ioup->AllIOUsEntry);
QListSetObj(&ioup->AllIOUsEntry, ioup);
ioup->nodep = (NodeData *)parent;
QListInitState(&ioup->Iocs);
if (! QListInit(&ioup->Iocs))
{
MemoryDeallocate(ioup);
IXmlParserPrintError(state, "Unable to initialize object");
return NULL;
}
return ioup;
}
static void IouDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
IouData *ioup = (IouData*)object;
NodeData *nodep = ioup->nodep;
FabricData_t *fabricp = IXmlParserGetContext(state);
ASSERT(nodep == (NodeData*)parent);
if (! valid) // missing mandatory fields
goto failvalidate;
if (nodep->ioup) {
IXmlParserPrintError(state, "More than 1 IOU for Node");
goto failinsert;
}
nodep->ioup = ioup;
return;
failinsert:
failvalidate:
IouDataFreeIocs(fabricp, ioup);
MemoryDeallocate(ioup);
}
#endif
/****************************************************************************/
/* SwitchInfo Input/Output functions */
/* most are in ixml_ib */
static void *SwitchInfoXmlParserStart(IXmlParserState_t *state,
void *parent, const char **attr)
{
void *p = IXmlParserStartStruct(state, parent, attr);
if (!p) return p;
STL_SWITCHINFO_RECORD *pSwitchInfo = (STL_SWITCHINFO_RECORD*)p;
// For compatibility with snapshots from older versions of OPA,
// provide default values for optional fields.
pSwitchInfo->SwitchInfoData.PortGroupFDBCap = DEFAULT_MAX_PGFT_LID + 1;
return p;
}
static void SwitchInfoXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_SWITCHINFO_RECORD *pSwitchInfo = (STL_SWITCHINFO_RECORD*)object;
NodeData *nodep = (NodeData*)parent;
if (! valid) // missing mandatory fields
goto failvalidate;
if (nodep->pSwitchInfo) {
IXmlParserPrintError(state, "More than 1 SwitchInfo for Node");
goto failinsert;
}
nodep->pSwitchInfo = pSwitchInfo;
return;
failinsert:
failvalidate:
MemoryDeallocate(pSwitchInfo);
}
/****************************************************************************/
/* SwitchData Input/Output functions */
boolean fbFDB = FALSE; // Flag for LinearFDB or MulticastFDB parsed
static uint32 lidFDB = 0xFFFFFFFF; // LID for Linear and PortGroup FDB entries
static uint32 portPGT = 0xFFFFFFFF; // PortGroupNumber for PortGroup Element entry
// Multicast FDB Value parsing context data
static struct McvParseCtx {
uint32 lid;
uint8 pos;
} mcvParseCtx;
static void *SwitchDataXmlParserStart(IXmlParserState_t *state,
void *parent, const char **attr)
{
void *p = IXmlParserStartStruct(state, parent, attr);
if (!p) return p;
SwitchData *switchp = (SwitchData*)p;
// For compatibility with snapshots from older versions of OPA,
// provide default values for optional fields.
switchp->PortGroupFDBSize = DEFAULT_MAX_PGFT_LID + 1;
return p;
}
static void SwitchDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SwitchData *switchp = (SwitchData*)object;
NodeData *nodep = (NodeData*)parent;
if (! valid) // missing mandatory fields
goto failvalidate;
if (nodep->switchp) {
IXmlParserPrintError(state, "More than 1 SwitchData for Node");
goto failinsert;
}
nodep->switchp = switchp;
return;
failinsert:
failvalidate:
MemoryDeallocate(switchp);
}
static void SwitchDataOutputLIDAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " LID=\"0x%x\"", *(unsigned int *)data);
}
static void SwitchDataOutputPortGroupNumberAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " PortGroupNumber=\"%d\"", *(unsigned int *)data);
}
static void *SwitchDataXmlParserStartLinearValue(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
// Save Value attribute LID value for use in SwitchDataXmlParserEndLinearValue()
if ( !attr || !attr[0] || 0 != strcmp(attr[0], "LID")) {
IXmlParserPrintError(state, "Missing LID attribute for LinearFDB.Value");
return NULL;
}
if ( FSUCCESS != StringToUint32(&lidFDB, attr[1], NULL, 0, TRUE)
|| lidFDB >= switchp->LinearFDBSize ) {
IXmlParserPrintError(state, "Invalid LID attribute for LinearFDB.Value LID: %s", attr[1]);
return NULL;
}
return ((void *)&lidFDB);
}
static void SwitchDataXmlParserEndLinearValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 *pLID = (uint32 *)object; // object points to LID
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
uint8 temp;
if (! valid)
return;
// Assign LinearFDB[LID] = port
if ( !switchp || !switchp->LinearFDB || !pLID || !content ||
!len || (*pLID >= switchp->LinearFDBSize) ) {
IXmlParserPrintError(state, "LinearFDB improperly allocated");
return;
}
if (FSUCCESS != StringToUint8(&temp, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid Port number in LinearFDB.Value for LID %u Value: %s", *pLID, content);
return;
}
STL_LFT_PORT_BLOCK(switchp->LinearFDB, *pLID) = (PORT)temp;
}
IXML_FIELD LinearFDBFields[] = {
{ tag:"Value", start_func:SwitchDataXmlParserStartLinearValue, end_func:SwitchDataXmlParserEndLinearValue },
{ NULL }
};
/**
arrays need special handling: LinearFDB
*/
static void SwitchDataOutputLinearFDB(IXmlOutputState_t *state, const char *tag, void *data)
{
unsigned int ix_lid;
SwitchData *switchp = (SwitchData *)data;
PORT *pPort = (PORT *)switchp->LinearFDB;
IXmlOutputStartTag(state, tag);
for ( ix_lid = 0; ix_lid < switchp->LinearFDBSize;
pPort++, ix_lid++ ) {
if (*pPort == 0xFF)
continue;
IXmlOutputStartAttrTag(state, "Value", &ix_lid, SwitchDataOutputLIDAttr);
IXmlOutputPrint(state, "%u", *pPort);
IXmlOutputEndTag(state, "Value");
}
IXmlOutputEndTag(state, tag);
}
static void *SwitchDataXmlParserStartLinearFDB(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
STL_LINEAR_FORWARDING_TABLE *pPort;
// Allocate LinearFDB
if (!switchp || switchp->LinearFDB) {
IXmlParserPrintError(state, "SwitchData improperly allocated");
return NULL;
}
if ( !( pPort = (STL_LINEAR_FORWARDING_TABLE *)MemoryAllocate2AndClear( //Make sure to allocate a full block of LftBLOCK not just PORTs
ROUNDUP(switchp->LinearFDBSize, MAX_LFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
memset(pPort, 255, ROUNDUP(switchp->LinearFDBSize, MAX_LFT_ELEMENTS_BLOCK) ); //Make sure to memset a full block not just whats used
switchp->LinearFDB = pPort;
fbFDB = TRUE;
return (switchp);
}
static void SwitchDataXmlParserEndLinearFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SwitchData *switchp = (SwitchData *)object;
if (! valid)
goto fail;
return;
fail:
if (switchp && switchp->LinearFDB) {
MemoryDeallocate(switchp->LinearFDB);
switchp->LinearFDB = NULL;
}
}
static void *SwitchDataXmlParserStartMulticastValue(IXmlParserState_t *state, void *parent, const char **attrs)
{
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
int i;
int lidParsed = 0;
memset(&mcvParseCtx, 0, sizeof(mcvParseCtx));
for (i = 0; attrs && attrs[i] != NULL;) {
uint32 temp;
// Save Value attribute LID value for use in SwitchDataXmlParserEndMulticastValue()
if (strcmp(attrs[i], "LID") == 0) {
if (!attrs[i+1]) {
IXmlParserPrintError(state, "No LID specified for MulticastFDB.Value");
return NULL;
}
if (StringToUint32(&temp, attrs[i+1], NULL, 0, TRUE) != FSUCCESS) {
IXmlParserPrintError(state, "Invalid LID attribute for MulticastFDB.Value LID: %s", attrs[i+1]);
return NULL;
}
if (IS_MCAST16(temp))
temp = MCAST16_TO_MCAST32(temp);
if ((temp < STL_LID_MULTICAST_BEGIN) || (temp >= switchp->MulticastFDBSize)) {
IXmlParserPrintError(state, "Invalid LID attribute for MulticastFDB.Value LID: %s", attrs[i+1]);
return NULL;
}
mcvParseCtx.lid = temp - STL_LID_MULTICAST_BEGIN;
lidParsed = 1;
i += 2;
} else if (strcmp(attrs[i], "pos") == 0) {
if (!attrs[i+1]) {
IXmlParserPrintError(state, "No pos specified for MulticastFDB.Value");
return NULL;
}
if (StringToUint32(&temp, attrs[i+1], NULL, 0, TRUE) != FSUCCESS ||
temp >= STL_NUM_MFT_POSITIONS_MASK) {
IXmlParserPrintError(state, "Invalid pos attribute for MulticastFDB.Value pos: %s", attrs[i+1]);
return NULL;
}
mcvParseCtx.pos = (uint8)temp;
i += 2;
} else
i++; // TODO print unrecognized attr warning?
}
if (!lidParsed) {
IXmlParserPrintError(state, "Missing LID attribute for MulticastFDB.Value");
return NULL;
}
return ((void *)&mcvParseCtx);
}
static void SwitchDataXmlParserEndMulticastValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
struct McvParseCtx *ctx = (struct McvParseCtx*) object;
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
STL_PORTMASK *pPortMask;
uint64 portMask; // Port masks up to 64 bits can be input
if (! valid)
return;
assert(switchp && switchp->MulticastFDB[0]);
if (!ctx || !content || !len) {
IXmlParserPrintError(state, "Empty multicast FDB value");
return;
}
if (ctx->lid >= switchp->MulticastFDBSize) {
IXmlParserPrintError(state, "Multicast LID exceeds multicast FDB range");
return;
}
if (ctx->pos >= STL_NUM_MFT_POSITIONS_MASK) {
IXmlParserPrintError(state, "Unsupported MulticastFDB pos: %u",
ctx->pos);
return;
}
pPortMask = switchp->MulticastFDB[ctx->pos] + ctx->lid;
if (FSUCCESS != StringToUint64(&portMask, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid PortMask in MulticastFDB: %s", content);
return;
}
*pPortMask = (STL_PORTMASK)portMask;
}
IXML_FIELD MulticastFDBFields[] = {
{ tag:"Value", start_func:SwitchDataXmlParserStartMulticastValue, end_func:SwitchDataXmlParserEndMulticastValue },
{ NULL }
};
/**
Arrays need special handling: MulticastFDB.
@param data @c SwitchData * to node of interest.
Assumes that ((SwitchData*)data)->parent is not NULL.
*/
static void SwitchDataOutputMulticastFDB(IXmlOutputState_t *state, const char *tag, void *data)
{
STL_LID mcastLid;
SwitchData *switchp = (SwitchData *)data;
uint64 portMask;
// MulticastFDBTop can be less than STL_LID_MULTICAST_BEGIN at POD.
// May not be an error but then there aren't any Mcast entries to be
// output either.
if ((switchp->MulticastFDBSize <= STL_LID_MULTICAST_BEGIN) || (switchp->MulticastFDBSize > STL_LID_MULTICAST_END + 1)) {
return;
}
IXmlOutputStartTag(state, tag);
uint32 i;
for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) {
uint32 j;
for (j = 0; j < (switchp->MulticastFDBSize - STL_LID_MULTICAST_BEGIN); ++j) {
portMask = (uint64)switchp->MulticastFDB[i][j];
if (!portMask)
continue;
mcastLid = STL_LID_MULTICAST_BEGIN + j;
IXmlOutputStartTag(state, "Value");
IXmlOutputAttrFmt(state, "pos", "%d", i);
IXmlOutputAttrFmt(state, "LID", "0x%x", mcastLid);
IXmlOutputPrint(state, "0x%"PRIx64, portMask);
IXmlOutputEndTag(state, "Value");
}
}
IXmlOutputEndTag(state, tag);
}
static void *SwitchDataXmlParserStartMulticastFDB(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent; // parent points to SwitchData
STL_PORTMASK *pPortMask;
size_t allocSize;
uint8_t i;
// Allocate MulticastFDB
if (!switchp || switchp->MulticastFDB[0]) {
IXmlParserPrintError(state, "SwitchData improperly allocated");
return NULL;
}
allocSize = switchp->MulticastFDBSize - STL_LID_MULTICAST_BEGIN;
if ((switchp->MulticastFDBSize <= STL_LID_MULTICAST_BEGIN) || (switchp->MulticastFDBSize > STL_LID_MULTICAST_END + 1)) {
IXmlParserPrintError(state, "Invalid MulticastFDBSize, cannot allocate MulticastFDB");
return NULL;
}
for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) {
if ( !( pPortMask = (STL_PORTMASK *)MemoryAllocate2AndClear(
allocSize * sizeof(STL_PORTMASK), IBA_MEM_FLAG_PREMPTABLE,
MYTAG ) ) ) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
switchp->MulticastFDB[i] = pPortMask;
}
fbFDB = TRUE;
return (switchp);
}
static void SwitchDataXmlParserEndMulticastFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SwitchData *switchp = (SwitchData *)object;
if (! valid)
goto fail;
return;
fail:
if (switchp) {
uint8_t i;
for (i = 0; i < STL_NUM_MFT_POSITIONS_MASK; ++i) {
if (switchp->MulticastFDB[i]) {
MemoryDeallocate(switchp->MulticastFDB[i]);
switchp->MulticastFDB[i] = NULL;
}
}
}
}
static void *SwitchDataXmlParserStartPortGroupElementsValue(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent;
uint32 temp;
if (!attr || !attr[0] || 0 != strcmp(attr[0], "PortGroupNumber")) {
IXmlParserPrintError(state, "Missing PortGroupNumber attribute for PortGroupElements.Value");
return NULL;
}
// we depend on PortGroupSize preceeding this tag in XML
if (FSUCCESS != StringToUint32(&temp, attr[1], NULL, 0, TRUE)
|| temp >= switchp->PortGroupSize) {
IXmlParserPrintError(state, "Invalid PortGroupNumber attribute for PortGroupElements.Value PortGroupNumber: %s", attr[1]);
return NULL;
}
portPGT = temp;
return ((void *)&portPGT);
}
static void SwitchDataXmlParserEndPortGroupElementsValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 portGroupNum = *(uint32 *)object;
SwitchData *switchp = (SwitchData *)parent;
STL_PORTMASK *pPortMask;
uint64 portMask;
if (!valid) {
return;
}
assert (switchp && switchp->PortGroupElements);
if (!content || !len) {
IXmlParserPrintError(state, "Empty PortGroupElements.Value");
return;
}
pPortMask = switchp->PortGroupElements + portGroupNum;
if (FSUCCESS != StringToUint64(&portMask, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "invalid PortMask in PortGroupElements.Value for PortGroupNumber %u Value: %s", portGroupNum, content);
return;
}
*pPortMask = (STL_PORTMASK)portMask;
}
IXML_FIELD PortGroupElementsFields[] = {
{ tag:"Value", start_func:SwitchDataXmlParserStartPortGroupElementsValue, end_func:SwitchDataXmlParserEndPortGroupElementsValue },
{ NULL }
};
static void SwitchDataOutputPortGroupElements(IXmlOutputState_t *state, const char *tag, void *data)
{
uint32 pgPortGroupNum;
SwitchData *switchp = (SwitchData *)data;
uint64 portMask;
IXmlOutputStartTag(state, tag);
uint32 i;
for (i = 0; i < switchp->PortGroupSize; i++) {
portMask = (uint64)switchp->PortGroupElements[i];
if (!portMask) {
continue;
}
pgPortGroupNum = i;
IXmlOutputStartAttrTag(state, "Value", &pgPortGroupNum, SwitchDataOutputPortGroupNumberAttr);
IXmlOutputPrint(state, "0x%"PRIx64, portMask);
IXmlOutputEndTag(state, "Value");
}
IXmlOutputEndTag(state, tag);
}
static void *SwitchDataXmlParserStartPortGroupElements(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent;
STL_PORTMASK *pPortMask;
if (!switchp || switchp->PortGroupElements) {
IXmlParserPrintError(state, "SwitchData improperly allocated");
return NULL;
}
size_t allocSize = switchp->PortGroupSize;
if (!(pPortMask = (STL_PORTMASK *)MemoryAllocate2AndClear(
allocSize * sizeof(STL_PORTMASK),
IBA_MEM_FLAG_PREMPTABLE, MYTAG))) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
switchp->PortGroupElements = pPortMask;
return (switchp);
}
static void SwitchDataXmlParserEndPortGroupElements(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SwitchData *switchp = (SwitchData *)object;
if (! valid) {
goto fail;
}
return;
fail:
if (switchp && switchp->PortGroupElements) {
MemoryDeallocate(switchp->PortGroupElements);
switchp->PortGroupElements = NULL;
}
}
// end of port group
static void *SwitchDataXmlParserStartPortGroupFDBValue(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent;
if ( !attr || !attr[0] || 0!= strcmp(attr[0], "LID")) {
IXmlParserPrintError(state, "Missing LID attribute for PortGroupFDB.Value");
return NULL;
}
if (FSUCCESS != StringToUint32(&lidFDB, attr[1], NULL, 0, TRUE)
|| lidFDB >= switchp->PortGroupFDBSize) {
IXmlParserPrintError(state, "Invalid LID attribute for PortGroupFDB.Value LID: %s", attr[1]);
return NULL;
}
return ((void *)&lidFDB);
}
static void SwitchDataXmlParserEndPortGroupFDBValue(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 *pLID = (uint32 *)object; //points to LID
SwitchData *switchp = (SwitchData *)parent;
uint8 temp;
if (!valid) {
return;
}
if (!switchp || !switchp->PortGroupFDB || !pLID || !content ||
!len || (*pLID >= switchp->PortGroupFDBSize)) {
IXmlParserPrintError(state, "PortGroupFDB improperly allocated");
return;
}
if (FSUCCESS != StringToUint8(&temp, content, NULL, 0, TRUE)) {
IXmlParserPrintError(state, "Invalid Port Group number in PortGroupFDB.Value for LID %u Value: %s", *pLID, content);
return;
}
STL_PGFT_PORT_BLOCK(switchp->PortGroupFDB, *pLID) = (PORT)temp;
}
IXML_FIELD PortGroupFDBFields[] = {
{ tag:"Value", start_func:SwitchDataXmlParserStartPortGroupFDBValue, end_func:SwitchDataXmlParserEndPortGroupFDBValue},
{ NULL }
};
static void SwitchDataOutputPortGroupFDB(IXmlOutputState_t *state, const char *tag, void *data)
{
unsigned int ix_lid;
SwitchData *switchp = (SwitchData *)data;
PORT *pPortGroup = (PORT *)switchp->PortGroupFDB;
IXmlOutputStartTag(state, tag);
for (ix_lid = 0; ix_lid < switchp->PortGroupFDBSize;
pPortGroup++, ix_lid++) {
if (*pPortGroup == 0xFF) {
continue;
}
IXmlOutputStartAttrTag(state, "Value", &ix_lid, SwitchDataOutputLIDAttr);
IXmlOutputPrint(state, "%u", *pPortGroup);
IXmlOutputEndTag(state, "Value");
}
IXmlOutputEndTag(state, tag);
}
static void *SwitchDataXmlParserStartPortGroupFDB(IXmlParserState_t *state, void *parent, const char **attr)
{
SwitchData *switchp = (SwitchData *)parent;
STL_PORT_GROUP_FORWARDING_TABLE *pPortGroup;
if (!switchp || switchp->PortGroupFDB) {
IXmlParserPrintError(state, "SwitchData improperly allocated");
return NULL;
}
if (!switchp->PortGroupFDBSize) {
// PortGroupFDB is not in snapshot. For earlier
// versions of STL1, use LinearFDB but cap at 8k
switchp->PortGroupFDBSize = MIN(switchp->LinearFDBSize, DEFAULT_MAX_PGFT_LID+1);
}
if ( !(pPortGroup = (STL_PORT_GROUP_FORWARDING_TABLE *)MemoryAllocate2AndClear(
ROUNDUP(switchp->PortGroupFDBSize, MAX_LFT_ELEMENTS_BLOCK), IBA_MEM_FLAG_PREMPTABLE, MYTAG))) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
memset(pPortGroup, 255, ROUNDUP(switchp->PortGroupFDBSize, MAX_LFT_ELEMENTS_BLOCK));
switchp->PortGroupFDB = pPortGroup;
return (switchp);
}
static void SwitchDataXmlParserEndPortGroupFDB(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SwitchData *switchp = (SwitchData *)object;
if (!valid) {
goto fail;
}
return;
fail:
if (switchp && switchp->PortGroupFDB) {
MemoryDeallocate(switchp->PortGroupFDB);
switchp->PortGroupFDB = NULL;
}
}
static void IXmlParserEndMulticastFDBSize(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
SwitchData *switchp = (SwitchData *)object;
if (IXmlParseUint32(state, content, len, &value)) {
if (IS_MCAST16(value))
value = MCAST16_TO_MCAST32(value);
if (value && ((value <= STL_LID_MULTICAST_BEGIN) || (value > STL_LID_MULTICAST_END + 1)))
IXmlParserPrintError(state, "MulticastFDBSize value 0x%08x out of range. Must be 0 or in the range 0x%08x through 0x%08x\n", value, STL_LID_MULTICAST_BEGIN + 1, STL_LID_MULTICAST_END + 1);
else
switchp->MulticastFDBSize = value;
}
}
IXML_FIELD SwitchDataFields[] = {
{ tag:"LinearFDBSize", format:'U', IXML_FIELD_INFO(SwitchData, LinearFDBSize) },
{ tag:"MulticastFDBSize", format:'U', IXML_FIELD_INFO(SwitchData, MulticastFDBSize), end_func:IXmlParserEndMulticastFDBSize},
{ tag:"PortGroupFDBSize", format:'u', IXML_FIELD_INFO(SwitchData, PortGroupFDBSize) },
{ tag:"PortGroupSize", format:'U', IXML_FIELD_INFO(SwitchData, PortGroupSize) },
{ tag:"LinearFDB", format:'k', format_func:SwitchDataOutputLinearFDB, subfields:LinearFDBFields, start_func:SwitchDataXmlParserStartLinearFDB, end_func:SwitchDataXmlParserEndLinearFDB },
{ tag:"MulticastFDB", format:'k', format_func:SwitchDataOutputMulticastFDB, subfields:MulticastFDBFields, start_func:SwitchDataXmlParserStartMulticastFDB, end_func:SwitchDataXmlParserEndMulticastFDB },
{ tag:"PortGroupElements", format:'k', format_func:SwitchDataOutputPortGroupElements, subfields:PortGroupElementsFields, start_func:SwitchDataXmlParserStartPortGroupElements, end_func:SwitchDataXmlParserEndPortGroupElements },
{ tag:"PortGroupFDB", format:'k', format_func:SwitchDataOutputPortGroupFDB, subfields:PortGroupFDBFields, start_func:SwitchDataXmlParserStartPortGroupFDB, end_func:SwitchDataXmlParserEndPortGroupFDB },
{ NULL }
};
void SwitchDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (SwitchData*)data, NULL, SwitchDataFields);
}
// only output if value != NULL
void SwitchDataXmlOutputOptional(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputOptionalStruct(state, tag, (SwitchData*)data, NULL, SwitchDataFields);
}
/****************************************************************************/
/* NodeData Input/Output functions */
static void NodeDataXmlOutputPorts(IXmlOutputState_t *state, const char *tag, void *data)
{
NodeData *nodep = (NodeData*)data;
cl_map_item_t *p;
for (p=cl_qmap_head(&nodep->Ports); p != cl_qmap_end(&nodep->Ports); p = cl_qmap_next(p)) {
PortDataXmlOutput(state, "PortInfo", PARENT_STRUCT(p, PortData, NodePortsEntry));
}
}
#if !defined(VXWORKS) || defined(BUILD_DMC)
static void NodeDataXmlOutputIou(IXmlOutputState_t *state, const char *tag, void *data)
{
NodeData *nodep = (NodeData*)data;
if (nodep->ioup)
IouDataXmlOutput(state, "Iou", nodep->ioup);
}
#endif
static void NodeDataXmlOutputSwitchInfo(IXmlOutputState_t *state, const char *tag, void *data)
{
NodeData *nodep = (NodeData*)data;
if (nodep->pSwitchInfo)
SwitchInfoXmlOutput(state, "SwitchInfo", nodep->pSwitchInfo);
}
static void NodeDataXmlOutputSwitchData(IXmlOutputState_t *state, const char *tag, void *data)
{
NodeData *nodep = (NodeData*)data;
if (nodep->switchp)
SwitchDataXmlOutput(state, "SwitchData", nodep->switchp);
}
/* bitfields needs special handling: VendorID */
static void NodeDataXmlOutputVendorID(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((NodeData *)data)->NodeInfo.u1.s.VendorID);
}
static void NodeDataXmlParserEndVendorID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint32 value;
if (IXmlParseUint32(state, content, len, &value))
((NodeData *)object)->NodeInfo.u1.s.VendorID = value;
}
IXML_FIELD CongestionInfoFields[] = {
{ tag:"IBACongestionInfo", format:'X', IXML_FIELD_INFO(STL_CONGESTION_INFO, CongestionInfo) },
{ tag:"ControlTableCap", format:'U', IXML_FIELD_INFO(STL_CONGESTION_INFO, ControlTableCap) },
{ tag:"CongestionLogLength", format:'U', IXML_FIELD_INFO(STL_CONGESTION_INFO, CongestionLogLength) },
{ NULL }
};
static void NodeDataXmlOutputCongestionInfo(IXmlOutputState_t *state, const char *tag, void *data)
{
NodeData *nodep = (NodeData*)data;
IXmlOutputStruct(state, tag, (STL_CONGESTION_INFO *)&nodep->CongestionInfo, NULL, CongestionInfoFields);
}
static void CongestionInfoXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_CONGESTION_INFO *pci = (STL_CONGESTION_INFO*)object;
NodeData *nodep = (NodeData*)parent;
if (! valid) // missing mandatory fields
goto failvalidate;
memcpy(&nodep->CongestionInfo, pci, sizeof(STL_CONGESTION_INFO));
failvalidate:
MemoryDeallocate(pci);
return;
}
const IXML_FIELD NodeDataFields[] = {
{ tag:"NodeDesc", format:'C', IXML_FIELD_INFO(NodeData, NodeDesc.NodeString) },
{ tag:"NodeGUID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.NodeGUID) },
{ tag:"NodeType", format:'k', IXML_FIELD_INFO(NodeData, NodeInfo.NodeType), format_func:IXmlOutputNodeType, end_func:IXmlParserEndNoop }, // output only
{ tag:"NodeType_Int", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.NodeType), format_func:IXmlOutputNoop }, // input only
{ tag:"BaseVersion", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.BaseVersion) },
{ tag:"ClassVersion", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.ClassVersion) },
{ tag:"NumPorts", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.NumPorts) },
{ tag:"SystemImageGUID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.SystemImageGUID) },
// NodeData.NodeInfo.PortGUID is not used
{ tag:"PartitionCap", format:'U', IXML_FIELD_INFO(NodeData, NodeInfo.PartitionCap) },
{ tag:"DeviceID", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.DeviceID) },
{ tag:"Revision", format:'H', IXML_FIELD_INFO(NodeData, NodeInfo.Revision) },
// NodeData.NodeInfo.u1.s.LocalPortNum is not used
{ tag:"VendorID", format:'H', format_func:NodeDataXmlOutputVendorID, end_func:NodeDataXmlParserEndVendorID },
{ tag:"PortInfo", format:'k', format_func:NodeDataXmlOutputPorts, subfields:PortDataFields, start_func:PortDataXmlParserStart, end_func:PortDataXmlParserEnd }, // structures
#if !defined(VXWORKS) || defined(BUILD_DMC)
{ tag:"Iou", format:'k', format_func:NodeDataXmlOutputIou, subfields:IouDataFields, start_func:IouDataXmlParserStart, end_func:IouDataXmlParserEnd }, // structure
#endif
{ tag:"SwitchInfo", format:'k', size:sizeof(STL_SWITCHINFO_RECORD), format_func:NodeDataXmlOutputSwitchInfo, subfields:SwitchInfoFields, start_func:SwitchInfoXmlParserStart, end_func:SwitchInfoXmlParserEnd }, // structure
{ tag:"SwitchData", format:'k', size:sizeof(SwitchData), format_func:NodeDataXmlOutputSwitchData, subfields:SwitchDataFields, start_func:SwitchDataXmlParserStart, end_func:SwitchDataXmlParserEnd }, // structure
{ tag:"CongestionInfo", format:'k', size:sizeof(STL_CONGESTION_INFO), format_func:NodeDataXmlOutputCongestionInfo, subfields:CongestionInfoFields, start_func:IXmlParserStartStruct, end_func:CongestionInfoXmlParserEnd }, // structure
{ NULL }
};
static void NodeDataXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
IXmlOutputPrint(state, " id=\"0x%016"PRIx64"\"", ((NodeData*)data)->NodeInfo.NodeGUID);
}
static void NodeDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (NodeData*)data, NodeDataXmlFormatAttr, NodeDataFields);
}
static void *NodeDataXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
NodeData *nodep = (NodeData*)MemoryAllocate2AndClear(sizeof(NodeData), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
// TBD - if enable then need quiet arg in a static global
//if (i%PROGRESS_FREQ == 0)
//ProgressPrint(FALSE, "Processed %6d of %6d Nodes...", i, p->NumNodeRecords);
if (! nodep) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
cl_qmap_init(&nodep->Ports, NULL);
ListItemInitState(&nodep->AllTypesEntry);
QListSetObj(&nodep->AllTypesEntry, nodep);
return nodep;
}
static void NodeDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
cl_map_item_t *mi;
NodeData *nodep = (NodeData*)object;
FabricData_t *fabricp = IXmlParserGetContext(state);
//FSTATUS status;
if (! valid) // missing mandatory fields
goto failvalidate;
// TODO should this enforce if NodeType == NI_TYPE_SWITCH that
// SwitchData has been parsed (nodep->switchp != NULL)?
mi = cl_qmap_insert(&fabricp->AllNodes, nodep->NodeInfo.NodeGUID, &nodep->AllNodesEntry);
if (mi != &nodep->AllNodesEntry)
{
IXmlParserPrintError(state, "Duplicate NodeGuid: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID);
goto failinsert;
}
//printf("processed NodeRecord GUID: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID);
if (FSUCCESS != AddSystemNode(fabricp, nodep)) {
IXmlParserPrintError(state, "Unable to track systems for NodeGuid: 0x%"PRIx64"\n", nodep->NodeInfo.NodeGUID);
goto failsystem;
}
// Set FF_ROUTES for cases (older opareport) where it was not set at
// snapshot generation time
if (fbFDB)
fabricp->flags |= FF_ROUTES;
return;
failsystem:
cl_qmap_remove_item(&fabricp->AllNodes, &nodep->AllNodesEntry);
failinsert:
failvalidate:
MemoryDeallocate(nodep);
}
static IXML_FIELD NodesFields[] = {
{ tag:"Node", format:'K', subfields:(IXML_FIELD*)NodeDataFields, start_func:NodeDataXmlParserStart, end_func:NodeDataXmlParserEnd }, // structure
{ NULL }
};
void Snapshot_NodeDataFree(NodeData * nodep, FabricData_t * fabricp)
{
NodeDataFreePorts(fabricp, nodep);
#if !defined(VXWORKS) || defined(BUILD_DMC)
if (nodep->ioup)
IouDataFree(fabricp, nodep->ioup);
#endif
if (nodep->pSwitchInfo)
MemoryDeallocate(nodep->pSwitchInfo);
NodeDataFreeSwitchData(fabricp, nodep);
}
/****************************************************************************/
/* SM Data Input/Output functions */
static void SMDataXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
PortDataXmlFormatAttr(state, ((SMData *)data)->portp);
}
#if 0
static void SMDataXmlOutputNodeGUID(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHexPad64(state, tag, ((SMData *)data)->portp->nodep->NodeInfo.NodeGUID);
}
#endif
#if 0
// since SM's don't nest, we can use a simple global
static struct {
EUI64 NodeGUID;
uint8 PortNum;
} TempSMData;
static void SMDataXmlParserEndNodeGUID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
IXmlParseUint64(state, content, len, &TempSMData.NodeGUID);
}
static void SMDataXmlParserEndPortNum(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
IXmlParseUint8(state, content, len, &TempSMData.PortNum);
}
#endif
#if 0
static void SMDataXmlOutputPortNum(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((SMData *)data)->portp->PortNum);
}
#endif
/* bitfields needs special handling: LID */
static void SMDataXmlOutputLID(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputLIDValue(state, tag, ((SMData *)data)->SMInfoRecord.RID.LID);
}
static void SMDataXmlParserEndLID(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
STL_LID value;
if (IXmlParseUint32(state, content, len, &value))
((SMData *)object)->SMInfoRecord.RID.LID = value;
}
/* bitfields needs special handling: SMState */
static void SMDataXmlOutputSMState(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputSMStateValue(state, tag, ((SMData *)data)->SMInfoRecord.SMInfo.u.s.SMStateCurrent);
}
static void SMDataXmlParserEndSMState(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((SMData *)object)->SMInfoRecord.SMInfo.u.s.SMStateCurrent = value;
}
/* bitfields needs special handling: Priority */
static void SMDataXmlOutputPriority(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputUint(state, tag, ((SMData *)data)->SMInfoRecord.SMInfo.u.s.Priority);
}
static void SMDataXmlParserEndPriority(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((SMData *)object)->SMInfoRecord.SMInfo.u.s.Priority = value;
}
static IXML_FIELD SMDataFields[] = {
//{ tag:"NodeGUID", format:'k', format_func:SMDataXmlOutputNodeGUID, end_func:IXmlParserEndNoop }, // output only
//{ tag:"PortNum", format:'k', format_func:SMDataXmlOutputPortNum, end_func:IXmlParserEndNoop }, // output only
{ tag:"LID", format:'K', format_func:SMDataXmlOutputLID, end_func:SMDataXmlParserEndLID }, // bitfield
{ tag:"PortGUID", format:'H', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.PortGUID) },
{ tag:"State", format:'k', format_func:SMDataXmlOutputSMState, end_func:IXmlParserEndNoop },// output only bitfield
{ tag:"State_Int", format:'K', format_func:IXmlOutputNoop, end_func:SMDataXmlParserEndSMState }, // input only bitfield
{ tag:"Priority", format:'K', format_func:SMDataXmlOutputPriority, end_func:SMDataXmlParserEndPriority }, // bitfield
{ tag:"SM_Key", format:'H', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.SM_Key) },
{ tag:"ActCount", format:'X', IXML_FIELD_INFO(SMData, SMInfoRecord.SMInfo.ActCount) },
{ NULL }
};
static void SMDataXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (SMData*)data, SMDataXmlFormatAttr, SMDataFields);
}
static void SMDataXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
SMData *smp = (SMData*)object;
FabricData_t *fabricp = IXmlParserGetContext(state);
if (! valid)
goto invalid;
smp->portp = FindLidPort(fabricp, smp->SMInfoRecord.RID.LID, 0);
if (! smp->portp) {
IXmlParserPrintError(state, "SM LID not found: 0x%x\n", smp->SMInfoRecord.RID.LID);
goto badport;
}
if (&smp->AllSMsEntry != cl_qmap_insert(&fabricp->AllSMs, smp->SMInfoRecord.SMInfo.PortGUID, &smp->AllSMsEntry)) {
IXmlParserPrintError(state, "Duplicate SM Port Guids: 0x%016"PRIx64"\n", smp->SMInfoRecord.SMInfo.PortGUID);
goto failinsert;
}
return;
failinsert:
badport:
invalid:
MemoryDeallocate(smp);
}
static IXML_FIELD SMsFields[] = {
{ tag:"SM", format:'k', size:sizeof(SMData), subfields:SMDataFields, start_func:IXmlParserStartStruct, end_func:SMDataXmlParserEnd }, // structure
{ NULL }
};
/****************************************************************************/
/* Link Input/Output functions */
static void LinkXmlOutputNodeGUID(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputHexPad64(state, tag, ((PortData*)data)->nodep->NodeInfo.NodeGUID);
}
/* Output fields for PortData to include in To and From Link */
static IXML_FIELD LinkPortFields[] = {
{ tag:"NodeGUID", format:'K', format_func:LinkXmlOutputNodeGUID },
{ tag:"PortNum", format:'U', IXML_FIELD_INFO(PortData, PortNum) },
{ NULL }
};
#ifndef JFORMAT
static void LinkXmlOutputFrom(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (PortData*)data, NULL /*PortDataXmlFormatAttr*/, LinkPortFields);
}
#endif
static void LinkXmlOutputTo(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, ((PortData*)data)->neighbor, NULL /*PortDataXmlFormatAttr*/, LinkPortFields);
}
struct portref {
EUI64 NodeGUID;
uint8 PortNum;
};
typedef struct TempLinkData {
struct portref from;
struct portref to;
} TempLinkData_t;
/* Input fields for TempLinkData */
static IXML_FIELD TempLinkDataFromFields[] = {
{ tag:"NodeGUID", format:'H', IXML_FIELD_INFO(TempLinkData_t, from.NodeGUID)},
{ tag:"PortNum", format:'U', IXML_FIELD_INFO(TempLinkData_t, from.PortNum) },
{ NULL }
};
static IXML_FIELD TempLinkDataToFields[] = {
{ tag:"NodeGUID", format:'H', IXML_FIELD_INFO(TempLinkData_t, to.NodeGUID)},
{ tag:"PortNum", format:'U', IXML_FIELD_INFO(TempLinkData_t, to.PortNum) },
{ NULL }
};
static void *LinkFromXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
return parent;
}
static void *LinkToXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
return parent;
}
/* <Link> description */
static IXML_FIELD LinkFields[] = {
#ifdef JFORMAT
{ tag:"From", format:'J', subfields: LinkPortFields, format_attr:PortDataXmlFormatAttr },
{ tag:"To", format:'K', subfields: LinkPortFields, format_func:LinkXmlOutputTo },
#else
{ tag:"From", format:'K', subfields: TempLinkDataFromFields, format_func:LinkXmlOutputFrom, start_func:LinkFromXmlParserStart, end_func:IXmlParserEndNoop }, // special handling
{ tag:"To", format:'K', subfields: TempLinkDataToFields, format_func:LinkXmlOutputTo, start_func:LinkToXmlParserStart, end_func:IXmlParserEndNoop }, // special handling
#endif
{ NULL }
};
static void LinkXmlOutput(IXmlOutputState_t *state, const char *tag, void *data)
{
IXmlOutputStruct(state, tag, (PortData*)data, PortDataXmlFormatAttr, LinkFields);
}
static void *LinkXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
/* since links don't nest, we can get away with a single static */
/* if we ever use this multi-threaded, will need to allocate */
static TempLinkData_t link;
MemoryClear(&link, sizeof(link));
return &link;
}
static void LinkXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
TempLinkData_t *link = (TempLinkData_t*)object;
PortData *p1, *p2;
FabricData_t *fabricp = IXmlParserGetContext(state);
if (! valid)
goto invalid;
p1 = FindNodeGuidPort(fabricp, link->from.NodeGUID, link->from.PortNum);
if (! p1) {
IXmlParserPrintError(state, "Port not found: 0x%016"PRIx64":%u\n",
link->from.NodeGUID, link->from.PortNum);
goto badport;
}
if (p1->neighbor) {
IXmlParserPrintError(state, "Duplicate Port found: 0x%016"PRIx64":%u\n",
link->from.NodeGUID, link->from.PortNum);
goto badport;
}
p2 = FindNodeGuidPort(fabricp, link->to.NodeGUID, link->to.PortNum);
if (! p2) {
IXmlParserPrintError(state, "Port not found: 0x%016"PRIx64":%u\n",
link->to.NodeGUID, link->to.PortNum);
goto badport;
}
if (p2->neighbor) {
IXmlParserPrintError(state, "Duplicate Port found: 0x%016"PRIx64":%u\n",
link->to.NodeGUID, link->to.PortNum);
goto badport;
}
p1->neighbor = p2;
p2->neighbor = p1;
p1->from = 1;
if (p1->rate != p2->rate) {
fprintf(stderr, "%s: Warning: Ignoring Inconsistent Active Speed/Width for link between:\n", g_Top_cmdname);
fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n",
StlStaticRateToText(p1->rate),
p1->nodep->NodeInfo.NodeGUID,
p1->PortNum,
StlNodeTypeToText(p1->nodep->NodeInfo.NodeType),
STL_NODE_DESCRIPTION_ARRAY_SIZE,
(char*)p1->nodep->NodeDesc.NodeString);
fprintf(stderr, " %4s 0x%016"PRIx64" %3u %s %.*s\n",
StlStaticRateToText(p2->rate),
p2->nodep->NodeInfo.NodeGUID,
p2->PortNum,
StlNodeTypeToText(p2->nodep->NodeInfo.NodeType),
STL_NODE_DESCRIPTION_ARRAY_SIZE,
(char*)p2->nodep->NodeDesc.NodeString);
}
++(fabricp->LinkCount);
if (! isInternalLink(p1))
++(fabricp->ExtLinkCount);
if (isFILink(p1))
++(fabricp->FILinkCount);
if (isISLink(p1))
++(fabricp->ISLinkCount);
if (! isInternalLink(p1)&& isISLink(p1))
++(fabricp->ExtISLinkCount);
badport:
invalid:
/* nothing to free */
return;
}
static IXML_FIELD LinksFields[] = {
{ tag:"Link", format:'K', subfields:LinkFields, start_func:LinkXmlParserStart, end_func:LinkXmlParserEnd }, // structure
{ NULL }
};
/****************************************************************************/
/* Virtual Fabrics Input/Output functions */
static void VFInfoXmlOutputSelectFlags(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.selectFlags);
}
static void VFInfoXmlParserEndSelectFlags(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.selectFlags = value;
}
static void VFInfoXmlOutputSL(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.slBase);
}
static void VFInfoXmlParserEndSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.slBase = value;
}
static void VFInfoXmlOutputRespSL(IXmlOutputState_t *state, const char *tag, void *data) {
if (((STL_VFINFO_RECORD*)data)->slResponseSpecified)
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slResponse);
}
static void VFInfoXmlParserEndRespSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value)) {
((STL_VFINFO_RECORD*)object)->slResponse = value;
((STL_VFINFO_RECORD*)object)->slResponseSpecified = 1;
}
}
static void VFInfoXmlOutputMulticastSL(IXmlOutputState_t *state, const char *tag, void *data) {
if (((STL_VFINFO_RECORD*)data)->slMulticastSpecified)
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slMulticast);
}
static void VFInfoXmlParserEndMulticastSL(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value)) {
((STL_VFINFO_RECORD*)object)->slMulticast = value;
((STL_VFINFO_RECORD*)object)->slMulticastSpecified = 1;
}
}
static void VFInfoXmlOutputMTUSpecified(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.mtuSpecified);
}
static void VFInfoXmlParserEndMTUSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.mtuSpecified = value;
}
static void VFInfoXmlOutputMTU(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.mtu);
}
static void VFInfoXmlParserEndMTU(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.mtu = value;
}
static void VFInfoXmlOutputRateSpecified(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.rateSpecified);
}
static void VFInfoXmlParserEndRateSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.rateSpecified = value;
}
static void VFInfoXmlOutputRate(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.rate);
}
static void VFInfoXmlParserEndRate(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.rate = value;
}
static void VFInfoXmlOutputPacketLifeSpecified(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.pktLifeSpecified);
}
static void VFInfoXmlParserEndPacketLifeSpecified(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.pktLifeSpecified = value;
}
static void VFInfoXmlOutputPacketLifeTimeInc(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->s1.pktLifeTimeInc);
}
static void VFInfoXmlParserEndPacketLifeTimeInc(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->s1.pktLifeTimeInc = value;
}
static void VFInfoXmlOutputSlResponse(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->slResponse);
}
static void VFInfoXmlParserEndSlResponse(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->slResponse = value;
}
static void VFInfoXmlOutputPriority(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->priority);
}
static void VFInfoXmlParserEndPriority(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->priority = value;
}
static void VFInfoXmlOutputPreemptionRank(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->preemptionRank);
}
static void VFInfoXmlParserEndPreemptionRank(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->preemptionRank = value;
}
static void VFInfoXmlOutputHoqLife(IXmlOutputState_t *state, const char *tag, void *data) {
IXmlOutputUint(state, tag, ((STL_VFINFO_RECORD *)data)->hoqLife);
}
static void VFInfoXmlParserEndHoqLife(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid) {
uint8 value;
if (IXmlParseUint8(state, content, len, &value))
((STL_VFINFO_RECORD *)object)->hoqLife = value;
}
static IXML_FIELD VFFields[] = {
{ tag:"Index", format:'U', IXML_FIELD_INFO(STL_VFINFO_RECORD, vfIndex) },
{ tag:"PKey", format:'u', IXML_FIELD_INFO(STL_VFINFO_RECORD, pKey) },
{ tag:"Name", format:'S', IXML_FIELD_INFO(STL_VFINFO_RECORD, vfName) },
{ tag:"ServiceID", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, ServiceID) },
{ tag:"MGIDHigh", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, MGID.AsReg64s.H) },
{ tag:"MGIDLow", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, MGID.AsReg64s.L) },
{ tag:"SelectFlags", format:'k', format_func:VFInfoXmlOutputSelectFlags, end_func:VFInfoXmlParserEndSelectFlags },
{ tag:"SL", format:'k', format_func:VFInfoXmlOutputSL, end_func:VFInfoXmlParserEndSL },
{ tag:"RespSL", format:'k', format_func:VFInfoXmlOutputRespSL, end_func:VFInfoXmlParserEndRespSL },
{ tag:"MulticastSL", format:'k', format_func:VFInfoXmlOutputMulticastSL, end_func:VFInfoXmlParserEndMulticastSL },
{ tag:"MTUSpecified", format:'k', format_func:VFInfoXmlOutputMTUSpecified, end_func:VFInfoXmlParserEndMTUSpecified },
{ tag:"MTU", format:'k', format_func:VFInfoXmlOutputMTU, end_func:VFInfoXmlParserEndMTU },
{ tag:"RateSpecified", format:'k', format_func:VFInfoXmlOutputRateSpecified, end_func:VFInfoXmlParserEndRateSpecified },
{ tag:"Rate", format:'k', format_func:VFInfoXmlOutputRate, end_func:VFInfoXmlParserEndRate },
{ tag:"PacketLifeSpecified", format:'k', format_func:VFInfoXmlOutputPacketLifeSpecified, end_func:VFInfoXmlParserEndPacketLifeSpecified },
{ tag:"PacketLifeTimeInc", format:'k', format_func:VFInfoXmlOutputPacketLifeTimeInc, end_func:VFInfoXmlParserEndPacketLifeTimeInc },
{ tag:"OptionFlags", format:'h', IXML_FIELD_INFO(STL_VFINFO_RECORD, optionFlags) },
{ tag:"BandwidthPercent", format:'u', IXML_FIELD_INFO(STL_VFINFO_RECORD, bandwidthPercent) },
{ tag:"SLResponse", format:'k', format_func:VFInfoXmlOutputSlResponse, end_func:VFInfoXmlParserEndSlResponse },
{ tag:"Priority", format:'k', format_func:VFInfoXmlOutputPriority, end_func:VFInfoXmlParserEndPriority },
{ tag:"PreemptionRank", format:'k', format_func:VFInfoXmlOutputPreemptionRank, end_func:VFInfoXmlParserEndPreemptionRank },
{ tag:"HOQLife", format:'k', format_func:VFInfoXmlOutputHoqLife, end_func:VFInfoXmlParserEndHoqLife },
{ NULL }
};
static void *VFDataXmlParserStartVF(IXmlParserState_t *state, void *parent, const char **attr)
{
VFData_t *vf = MemoryAllocate2AndClear(sizeof(VFData_t), IBA_MEM_FLAG_PREMPTABLE, MYTAG);
if (!vf) {
IXmlParserPrintError(state, "Unable to allocate memory");
return NULL;
}
return &vf->record;
}
static void VFDataXmlParserEndVF(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
FabricData_t *fabricp = IXmlParserGetContext(state);
STL_VFINFO_RECORD *vfinfo = object;
VFData_t *vf = PARENT_STRUCT(vfinfo, VFData_t, record);
if (valid) {
QListSetObj(&vf->AllVFsEntry, vf);
QListInsertTail(&fabricp->AllVFs, &vf->AllVFsEntry);
} else if (vf) {
MemoryDeallocate(vf);
}
}
static IXML_FIELD VFsFields[] = {
{ tag:"VF", format:'K', subfields:VFFields, start_func:VFDataXmlParserStartVF, end_func:VFDataXmlParserEndVF },
{ NULL }
};
/****************************************************************************/
/* Overall Serialization Input/Output functions */
/* only used for input parsing */
static IXML_FIELD SnapshotFields[] = {
{ tag:"Nodes", format:'K', subfields:NodesFields }, // list
{ tag:"SMs", format:'K', subfields:SMsFields }, // list
{ tag:"Links", format:'K', subfields:LinksFields }, // list
{ tag:"McMembers", format:'k', subfields:MulticastFields }, // list
{ tag:"VirtualFabrics", format:'k', subfields:VFsFields },
{ NULL }
};
static void *SnapshotXmlParserStart(IXmlParserState_t *state, void *parent, const char **attr)
{
int i;
boolean gottime = FALSE;
boolean gotstats = FALSE;
FabricData_t *fabricp = IXmlParserGetContext(state);
uint64 temp;
// process unixtime attribute and update fabricp->time
for (i = 0; attr[i]; i += 2) {
if (strcmp(attr[i], "unixtime") == 0) {
gottime = TRUE;
// typically time_t is 32 bits, but allow 64 bits
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid unixtime attribute: %s", attr[i+1]);
else
fabricp->time = (time_t)temp;
} else if (strcmp(attr[i], "stats") == 0) {
gotstats = TRUE;
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid stats attribute: %s", attr[i+1]);
else
fabricp->flags |= temp?FF_STATS:FF_NONE;
} else if (strcmp(attr[i], "routes") == 0) {
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid routes attribute: %s", attr[i+1]);
else
fabricp->flags |= temp?FF_ROUTES:FF_NONE;
} else if (strcmp(attr[i], "qosdata") == 0) {
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid qosdata attribute: %s", attr[i+1]);
else
fabricp->flags |= temp?FF_QOSDATA:FF_NONE;
} else if (strcmp(attr[i], "bfrctrl") == 0) {
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid bfrctrl attribute: %s", attr[i+1]);
else
fabricp->flags |= temp?FF_BUFCTRLTABLE:FF_NONE;
} else if (strcmp(attr[i], "downports") == 0) {
if (FSUCCESS != StringToUint64(&temp, attr[i+1], NULL, 0, TRUE))
IXmlParserPrintError(state, "Invalid downports attribute: %s", attr[i+1]);
else
fabricp->flags |= temp?FF_DOWNPORTINFO:FF_NONE;
}
}
if (! gottime) {
IXmlParserPrintError(state, "Missing unixtime attribute");
}
if (! gotstats) {
IXmlParserPrintError(state, "Missing stats attribute");
}
fabricp->NumOfMcGroups = 0;
return NULL;
}
static void SnapshotXmlParserEnd(IXmlParserState_t *state, const IXML_FIELD *field, void *object, void *parent, XML_Char *content, unsigned len, boolean valid)
{
FabricData_t *fabricp = IXmlParserGetContext(state);
if (! valid) {
// This free's everything we built while parsing, leaving empty lists
SMDataFreeAll(fabricp);
NodeDataFreeAll(fabricp);
MCDataFreeAll(fabricp);
VFDataFreeAll(fabricp);
fabricp->LinkCount = 0;
fabricp->ExtLinkCount = 0;
}
}
static IXML_FIELD TopLevelFields[] = {
{ tag:"Snapshot", format:'K', subfields:SnapshotFields, start_func:SnapshotXmlParserStart, end_func:SnapshotXmlParserEnd }, // structure
{ NULL }
};
#if 0
static IXML_FIELD TopLevelFields[] = {
{ tag:"Report", format:'K', subfields:ReportFields }, // structure
{ NULL }
};
#endif
static void SnapshotInfoXmlFormatAttr(IXmlOutputState_t *state, void *data)
{
SnapshotOutputInfo_t *info = (SnapshotOutputInfo_t *)IXmlOutputGetContext(state);
char datestr[80] = "";
int i;
Top_formattime(datestr, sizeof(datestr), info->fabricp->time);
IXmlOutputPrint( state, " date=\"%s\" unixtime=\"%ld\" stats=\"%d\""
" routes=\"%d\" qosdata=\"%d\" bfrctrl=\"%d\" downports=\"%d\" options=\"",
datestr, info->fabricp->time, (info->fabricp->flags & FF_STATS) ? 1:0,
(info->fabricp->flags & FF_ROUTES) ? 1:0,
(info->fabricp->flags & FF_QOSDATA) ? 1:0,
(info->fabricp->flags & FF_BUFCTRLTABLE) ? 1:0,
(info->fabricp->flags & FF_DOWNPORTINFO) ? 1:0 );
for (i=1; i<info->argc; i++)
IXmlOutputPrint(state, "%s%s", i>1?" ":"", info->argv[i]);
IXmlOutputPrint(state, "\"");
}
static void Xml2PrintAll(IXmlOutputState_t *state, const char *tag, void *data)
{
SnapshotOutputInfo_t *info = (SnapshotOutputInfo_t *)IXmlOutputGetContext(state);
FabricData_t *fabricp = info->fabricp;
IXmlOutputStartAttrTag(state, tag, NULL, SnapshotInfoXmlFormatAttr);
{
cl_map_item_t *p;
IXmlOutputStartAttrTag(state, "Nodes", NULL, NULL);
for (p=cl_qmap_head(&fabricp->AllNodes); p != cl_qmap_end(&fabricp->AllNodes); p = cl_qmap_next(p)) {
NodeData *nodep = PARENT_STRUCT(p, NodeData, AllNodesEntry);
#if 0
if (! CompareNodePoint(nodep, info->focus))
continue;
#endif
NodeDataXmlOutput(state, "Node", nodep);
}
IXmlOutputEndTag(state, "Nodes");
}
{
cl_map_item_t *p;
IXmlOutputStartAttrTag(state, "SMs", NULL, NULL);
for (p=cl_qmap_head(&fabricp->AllSMs); p != cl_qmap_end(&fabricp->AllSMs); p = cl_qmap_next(p)) {
SMDataXmlOutput(state, "SM", PARENT_STRUCT(p, SMData, AllSMsEntry));
}
IXmlOutputEndTag(state, "SMs");
}
{
LIST_ITEM *p;
IXmlOutputStartAttrTag(state, "Links", NULL, NULL);
for (p=QListHead(&fabricp->AllPorts); p != NULL; p = QListNext(&fabricp->AllPorts, p)) {
PortData *portp = (PortData *)QListObj(p);
// to avoid duplicated processing, only process "from" ports in link
if (! portp->from)
continue;
LinkXmlOutput(state, "Link", portp);
}
IXmlOutputEndTag(state, "Links");
}
{
LIST_ITEM *p;
IXmlOutputStartAttrTag(state, "McMembers", NULL, NULL);
for (p=QListHead(&fabricp->AllMcGroups); p != NULL; p = QListNext(&fabricp->AllMcGroups, p)) {
McGroupData *mcgroupp = (McGroupData *)QListObj(p);
McGroupMemberXmlOutput(state, "MulticastGroup", mcgroupp);
}
IXmlOutputEndTag(state, "McMembers");
}
{
LIST_ITEM *p;
IXmlOutputStartTag(state, "VirtualFabrics");
for (p=QListHead(&fabricp->AllVFs); p != NULL; p = QListNext(&fabricp->AllVFs, p)) {
VFData_t *vf = (VFData_t *)QListObj(p);
IXmlOutputStruct(state, "VF", &vf->record, NULL, VFFields);
}
IXmlOutputEndTag(state, "VirtualFabrics");
}
IXmlOutputEndTag(state, tag);
}
void Xml2PrintSnapshot(FILE *file, SnapshotOutputInfo_t *info)
{
IXmlOutputState_t state;
/* using SERIALIZE with no indent makes output less pretty but 1/2 the size */
if (FSUCCESS != IXmlOutputInit(&state, file, 0, IXML_OUTPUT_FLAG_SERIALIZE, info))
//if (FSUCCESS != IXmlOutputInit(&state, file, 4, IXML_OUTPUT_FLAG_NONE, info))
goto fail;
//IXmlOutputStartAttrTag(&state, "Report", NULL, NULL);
Xml2PrintAll(&state, "Snapshot", NULL);
//IXmlOutputEndTag(&state, "Report");
IXmlOutputDestroy(&state);
return;
fail:
return;
}
#ifndef __VXWORKS__
FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull)
{
unsigned tags_found, fields_found;
const char *filename=input_file;
if (FSUCCESS != InitFabricData(fabricp, flags)) {
fprintf(stderr, "%s: Unable to initialize fabric data memory\n", g_Top_cmdname);
return FERROR;
}
if (strcmp(input_file, "-") == 0) {
filename="stdin";
if (! quiet) ProgressPrint(TRUE, "Parsing stdin...");
if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found)) {
return FERROR;
}
} else {
if (! quiet) ProgressPrint(TRUE, "Parsing %s...", Top_truncate_str(input_file));
if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found)) {
return FERROR;
}
}
if (tags_found != 1 || fields_found != 1) {
fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found);
}
BuildFabricDataLists(fabricp);
/*
Resize the switch FDB tables to their full capacity.
*/
if (allocFull) {
LIST_ITEM * n;
for (n = QListHead(&fabricp->AllSWs); n != NULL; n = QListNext(&fabricp->AllSWs, n)) {
NodeData * node = (NodeData*)QListObj(n);
STL_SWITCH_INFO * swInfo = &node->pSwitchInfo->SwitchInfoData;
// The snapshot may not have SwitchData in it. Tables will have to be provided by application (e.g.
// fabric_sim).
if (!node->switchp) continue;
assert(NodeDataSwitchResizeFDB(node, swInfo->LinearFDBCap, swInfo->MulticastFDBCap) == FSUCCESS);
}
}
return FSUCCESS;
}
#else
FSTATUS Xml2ParseSnapshot(const char *input_file, int quiet, FabricData_t *fabricp, FabricFlags_t flags, boolean allocFull, XML_Memory_Handling_Suite* memsuite)
{
unsigned tags_found, fields_found;
const char *filename=input_file;
if (FSUCCESS != InitFabricData(fabricp, flags)) {
fprintf(stderr, "%s: Unable to initialize fabric data memory\n", g_Top_cmdname);
return FERROR;
}
if (strcmp(input_file, "-") == 0) {
filename="stdin";
if (! quiet) ProgressPrint(TRUE, "Parsing stdin...");
if (FSUCCESS != IXmlParseFile(stdin, "stdin", IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found, memsuite)) {
return FERROR;
}
} else {
if (! quiet) ProgressPrint(TRUE, "Parsing %s...", Top_truncate_str(input_file));
if (FSUCCESS != IXmlParseInputFile(input_file, IXML_PARSER_FLAG_NONE, TopLevelFields, NULL, fabricp, NULL, NULL, &tags_found, &fields_found, memsuite)) {
return FERROR;
}
}
if (tags_found != 1 || fields_found != 1) {
fprintf(stderr, "Warning: potentially inaccurate input '%s': found %u recognized top level tags, expected 1\n", filename, tags_found);
}
BuildFabricDataLists(fabricp);
/*
Resize the switch FDB tables to their full capacity.
*/
if (allocFull) {
LIST_ITEM * n;
for (n = QListHead(&fabricp->AllSWs); n != NULL; n = QListNext(&fabricp->AllSWs, n)) {
NodeData * node = (NodeData*)QListObj(n);
STL_SWITCH_INFO * swInfo = &node->pSwitchInfo->SwitchInfoData;
// The snapshot may not have SwitchData in it. Tables will have to be provided by application (e.g.
// fabric_sim).
if (!node->switchp) continue;
assert(NodeDataSwitchResizeFDB(node, swInfo->LinearFDBCap, swInfo->MulticastFDBCap) == FSUCCESS);
}
}
return FSUCCESS;
}
#endif