// Regional Manager has a credit queue to send back flowcontrol credits?? void FLOWCONTROL_LI_CHANNEL_IN_CLASS::freeCredits(UINT32 serviceID) { if(SWITCH_DEBUG) { cout << "Channel " << serviceID << "Freeing credits: local: " << flowcontrolCredits << " regional: " << regionalFlowcontrol->GetRegionalCredits() << " returnThreshold: " << regionalReturnThreshold << endl; } if(((flowcontrolCredits > 0) && (regionalFlowcontrol->GetRegionalCredits() > regionalReturnThreshold)) || (flowcontrolCredits > regionalReturnThreshold / 2)) { if(SWITCH_DEBUG) { cout << "Channel " << serviceID << " sending back credits " << flowcontrolCredits << endl; } UMF_MESSAGE outMesg = factory->createUMFMessage(); outMesg->SetLength(sizeof(UMF_CHUNK)); outMesg->SetServiceID(flowcontrolChannelID); // Atomic read returns the old value, making this operation thread safe under idempotence. UINT32 creditsToReturn = flowcontrolCredits.fetch_and_store(0); UINT32 phyPvt = (serviceID * 2 * MULTIFPGA_FIFO_SIZES) | creditsToReturn; if(SWITCH_DEBUG) { cout << "Setting phy pvt to " << hex << phyPvt << dec <<endl; } outMesg->AppendChunk((UINT128) phyPvt); regionalFlowcontrol->FreeRegionalCredits(creditsToReturn); flowcontrolQ->push(outMesg); } }
void ROUTE_THROUGH_LI_CHANNEL_OUT_CLASS::push(UMF_MESSAGE &outMesg) { // Software expects encoding in terms of bytes while the credit scheme speaks in terms of chunks UINT32 messageLengthBytes = outMesg->GetLength(); UINT32 messageLengthChunks = 1 + ((outMesg->GetLength()) / sizeof(UMF_CHUNK)); // Each chunk takes a header plus one bit for encoding? if (DEBUG_CHANNELIO) { debugLog << endl << "****Outbound Channel "<< this->name << " Sends message " << endl; debugLog << endl << "Base Message length "<< dec << (UINT32) (outMesg->GetLength()) << endl; debugLog << "UMF_CHUNK (bytes) " << sizeof(UMF_CHUNK) << endl; debugLog << "Message Length (bytes) "<< dec << messageLengthBytes << endl; debugLog << "Message Credits (chunks) "<< dec << messageLengthChunks << endl; debugLog << "Channel ID "<< dec << this->channelID << endl; } // For now we will allow the system to deadlock here. What is really needed is an // means of back pressure all the way to the incoming route through. // TODO: Fix this deadlock with better backpressure cooperation among threads acquireCredits(messageLengthChunks); // Recode message for the outbound link and send { outMesg->SetServiceID(this->channelID); outputQ->push(outMesg); } if(DEBUG_CHANNELIO) { debugLog << endl << "****Outbound Route-through Channel "<< this->name << " message complete" << endl; } }
// accept a delivered message from channelio void RRR_SERVER_MONITOR_CLASS::DeliverMessage( UMF_MESSAGE message) { // record channelID for backwards compatibility int channelID = message->GetChannelID(); int serviceID = message->GetServiceID(); // validate serviceID if (isServerRegistered(serviceID) == false) { fprintf(stderr, "software server: invalid serviceID: %u\n", serviceID); parent->CallbackExit(1); } // call service and obtain result UMF_MESSAGE result = ServerMap[serviceID]->Request(message); // see if we need to respond if (result) { // set serviceID result->SetServiceID(serviceID); // send to channelio... send on original virtual channel (BC) channelio->Write(channelID, result); } }