| /****************************************************************************** |
| * |
| * Copyright (c) 2019 Intel. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *******************************************************************************/ |
| |
| /** |
| * WLS interface test application |
| * (contains functional unit tests and diagnostics to test wls |
| * supported by WLS interface) |
| */ |
| |
| #define _GNU_SOURCE |
| #include <stdio.h> // for printf |
| #include <string.h> // for memset |
| #include <signal.h> // for SIGINT |
| #include <unistd.h> // for usleep |
| #include <stdlib.h> // for rand |
| #include <getopt.h> // for getopt |
| #include <sys/time.h> |
| #include <pthread.h> |
| #include <sched.h> |
| #include "ttypes.h" |
| #include "wls_lib.h" |
| #include "pool.h" |
| |
| #define HANDLE PVOID |
| |
| |
| #define K 1024 |
| #define M (K*K) |
| |
| #define DEFAULT_TEST_MEMORY_SIZE 256*M |
| #define DEFAUTL_TEST_BLOCK_SIZE 16*K |
| |
| #define DEFAULT_MESSAGE_COUNT_PER_MS 10 |
| #define DEFAULT_MAX_MESSAGE_SIZE 2000 |
| #define DEFUALT_MIN_MESSAGE_SIZE 100 |
| |
| #define APP_QUEUE_SIZE 255 /* number of elements each queue of the WLS being registered will have */ |
| #define MAX_MESSAGES 1000 /* per ms */ |
| |
| |
| #ifndef TRUE |
| #define TRUE 1 |
| #endif |
| |
| #ifndef FALSE |
| #define FALSE 0 |
| #endif |
| |
| typedef enum { |
| APP_TC_SANITY_TEST = 0, |
| } APP_TEST_CASES; |
| |
| typedef struct tagAPP_PARAMS { |
| char *wls_dev_name; |
| int aff_core; |
| int test_id; |
| int rx_id; |
| int tx_id; |
| int n_messages; |
| int max_size; |
| int min_size; |
| int interface_count; |
| U8 master; |
| U8 debug; |
| U8 crc; |
| U8 trusted; |
| } APP_PARAMS, *PAPP_PARAMS; |
| |
| typedef struct tagAPP_MESSAGE { |
| U32 id; |
| } APP_MESSAGE, *PAPP_MESSAGE; |
| |
| typedef struct tagAPP_CONTEXT { |
| V32 ExitStatus; |
| HANDLE hWls; |
| |
| U32 master; |
| |
| PVOID shm_memory; |
| |
| POOL Pool; // The pool descriptor |
| void* PoolStrPtr; // The pool storage pointer to keep indexes |
| |
| U16 RxID; |
| U16 TxID; |
| |
| U16 nInterfaces; // number of RX identifiers used by the APP |
| // |
| U16 InitQueueSize; // for invalid messages test (to trigger WLS blocking) |
| |
| // |
| U32 MsgPerMs; |
| U32 MaxMsgSize; |
| U32 MinMsgSize; |
| |
| U32 TxCnt; |
| U32 RxCnt; |
| |
| U64 nTxMsgs; // Messages transmitted |
| U64 nTxOctets; // Octets transmitted |
| U64 nRxMsgs; // Messages received |
| U64 nRxOcters; // Octets received |
| U64 Cycles; // number of 1ms cycles |
| |
| int AppSanityMsgSize; // 4 or 8 depending on CRC feature |
| U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms |
| U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking. |
| |
| void (*Receive)(HANDLE h); |
| void (*Transmit)(HANDLE h); |
| |
| void (*ThreadReceive)(HANDLE h); |
| void (*ThreadTransmit)(HANDLE h); |
| |
| int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags); |
| unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags); |
| unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags); |
| |
| U8 *pLastRx; // used for scatter-gather test |
| U32 LastRxSize; // used for scatter-gather test |
| |
| U32 *pServiceBuffer; |
| |
| U32 TxMsgCnt; |
| PVOID TxMessages[MAX_MESSAGES]; |
| U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes |
| int core; |
| |
| } APP_CONTEXT, *PAPP_CONTEXT; |
| |
| APP_CONTEXT AppContext; |
| |
| static int pool_alloc = 0; |
| static int pool_free = 0; |
| |
| static void ShowData(void* ptr, unsigned int size) |
| { |
| U8 *d = ptr; |
| unsigned int i; |
| |
| for (i = 0; i < size; i++) { |
| if (!(i & 0xf)) |
| printf("\n"); |
| printf("%02x ", d[i]); |
| } |
| printf("\n"); |
| } |
| |
| static void App_SigExitCallback(int signum) |
| { |
| (void) signum; |
| AppContext.ExitStatus = TRUE; |
| } |
| |
| static void* WlsVaToPa(void * ptr) |
| { |
| PAPP_CONTEXT pCtx = &AppContext; |
| return (void*) WLS_VA2PA(pCtx->hWls, ptr); |
| } |
| |
| static void* WlsPaToVa(void * ptr) |
| { |
| PAPP_CONTEXT pCtx = &AppContext; |
| return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr); |
| } |
| |
| static void* App_Alloc(void* h, unsigned long size) |
| { |
| (void) h; |
| (void) size; |
| void * retval = NULL; |
| if (AppContext.master) { |
| retval = PoolAlloc(&(AppContext.Pool)); |
| //printf("pPool->FreeGet %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut); |
| } else { |
| retval = (void*) WLS_DequeueBlock(AppContext.hWls); |
| if (retval) |
| retval = (void*) WlsPaToVa(retval); |
| else |
| printf("WLS_DequeueBlock returned null\n"); |
| } |
| |
| if (retval == NULL) { |
| printf("no memory %d %d\n", pool_alloc, pool_free); |
| exit(-1); |
| } else |
| pool_alloc++; |
| |
| return retval; |
| } |
| |
| static int App_Free(void* h, void* pMsg) |
| { |
| (void) h; |
| if (AppContext.master) |
| if (pMsg) { |
| pool_free++; |
| return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1); |
| } else { |
| printf("Free Null pointer\n"); |
| exit(-1); |
| } else |
| return 0; |
| } |
| |
| static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize) |
| { |
| int ret = 0; |
| unsigned long long* pUsed; |
| unsigned long long* pFree; |
| PAPP_CONTEXT pCtx = &AppContext; |
| U32 nBlocksSlave = 0; |
| |
| U32 nElmNum = size / BlockSize - 1; |
| |
| // We need to allocate the memory for indexes and to initialize the |
| // pool descriptor, (x+1) is used to prevent queues overflow |
| |
| pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long)); |
| |
| if (pCtx->PoolStrPtr == NULL) |
| return -1; |
| |
| pFree = (unsigned long long*) pCtx->PoolStrPtr; |
| pUsed = pFree + (nElmNum + 1); |
| |
| ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed); |
| |
| if (ret == 0) { |
| |
| if (AppContext.master) { |
| int res = TRUE; |
| /* allocate blocks for Slave to Master transmittion */ |
| while (res) { |
| void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE); |
| if (pBlock) { |
| res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock)); |
| if (res) |
| nBlocksSlave++; |
| else |
| App_Free(AppContext.hWls, pBlock); |
| } else |
| res = FALSE; |
| } |
| printf("Slave has %d free blocks\n", nBlocksSlave); |
| } |
| } |
| |
| return ret; |
| } |
| |
| /********************************/ |
| |
| #define FAST_CRC16 1 |
| |
| #if (FAST_CRC16) |
| const U8 mb_table_level1[] = { |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 |
| }; |
| |
| const U8 mb_table_level2[] = { |
| 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, |
| 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, |
| 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, |
| 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, |
| 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, |
| 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, |
| 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, |
| 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, |
| 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, |
| 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, |
| 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, |
| 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, |
| 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, |
| 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, |
| 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, |
| 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, |
| 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, |
| 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, |
| 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, |
| 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, |
| 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, |
| 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, |
| 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, |
| 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, |
| 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, |
| 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, |
| 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, |
| 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, |
| 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, |
| 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, |
| 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, |
| 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 |
| }; |
| |
| #if 0 |
| // big endian CPU |
| |
| U16 |
| crc16(U16 crc, U8 data) |
| { |
| U8 index; |
| U8 crc_Low = crc & 0xFF; |
| U8 crc_High = crc >> 8; |
| |
| index = (crc_High ^ data) & 0xFF; |
| crc_High = crc_Low ^ mb_table_level1[ index ]; |
| crc_Low = mb_table_level2[ index ]; |
| |
| return (crc_High << 8) | crc_Low; |
| } |
| #else |
| // little endian CPU |
| #if 0 |
| static U16 CRC16_Update(U16 crc, U8 data) |
| { |
| U8 index; |
| U8 crc_High = crc >> 8; |
| U8 crc_Low = crc & 0xFF; |
| |
| index = crc_Low ^ data; |
| crc_Low = crc_High ^ mb_table_level1[ index ]; |
| crc_High = mb_table_level2[ index ]; |
| |
| return (crc_High << 8) | crc_Low; |
| } |
| #endif |
| #endif |
| |
| #if 0 |
| /*********************************************** |
| * CRC16 polynomial : X16 + X15 + X2 + 1 * |
| * FAST CRC16 routine * |
| * ---> pData - msg to be protected * |
| * ---> size - msg size in bytes * |
| * ---> aCRC - initializer (0xFFFF for 1st page)* |
| * <--- crc16 * |
| ***********************************************/ |
| static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size) |
| { |
| |
| if (!size) |
| return aCRC; |
| else { |
| U8 index; |
| U8 crc_High = aCRC >> 8; |
| U8 crc_Low = aCRC & 0xFF; |
| |
| do { |
| index = crc_Low ^ *pData++; |
| crc_Low = crc_High ^ mb_table_level1[ index ]; |
| crc_High = mb_table_level2[ index ]; |
| } while (--size); |
| |
| return (crc_High << 8) | crc_Low; |
| } |
| } |
| #endif |
| |
| #else // SLOW (canonic CRC16 calculation) |
| |
| /*********************************************** |
| * CRC16 polynomial : X16 + X15 + X2 + 1 * |
| * ---> pData - msg to be protected * |
| * ---> size - msg size in bytes * |
| * ---> aCRC - initializer (0xFFFF for 1st page)* |
| * <--- crc16 * |
| ***********************************************/ |
| U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size) |
| { |
| U8 i, tmp; |
| |
| if (!size) |
| return aCRC; |
| |
| do { |
| aCRC ^= *pData++; |
| for (i = 0; i < 8; i++) { |
| tmp = aCRC & 0x01; |
| aCRC >>= 1; |
| if (tmp) { |
| aCRC ^= CRC16_DIVISOR; |
| } |
| } |
| } while (--size); |
| return aCRC; |
| } |
| |
| #endif // FAST_CRC16 |
| |
| |
| #define CRC32_INIT_VAL 0xFFFFFFFF |
| #define CRC32_DIVISOR 0xA0000001 |
| |
| static U32 ICC_CRC32(U8 *pData, U32 size) |
| { |
| U32 retval = CRC32_INIT_VAL; |
| U8 i, tmp; |
| |
| if (!size) |
| return CRC32_INIT_VAL; // mean CRC error |
| do { |
| retval ^= *pData++; |
| for (i = 8; i > 0; --i) { |
| tmp = retval & 0x01; |
| retval >>= 1; |
| if (tmp) { |
| retval ^= CRC32_DIVISOR; |
| } |
| } |
| } while (--size); |
| return retval; |
| } |
| |
| #if 0 |
| |
| static U16 ICC_CRC16(U8 *pData, U16 size) |
| { |
| #define CRC16_ERROR (0xffff) |
| return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer |
| } |
| #endif |
| |
| static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags) |
| { |
| U8 *p; |
| U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg); |
| |
| if (pMsgVa == 0) |
| { |
| return 0; |
| } |
| p = (U8 *) pMsgVa; |
| #if 1 |
| U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc)); |
| // CRC32 |
| p[MsgSize - 4] = (crc >> 0) & 0xff; |
| p[MsgSize - 3] = (crc >> 8) & 0xff; |
| p[MsgSize - 2] = (crc >> 16) & 0xff; |
| p[MsgSize - 1] = (crc >> 24) & 0xff; |
| #else |
| U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc)); |
| // CRC16 |
| p[MsgSize - 2] = (crc >> 0) & 0xff; |
| p[MsgSize - 1] = (crc >> 8) & 0xff; |
| #endif |
| |
| return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags); |
| } |
| |
| static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags) |
| { |
| U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags); |
| U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa); |
| |
| if (pMsg) { |
| U32 size = *MsgSize; |
| #if 1 |
| U32 crc = ICC_CRC32((U8*) pMsg, size); |
| #else |
| U16 crc = ICC_CRC16((U8*) pMsg, size); |
| #endif |
| |
| if (crc != 0) { |
| printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size); |
| ShowData((U8*) pMsg, size); |
| } |
| } |
| return pMsgPa; |
| } |
| |
| static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags) |
| { |
| U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags); |
| U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa); |
| |
| if (pMsg) { |
| U32 size = *MsgSize; |
| #if 1 |
| U32 crc = ICC_CRC32((U8*) pMsg, size); |
| #else |
| U16 crc = ICC_CRC16((U8*) pMsg, size); |
| #endif |
| |
| if (crc != 0) { |
| printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size); |
| ShowData((U8*) pMsg, size); |
| } |
| } |
| return pMsgPa; |
| } |
| |
| static void CreateMessage(PAPP_MESSAGE p, U32 size) |
| { |
| (void) size; |
| p->id = AppContext.TxCnt++; |
| } |
| |
| static void CheckMessage(PAPP_MESSAGE p, U32 size) |
| { |
| if (AppContext.RxCnt && p->id != AppContext.RxCnt) { |
| // char buf[8*K]; |
| printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id); |
| ShowData(p, size); |
| // if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf))) |
| // printf("%s", buf); |
| } |
| |
| AppContext.RxCnt = p->id; |
| AppContext.RxCnt += 1; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_AllocMultiple |
| * @brief used to allocate multiple blocks of the same size from the WLS |
| * |
| * @param[h] hWls - app thread WLS handle |
| * @param[o] pMsgs - ptr to beginning of array of points to allocated blocks |
| * @param[o] pMsgSizes - array to write size for each allocated blocks |
| * @param[i] nMsgs - number of blocks to allocate |
| * @return U32 - number of allocated blocks |
| * |
| * @description |
| * The routine is used allocate multiple blocks from the ICC service, |
| * the blocks are supposed to be same size blocks, satisfying |
| * appContext.MaxMsgSize parameter. |
| * In case the service is unable to provide requested number of blocks, |
| * smaller count is allocated. The routine returns actual number of allocated |
| * blocks |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs) |
| { |
| unsigned n = 0; |
| unsigned i, j; |
| |
| memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs); |
| |
| while (nMsgs--) { |
| pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize); |
| pMsgSizes[n] = AppContext.MaxMsgSize; |
| if (!pMsgs[n]) { |
| printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs); |
| break; |
| } |
| n += 1; |
| } |
| |
| // check for duplicated pointers |
| for (i = 0; i < n; i++) { |
| for (j = i + 1; j < n; j++) { |
| if (pMsgs[i] == pMsgs[j]) { |
| printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j); |
| break; |
| } |
| } |
| } |
| |
| return n; |
| //ShowData(TxMessages, sizeof(TxMessages)); |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_SanityTestTransmitter |
| * @brief transmitter of default test case (0). |
| * |
| * @param[h] hWls - app thread WLS handle |
| * @return void |
| * |
| * @description |
| * The routine is used in test case 0 (non-blocking sanity unit test) |
| * The transmitter does allocate multiple blocks of the same size from the ICC |
| * service. Then it fills each block with incremental counter and transfers |
| * to other application specified by parameter TxID. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_SanityTestTransmitter(HANDLE hWls) |
| { |
| U8 *pMsg; |
| unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs); |
| unsigned fn = n; |
| unsigned cnt = 0; |
| unsigned k = 0; |
| unsigned alloc = n; |
| |
| // lets transmit some message for test |
| while (n--) { |
| pMsg = AppContext.TxMessages[cnt++]; |
| if (pMsg) { |
| U32 size = (rand() % AppContext.MaxMsgSize); |
| |
| if (size < AppContext.MinMsgSize) |
| size = AppContext.MinMsgSize; |
| |
| memset(pMsg, cnt, size); |
| CreateMessage((PAPP_MESSAGE) pMsg, size); |
| if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) { |
| printf("could not send the message_%p\n", pMsg); |
| break; |
| } else { |
| k++; |
| } |
| AppContext.nTxOctets += size; |
| AppContext.nTxMsgs += 1; |
| } |
| } |
| |
| if (alloc != k) |
| printf("inorrect sent %d alloc %d \n", k, alloc); |
| |
| cnt = 0; |
| while (fn--) { |
| pMsg = AppContext.TxMessages[cnt++]; |
| if (pMsg) { |
| if (App_Free(hWls, pMsg) != 0) |
| printf("could not release the message_%p\n", pMsg); |
| } else |
| printf("pMsg is NULL [%d]\n", cnt); |
| } |
| if (cnt != k) { |
| printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt); |
| AppContext.ExitStatus = 1; |
| } |
| } |
| |
| #if 0 |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_ScatterGatherTransmitter |
| * @brief transmitter of default test case (15/16). |
| * |
| * @param[h] hWls - app thread WLS handle |
| * @return void |
| * |
| * @description |
| * The routine is used in test case 0 (non-blocking sanity unit test) |
| * The transmitter does allocate multiple blocks of the same size from the ICC |
| * service. Then it fills each block with incremental counter and transfers |
| * to other application specified by parameter TxID. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_ScatterGatherTransmitter(HANDLE hWls) |
| { |
| U8 *pMsg; |
| unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs + 2); |
| unsigned i, cnt = 0, flags = 0; |
| U8 *p, *pOriginMsg = (U8 *)App_Alloc(hWls, AppContext.MaxMsgSize); |
| unsigned TotalSize = 0; |
| |
| unsigned fn = n; |
| unsigned k = 0; |
| unsigned alloc = n; |
| |
| if (!pOriginMsg) { |
| printf("No memory for App_Alloc()\n"); |
| return; |
| } |
| |
| flags = rand() & 0xff; |
| |
| for(i = 0; i < AppContext.MaxMsgSize; i++) |
| pOriginMsg[i] = (flags + i) & 0xff; |
| |
| // scatter original message among several blocks |
| for(i = 0; i < n; i++) |
| { |
| U32 size = (rand() % (AppContext.MaxMsgSize / n)); |
| |
| if (size < AppContext.MinMsgSize) |
| size = AppContext.MinMsgSize; |
| |
| TotalSize += size; |
| AppContext.TxMessageSizes[i] = size; |
| //printf("size%d=%lu\n", i, size); |
| } |
| |
| // adjust size of the last block |
| if (TotalSize < AppContext.MaxMsgSize) |
| { |
| AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize; |
| } |
| else if (TotalSize > AppContext.MaxMsgSize) |
| { |
| printf("error: size of the scatted blocks exceeding size of the original message\n"); |
| } |
| |
| p = pOriginMsg; |
| for(i = 0; i < n; i++) |
| { |
| // copy data into the scattered blocks |
| pMsg = AppContext.TxMessages[i]; |
| memcpy(pMsg, p, AppContext.TxMessageSizes[i]); |
| p += AppContext.TxMessageSizes[i]; |
| } |
| |
| // transmit original message first |
| if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0) |
| { |
| printf("could not send the message_%p\n", pOriginMsg); |
| if (App_Free(hWls, pOriginMsg) != 0) |
| printf("could not release the message_%p\n", pOriginMsg); |
| } |
| else |
| { |
| AppContext.nTxOctets += AppContext.MaxMsgSize; |
| AppContext.nTxMsgs += 1; |
| } |
| |
| if(pOriginMsg){ |
| if (App_Free(hWls, pOriginMsg) != 0) |
| printf("could not release the message_%p\n", pMsg); |
| } |
| else |
| printf("pOriginMsg is NULL \n"); |
| |
| // transmit scattered messages following their creation order |
| while (n--) |
| { |
| pMsg = AppContext.TxMessages[cnt]; |
| if (!cnt) |
| flags = WLS_SG_FIRST; |
| else if (n == 0) |
| flags = WLS_SG_LAST; |
| else |
| flags = WLS_SG_NEXT; |
| |
| if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0) |
| { |
| printf("could not send the message_%p\n", pMsg); |
| if (App_Free(hWls, pMsg) != 0) |
| printf("could not release the message_%p\n", pMsg); |
| } |
| else |
| k++; |
| |
| AppContext.nTxOctets += AppContext.TxMessageSizes[cnt]; |
| AppContext.nTxMsgs += 1; |
| cnt++; |
| } |
| if(alloc != k) |
| printf("inorrect sent %d alloc %d \n", k, alloc); |
| |
| cnt = 0; |
| while (fn--) |
| { |
| pMsg = AppContext.TxMessages[cnt++]; |
| if(pMsg){ |
| if (App_Free(hWls, pMsg) != 0) |
| printf("could not release the message_%p\n", pMsg); |
| } |
| else |
| printf("pMsg is NULL [%d]\n", cnt); |
| } |
| if(cnt != k) |
| printf("inorrect free sent %d free %d \n", k, cnt); |
| } |
| #endif |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_SanityTestReceiver |
| * @brief default sanity checking receiver used in multiple tests. |
| * |
| * @param[h] hWls - app thread WLS handle |
| * @return void |
| * |
| * @description |
| * The routine takes received messages and checks the sanity incremental |
| * counter to confirm the order. In case the counter does not correspond to |
| * expected counter (misordered message or incorrect message) an error is |
| * printed to STDOUT. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_SanityTestReceiver(HANDLE hWls) |
| { |
| (void) hWls; |
| U32 MsgSize; |
| U8 *pMsg; |
| U8 *pMsgPa; |
| U8 *pMsgVa; |
| U8 TempBuf[16 * K]; |
| unsigned short MsgTypeID; |
| unsigned short Flags; |
| U32 nBlocksSlave = 0; |
| |
| // handle RX receiver |
| while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) { |
| pMsgVa = (U8 *) WlsPaToVa(pMsgPa); |
| |
| if (pMsgVa == NULL) { |
| printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa); |
| continue; |
| } |
| |
| pMsg = pMsgVa; |
| |
| if (((U64) pMsg & 0x3) == 0) { |
| // aligned message |
| CheckMessage((PAPP_MESSAGE) pMsg, MsgSize); |
| } else { |
| // misaligned message |
| printf("Unaligned message\n"); |
| MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize; |
| memcpy(TempBuf, pMsg, MsgSize); |
| // handle received message |
| CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize); |
| } |
| App_Free(AppContext.hWls, pMsg); |
| AppContext.nRxOcters += MsgSize; |
| AppContext.nRxMsgs += 1; |
| |
| if (AppContext.master) { |
| int res = TRUE; |
| /* allocate blocks for Slave to Master transmittion */ |
| while (res) { |
| void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE); |
| if (pBlock) { |
| res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock)); |
| if (res) |
| nBlocksSlave++; |
| else |
| App_Free(AppContext.hWls, pBlock); |
| } else |
| res = FALSE; |
| } |
| } |
| |
| } |
| } |
| |
| #if 0 |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_ScatterGatherReceiver |
| * @brief scatter gather test receiver |
| * |
| * @param[h] hWls - app thread WLS handle |
| * @return void |
| * |
| * @description |
| * The routine takes received messages and checks the sanity incremental |
| * counter to confirm the order. In case the counter does not correspond to |
| * expected counter (misordered message or incorrect message) an error is |
| * printed to STDOUT. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_ScatterGatherReceiver(HANDLE hWls) |
| { |
| (void)hWls; |
| U32 MsgSize; |
| U8 *pMsg; |
| U8 *pMsgPa; |
| U8 *pMsgVa; |
| U32 size; |
| U8 err = 0; |
| unsigned short MsgTypeID; |
| unsigned short Flags; |
| |
| // handle RX receiver |
| while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL) |
| { |
| pMsgVa = (U8 *)WlsPaToVa(pMsgPa); |
| |
| pMsg = pMsgVa; |
| |
| AppContext.nRxOcters += MsgSize; |
| AppContext.nRxMsgs += 1; |
| |
| if (!AppContext.pLastRx) |
| { |
| AppContext.pLastRx = pMsg; |
| AppContext.LastRxSize = MsgSize; |
| } |
| else // compare with received and release both |
| { |
| U32 i; |
| if (AppContext.LastRxSize != MsgSize) |
| printf("received wrong size, unsync? try to re-run app both clusters\n"); |
| |
| size = MsgSize; |
| if (size > AppContext.LastRxSize) |
| size = AppContext.LastRxSize; |
| |
| for(i = 0; i < size; i++) |
| { |
| if (pMsg[i] != AppContext.pLastRx[i]) |
| { |
| // error content doesn't match |
| err = TRUE; |
| break; |
| } |
| } |
| |
| if (err) |
| { |
| printf("content verification failed, scatter-gather test FAIL\n"); |
| // terminate |
| AppContext.Receive = NULL; |
| AppContext.Transmit = NULL; |
| App_Free(AppContext.hWls, pMsg); |
| App_Free(AppContext.hWls, AppContext.pLastRx); |
| return; |
| } |
| |
| App_Free(AppContext.hWls, pMsg); |
| App_Free(AppContext.hWls, AppContext.pLastRx); |
| AppContext.pLastRx = NULL; |
| } |
| |
| } |
| } |
| |
| |
| |
| static U32 app_GetTime(void) |
| { |
| struct timeval tv; |
| U32 time_ms = 0; |
| if (gettimeofday(&tv, NULL) == 0) |
| time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; |
| return time_ms; |
| } |
| #endif |
| |
| /****************************************************************************** |
| * * |
| * Application common routines * |
| * * |
| ******************************************************************************/ |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_UpdateStatistics |
| * @brief is used to update RX and TX statistics |
| * |
| * @param[n] void |
| * @return void |
| * |
| * @description |
| * The routine prints out the statistics of received and transmitted |
| * messages. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| |
| static void app_UpdateStatistics(void) |
| { |
| AppContext.Cycles += 1; |
| |
| if (AppContext.Debug || AppContext.Cycles % 1000 == 0) { |
| printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10); |
| printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10); |
| } |
| |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_Help |
| * @brief prints app help content |
| * |
| * @param[n] void |
| * @return void |
| * |
| * @description |
| * The routine is used to print help content to stdout. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_Help(void) |
| { |
| char help_content[] = \ |
| "WLS test application\n\n"\ |
| "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\ |
| "supports the following parameters:\n\n" |
| "-c | --testcase <test number> 0 - default sanity test\n"\ |
| " 1 - misaligned pointers test\n"\ |
| " 2 - aligned 4 pointers test\n"\ |
| " 3 - random pools test\n"\ |
| " 4 - ping-pong (ZBC test)\n"\ |
| " 5 - invalid messages test\n\n"\ |
| "--trusted switches WLS to trusted mode\n"\ |
| "-r | --rxid <id> used to specify RxTypeID\n"\ |
| "-t | --txid <id> used to specify TxTypeID\n"\ |
| "-n | --msgcount <count> used to specify number of messages per timeframe\n"\ |
| "-l | --minsize <size> specifies MIN message size in bytes\n"\ |
| "-s | --maxsize <size> specifies MAX message size in bytes\n"\ |
| "--crc enables CRC generation and checking\n"\ |
| "--debug increases sleep interval to 1 second\n"\ |
| "-m | --master set predefined rxid and txid\n"; |
| |
| printf("%s", help_content); |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_ParseArgs |
| * @brief is used to parse incoming app args |
| * |
| * @param[i] argc - app arg count |
| * @param[i] argv - array of args |
| * @param[o] params - app startup params filled basing on args parse |
| * @return number of parsed args |
| * |
| * @description |
| * The routine is parse input args and convert them into app startup params |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params) |
| { |
| int c; |
| int *pInt; |
| int cnt = 0; |
| |
| struct option long_options[] = { |
| {"wlsdev", required_argument, 0, 'w'}, |
| {"affinity", required_argument, 0, 'a'}, |
| {"testcase", required_argument, 0, 'c'}, |
| {"rxid", required_argument, 0, 'r'}, |
| {"txid", required_argument, 0, 't'}, |
| {"msgcount", required_argument, 0, 'n'}, |
| {"maxsize", required_argument, 0, 's'}, |
| {"minsize", required_argument, 0, 'l'}, |
| {"master", no_argument, 0, 'm'}, |
| {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/ |
| {"icount", required_argument, 0, 'i'}, |
| {"crc", no_argument, 0, 1}, |
| {"trusted", no_argument, 0, 2}, |
| {"help", no_argument, 0, 'h'}, |
| {0, 0, 0, 0} |
| }; |
| |
| memset(params, 0, sizeof (*params)); |
| |
| // set default values here |
| params->interface_count = 1; |
| |
| while (1) { |
| //int this_option_optind = optind ? optind : 1; |
| int option_index = 0; |
| |
| c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index); |
| |
| if (c == -1) |
| break; |
| |
| cnt += 1; |
| pInt = NULL; |
| |
| switch (c) { |
| case 'a': // test Case selection |
| pInt = ¶ms->aff_core; |
| break; |
| case 'c': // test Case selection |
| pInt = ¶ms->test_id; |
| break; |
| case 'r': // rx id selection |
| pInt = ¶ms->rx_id; |
| break; |
| case 't': // tx id selection |
| pInt = ¶ms->tx_id; |
| break; |
| case 's': // select message size |
| pInt = ¶ms->max_size; |
| break; |
| case 'l': // select message size |
| pInt = ¶ms->min_size; |
| break; |
| case 'n': // select number of messages |
| pInt = ¶ms->n_messages; |
| break; |
| case 'i': // select number of interfaces to register |
| pInt = ¶ms->interface_count; |
| break; |
| case 'm': |
| params->master = TRUE; |
| break; |
| case 'd': |
| params->debug = TRUE; |
| break; |
| case 'w': |
| params->wls_dev_name = optarg; |
| break; |
| case 'h': |
| app_Help(); |
| exit(0); |
| case 2: |
| params->trusted = TRUE; |
| break; |
| case 1: // crc checking enabled |
| params->crc = TRUE; |
| break; |
| } |
| |
| if (pInt && optarg) { |
| // get int arg |
| if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) { |
| sscanf(optarg, "%x", (unsigned *) pInt); |
| } else { |
| *pInt = atoi(optarg); |
| } |
| } |
| } |
| return cnt; |
| } |
| |
| static int app_set_affinity(int coreNum) |
| { |
| cpu_set_t cpuset; |
| int i, rc; |
| |
| /* set main thread affinity mask to CPU7 */ |
| |
| CPU_ZERO(&cpuset); |
| CPU_SET(coreNum, &cpuset); |
| |
| rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset); |
| if (rc) { |
| perror("pthread_setaffinity_np failed"); |
| printf("pthread_setaffinity_np failed: %d", rc); |
| } |
| |
| /* check the actual affinity mask assigned to the thread */ |
| |
| CPU_ZERO(&cpuset); |
| |
| rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset); |
| |
| if (rc) { |
| perror("pthread_getaffinity_np failed"); |
| printf("pthread_getaffinity_np failed: %d", rc); |
| } |
| |
| printf("set affinity: "); |
| for (i = 0; i < CPU_SETSIZE; i++) |
| if (CPU_ISSET(i, &cpuset)) |
| printf(" CPU %d\n", i); |
| |
| if (!CPU_ISSET(coreNum, &cpuset)) { |
| printf("affinity failed"); |
| } |
| |
| /** |
| A new thread created by pthread_create(3) inherits a copy of its |
| creator's CPU affinity mask. */ |
| |
| return rc; |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_ApplyParams |
| * @brief is used to apply application startup parameters |
| * |
| * @param[i] params - app startup params |
| * @return void |
| * |
| * @description |
| * The applies startup parameters |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_ApplyParams(PAPP_PARAMS params) |
| { |
| // apply parameters |
| printf("selected test case %d - ", params->test_id); |
| switch (params->test_id) { |
| case APP_TC_SANITY_TEST: |
| default: |
| printf("NON-BLOCKING SANITY TEST\n"); |
| AppContext.Receive = app_SanityTestReceiver; |
| AppContext.Transmit = app_SanityTestTransmitter; |
| break; |
| } |
| |
| AppContext.wls_put = WLS_Put; |
| AppContext.wls_get = WLS_Get; |
| AppContext.wls_wget = WLS_WGet; |
| |
| AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS; |
| AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE; |
| AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE; |
| AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE); |
| |
| if (params->master) { |
| printf("WLS test app (supposed to run as MEMORY MASTER)\n"); |
| AppContext.master = TRUE; |
| AppContext.RxID = 1; |
| AppContext.TxID = 2; |
| } else { |
| AppContext.master = FALSE; |
| AppContext.RxID = 2; |
| AppContext.TxID = 1; |
| } |
| |
| if (params->rx_id) |
| AppContext.RxID = params->rx_id; |
| |
| if (params->tx_id) |
| AppContext.TxID = params->tx_id; |
| |
| if (params->n_messages && params->n_messages < MAX_MESSAGES) |
| AppContext.MsgPerMs = params->n_messages; |
| |
| if (params->min_size && params->min_size >= 4) |
| AppContext.MinMsgSize = params->min_size; |
| |
| // default is 1 RX interface |
| printf("if count = %u\n", params->interface_count); |
| AppContext.nInterfaces = 1; |
| if (params->interface_count == 0) { |
| printf("WLS test app started as simple data source, no RX ID will be specified\n"); |
| AppContext.nInterfaces = 0; |
| AppContext.RxID = 0; // override RxID |
| } else if (params->interface_count <= 7) { |
| AppContext.nInterfaces = params->interface_count; |
| } |
| |
| |
| AppContext.TrustedDataSource = params->trusted; |
| |
| if (params->crc) { |
| if (AppContext.MinMsgSize < 8) |
| AppContext.MinMsgSize = 8; |
| |
| AppContext.wls_put = app_PutMessageCRC; |
| AppContext.wls_get = app_GetMessageCRC; |
| AppContext.wls_wget = app_WGetMessageCRC; |
| |
| AppContext.AppSanityMsgSize += 4; // + sizeof CRC |
| } |
| |
| if (params->max_size && params->max_size <= 16 * K) |
| AppContext.MaxMsgSize = params->max_size; |
| |
| if (params->max_size < params->min_size) |
| params->max_size = params->min_size; |
| |
| AppContext.Debug = params->debug; |
| |
| if (params->aff_core) { |
| AppContext.core = params->aff_core; |
| app_set_affinity(AppContext.core); |
| } |
| |
| printf("The application started with:\n"); |
| printf("Core ................ %d\n", AppContext.core); |
| printf("Rx interface count .. %d\n", AppContext.nInterfaces); |
| printf("RxID ................ %d\n", AppContext.RxID); |
| printf("TxID ................ %d\n", AppContext.TxID); |
| if (AppContext.Debug) |
| printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs); |
| else |
| printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs); |
| printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize); |
| printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize); |
| printf("Number of threads ... 1\n"); |
| printf("CRC checking ........ "); |
| if (params->crc) |
| printf("ENABLED\n"); |
| else |
| printf("DISABLED\n"); |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn app_ReleaseAllocatedBuffers |
| * @brief releases ICC buffers allocated by the application |
| * |
| * @param[n] void |
| * @return void |
| * |
| * @description |
| * In process of making some tests when signal to close the application |
| * happens the app may keep some allocated buffers from the ICC pools. This |
| * routine does release these buffers back to ICC. |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ******************************************************************************/ |
| static void app_ReleaseAllocatedBuffers(void) |
| { |
| if (AppContext.TxMsgCnt && AppContext.master) |
| do { |
| AppContext.TxMsgCnt -= 1; |
| App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]); |
| } while (AppContext.TxMsgCnt != 0); |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @fn main |
| * @brief ICC test application main routine |
| * |
| * @param[n] void |
| * @return void |
| * |
| * @description |
| * Contains logic of the test (one RX/TX thread) |
| * |
| * @references |
| * MS-111070-SP |
| * |
| * @ingroup icc_service_unit_test |
| * |
| ****************************************************************************/ |
| int main(int argc, char* argv[]) |
| { |
| int retval = 0; |
| APP_PARAMS params; |
| |
| signal(SIGINT, App_SigExitCallback); |
| |
| memset(&AppContext, 0, sizeof (AppContext)); |
| memset(¶ms, 0, sizeof (params)); |
| |
| #ifdef DPDK_WLS |
| int ret = rte_eal_init(argc, argv); |
| if (ret < 0) |
| rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); |
| |
| argc -= ret; |
| argv += ret; |
| #endif |
| |
| app_ParseArgs(argc, argv, ¶ms); |
| app_ApplyParams(¶ms); |
| |
| AppContext.InitQueueSize = APP_QUEUE_SIZE; |
| |
| AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE); |
| |
| if (!AppContext.hWls) { |
| printf("could not register WLS client\n"); |
| return 1; |
| } else { |
| printf("WLS has been registered\n"); |
| } |
| |
| AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE); |
| |
| if (AppContext.shm_memory == NULL) { |
| if (AppContext.master) |
| printf("could not create WLS shared memory\n"); |
| else |
| printf("could not attach WLS shared memory\n"); |
| |
| return -1; |
| } |
| |
| if (AppContext.master) { |
| if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) { |
| WLS_Free(AppContext.hWls, AppContext.shm_memory); |
| WLS_Close(AppContext.hWls); |
| exit(1); |
| } |
| |
| } |
| |
| // APPLICATION MAIN LOOP |
| while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) { |
| if (AppContext.Receive) |
| AppContext.Receive(AppContext.hWls); |
| |
| if (AppContext.Debug) |
| //usleep(10000); // 1 sec delay |
| sleep(1); // 1 sec delay |
| else |
| usleep(1000); // 1 ms delay |
| |
| if (AppContext.Transmit) |
| AppContext.Transmit(AppContext.hWls); |
| |
| app_UpdateStatistics(); |
| } |
| |
| app_ReleaseAllocatedBuffers(); |
| printf("deregistering WLS (TxTotal_%llu, RxTotal_%llu)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs); |
| WLS_Free(AppContext.hWls, AppContext.shm_memory); |
| WLS_Close(AppContext.hWls); |
| return retval; |
| } |