📄 ixatmschserviceif.c
字号:
/* * @file IxAtmSchServiceIf.c * * * * * @brief Implementation file for Service Interface of the Atm scheduler. * * Design Notes: * All non data path invoked functionality is contained in this * file. Other functionality is separated as it is included * in internal IXP22x RAM. * * 26-FEB-02 Ported this code from IXP22x and modified to support * multiple ports. * * * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. Neither the name of the 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. * * * @par * 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. * * * @par * -- End of Copyright Notice -- *//* * Put the system defined include files required */#include "IxOsal.h"#include "IxAtmSch.h"#include "IxAtmSch_p.h"#include "IxAtmSchUtils_p.h"/* * Variable declarations global to this file only. Externs are followed by * static variables. */static UINT32 schPortRate[IX_UTOPIA_MAX_PORTS];static BOOL schInitDone = FALSE;static IxAtmTrafficDescriptor schTd[IX_ATM_MAX_NUM_AAL_OAM_TX_VCS];/* External variables defined in the AtmSch component.*/extern BOOL ixAtmSchedulingEnabled[IX_UTOPIA_MAX_PORTS];extern IxAtmSchVcInfo ixAtmSchVcTable[IX_ATM_MAX_NUM_AAL_OAM_TX_VCS];extern IxAtmSchedulerVcId ixAtmSchNextUbrToBeScheduled[IX_UTOPIA_MAX_PORTS];extern IxAtmSchedulerVcId ixAtmSchRtQueueHead[IX_UTOPIA_MAX_PORTS];extern IxAtmSchStats ixAtmSchStats[IX_UTOPIA_MAX_PORTS];extern UINT32 ixAtmSchBaseTime[IX_UTOPIA_MAX_PORTS];extern UINT32 ixAtmSchTime[IX_UTOPIA_MAX_PORTS];extern UINT32 ixAtmSchCacPortAllocated[IX_UTOPIA_MAX_PORTS];/* Function definition */PRIVATE intixAtmSchCac(IxAtmLogicalPort port, IxAtmTrafficDescriptor *trafficDesc);PRIVATE IxAtmSchedulerVcId ixAtmSchFreeVcIdGet( void );PRIVATE voidixAtmSchUbrChainVcInsert(IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);PRIVATE voidixAtmSchUbrChainVcRemove(IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);PRIVATE BOOLixAtmSchParamIsValid(IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);PRIVATE IX_STATUSixAtmSchRtVcInsert (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);PRIVATE voidixAtmSchRtVcRemove(IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);/************************************************************************//* This function is to initialize the scheduler component. It initialize * the variables and statistics value. This has to be called first.*/PUBLIC IX_STATUS ixAtmSchInit(void){ if (!schInitDone ) { ixAtmSchedulingInit(); ixAtmSchStatsClear(); schInitDone = TRUE; return IX_SUCCESS; } return IX_FAIL;}PUBLIC IX_STATUSixAtmSchUninit(void){ if (schInitDone) { schInitDone = FALSE; return IX_SUCCESS; } return IX_FAIL;}/************************************************************************//* This function is to show the information about the scheduler. */PUBLIC voidixAtmSchShow(void){ IxAtmSchedulerVcId i; IxAtmLogicalPort port; UINT32 vcCnt; if (!schInitDone) { printf("\n=========== IxAtmSch not initialized ==============\n"); } else { printf("\n================== IxAtmSch State =================="); for (port=0; port<IX_UTOPIA_MAX_PORTS; port++) { if (ixAtmSchedulingEnabled[port]) { printf("\n--- UTOPIA_PORT_%d Info ---",port); printf("\nRate = %u, UBR VC VcId = %d, Real-Time VcId = %d", schPortRate[port], ixAtmSchNextUbrToBeScheduled[port], ixAtmSchRtQueueHead[port]); /* */ printf("\n--- Shaping Statistics:"); printf("\nDemand Update Calls \t= %u", ixAtmSchStats[port].updateCalls); printf("\nCells Queued \t\t= %u", ixAtmSchStats[port].cellsQueued); printf("\nTable Update Calls \t= %u", ixAtmSchStats[port].scheduleTableCalls); printf("\nCells Scheduled \t= %u", ixAtmSchStats[port].cellsScheduled); printf("\nIdle Cells Scheduled \t= %u", ixAtmSchStats[port].idleCellsScheduled); printf("\nQueue Full Occurences\t= %u", ixAtmSchStats[port].queueFull); printf ("\nAllocated Bandwidth \t= %d\n",ixAtmSchCacPortAllocated[port]); /* */ printf("\n--- VC information:"); printf("\n%-4s %-4s %-8s %-8s %-8s %-4s %-4s %-8s %-7s %-8s", "VcId", "serv", "pcr", "scr", "cdvt", "mbs", "mfs", "count", "nextVc", "connId"); for (i=0, vcCnt = 0; i<IX_ATM_MAX_NUM_AAL_OAM_TX_VCS; i++) { if ((ixAtmSchVcTable[i].inUse == TRUE) && (ixAtmSchVcTable[i].port == port)) { vcCnt++; printf("\n%-4d %-4d %-8u %-8u %-8u %-4u %-4d %-8u %-7d %-8u", i, schTd[i].atmService, schTd[i].pcr, schTd[i].scr, schTd[i].cdvt, schTd[i].mbs, schTd[i].mfs, ixAtmSchVcTable[i].count, ixAtmSchVcTable[i].nextVc, ixAtmSchVcTable[i].connId); } } if ( vcCnt == 0 ) { printf("\nNo VCs"); } } } printf("\n====================================================\n"); }}/************************************************************************//* This function is to clear the scheduler statistics */PUBLIC voidixAtmSchStatsClear(void){ IxAtmLogicalPort port; /* clear all port statistics */ for ( port = 0 ; port < IX_UTOPIA_MAX_PORTS ; port++ ) { ixAtmSchStats[port].idleCellsScheduled = 0; ixAtmSchStats[port].updateCalls = 0; ixAtmSchStats[port].cellsQueued = 0; ixAtmSchStats[port].cellsScheduled = 0; ixAtmSchStats[port].queueFull = 0; ixAtmSchStats[port].scheduleTableCalls = 0; } return;}/************************************************************************//* This is to initialize the scheduler model by setting the portRate and * the minimum cells to scheduler for that particular port. This is done * once the IxAtmSchInit is completed. Also, the PortEnabling for that * port is set to TRUE to indicate that the port is enabled */PUBLIC IX_STATUSixAtmSchPortModelInitialize( IxAtmLogicalPort port, unsigned int portRate, unsigned int minCellsToSchedule){ if (!schInitDone|| (port<IX_UTOPIA_PORT_0)|| (port>=IX_UTOPIA_MAX_PORTS)|| (ixAtmSchedulingEnabled[port])|| (portRate == 0)) { return IX_FAIL; } else { /* Store the port rate into a global variable for a particular port */ schPortRate[port] = portRate; /* set the time between cell */ ixAtmSchCellTimeSet(port, (IX_ATMSCH_US_PER_SECOND / portRate)); /* Set the min cell that can be scheduled */ ixAtmSchMinCellsSet(port, minCellsToSchedule); ixAtmSchedulingEnabled[port] = TRUE; return IX_SUCCESS; }}/************************************************************************/PUBLIC IX_STATUSixAtmSchPortModelUninitialize( IxAtmLogicalPort port){ if (!schInitDone|| /* Check the port limits */ (port<IX_UTOPIA_PORT_0)|| (port>=IX_UTOPIA_MAX_PORTS)|| (!ixAtmSchedulingEnabled[port])) { return IX_FAIL; } else { ixAtmSchedulingEnabled[port] = FALSE; /* Set the port to disabled */ return IX_SUCCESS; }}/************************************************************************//* This function allows the modification of port rate for that particular * port. The requested port rate can be set below the CacPortAllocated value, * i.e. allows oversubscription */PUBLIC IX_STATUSixAtmSchPortRateModify( IxAtmLogicalPort port, unsigned int portRate){ IxAtmSchedulerVcId thisRtVc; if (!schInitDone|| (port<IX_UTOPIA_PORT_0)|| (port>=IX_UTOPIA_MAX_PORTS)|| !ixAtmSchedulingEnabled[port]) { return IX_FAIL; } thisRtVc = ixAtmSchRtQueueHead[port]; schPortRate[port] = portRate; ixAtmSchCellTimeSet(port, IX_ATMSCH_US_PER_SECOND / portRate); return IX_SUCCESS;}/************************************************************************//* This function is to check whether atm services complies with the CAC */PRIVATE intixAtmSchCac(IxAtmLogicalPort port, IxAtmTrafficDescriptor *trafficDesc){ IX_STATUS retval = IX_SUCCESS; switch(trafficDesc->atmService) { case IX_ATM_ABR: return IX_FAIL; case IX_ATM_CBR: if ((trafficDesc->pcr > (schPortRate[port] - ixAtmSchCacPortAllocated[port])) || (trafficDesc->pcr == 0)) { retval = IX_ATMSCH_RET_NOT_ADMITTED; } else { ixAtmSchCacPortAllocated[port] += trafficDesc->pcr; } break; case IX_ATM_UBR: /* UBR PCR must be at least equal to the port rate */ if (trafficDesc->pcr < schPortRate[port]) { retval = IX_ATMSCH_RET_NOT_ADMITTED; } break; case IX_ATM_VBR: case IX_ATM_RTVBR: if ((trafficDesc->scr > (schPortRate[port] - ixAtmSchCacPortAllocated[port])) || (trafficDesc->scr > trafficDesc->pcr) || (trafficDesc->pcr > schPortRate[port]) || (trafficDesc->pcr == 0) || (trafficDesc->scr == 0)) { retval = IX_ATMSCH_RET_NOT_ADMITTED; } else { ixAtmSchCacPortAllocated[port] += trafficDesc->scr; } break; default: /* Unknown service type */ IX_ATMSCH_ASSERT(FALSE); retval = IX_FAIL; } return retval;}/************************************************************************//* This function is to search for the free VC ID */PRIVATE IxAtmSchedulerVcIdixAtmSchFreeVcIdGet( void ) { IxAtmSchedulerVcId i; for (i=0; i<IX_ATM_MAX_NUM_AAL_OAM_TX_VCS; i++) { if (ixAtmSchVcTable[i].inUse == FALSE) { return i; } } return IX_ATMSCH_NULL_INDEX;}/************************************************************************//* This function is used to insert the real-time VCs into a list. It also * calculates the PCR and SCR in microseconds, and BT. */PRIVATE IX_STATUSixAtmSchRtVcInsert (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId){ IxAtmSchedulerVcId qPtr; IX_STATUS retVal = IX_SUCCESS; /* Port and vcId already been check by the caller function. No * additional check */ /* Calculate #microseconds between each VBR cell for PCR and SCR */ ixAtmSchVcTable[vcId].schInfo.usPcr = IX_ATMSCH_US_PER_SECOND / schTd[vcId].pcr; ixAtmSchVcTable[vcId].schInfo.pcr = schTd[vcId].pcr; /* insert the ATM service category for that VC */ ixAtmSchVcTable[vcId].atmService = schTd[vcId].atmService; if (schTd[vcId].atmService != IX_ATM_CBR) { /* This is for VBR */ ixAtmSchVcTable[vcId].schInfo.usScr = IX_ATMSCH_US_PER_SECOND / schTd[vcId].scr; ixAtmSchVcTable[vcId].schInfo.scr = schTd[vcId].scr; if (schTd[vcId].mbs > 0) { /* BT = ((MBS - 1) * (1/SCR - 1/PCR)) */ ixAtmSchVcTable[vcId].schInfo.bt = (schTd[vcId].mbs - 1) * (ixAtmSchVcTable[vcId].schInfo.usScr - ixAtmSchVcTable[vcId].schInfo.usPcr); /* Store mbs locally and VBR's PCR cell count for future ref */ ixAtmSchVcTable[vcId].vbrPcrCellsCnt = ixAtmSchVcTable[vcId].schInfo.mbs = schTd[vcId].mbs; /* Store BT for future reference */ ixAtmSchVcTable[vcId].schInfo.baseBt = ixAtmSchVcTable[vcId].schInfo.bt; } else { /* No MBS value. Hence set bt to 0 */ ixAtmSchVcTable[vcId].schInfo.bt = 0; } /* The largest Burst Tolerance of the system determines the * lowest value of 'time' that will be used in the scheduling * algorithm */ if (ixAtmSchBaseTime[port] <= ixAtmSchVcTable[vcId].schInfo.bt) { retVal = ixAtmSchBaseTimeSet(port,ixAtmSchVcTable[vcId].schInfo.bt + 1); if (IX_SUCCESS != retVal) { return retVal; } } } else { /* CBR does not use these fields. The fact that they are zero * identifies this VC as CBR more efficiently. */ ixAtmSchVcTable[vcId].schInfo.usScr = 0; ixAtmSchVcTable[vcId].schInfo.bt = 0; } /* Once the calculation is completed. The next thing to do is to insert * the VC into the list */ qPtr = ixAtmSchRtQueueHead[port]; if (qPtr == IX_ATMSCH_NULL_INDEX) { /* First entry in the queue */ ixAtmSchVcTable[vcId].nextVc = IX_ATMSCH_NULL_INDEX; ixAtmSchRtQueueHead[port] = vcId; } else { /* Insert VC at the end of the queue */ while (ixAtmSchVcTable[qPtr].nextVc != IX_ATMSCH_NULL_INDEX) { qPtr = ixAtmSchVcTable[qPtr].nextVc; } ixAtmSchVcTable[qPtr].nextVc = vcId; ixAtmSchVcTable[vcId].nextVc = IX_ATMSCH_NULL_INDEX; } /* This initial setting will cause the first cell to be scheduled * immediately on this VC */ ixAtmSchVcTable[vcId].schInfo.cet = ixAtmSchTime[port] | IX_ATMSCH_UINT_MASK; return retVal;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -