/** * @brief writes a filtering entry in NPE linear format * * @param node: node to be written * @param baseAddress: base memory address to write node to * @param entryOffset: number of entries to offset * @param maxByteSize: maximum size of memory area to write to * * @return the byte offset of the next entry * * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree * in NPE-readable format. * * @internal */ IX_ETH_DB_PRIVATE UINT32 ixEthDBNPELearningNodeWrite(MacTreeNode *node, void *baseAddress, UINT32 entryOffset, UINT32 maxByteSize) { void *address = (void*) ((UINT32)baseAddress + (entryOffset * ELT_ENTRY_SIZE)); UINT32 byteSize = (entryOffset+1) * ELT_ENTRY_SIZE; /* if the size is greater than max, do nothing and return the max */ if(byteSize > maxByteSize) return byteSize; /* If node is NULL, zero out this record in memory */ if(NULL == node) { ixOsalMemSet(address, 0, ELT_ENTRY_SIZE); return byteSize; } /* copy mac address */ ixOsalMemCopy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); /* copy port ID */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_PORT_ID_OFFSET) = IX_ETHNPE_PHYSICAL_ID_TO_LOGICAL_ID(node->descriptor->portID); /* copy flags (valid and not active, as the NPE sets it to active) and clear reserved section (bits 2-7) */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_ELT_FLAGS_OFFSET) = (UINT8) IX_EDB_FLAGS_INACTIVE_VALID; IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing ELT node 0x%08x:0x%08x\n", * (UINT32 *) address, * (((UINT32 *) (address)) + 1)); return byteSize; }
/* * Function definition : ixDmaAccCodeletTestPatternReset() * See header file for documentation. */ PRIVATE void ixDmaAccCodeletTestPatternReset(void) { /* Counter for Test For-Loops */ UINT32 i,j; /* Test pattern is loaded into a temporary array here */ UINT8 testPattern[IX_DMA_CODELET_TESTPATTERN_LENGTH] = IX_DMA_CODELET_TESTPATTERN_LIST; /* Initialise the values in the Source Array */ for ( i = 0; i < IX_DMA_CODELET_TEST_MAXLENGTH; i += IX_DMA_CODELET_TESTPATTERN_LENGTH) { for ( j = 0; j < IX_DMA_CODELET_TESTPATTERN_LENGTH; j += 1) { ixDmaAccCodeletSrcBlock[i+j] = testPattern[j]; } } /* Flush the cache before performing a write to memory block */ IX_OSAL_CACHE_FLUSH(ixDmaAccCodeletSrcBlock,IX_DMA_CODELET_TESTPATTERN_LENGTH); /* Initialise the values in the Destination Array */ ixOsalMemSet( ixDmaAccCodeletDestBlock, 0xFF, IX_DMA_CODELET_TEST_MAXLENGTH); /* Flush the cache before performing a write to memory block */ IX_OSAL_CACHE_FLUSH(ixDmaAccCodeletDestBlock,IX_DMA_CODELET_TESTPATTERN_LENGTH); return; }
/** * @fn ixCryptoCCDMgmtCryptoCtxReleaseAll * @brief Release ALL Crypto Context back to the CCD pool. * */ void ixCryptoCCDMgmtCryptoCtxReleaseAll (void) { UINT32 i; for (i = 0; i < IX_CRYPTO_ACC_MAX_ACTIVE_SA_TUNNELS; i++) { /* Mark valid bit in Crypto Context to FALSE */ ixCryptoCtx[i].valid = FALSE; /* Assign Crypto Context ID to Crypto Context list */ cryptoCtxList[i] = i; /* Clear NPE Param structure */ ixOsalMemSet ( ixCryptoCtx[i].pNpeCryptoParam->npeCryptoInfo, 0, IX_CRYPTO_MAX_CRYPTO_INFO_BYTES); } /* end of for (cryptoCtxCount) */ /* Reset Crypto Context List head pointer */ cryptoCtxCount = IX_CRYPTO_ACC_MAX_ACTIVE_SA_TUNNELS; } /* end of ixCryptoCCDMgmtCryptoCtxReleaseAll () function */
/** * @brief writes a WiFi bssid header conversion record in * NPE linear format * * @param node: node to be written * @param baseAddress: base memory address to write node to * @param entryOffset: number of entries to offset * @param maxByteSize: maximum size of memory area to write to * * @return the byte offset of the next entry * * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree * in NPE-readable format. * * @internal */ IX_ETH_DB_PUBLIC UINT32 ixEthDBNPEBssidNodeWrite(MacTreeNode *node, void *baseAddress, UINT32 entryOffset, UINT32 maxByteSize) { void *address = (void*) ((UINT32)baseAddress + (entryOffset * ELT_ENTRY_SIZE)); UINT32 byteSize = (entryOffset+1) * ELT_ENTRY_SIZE; /* if the size is greater than max, do nothing and return the max */ if(byteSize > maxByteSize) return byteSize; /* If node is NULL, zero out this record in memory */ if(NULL == node) { ixOsalMemSet(address, 0, ELT_ENTRY_SIZE); return byteSize; } /* copy mac address */ ixOsalMemCopy(address, node->descriptor->recordData.wifiData.bssid, IX_IEEE803_MAC_ADDRESS_SIZE); /* set destination port and reserved fields */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_BSSID_DEST_PORT_OFFSET) = node->descriptor->recordData.wifiData.logicalPortID; NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_BSSID_RESERVED_OFFSET) = 0; return byteSize; }
/** * @brief writes a WiFi header conversion record in * NPE linear format * * @param node: node to be written * @param baseAddress: base memory address to write node to * @param entryOffset: number of entries to offset * @param maxByteSize: maximum size of memory area to write to * * @return the byte offset of the next entry * * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree * in NPE-readable format. * * @internal */ IX_ETH_DB_PRIVATE UINT32 ixEthDBNPEWiFiNodeWrite(MacTreeNode *node, void *baseAddress, UINT32 entryOffset, UINT32 maxByteSize) { void *address = (void*) ((UINT32)baseAddress + (entryOffset * ELT_ENTRY_SIZE)); UINT32 byteSize = (entryOffset+1) * ELT_ENTRY_SIZE; /* if the size is greater than max, do nothing and return the max */ if(byteSize > maxByteSize) return byteSize; /* If node is NULL, zero out this record in memory */ if(NULL == node) { ixOsalMemSet(address, 0, ELT_ENTRY_SIZE); return byteSize; } /* copy mac address */ ixOsalMemCopy(address, node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); /* copy index */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_INDEX_OFFSET) = node->descriptor->recordData.wifiData.recIndex; /* copy flags (type and valid) */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_WIFI_FLAGS_OFFSET) = node->descriptor->recordData.wifiData.padLength << 4 | node->descriptor->recordData.wifiData.recType << 1 | IX_EDB_FLAGS_VALID; return byteSize; }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletPTPMsgBuild ( UINT8 control) * * @brief Build PTP message using UDP protocol. * * UDP headers for all PTP messages * * N Byte Count Field Name * * 0 6 destination MAC address * 6 6 source MAC address * 12 2 type (0x0800 = IP datagram) * 14 1 version IPV4, IP header length * 15 1 type of service * 16 2 IP datagram length * 18 2 datagram sequence number * 20 2 flags/fragments * 22 1 time to live (TTL) * 23 1 Protocol: UDP * 24 2 IP header checksum * 26 4 source IP address * 30 4 destination IP address * 34 2 source port number * 36 2 destination port number * 38 2 UDP length * 40 2 UDP checksum * * PTP Sync and Delay_Req message specification (UDP user payload portion) * * 42 2 version PTP * 44 2 version network * 46 16 subdomain * 62 1 message type * 63 1 source communication technology * 64 6 source UUID * 70 2 source port ID * 72 2 sequence ID * 74 1 control * 75 1 reserved * 76 2 flags * 78 4 reserved * 82 4 origin timestamp (seconds) * 86 4 origin timestamp (nanoseconds) * 90 2 epoch number * 92 2 current UTC offset * 94 1 reserved * 95 1 grandmaster communication technology * 96 6 grandmaster clock UUID * 102 2 grandmaster port ID * 104 2 grandmaster sequence ID * 106 3 reserved * 109 1 grandmaster clock stratum * 110 4 grandmaster clock identifier * 114 2 reserved * 116 2 grandmaster clock variance * 118 1 reserved * 119 1 grandmaster preferred * 120 1 reserved * 121 1 grandmaster's boundary clock * 122 3 reserved * 125 1 sync interval * 126 2 reserved * 128 2 local clock variance * 130 2 reserved * 132 2 local steps removed * 134 3 reserved * 137 1 local clock stratum * 138 4 local clock identifier * 142 1 reserved * 143 1 parent comminucation technology * 144 6 parent UUID * 150 2 reserved * 152 2 parent port field * 154 2 reserved * 156 2 estimate master variance * 158 4 estimate master drift * 162 3 reserved * 165 1 utc reasonable * * This function only fills the relevant fields that the Time Sync * hardware reads to recognize the frame as PTP message. * * @param * control UINT8 [in] - control field of PTP message * - 0 : Sync Message * - 1 : Delay_Req Message * * @return void */ PRIVATE void ixTimeSyncAccCodeletPTPMsgBuild (UINT8 control) { UINT8 *compPtr; compPtr = ixTimeSyncAccCodeletPtpMsgData; ixOsalMemSet (compPtr, 0, IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN); compPtr[12] = IX_TIMESYNCACC_CODELET_MSB_VALUE(IX_TIMESYNCACC_CODELET_IP_DATAGRAM); compPtr[13] = IX_TIMESYNCACC_CODELET_LSB_VALUE(IX_TIMESYNCACC_CODELET_IP_DATAGRAM); compPtr[14] = IX_TIMESYNCACC_CODELET_IP_HEADER_LEN; compPtr[16] = IX_TIMESYNCACC_CODELET_MSB_VALUE(IX_TIMESYNCACC_CODELET_IP_DATAGRAM_LEN); compPtr[17] = IX_TIMESYNCACC_CODELET_LSB_VALUE(IX_TIMESYNCACC_CODELET_IP_DATAGRAM_LEN); compPtr[22] = IX_TIMESYNCACC_CODELET_TIME_TO_LIVE; compPtr[23] = IX_TIMESYNCACC_CODELET_UDP_PROTOCOL; compPtr[30] = ixTimeSyncAccCodeletPTPMulticastAddress[0]; compPtr[31] = ixTimeSyncAccCodeletPTPMulticastAddress[1]; compPtr[32] = ixTimeSyncAccCodeletPTPMulticastAddress[2]; compPtr[33] = ixTimeSyncAccCodeletPTPMulticastAddress[3]; compPtr[36] = IX_TIMESYNCACC_CODELET_MSB_VALUE(IX_TIMESYNCACC_CODELET_PTP_EVENT_PORT); compPtr[37] = IX_TIMESYNCACC_CODELET_LSB_VALUE(IX_TIMESYNCACC_CODELET_PTP_EVENT_PORT); compPtr[39] = IX_TIMESYNCACC_CODELET_UDP_PAYLOAD_LEN; compPtr[62] = IX_TIMESYNCACC_CODELET_PTP_MESSAGE_TYPE; compPtr[74] = control; } /* end of ixTimeSyncAccCodeletPTPMsgBuild function */
/** * @brief writes a firewall record in * NPE linear format * * @param node: node to be written * @param baseAddress: base memory address to write node to * @param entryOffset: number of entries to offset * @param maxByteSize: maximum size of memory area to write to * * @return the byte offset of the next entry * * Used by @ref ixEthDBNPETreeWrite to liniarize a search tree * in NPE-readable format. * * @internal */ IX_ETH_DB_PRIVATE UINT32 ixEthDBNPEFirewallNodeWrite(MacTreeNode *node, void *baseAddress, UINT32 entryOffset, UINT32 maxByteSize) { void *address = (void*) ((UINT32)baseAddress + (entryOffset * FW_ENTRY_SIZE)); UINT32 byteSize = (entryOffset+1) * FW_ENTRY_SIZE; /* if the size is greater than max, do nothing and return the max */ if(byteSize > maxByteSize) return byteSize; /* If node is NULL, zero out this record in memory */ if(NULL == node) { ixOsalMemSet(address, 0, FW_ENTRY_SIZE); return byteSize; } /* set reserved field */ NPE_NODE_BYTE(address, 0) = 0; /* set flags */ NPE_NODE_BYTE(address, IX_EDB_NPE_NODE_FW_FLAGS_OFFSET) = IX_EDB_FLAGS_VALID; /* copy mac address */ ixOsalMemCopy((void *) ((UINT32) address + IX_EDB_NPE_NODE_FW_ADDR_OFFSET), node->descriptor->macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); return byteSize; }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletMbufAllocate () * * @brief Allocate memory for mBuf and its associated data buffer * * @return * @li IX_OSAL_MBUF * - successfully allocated memory for mBuf * @li NULL - fail */ PRIVATE IX_OSAL_MBUF *ixTimeSyncAccCodeletMbufAllocate () { IX_OSAL_MBUF *mBufPtr; UINT8 *dataPtr; /* Allocate cache-aligned memory for mbuf header */ mBufPtr = (IX_OSAL_MBUF *) IX_OSAL_CACHE_DMA_MALLOC (sizeof (IX_OSAL_MBUF)); if (NULL == mBufPtr) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletMbufAllocate: failed to allocate memory for mBuf\n", 0, 0, 0, 0, 0, 0); return NULL; } /* initialize mBuf */ ixOsalMemSet (mBufPtr, 0, sizeof (IX_OSAL_MBUF)); /* Allocate cache-aligned memory for mbuf data */ dataPtr = (UINT8 *) IX_OSAL_CACHE_DMA_MALLOC (IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN); if (NULL == dataPtr) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletMbufAllocate: failed to allocate memory for mBuf's data buffer\n", 0, 0, 0, 0, 0, 0); return NULL; } /* initialize mBuf's data buffer */ ixOsalMemSet (dataPtr, 0, IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN); /* Fill in mbuf header fields */ IX_OSAL_MBUF_MDATA (mBufPtr) = dataPtr; IX_OSAL_MBUF_ALLOCATED_BUFF_DATA (mBufPtr) = (UINT32)dataPtr; IX_OSAL_MBUF_MLEN (mBufPtr) = IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN; IX_OSAL_MBUF_ALLOCATED_BUFF_LEN (mBufPtr) = IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN; IX_OSAL_MBUF_PKT_LEN (mBufPtr) = IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN; return mBufPtr; } /* end of ixTimeSyncAccCodeletMbufAllocate function */
/* ----------------------------------------------------- * reset tx statistics */ void ixAtmdAccTxCfgIfStatsReset (void) { /* initialise the error counters */ ixOsalMemSet(&ixAtmdAccTxStats, 0, sizeof(ixAtmdAccTxStats)); /* initialise the stats of the dependant component */ ixAtmdAccTxCfgInfoStatsReset(); }
/** * @brief event processor routine * * @param event event to be processed * @param triggerPorts port map accumulating ports to be updated * * Processes learning events by synchronizing the database with * newly learnt data. Called only by @ref ixEthDBEventProcessorLoop(). * * @warning do not call directly * * @internal */ IX_ETH_DB_PRIVATE void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts) { MacDescriptor recordTemplate; switch (local_event->eventType) { case IX_ETH_DB_ADD_FILTERING_RECORD: /* add record */ ixOsalMemSet(&recordTemplate, 0, sizeof (recordTemplate)); ixOsalMemCopy(recordTemplate.macAddress, local_event->macAddr.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); recordTemplate.type = IX_ETH_DB_FILTERING_RECORD; recordTemplate.portID = local_event->portID; recordTemplate.recordData.filteringData.staticEntry = local_event->staticEntry; ixEthDBAdd(&recordTemplate, triggerPorts); IX_ETH_DB_EVENTS_TRACE("DB: (Events) Added record on port %d\n", local_event->portID); break; case IX_ETH_DB_REMOVE_FILTERING_RECORD: /* remove record */ ixOsalMemSet(&recordTemplate, 0, sizeof (recordTemplate)); ixOsalMemCopy(recordTemplate.macAddress, local_event->macAddr.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); recordTemplate.type = IX_ETH_DB_FILTERING_RECORD | IX_ETH_DB_FILTERING_VLAN_RECORD; ixEthDBRemove(&recordTemplate, triggerPorts); IX_ETH_DB_EVENTS_TRACE("DB: (Events) Removed record on port %d\n", local_event->portID); break; default: /* can't handle/not interested in this event type */ ERROR_LOG("DB: (Events) Event processor received an unknown event type (0x%X)\n", local_event->eventType); return; } }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, char *label) * * @brief Spawn a thread to execute given function * * @param * func IxOsalVoidFnPtr [in] - pointer to the function that will be * executed after the thread is spawned. * @param * label char* [in] - pointer to the Thread name's buffer * * @return IX_STATUS * @li IX_SUCCESS - create and start Thread successfully * @li IX_FAIL - fail */ PRIVATE IX_STATUS ixTimeSyncAccCodeletNewThreadCreate ( IxOsalVoidFnPtr func, char *label) { IxOsalThread threadId; IxOsalThreadAttr threadAttr; /* check the validity of function pointer */ if (NULL == func) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: NULL function pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* check the validity of Thread name's buffer pointer */ if (NULL == label) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: NULL Thread name's pointer\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* zero out the thread attribute buffer */ ixOsalMemSet ((void *)&threadAttr, 0, sizeof (IxOsalThreadAttr)); /* setup thread attribute */ threadAttr.name = label; threadAttr.priority = IX_OSAL_DEFAULT_THREAD_PRIORITY; if (IX_SUCCESS != ixOsalThreadCreate (&threadId, &threadAttr, (IxOsalVoidFnVoidPtr)func, NULL)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: Failed to spawn %s thread\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } if (IX_SUCCESS != ixOsalThreadStart (&threadId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletNewThreadCreate: Failed to start %s thread\n", (UINT32) label, 0, 0, 0, 0, 0); return IX_FAIL; } return IX_SUCCESS; } /* end of ixTimeSyncAccCodeletNewThreadCreate function */
IX_STATUS ixAtmmUtopiaCfgUninit (void) { IX_STATUS retval; /* Fill out the utopia Sysconfig structure to reset*/ utopiaSysConfigReset (&ixAtmmUtCfg); /* Call IxAtmdAcc to write the Config */ retval = ixAtmdAccUtopiaConfigReset (&ixAtmmUtCfg); /* Clear the Config struct */ ixOsalMemSet (&ixAtmmUtCfg, 0, sizeof (IxAtmdAccUtopiaConfig)); return retval; }
/** * @brief register record key types * * This function registers the appropriate key types, * depending on record types. * * All filtering records use the MAC address as the key. * WiFi records use a compound key consisting * in both the MAC address and the port ID. * Firewall records use a compound key consisting * of the masked MAC address, the mask and the port ID. * * @return the number of registered record types */ IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyTypeRegister(UINT32 *keyType) { /* safety */ ixOsalMemSet(keyType, 0, sizeof (keyType)); /* register all known record types */ keyType[IX_ETH_DB_FILTERING_RECORD] = IX_ETH_DB_MAC_KEY; keyType[IX_ETH_DB_FILTERING_VLAN_RECORD] = IX_ETH_DB_MAC_KEY; keyType[IX_ETH_DB_ALL_FILTERING_RECORDS] = IX_ETH_DB_MAC_KEY; keyType[IX_ETH_DB_WIFI_RECORD] = IX_ETH_DB_MAC_PORT_KEY; keyType[IX_ETH_DB_FIREWALL_RECORD] = IX_ETH_DB_MAC_PORT_KEY; keyType[IX_ETH_DB_MASKED_FIREWALL_RECORD]= IX_ETH_DB_MAC_MASK_PORT_KEY; return 6; }
/* ---------------------------------------------- */ PRIVATE IX_STATUS ixAtmdAccUtopiaStatusRead (IxAtmdAccUtopiaStatus *utStatus) { IX_STATUS returnStatus = IX_SUCCESS; UINT32 utStatusWords[sizeof(IxAtmdAccUtopiaStatus)/sizeof(UINT32)]; int numWords = sizeof(IxAtmdAccUtopiaStatus)/sizeof(UINT32); int wordCnt; UINT32 readOffset; IX_ATMDACC_ENSURE (numWords < 64, "out of bound structure"); ixOsalMemSet (utStatus, 0, sizeof (IxAtmdAccUtopiaStatus)); /* Read the status table from NPE memory */ for (wordCnt = 0; (wordCnt < numWords) && (returnStatus == IX_SUCCESS); wordCnt++) { /* offset to read */ readOffset = wordCnt * sizeof(UINT32); /* read the word of the status table at this offset */ returnStatus = ixAtmdAccUtilNpeMsgWithResponseSend( IX_NPE_A_MSSG_ATM_UTOPIA_STATUS_READ, readOffset, NPE_IGNORE, ixAtmdAccNpeStatusReadCallback); if (returnStatus == IX_SUCCESS) { /* Wait for ixAtmdAccNpeReadCallback to release */ IX_ATMDACC_NPE_RESPONSE_LOCK_GET (); /* Check the address matches the address from ixAtmdAccNpeReadCallback */ IX_ATMDACC_ENSURE (npeRespOffsetRead == readOffset, "Read error"); /* Copy the word read from NPE memory into the utopia status * structure. NOTE: npewordRead is set by ixAtmdAccNpeReadCallback */ utStatusWords[wordCnt] = npeRespWordRead; } /* end of if(returnStatus) */ } /* end of for(wordCnt) */ ixAtmdAccNpeStatusGenerate(utStatus,utStatusWords); return returnStatus; }
/** * @fn ixCryptoCCDMgmtKeyCryptoParamRelease * @brief Release Crypto Param structure back to the key crypto param pool. * */ IxCryptoAccStatus ixCryptoCCDMgmtKeyCryptoParamRelease (UINT32 keyId) { IxCryptoAccStatus status; /* Clear NPE Param structure */ ixOsalMemSet ( ixKeyCryptoParam[keyId].pNpeCryptoParam->npeCryptoInfo, 0, IX_CRYPTO_MAX_CRYPTO_INFO_BYTES); /* Lock keyCryptoParamList to protect critical section */ IX_CRYPTO_ACC_LOCK (keyCryptoParamLock); if (keyCryptoParamCount < IX_CRYPTO_ACC_KEY_CRYPTO_PARAM_NUM) { /* Push the crypto param back to the pool */ keyCryptoParamList[keyCryptoParamCount++] = keyId; status = IX_CRYPTO_ACC_STATUS_SUCCESS; } else /* keyCryptoParamCount >= IX_CRYPTO_ACC_KEY_CRYPTO_PARAM_NUM) */ { /* Log error message in debugging mode */ IX_CRYPTO_ACC_LOG ( IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "Key Crypto Param %d release failed.\n", keyId, 0, 0, 0, 0, 0); /* Key Crypto Param overflow */ status = IX_CRYPTO_ACC_STATUS_FAIL; } /* end of if-else(keyCryptoParamCount) */ /* Unlock given mutex */ IX_CRYPTO_ACC_UNLOCK (keyCryptoParamLock); return status; } /* end of ixCryptoCCDMgmtKeyCryptoParamRelease () function */
/** * @fn ixCryptoCCDMgmtCryptoCtxRelease * @brief Release Crypto Context back to the CCD pool. * */ IxCryptoAccStatus ixCryptoCCDMgmtCryptoCtxRelease (UINT32 cryptoCtxId) { /* Mark valid bit in Crypto Context to FALSE */ ixCryptoCtx[cryptoCtxId].valid = FALSE; if (cryptoCtxCount < IX_CRYPTO_ACC_MAX_ACTIVE_SA_TUNNELS) { /* Clear NPE Param structure */ ixOsalMemSet ( ixCryptoCtx[cryptoCtxId].pNpeCryptoParam->npeCryptoInfo, 0, IX_CRYPTO_MAX_CRYPTO_INFO_BYTES); /* Lock cryptoCtxList to protect critical section */ IX_CRYPTO_ACC_LOCK (cryptoCtxListLock); /* Push the Crypto Context back to the CCD */ cryptoCtxList[cryptoCtxCount++] = cryptoCtxId; /* Unlock */ IX_CRYPTO_ACC_UNLOCK (cryptoCtxListLock); return IX_CRYPTO_ACC_STATUS_SUCCESS; } else /* cryptoCtxCount >= IX_CRYPTO_ACC_MAX_ACTIVE_SA_TUNNELS) */ { /* Log error message in debugging mode */ IX_CRYPTO_ACC_LOG ( IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "Crypto Context %d release failed.\n", cryptoCtxId, 0, 0, 0, 0, 0); /* CCD overflow */ return IX_CRYPTO_ACC_STATUS_FAIL; } /* end of if-else(cryptoCtxCount) */ } /* end of ixCryptoCCDMgmtCryptoCtxRelease () function */
/* ---------------------------------------------------- get a NPE descriptor */ IX_STATUS ixAtmdAccDescNpeDescriptorGet (IxAtmdAccNpeDescriptor** npeDescriptorPtr) { IX_STATUS returnStatus = IX_SUCCESS; IX_ATMDACC_ENSURE (initDone, "Initialisation Error"); IX_ATMDACC_DESCMGMT_LOCK(); /* check parameter */ IX_ATMDACC_ENSURE (npeDescriptorPtr != NULL, "null pointer parameter"); /* sanity check */ IX_ATMDACC_ENSURE(npeDescCount <= IX_ATMDACC_MAX_NPE_DESCRIPTORS, "descriptor pool index corrupted"); /* check there is an entry in the pool */ IX_ATMDACC_ENSURE (npeDescCount > 0, "Pool size mismatch"); if (npeDescCount > 0) { /* get the descriptor from the pool */ *npeDescriptorPtr = npeDescriptorArray[--npeDescCount]; ixOsalMemSet(&(*npeDescriptorPtr)->npe, 0, sizeof((*npeDescriptorPtr)->npe)); /* update stats */ descMgmtStats.allocateCount++; } else { returnStatus = IX_FAIL; } /* end of if-else(npeDescCount) */ IX_ATMDACC_DESCMGMT_UNLOCK(); return returnStatus; }
/* ------------------------------------------------------ Function definitions visable to this file only. ------------------------------------------------------ */ IX_STATUS ixAtmmUtopiaCfgInit (unsigned numPorts, IxAtmmPhyMode phyMode, IxAtmmPortCfg portCfgs[], IxAtmmUtopiaLoopbackMode loopbackMode) { IX_STATUS retval; retval = utCfgParamsCheck (numPorts, phyMode, portCfgs, loopbackMode); /* Loopback mode */ if (retval == IX_SUCCESS) { if (loopbackMode == IX_ATMM_UTOPIA_LOOPBACK_ENABLED) { ixAtmmLoopbackOn = TRUE; } /* Clear the config struct */ ixOsalMemSet (&ixAtmmUtCfg, 0, sizeof (IxAtmdAccUtopiaConfig)); /* Fill out the utopia config structure */ utopiaConfigCreate (numPorts, phyMode, portCfgs, &ixAtmmUtCfg, loopbackMode); /* Call IxAtmdAcc to write the config */ retval = ixAtmdAccUtopiaConfigSet (&ixAtmmUtCfg); } return retval; }
void ixAtmSchedulingInit(void) { IxAtmLogicalPort i; /* Initialise the scheduling info for all ports */ ixOsalMemSet(portSchedulingInfo, 0, sizeof(portSchedulingInfo)); for (i=0; i<IX_UTOPIA_MAX_PORTS; i++) { ixAtmSchNextUbrToBeScheduled[i] = IX_ATMSCH_NULL_INDEX; ixAtmSchRtQueueHead[i] = IX_ATMSCH_NULL_INDEX; ixAtmSchedulingEnabled[i] = FALSE; ixAtmSchBaseTime[i] = 0; ixAtmSchTime[i] = 0; ixAtmSchCacPortAllocated[i] = 0; } for (i=0; i<IX_ATM_MAX_NUM_AAL_OAM_TX_VCS; i++) { ixAtmSchVcTable[i].inUse = FALSE; ixAtmSchVcTable[i].port = IX_UTOPIA_MAX_PORTS; } }
/** * @brief initializes a port * * @param portID ID of the port to be initialized * * Note that redundant initializations are silently * dealt with and do not constitute an error * * This function is fully documented in the main * header file, IxEthDB.h */ IX_ETH_DB_PUBLIC void ixEthDBPortInit(IxEthDBPortId portID) { PortInfo *portInfo; if (portID >= IX_ETH_DB_NUMBER_OF_PORTS) { return; } portInfo = &ixEthDBPortInfo[portID]; if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS) { WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID); return; } if (portInfo->initialized) { /* redundant */ return; } /* initialize core fields */ portInfo->portID = portID; SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID); /* default values */ portInfo->agingEnabled = FALSE; portInfo->enabled = FALSE; portInfo->macAddressUploaded = FALSE; portInfo->maxRxFrameSize = IX_ETHDB_MAX_NPE_FRAME_SIZE; portInfo->maxTxFrameSize = IX_ETHDB_MAX_NPE_FRAME_SIZE; portInfo->wifiRecordsCount = 1; portInfo->fwRecordsCount = 1; /* default update control values */ portInfo->updateMethod.searchTree = NULL; portInfo->updateMethod.searchTreePendingWrite = FALSE; portInfo->updateMethod.treeInitialized = FALSE; portInfo->updateMethod.updateEnabled = FALSE; portInfo->updateMethod.userControlled = FALSE; /* default WiFi parameters */ ixOsalMemSet(portInfo->bssid, 0, sizeof (portInfo->bssid)); portInfo->frameControlDurationID = 0; /* Ethernet NPE-specific initializations */ if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { /* update handler */ portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler; } /* initialize state save */ ixEthDBPortState[portID].saved = FALSE; portInfo->initialized = TRUE; }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletPTPMsgCheck (void) * * @brief Check if any PTP message is received or transmitted at * any channel. * * @param void * * @return IX_STATUS * @li IX_SUCCESS - no error detected during check * @li IX_FAIL - error detected during check */ PUBLIC IX_STATUS ixTimeSyncAccCodeletPTPMsgCheck (void) { IxTimeSyncAccPtpMsgData ptpMsgData; IxTimeSyncAccStatus tsStatus; IxTimeSyncAcc1588PTPPort channel; for (channel = IX_TIMESYNCACC_NPE_A_1588PTP_PORT; channel < IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS; channel++) { /* initialize ptpMsgData buffer */ ixOsalMemSet ((void *)&ptpMsgData, 0xff, sizeof (IxTimeSyncAccPtpMsgData)); /* check if any PTP message is received */ tsStatus = ixTimeSyncAccPTPRxPoll (channel, &ptpMsgData); /* PTP message is detected */ if (IX_TIMESYNCACC_SUCCESS == tsStatus) { ixTimeSyncAccCodeletPTPMsgShow (TRUE, channel, &ptpMsgData); } else if (IX_TIMESYNCACC_NOTIMESTAMP == tsStatus) { ixOsalLog (IX_OSAL_LOG_LVL_DEBUG1, IX_OSAL_LOG_DEV_STDOUT, "ixTimeSyncAccCodeletPTPMsgCheck: no new PTP message is received at %s channel\n", (UINT32) (ixTimeSyncAccCodeletTSChannelLabel[channel]), 0, 0, 0, 0, 0); } /* error is detected */ else { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgCheck: failed to determine if PTP message is received at channel %d, error code %d\n", channel, tsStatus, 0, 0, 0, 0); return IX_FAIL; } /* initialize ptpMsgData buffer */ ixOsalMemSet ((void *)&ptpMsgData, 0xff, sizeof (IxTimeSyncAccPtpMsgData)); /* check if any PTP message is transmitted */ tsStatus = ixTimeSyncAccPTPTxPoll (channel, &ptpMsgData); /* PTP message is detected */ if (IX_TIMESYNCACC_SUCCESS == tsStatus) { ixTimeSyncAccCodeletPTPMsgShow (FALSE, channel, &ptpMsgData); } else if (IX_TIMESYNCACC_NOTIMESTAMP == tsStatus) { ixOsalLog (IX_OSAL_LOG_LVL_DEBUG1, IX_OSAL_LOG_DEV_STDOUT, "ixTimeSyncAccCodeletPTPMsgCheck: no new PTP message is transmitted at %s channel\n", (UINT32) (ixTimeSyncAccCodeletTSChannelLabel[channel]), 0, 0, 0, 0, 0); } /* error is detected */ else { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgCheck: failed to determine if PTP message is transmitted at channel %d, error code %d\n", channel, tsStatus, 0, 0, 0, 0); return IX_FAIL; } } ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "\n", 0, 0, 0, 0, 0, 0); return IX_SUCCESS; } /* end of ixTimeSyncAccCodeletPTPMsgCheck function */
/** * @brief enables or disables a port capability * * @param portID ID of the port * @param feature feature to enable or disable * @param enabled TRUE to enable the selected feature or FALSE to disable it * * Note that this function is documented in the main component * header file, IxEthDB.h. * * @return IX_ETH_DB_SUCCESS if the operation completed * successfully or an appropriate error message otherwise */ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enable) { PortInfo *portInfo; IxEthDBPriorityTable defaultPriorityTable; IxEthDBVlanSet vlanSet; IxEthDBStatus status = IX_ETH_DB_SUCCESS; BOOL portEnabled; IX_ETH_DB_CHECK_PORT_INITIALIZED(portID); portInfo = &ixEthDBPortInfo[portID]; portEnabled = portInfo->enabled; /* check that only one feature is selected */ if (!ixEthDBCheckSingleBitValue(feature)) { return IX_ETH_DB_FEATURE_UNAVAILABLE; } /* port capable of this feature? */ if ((portInfo->featureCapability & feature) == 0) { return IX_ETH_DB_FEATURE_UNAVAILABLE; } /* mutual exclusion between learning and WiFi header conversion */ if (enable && ((feature | portInfo->featureStatus) & (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION)) == (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION)) { return IX_ETH_DB_NO_PERMISSION; } /* learning must be enabled before filtering */ if (enable && (feature == IX_ETH_DB_FILTERING) && ((portInfo->featureStatus & IX_ETH_DB_LEARNING) == 0)) { return IX_ETH_DB_NO_PERMISSION; } /* filtering must be disabled before learning */ if (!enable && (feature == IX_ETH_DB_LEARNING) && ((portInfo->featureStatus & IX_ETH_DB_FILTERING) != 0)) { return IX_ETH_DB_NO_PERMISSION; } /* redundant enabling or disabling */ if ((!enable && ((portInfo->featureStatus & feature) == 0)) || (enable && ((portInfo->featureStatus & feature) != 0))) { /* do nothing */ return IX_ETH_DB_SUCCESS; } /* force port enabled */ portInfo->enabled = TRUE; if (enable) { /* turn on enable bit */ portInfo->featureStatus |= feature; /* if this is VLAN/QoS set the default priority table */ if (feature == IX_ETH_DB_VLAN_QOS) { /* turn on VLAN/QoS (most permissive mode): - set default 802.1Q priority mapping table, in accordance to the availability of traffic classes - set the acceptable frame filter to accept all - set the Ingress tagging mode to pass-through - set full VLAN membership list - set full TTI table - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0) - enable TPID port extraction */ portInfo->ixEthDBTrafficClassCount = portInfo->ixEthDBTrafficClassAvailable; /* set default 802.1Q priority mapping table - note that C indexing starts from 0, so we substract 1 here */ ixOsalMemCopy (defaultPriorityTable, (void *) ixEthIEEE802_1QUserPriorityToTrafficClassMapping[portInfo->ixEthDBTrafficClassCount - 1], sizeof (defaultPriorityTable)); /* update priority mapping and AQM queue assignments */ status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_ENABLE_VLAN); } /* set membership and TTI tables */ ixOsalMemSet (vlanSet, 0xFF, sizeof (vlanSet)); if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet); } if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet); } /* reset the PVID */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBPortVlanTagSet(portID, 0); } /* enable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBVlanPortExtractionEnable(portID, TRUE); } } else if (feature == IX_ETH_DB_FIREWALL) { /* firewall starts in black-list mode unless otherwise configured before * * note that invalid source MAC address filtering is disabled by default */ if (portInfo->firewallMode != IX_ETH_DB_FIREWALL_BLACK_LIST && portInfo->firewallMode != IX_ETH_DB_FIREWALL_WHITE_LIST) { status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); } } } if (status != IX_ETH_DB_SUCCESS) { /* checks failed, disable */ portInfo->featureStatus &= ~feature; } } else { /* turn off features */ if (feature == IX_ETH_DB_FIREWALL) { /* turning off the firewall is equivalent to: - set to black-list mode - clear all the entries and download the new table - turn off the invalid source address checking */ status = ixEthDBDatabaseClear(portID, IX_ETH_DB_FIREWALL_RECORD); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBFirewallTableDownload(portID); } } else if (feature == IX_ETH_DB_WIFI_HEADER_CONVERSION) { /* turn off header conversion */ status = ixEthDBDatabaseClear(portID, IX_ETH_DB_WIFI_RECORD); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBWiFiConversionTableDownload(portID); } } else if (feature == IX_ETH_DB_VLAN_QOS) { /* turn off VLAN/QoS: - set a priority mapping table with one traffic class - set the acceptable frame filter to accept all - set the Ingress tagging mode to pass-through - clear the VLAN membership list - clear the TTI table - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0) - disable TPID port extraction */ /* initialize all => traffic class 0 priority mapping table */ ixOsalMemSet (defaultPriorityTable, 0, sizeof (defaultPriorityTable)); portInfo->ixEthDBTrafficClassCount = 1; status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable); if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); } if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_DISABLE_VLAN); } /* clear membership and TTI tables */ ixOsalMemSet (vlanSet, 0, sizeof (vlanSet)); if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet); } if (status == IX_ETH_DB_SUCCESS) { /* use the internal function to bypass PVID check */ status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet); } /* reset the PVID */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBPortVlanTagSet(portID, 0); } /* disable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { status = ixEthDBVlanPortExtractionEnable(portID, FALSE); } } if (status == IX_ETH_DB_SUCCESS) { /* checks passed, disable */ portInfo->featureStatus &= ~feature; } } /* restore port enabled state */ portInfo->enabled = portEnabled; return status; }
/** * @brief disables a port * * @param portID ID of the port to disable * * This function is fully documented in the * main header file, IxEthDB.h * * @return IX_ETH_DB_SUCCESS if disabling was * successful or an appropriate error message * otherwise */ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) { HashIterator iterator; IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */ BOOL result; PortInfo *portInfo; IxEthDBFeature learningEnabled; IxEthDBPriorityTable classZeroTable; IX_ETH_DB_CHECK_PORT_EXISTS(portID); IX_ETH_DB_CHECK_SINGLE_NPE(portID); portInfo = &ixEthDBPortInfo[portID]; if (!portInfo->enabled) { /* redundant */ return IX_ETH_DB_SUCCESS; } if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { /* save filtering state */ ixEthDBPortState[portID].firewallMode = portInfo->firewallMode; ixEthDBPortState[portID].frameFilter = portInfo->frameFilter; ixEthDBPortState[portID].taggingAction = portInfo->taggingAction; ixEthDBPortState[portID].stpBlocked = portInfo->stpBlocked; ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled; ixEthDBPortState[portID].maxRxFrameSize = portInfo->maxRxFrameSize; ixEthDBPortState[portID].maxTxFrameSize = portInfo->maxTxFrameSize; ixOsalMemCopy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet)); ixOsalMemCopy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet)); ixOsalMemCopy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable)); ixEthDBPortState[portID].saved = TRUE; /* now turn off all EthDB filtering features on the port */ /* VLAN & QoS */ if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) { ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID); ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, FALSE); ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH); ixOsalMemSet(classZeroTable, 0, sizeof (classZeroTable)); ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable); } /* STP */ if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0) { ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, FALSE); } /* Firewall */ if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0) { ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST); ixEthDBFirewallTableDownload((IxEthDBPortId) portID); ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, FALSE); } /* Frame size filter */ ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE); /* WiFi */ if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0) { ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID); } /* save and disable the learning feature bit */ learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING; portInfo->featureStatus &= ~IX_ETH_DB_LEARNING; } else { /* save the learning feature bit */ learningEnabled = portInfo->featureStatus & IX_ETH_DB_LEARNING; } SET_EMPTY_DEPENDENCY_MAP(triggerPorts); ixEthDBUpdateLock(); /* wipe out current entries for this port */ BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator)); while (IS_ITERATOR_VALID(&iterator)) { MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; /* check if the port match. If so, remove the entry */ if (descriptor->portID == portID && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD) && !descriptor->recordData.filteringData.staticEntry) { /* delete entry */ BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator)); /* add port to the set of update trigger ports */ JOIN_PORT_TO_MAP(triggerPorts, portID); } else { /* move to the next record */ BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator)); } } if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { if (portInfo->updateMethod.searchTree != NULL) { ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree); portInfo->updateMethod.searchTree = NULL; } ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD); } /* mark as disabled */ portInfo->enabled = FALSE; /* disable updates unless the user has specifically altered the default behavior */ if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { if (!portInfo->updateMethod.userControlled) { portInfo->updateMethod.updateEnabled = FALSE; } /* make sure we re-initialize the NPE learning tree when the port is re-enabled */ portInfo->updateMethod.treeInitialized = FALSE; } ixEthDBUpdateUnlock(); /* restore learning feature bit */ portInfo->featureStatus |= learningEnabled; /* if we've removed any records or lost any events make sure to force an update */ IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts); if (!result) { ixEthDBUpdatePortLearningTrees(triggerPorts); } return IX_ETH_DB_SUCCESS; }
/** * @brief registers the NPE serialization methods * * This functions registers NPE serialization methods * for writing the following types of records in NPE * readable linear format: * - filtering records * - WiFi header conversion records * - WiFi gateway header conversion records * - firewall records * * Note that this function should be called by the * component initialization function. * * @return number of registered record types * * @internal */ IX_ETH_DB_PUBLIC UINT32 ixEthDBRecordSerializeMethodsRegister() { int i; /* safety - register a blank method for everybody first */ for ( i = 0 ; i < IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1 ; i++) { ixEthDBNPENodeWrite[i] = ixEthDBNullSerialize; } /* register real methods */ ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_RECORD] = ixEthDBNPELearningNodeWrite; ixEthDBNPENodeWrite[IX_ETH_DB_FILTERING_VLAN_RECORD] = ixEthDBNPELearningNodeWrite; ixEthDBNPENodeWrite[IX_ETH_DB_WIFI_RECORD] = ixEthDBNPEWiFiNodeWrite; ixEthDBNPENodeWrite[IX_ETH_DB_FIREWALL_RECORD] = ixEthDBNPEFirewallNodeWrite; ixEthDBNPENodeWrite[IX_ETH_DB_MASKED_FIREWALL_RECORD]= ixEthDBNPEFirewallMaskedNodeWrite; ixEthDBNPENodeWrite[IX_ETH_DB_GATEWAY_RECORD] = ixEthDBNPEGatewayNodeWrite; /* EP Delta arrays */ ixOsalMemSet(ixEthDBEPDeltaOffset, 0, sizeof (ixEthDBEPDeltaOffset)); ixOsalMemSet(ixEthDBEPDelta, 0, sizeof (ixEthDBEPDelta)); /* filtering records */ ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][0] = 1; ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][0] = 0; ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][1] = 3; ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][1] = 7; ixEthDBEPDeltaOffset[IX_ETH_DB_FILTERING_RECORD][2] = 511; ixEthDBEPDelta[IX_ETH_DB_FILTERING_RECORD][2] = 14; /* wifi records */ ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][0] = 1; ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][0] = 0; ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][1] = 3; ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][1] = 7; ixEthDBEPDeltaOffset[IX_ETH_DB_WIFI_RECORD][2] = 511; ixEthDBEPDelta[IX_ETH_DB_WIFI_RECORD][2] = 14; /* firewall records */ ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][0] = 0; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][0] = 0; ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][1] = 1; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][1] = 5; ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][2] = 3; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][2] = 13; ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][3] = 7; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][3] = 21; ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][4] = 15; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][4] = 29; ixEthDBEPDeltaOffset[IX_ETH_DB_FIREWALL_RECORD][5] = 31; ixEthDBEPDelta[IX_ETH_DB_FIREWALL_RECORD][5] = 37; /* masked firewall records */ ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][0] = 0; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][0] = 0; ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][1] = 1; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][1] = 9; ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][2] = 3; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][2] = 23; ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][3] = 7; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][3] = 37; ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][4] = 15; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][4] = 51; ixEthDBEPDeltaOffset[IX_ETH_DB_MASKED_FIREWALL_RECORD][5] = 31; ixEthDBEPDelta[IX_ETH_DB_MASKED_FIREWALL_RECORD][5] = 65; return 6; /* 6 methods registered */ }
/** * @brief allocates non-cached or contiguous NPE tree update areas for all the ports * * This function is called only once at initialization time from * @ref ixEthDBInit(). * * @warning do not call manually * * @see ixEthDBInit() * * @internal */ IX_ETH_DB_PUBLIC void ixEthDBNPEUpdateAreasInit(void) { UINT32 portIndex; PortUpdateMethod *update; for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { update = &ixEthDBPortInfo[portIndex].updateMethod; if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE) { update->npeUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_ELT_BYTE_SIZE); if (update->npeUpdateZone == NULL) { ERROR_LOG("Fatal error: IX_OSAL_CACHE_DMA_MALLOC() returned NULL, no NPE update zones available\n"); } else { ixOsalMemSet(update->npeUpdateZone, 0, FULL_ELT_BYTE_SIZE); } update->npeGwUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_GW_BYTE_SIZE); if (update->npeGwUpdateZone == NULL) { ERROR_LOG("Fatal error: IX_OSAL_CACHE_DMA_MALLOC() returned NULL, no gateway update zones available\n"); } else { ixOsalMemSet(update->npeGwUpdateZone, 0, FULL_GW_BYTE_SIZE); } update->npeBssidUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_BSSID_BYTE_SIZE); if (update->npeBssidUpdateZone == NULL) { ERROR_LOG("Fatal error: IX_OSAL_CACHE_DMA_MALLOC() returned NULL, no bssid update zones available\n"); } else { ixOsalMemSet(update->npeBssidUpdateZone, 0, FULL_BSSID_BYTE_SIZE); } update->vlanUpdateZone = IX_OSAL_CACHE_DMA_MALLOC(FULL_VLAN_BYTE_SIZE); if (update->vlanUpdateZone == NULL) { ERROR_LOG("Fatal error: IX_OSAL_CACHE_DMA_MALLOC() returned NULL, no vlan update zones available\n"); } else { ixOsalMemSet(update->vlanUpdateZone, 0, FULL_VLAN_BYTE_SIZE); } } else { /* unused */ update->npeUpdateZone = NULL; update->npeGwUpdateZone = NULL; update->npeBssidUpdateZone = NULL; update->vlanUpdateZone = NULL; } } }
/** * @brief scans the capabilities of the loaded NPE images * * This function MUST be called by the ixEthDBInit() function. * No EthDB features (including learning and filtering) are enabled * before this function is called. * * @return none * * @internal */ IX_ETH_DB_PUBLIC void ixEthDBFeatureCapabilityScan(void) { UINT8 functionalityId, npeAFunctionalityId; IxEthDBPortId portIndex; PortInfo *portInfo; IxEthDBPriorityTable defaultPriorityTable; IX_STATUS result; UINT32 queueIndex; UINT32 queueStructureIndex; UINT32 trafficClassDefinitionIndex, totalTrafficClass; totalTrafficClass = sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]); /* ensure there's at least 2 traffic class records in the definition table, otherwise we have no default cases, hence no queues */ IX_ENSURE(totalTrafficClass >= 2, "DB: no traffic class definitions found, check IxEthDBQoS.h"); /* read version of NPE A - required to set the AQM queues for B and C */ npeAFunctionalityId = 0; if(IX_FAIL == ixNpeDlLoadedImageFunctionalityGet(IX_NPEDL_NPEID_NPEA, &npeAFunctionalityId)) { /* IX_FAIL is returned when there is no image loaded in NPEA. Then we can use all 8 queues */ trafficClassDefinitionIndex = 1; /* the second record is the default if no image loaded */ } else { /* find the traffic class definition index compatible with the current NPE A functionality ID */ for (trafficClassDefinitionIndex = 0 ; trafficClassDefinitionIndex < totalTrafficClass ; trafficClassDefinitionIndex++) { if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAFunctionalityId) { /* found it */ break; } } /* select the default case if we went over the array boundary */ if (trafficClassDefinitionIndex == totalTrafficClass) { trafficClassDefinitionIndex = 0; /* the first record is the default case */ } } /* To decide port definition for NPE A - IX_ETH_NPE or IX_ETH_GENERIC IX_ETH_NPE will be set for NPE A when the functionality id is ranged from 0x80 to 0x8F and ethernet + hss co-exists images range from 0x90 to 0x9F. For the rest of functionality Ids, the port type will be set to IX_ETH_GENERIC. */ if ((npeAFunctionalityId & 0xF0) != 0x80 && (npeAFunctionalityId & 0xF0) != 0x90) { /* NPEA is not Ethernet capable. Override default port definition */ ixEthDBPortDefinitions[IX_NPEA_PORT].type = IX_ETH_GENERIC; } /* select queue assignment structure based on the traffic class configuration index */ queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX]; for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { IxNpeMhMessage msg; portInfo = &ixEthDBPortInfo[portIndex]; /* check and bypass if NPE A, B or C is fused out */ if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue; /* all ports are capable of LEARNING by default */ portInfo->featureCapability = IX_ETH_DB_LEARNING; portInfo->featureStatus = IX_ETH_DB_LEARNING; if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE) { if (IX_SUCCESS != ixNpeDlLoadedImageFunctionalityGet(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), &functionalityId)) { WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex); } else { /* initialize and empty NPE response mutex */ ixOsalMutexInit(&portInfo->npeAckLock); ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER); /* check NPE response to GetStatus */ msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24; msg.data[1] = 0; IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), msg, result); if (result != IX_SUCCESS) { WARNING_LOG("DB: (FeatureScan) warning, %d port could not send message to the NPE\n", portIndex); continue; } if (functionalityId == 0x00 || functionalityId == 0x03 || functionalityId == 0x04 || functionalityId == 0x80) { portInfo->featureCapability |= IX_ETH_DB_FILTERING; portInfo->featureCapability |= IX_ETH_DB_FIREWALL; portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL; } else if (functionalityId == 0x01 || functionalityId == 0x81 || functionalityId == 0x0B || functionalityId == 0x8B || functionalityId == 0x90) { portInfo->featureCapability |= IX_ETH_DB_FILTERING; portInfo->featureCapability |= IX_ETH_DB_FIREWALL; portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL; portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS; } else if (functionalityId == 0x02 || functionalityId == 0x82 || functionalityId == 0x0D || functionalityId == 0x8D || functionalityId == 0x91) { portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION; portInfo->featureCapability |= IX_ETH_DB_FIREWALL; portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL; portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS; } else if (functionalityId == 0x0C || functionalityId == 0x8C) { portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION; portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL; portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS; } /* check if image supports mask based firewall */ if (functionalityId == 0x0B || functionalityId == 0x8B || functionalityId == 0x0D || functionalityId == 0x8D || functionalityId == 0x90 || functionalityId == 0x91) { /* this feature is always on and is based on the NPE */ portInfo->featureStatus |= IX_ETH_DB_ADDRESS_MASKING; portInfo->featureCapability |= IX_ETH_DB_ADDRESS_MASKING; } /* reset AQM queues */ ixOsalMemSet(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments)); /* only traffic class 0 is active at initialization time */ portInfo->ixEthDBTrafficClassCount = 1; /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */ portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS; portInfo->featureStatus |= IX_ETH_DB_FIREWALL; portInfo->enabled = TRUE; /* set VLAN initial configuration (permissive) */ if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */ { /* QoS capable */ portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX]; /* set AQM queues */ for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++) { portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex]; } /* set default PVID (0) and default traffic class 0 */ ixEthDBPortVlanTagSet(portIndex, 0); /* enable reception of all frames */ ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES); /* clear full VLAN membership */ ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID); /* clear TTI table - no VLAN tagged frames will be transmitted */ ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE); /* set membership on 0, otherwise no Tx or Rx is working */ ixEthDBPortVlanMembershipAdd(portIndex, 0); } else /* QoS not available in this image */ { /* initialize traffic class availability (only class 0 is available) */ portInfo->ixEthDBTrafficClassAvailable = 1; /* point all AQM queues to traffic class 0 */ for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++) { portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][0]; } } /* download priority mapping table and Rx queue configuration */ ixOsalMemSet (defaultPriorityTable, 0, sizeof (defaultPriorityTable)); ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable); /* by default we turn on invalid source MAC address filtering */ ixEthDBFirewallInvalidAddressFilterEnable(portIndex, TRUE); /* Notify VLAN tagging is disabled */ if (ixEthDBIngressVlanTaggingEnabledSet(portIndex, IX_ETH_DB_DISABLE_VLAN) != IX_SUCCESS) { WARNING_LOG("DB: (FeatureScan) warning, %d port could not disable VLAN \n", portIndex); continue; } /* disable port, VLAN, Firewall feature bits */ portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS; portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL; portInfo->enabled = FALSE; /* enable filtering by default if present */ if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0) { portInfo->featureStatus |= IX_ETH_DB_FILTERING; } } } } }
/* -------------------------------------------------------------- Software queue manipulation functions. -------------------------------------------------------------- */ PRIVATE void ixOamQueueInit( int port ) { ixOsalMemSet(&ixOamSwQueue[port], 0, sizeof(ixOamSwQueue[port])); ixOamSwQueue[port].size = IX_OAMCODELET_NUM_MBUFS_IN_SW_MBUF_Q; ixOamSwQueue[port].mask = IX_OAMCODELET_NUM_MBUFS_IN_SW_MBUF_Q - 1; }
PUBLIC IX_STATUS ixOamCodeletInit (UINT32 numPorts) { IX_STATUS retval; UINT32 txRate[IX_UTOPIA_MAX_PORTS]; UINT32 rxRate; IxAtmmVc txVc; IxAtmmVc rxVc; IxAtmLogicalPort port; IxAtmSchedulerVcId rxVcId; IxAtmSchedulerVcId txVcId; IxAtmNpeRxVcId npeRxVcId; IxOsalThread tid; IxOsalThreadAttr threadAttr; char *pThreadName = "OAM Receive"; if (ixOamCodeletInitialized) { IX_OAM_CODELET_LOG_ERROR("Already initialized"); return IX_FAIL; } /* Check parameters */ if (numPorts < 1 || numPorts > IX_UTOPIA_MAX_PORTS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) invalid\n", numPorts); return IX_FAIL; } ixOamCodeletNumPorts = numPorts; /* Check how many ports have been configured, rxRate not used */ for (port =0; port< (IxAtmLogicalPort)numPorts; port++) { if (ixAtmmPortQuery (port, &txRate[port], &rxRate) != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) not configured, %u ports configured\n", numPorts, port); } } /* Initialize stats */ for (port = 0; port < IX_UTOPIA_MAX_PORTS; port++) { parentLbCellTxCount[port] = 0; childLbCellTxCount[port] = 0; parentLbCellRxCount[port] = 0; childLbCellRxCount[port] = 0; childLbCellRxErrCount[port] = 0; parentLbCellRxErrCount[port] = 0; unsupportedOamRxCount[port] = 0; txDoneCallbackCount[port] = 0; } replenishCallbackCount = 0; /* 1 for all ports */ /* Setup the OAM Tx Port Channels */ for (port=0; port< (IxAtmLogicalPort)numPorts; port++) { ixOsalMemSet(&txVc, 0, sizeof(txVc)); /* Setup Tx Vc descriptor */ txVc.vpi = IX_ATMDACC_OAM_TX_VPI; txVc.vci = IX_ATMDACC_OAM_TX_VCI; txVc.direction = IX_ATMM_VC_DIRECTION_TX; txVc.trafficDesc.atmService = IX_ATM_UBR; txVc.trafficDesc.pcr = txRate[port]; /* Setup tx VC, N.B. TxVcId not used in this codelet, * would typically be used for Vc Deregister */ retval = ixAtmmVcRegister (port, &txVc, &txVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Tx Port VC\n"); return IX_FAIL; } retval = ixAtmdAccTxVcConnect (port, IX_ATMDACC_OAM_TX_VPI, IX_ATMDACC_OAM_TX_VCI, IX_ATMDACC_OAM, port, /* set userId to port */ ixOamTxDoneCallback, &oamTxConnId[port]); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR ("Failed to connect Tx Port Channel\n"); return IX_FAIL; } /* setup the Rx sw queues */ ixOamQueueInit( port ); } /* * Setup OAM Rx Channel * N.B. OAM traffic for all ports is received on this VC */ /*Set thread attributes*/ threadAttr.name = pThreadName; threadAttr.stackSize = IX_ATMCODELET_QMGR_DISPATCHER_THREAD_STACK_SIZE; threadAttr.priority = IX_ATMCODELET_QMGR_DISPATCHER_PRIORITY; /* start a receive task */ if (ixOsalThreadCreate(&tid, &threadAttr, (IxOsalVoidFnVoidPtr)ixOamCellRxTask, NULL) != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR ("Error spawning SduSend task\n"); return IX_FAIL; } if(IX_SUCCESS != ixOsalThreadStart(&tid)) { printf("Error starting dispatch task\n"); return IX_FAIL; } ixOsalMemSet(&rxVc, 0, sizeof(rxVc)); /* Setup Rx Vc descriptor */ rxVc.vpi = IX_ATMDACC_OAM_RX_VPI; rxVc.vci = IX_ATMDACC_OAM_RX_VCI; rxVc.direction = IX_ATMM_VC_DIRECTION_RX; rxVc.trafficDesc.atmService = IX_ATM_UBR; rxVc.trafficDesc.pcr = 0; /* Ignored for Rx */ /* Setup rx VC, N.B. RxVcId not used in this codelet, * would typically be used for Vc Deregister */ retval = ixAtmmVcRegister (IX_ATMDACC_OAM_RX_PORT, &rxVc, &rxVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Rx Channel\n"); return IX_FAIL; } /* Connect Rx VC, N.B. npeRxVcId not used again */ retval = ixAtmdAccRxVcConnect (IX_ATMDACC_OAM_RX_PORT, IX_ATMDACC_OAM_RX_VPI, IX_ATMDACC_OAM_RX_VCI, IX_ATMDACC_OAM, IX_ATM_RX_B, /* low priority Q */ oamRxUserId, ixOamCellRxCallback, IX_ATMDACC_DEFAULT_REPLENISH_COUNT, &oamRxConnId, &npeRxVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to connect Rx Channel\n"); return IX_FAIL; } /* Replenish Rx then register replenish callback */ ixOamRxFreeLowReplenishCallback (oamRxUserId); retval = ixAtmdAccRxVcFreeLowCallbackRegister (oamRxConnId, IX_OAM_REPLENISH_WATERMARK, ixOamRxFreeLowReplenishCallback); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Rx replenish callback\n"); return IX_FAIL; } /* enable the oam vc */ retval = ixAtmdAccRxVcEnable (oamRxConnId); if (retval != IX_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR,IX_OSAL_LOG_DEV_STDERR, "Failed to enable Rx VC \n", 0, 0, 0, 0, 0, 0); return retval; } /* Set the number of ports configured */ ixOamCodeletNumPortsConfigured = numPorts; /* set initialised flag */ ixOamCodeletInitialized = TRUE; IX_OAM_CODELET_LOG ("Initialization Phase Complete\n"); return IX_SUCCESS; }
IX_STATUS ixEthAccCodeletPortConfigure(IxEthAccPortId portId, IxEthAccPortRxCallback portRxCB, IxEthAccPortMultiBufferRxCallback portMultiBufferRxCB, IxEthAccPortTxDoneCallback portTxDoneCB, UINT32 callbackTag) { IxEthAccMacAddr npeMacAddr1 = IX_ETHACC_CODELET_NPEB_MAC; IxEthAccMacAddr npeMacAddr2 = IX_ETHACC_CODELET_NPEC_MAC; IxEthAccMacAddr npeMacAddr3 = IX_ETHACC_CODELET_NPEA_MAC; IxEthAccMacAddr npeMacAddr; /* Clear stats */ ixOsalMemSet(&ixEthAccCodeletStats[portId], 0, sizeof(ixEthAccCodeletStats[portId])); /* check the PHY is up, ignore the result. This is called to * display the current PHY status to the console */ (void)ixEthAccCodeletLinkUpCheck(portId); /* register the datapath Rx callbacks */ if (NULL != portRxCB) { if(ixEthAccPortRxCallbackRegister(portId, portRxCB, callbackTag) != IX_ETH_ACC_SUCCESS) { printf("PortSetup: Failed to register Rx callback for port %u\n", (UINT32)portId); return (IX_FAIL); } } else if (NULL != portMultiBufferRxCB) { if(ixEthAccPortMultiBufferRxCallbackRegister(portId, portMultiBufferRxCB, callbackTag) != IX_ETH_ACC_SUCCESS) { printf("PortSetup: Failed to register multiBuffer Rx callback for port %u\n", (UINT32)portId); return (IX_FAIL); } } else { printf("PortSetup: Failed to register any Rx callback for port %u\n", (UINT32)portId); return (IX_FAIL); } /* register the datapath TxDone callbacks */ if(ixEthAccPortTxDoneCallbackRegister(portId, portTxDoneCB, callbackTag) != IX_ETH_ACC_SUCCESS) { printf("PortSetup: Failed to register Tx done callback for port %u\n", (UINT32)portId); return (IX_FAIL); } #if defined (__vxworks) && defined (IX_ETHACC_CODELET_USE_NVRAM_MAC) printf("\nReading MAC address information from non-volatile storage...\n"); if (portId == IX_ETH_PORT_1) { if(sysNvRamGet((UINT8 *)&npeMacAddr.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE, NV_MAC_ADRS_NPE1) == ERROR) { printf("PortSetup: Unable to read MAC address from non-volatile storage!\n"); return (IX_FAIL); } } else if (portId == IX_ETH_PORT_2) { if(sysNvRamGet((UINT8 *)&npeMacAddr.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE, NV_MAC_ADRS_NPE2) == ERROR) { printf("PortSetup: Unable to read MAC address from non-volatile storage!\n"); return (IX_FAIL); } } else { printf("PortSetup: Unsupported port!\n"); return (IX_FAIL); } #else if (portId == IX_ETH_PORT_1) { ixOsalMemCopy(npeMacAddr.macAddress, npeMacAddr1.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); } else if (portId == IX_ETH_PORT_2) { ixOsalMemCopy(npeMacAddr.macAddress, npeMacAddr2.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); } else if (portId == IX_ETH_PORT_3) { ixOsalMemCopy(npeMacAddr.macAddress, npeMacAddr3.macAddress, IX_IEEE803_MAC_ADDRESS_SIZE); } else { printf("PortSetup: Unsupported port!\n"); return (IX_FAIL); } #endif printf ("Configure MAC address...\n"); if(ixEthAccPortUnicastMacAddressSet(portId, &npeMacAddr) != IX_ETH_ACC_SUCCESS) { printf("PortSetup: Failed to set the Unicast MAC Address of port %u\n", portId); return (IX_FAIL); } printf("Port %u MAC address is:\t\n", (UINT32)portId); ixEthAccPortUnicastAddressShow(portId); printf ("Provision the first RX buffers...\n"); if(ixEthAccCodeletReplenishBuffers(portId, IX_ETHACC_CODELET_RX_MBUF_POOL_SIZE/IX_ETHACC_CODELET_MAX_PORT) != IX_SUCCESS) { printf("PortSetup: Error replenishing port %u\n", (UINT32)portId); return (IX_FAIL); } return IX_SUCCESS; }
/** * @brief writes a search tree in NPE format * * @param type type of records to be written into the NPE update zone * @param totalSize maximum size of the linearized tree * @param baseAddress memory base address where to write the NPE tree into * @param tree search tree to write in NPE format * @param blocks number of written 64-byte blocks * @param startIndex optimal binary search start index * * Serializes the given tree in NPE linear format * * @return none * * @internal */ IX_ETH_DB_PUBLIC void ixEthDBNPETreeWrite(IxEthDBRecordType type, UINT32 totalSize, void *baseAddress, MacTreeNode *tree, UINT32 *epDelta, UINT32 *blocks) { MacTreeNodeStack *stack; UINT32 currentSize = 0; UINT32 offset = 0; UINT32 maxOffset = 0; stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack)); if (stack == NULL) { ERROR_LOG("DB: (NPEAdaptor) failed to allocate the node stack for learning tree linearization, out of memory?\n"); return; } /* zero out empty root */ currentSize = ixEthDBNPENodeWrite[type](NULL, baseAddress, 0, totalSize); NODE_STACK_INIT(stack); if (tree != NULL) { /* push tree root at offset 1 */ NODE_STACK_PUSH(stack, tree, 1); } while (NODE_STACK_NONEMPTY(stack)) { MacTreeNode *node; NODE_STACK_POP(stack, node, offset); /* Add node to NPE table at position indicated by offset */ /* In the case where a node is NULL, the NodeWrite function will zero out * the memory based on the offset. * In the case where the given offset goes past totalSize, no entry is written */ currentSize = ixEthDBNPENodeWrite[type](node, baseAddress, offset, totalSize); if ((node != NULL) && (currentSize <= totalSize)) { IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) writing MAC [%s] at offset %d\n", mac2string(node->descriptor->macAddress), offset); if(maxOffset<offset) maxOffset = offset; NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset)); NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset)); } } /* this extra write is done to determine if any more empty entries in the table need * to be cleared. */ currentSize = ixEthDBNPENodeWrite[type](NULL, baseAddress, maxOffset+1, totalSize); if (currentSize < totalSize) { /* zero out rest of the tree */ IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Clearing rest of tree\n"); /* zero out the rest of the table */ ixOsalMemSet((void *) (((UINT32) baseAddress) + currentSize), 0, (totalSize - currentSize)); } else { currentSize = totalSize ; } /* flush cache */ IX_OSAL_CACHE_FLUSH(baseAddress, totalSize); IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Ethernet learning/filtering tree XScale wrote at address 0x%08X (max %d bytes):\n\n", (UINT32) baseAddress, totalSize); /* compute number of 64-byte blocks */ if (blocks != NULL) { *blocks = currentSize ? 1 + ((currentSize - 1) / 64) : 0; IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Wrote %d 64-byte blocks\n", *blocks); } /* compute epDelta - start index for binary search */ if (epDelta != NULL) { UINT32 deltaIndex = 0; *epDelta = 0; for (; deltaIndex < IX_ETH_DB_MAX_DELTA_ZONES ; deltaIndex ++) { if (ixEthDBEPDeltaOffset[type][deltaIndex] >= maxOffset) { *epDelta = ixEthDBEPDelta[type][deltaIndex]; break; } } IX_ETH_DB_NPE_TRACE("DB: (NPEAdaptor) Computed epDelta %d (based on maxOffset %d)\n", *epDelta, maxOffset); } ixOsalCacheDmaFree(stack); }