1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
20 * WLS interface test application
21 * (contains functional unit tests and diagnostics to test wls
22 * supported by WLS interface)
26 #include <stdio.h> // for printf
27 #include <string.h> // for memset
28 #include <signal.h> // for SIGINT
29 #include <unistd.h> // for usleep
30 #include <stdlib.h> // for rand
31 #include <getopt.h> // for getopt
45 #define DEFAULT_TEST_MEMORY_SIZE 256*M
46 #define DEFAUTL_TEST_BLOCK_SIZE 16*K
48 #define DEFAULT_MESSAGE_COUNT_PER_MS 10
49 #define DEFAULT_MAX_MESSAGE_SIZE 2000
50 #define DEFUALT_MIN_MESSAGE_SIZE 100
52 #define APP_QUEUE_SIZE 255 /* number of elements each queue of the WLS being registered will have */
53 #define MAX_MESSAGES 1000 /* per ms */
65 APP_TC_SANITY_TEST = 0,
68 typedef struct tagAPP_PARAMS {
82 } APP_PARAMS, *PAPP_PARAMS;
84 typedef struct tagAPP_MESSAGE {
86 } APP_MESSAGE, *PAPP_MESSAGE;
88 typedef struct tagAPP_CONTEXT {
96 POOL Pool; // The pool descriptor
97 void* PoolStrPtr; // The pool storage pointer to keep indexes
102 U16 nInterfaces; // number of RX identifiers used by the APP
104 U16 InitQueueSize; // for invalid messages test (to trigger WLS blocking)
114 U64 nTxMsgs; // Messages transmitted
115 U64 nTxOctets; // Octets transmitted
116 U64 nRxMsgs; // Messages received
117 U64 nRxOcters; // Octets received
118 U64 Cycles; // number of 1ms cycles
120 int AppSanityMsgSize; // 4 or 8 depending on CRC feature
121 U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms
122 U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking.
124 void (*Receive)(HANDLE h);
125 void (*Transmit)(HANDLE h);
127 void (*ThreadReceive)(HANDLE h);
128 void (*ThreadTransmit)(HANDLE h);
130 int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
131 unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
132 unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
134 U8 *pLastRx; // used for scatter-gather test
135 U32 LastRxSize; // used for scatter-gather test
140 PVOID TxMessages[MAX_MESSAGES];
141 U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
144 } APP_CONTEXT, *PAPP_CONTEXT;
146 APP_CONTEXT AppContext;
148 static int pool_alloc = 0;
149 static int pool_free = 0;
151 static void ShowData(void* ptr, unsigned int size)
156 for (i = 0; i < size; i++) {
159 printf("%02x ", d[i]);
164 static void App_SigExitCallback(int signum)
167 AppContext.ExitStatus = TRUE;
170 static void* WlsVaToPa(void * ptr)
172 PAPP_CONTEXT pCtx = &AppContext;
173 return (void*) WLS_VA2PA(pCtx->hWls, ptr);
176 static void* WlsPaToVa(void * ptr)
178 PAPP_CONTEXT pCtx = &AppContext;
179 return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
182 static void* App_Alloc(void* h, unsigned long size)
186 void * retval = NULL;
187 if (AppContext.master) {
188 retval = PoolAlloc(&(AppContext.Pool));
189 //printf("pPool->FreeGet %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut);
191 retval = (void*) WLS_DequeueBlock(AppContext.hWls);
193 retval = (void*) WlsPaToVa(retval);
195 printf("WLS_DequeueBlock returned null\n");
198 if (retval == NULL) {
199 printf("no memory %d %d\n", pool_alloc, pool_free);
207 static int App_Free(void* h, void* pMsg)
210 if (AppContext.master)
213 return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
215 printf("Free Null pointer\n");
221 static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
224 unsigned long long* pUsed;
225 unsigned long long* pFree;
226 PAPP_CONTEXT pCtx = &AppContext;
227 U32 nBlocksSlave = 0;
229 U32 nElmNum = size / BlockSize - 1;
231 // We need to allocate the memory for indexes and to initialize the
232 // pool descriptor, (x+1) is used to prevent queues overflow
234 pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
236 if (pCtx->PoolStrPtr == NULL)
239 pFree = (unsigned long long*) pCtx->PoolStrPtr;
240 pUsed = pFree + (nElmNum + 1);
242 ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
246 if (AppContext.master) {
248 /* allocate blocks for Slave to Master transmittion */
250 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
252 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
256 App_Free(AppContext.hWls, pBlock);
260 printf("Slave has %d free blocks\n", nBlocksSlave);
267 /********************************/
272 const U8 mb_table_level1[] = {
273 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
274 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
275 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
276 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
277 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
278 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
279 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
280 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
281 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
282 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
283 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
284 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
285 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
286 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
287 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
288 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
289 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
290 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
291 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
292 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
293 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
294 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
295 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
296 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
297 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
298 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
299 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
300 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
301 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
302 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
303 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
304 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
307 const U8 mb_table_level2[] = {
308 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
309 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
310 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
311 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
312 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
313 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
314 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
315 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
316 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
317 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
318 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
319 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
320 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
321 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
322 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
323 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
324 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
325 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
326 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
327 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
328 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
329 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
330 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
331 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
332 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
333 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
334 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
335 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
336 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
337 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
338 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
339 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
346 crc16(U16 crc, U8 data)
349 U8 crc_Low = crc & 0xFF;
350 U8 crc_High = crc >> 8;
352 index = (crc_High ^ data) & 0xFF;
353 crc_High = crc_Low ^ mb_table_level1[ index ];
354 crc_Low = mb_table_level2[ index ];
356 return (crc_High << 8) | crc_Low;
361 static U16 CRC16_Update(U16 crc, U8 data)
364 U8 crc_High = crc >> 8;
365 U8 crc_Low = crc & 0xFF;
367 index = crc_Low ^ data;
368 crc_Low = crc_High ^ mb_table_level1[ index ];
369 crc_High = mb_table_level2[ index ];
371 return (crc_High << 8) | crc_Low;
377 /***********************************************
378 * CRC16 polynomial : X16 + X15 + X2 + 1 *
379 * FAST CRC16 routine *
380 * ---> pData - msg to be protected *
381 * ---> size - msg size in bytes *
382 * ---> aCRC - initializer (0xFFFF for 1st page)*
384 ***********************************************/
385 static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
392 U8 crc_High = aCRC >> 8;
393 U8 crc_Low = aCRC & 0xFF;
396 index = crc_Low ^ *pData++;
397 crc_Low = crc_High ^ mb_table_level1[ index ];
398 crc_High = mb_table_level2[ index ];
401 return (crc_High << 8) | crc_Low;
406 #else // SLOW (canonic CRC16 calculation)
408 /***********************************************
409 * CRC16 polynomial : X16 + X15 + X2 + 1 *
410 * ---> pData - msg to be protected *
411 * ---> size - msg size in bytes *
412 * ---> aCRC - initializer (0xFFFF for 1st page)*
414 ***********************************************/
415 U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
424 for (i = 0; i < 8; i++) {
428 aCRC ^= CRC16_DIVISOR;
438 #define CRC32_INIT_VAL 0xFFFFFFFF
439 #define CRC32_DIVISOR 0xA0000001
441 static U32 ICC_CRC32(U8 *pData, U32 size)
443 U32 retval = CRC32_INIT_VAL;
447 return CRC32_INIT_VAL; // mean CRC error
450 for (i = 8; i > 0; --i) {
454 retval ^= CRC32_DIVISOR;
463 static U16 ICC_CRC16(U8 *pData, U16 size)
465 #define CRC16_ERROR (0xffff)
466 return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer
470 static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
473 U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
481 U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
483 p[MsgSize - 4] = (crc >> 0) & 0xff;
484 p[MsgSize - 3] = (crc >> 8) & 0xff;
485 p[MsgSize - 2] = (crc >> 16) & 0xff;
486 p[MsgSize - 1] = (crc >> 24) & 0xff;
488 U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc));
490 p[MsgSize - 2] = (crc >> 0) & 0xff;
491 p[MsgSize - 1] = (crc >> 8) & 0xff;
494 return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
497 static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
499 U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
500 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
505 U32 crc = ICC_CRC32((U8*) pMsg, size);
507 U16 crc = ICC_CRC16((U8*) pMsg, size);
511 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
512 ShowData((U8*) pMsg, size);
518 static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
520 U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
521 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
526 U32 crc = ICC_CRC32((U8*) pMsg, size);
528 U16 crc = ICC_CRC16((U8*) pMsg, size);
532 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
533 ShowData((U8*) pMsg, size);
539 static void CreateMessage(PAPP_MESSAGE p, U32 size)
542 p->id = AppContext.TxCnt++;
545 static void CheckMessage(PAPP_MESSAGE p, U32 size)
547 if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
549 printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id);
551 // if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
552 // printf("%s", buf);
555 AppContext.RxCnt = p->id;
556 AppContext.RxCnt += 1;
560 *******************************************************************************
562 * @fn app_AllocMultiple
563 * @brief used to allocate multiple blocks of the same size from the WLS
565 * @param[h] hWls - app thread WLS handle
566 * @param[o] pMsgs - ptr to beginning of array of points to allocated blocks
567 * @param[o] pMsgSizes - array to write size for each allocated blocks
568 * @param[i] nMsgs - number of blocks to allocate
569 * @return U32 - number of allocated blocks
572 * The routine is used allocate multiple blocks from the ICC service,
573 * the blocks are supposed to be same size blocks, satisfying
574 * appContext.MaxMsgSize parameter.
575 * In case the service is unable to provide requested number of blocks,
576 * smaller count is allocated. The routine returns actual number of allocated
582 * @ingroup icc_service_unit_test
584 ******************************************************************************/
585 static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
590 memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
593 pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
594 pMsgSizes[n] = AppContext.MaxMsgSize;
596 printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
602 // check for duplicated pointers
603 for (i = 0; i < n; i++) {
604 for (j = i + 1; j < n; j++) {
605 if (pMsgs[i] == pMsgs[j]) {
606 printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j);
613 //ShowData(TxMessages, sizeof(TxMessages));
617 *******************************************************************************
619 * @fn app_SanityTestTransmitter
620 * @brief transmitter of default test case (0).
622 * @param[h] hWls - app thread WLS handle
626 * The routine is used in test case 0 (non-blocking sanity unit test)
627 * The transmitter does allocate multiple blocks of the same size from the ICC
628 * service. Then it fills each block with incremental counter and transfers
629 * to other application specified by parameter TxID.
634 * @ingroup icc_service_unit_test
636 ******************************************************************************/
637 static void app_SanityTestTransmitter(HANDLE hWls)
640 unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
646 // lets transmit some message for test
648 pMsg = AppContext.TxMessages[cnt++];
650 U32 size = (rand() % AppContext.MaxMsgSize);
652 if (size < AppContext.MinMsgSize)
653 size = AppContext.MinMsgSize;
655 memset(pMsg, cnt, size);
656 CreateMessage((PAPP_MESSAGE) pMsg, size);
657 if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) {
658 printf("could not send the message_%p\n", pMsg);
663 AppContext.nTxOctets += size;
664 AppContext.nTxMsgs += 1;
669 printf("inorrect sent %d alloc %d \n", k, alloc);
673 pMsg = AppContext.TxMessages[cnt++];
675 if (App_Free(hWls, pMsg) != 0)
676 printf("could not release the message_%p\n", pMsg);
678 printf("pMsg is NULL [%d]\n", cnt);
681 printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
682 AppContext.ExitStatus = 1;
688 *******************************************************************************
690 * @fn app_ScatterGatherTransmitter
691 * @brief transmitter of default test case (15/16).
693 * @param[h] hWls - app thread WLS handle
697 * The routine is used in test case 0 (non-blocking sanity unit test)
698 * The transmitter does allocate multiple blocks of the same size from the ICC
699 * service. Then it fills each block with incremental counter and transfers
700 * to other application specified by parameter TxID.
705 * @ingroup icc_service_unit_test
707 ******************************************************************************/
708 static void app_ScatterGatherTransmitter(HANDLE hWls)
711 unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs + 2);
712 unsigned i, cnt = 0, flags = 0;
713 U8 *p, *pOriginMsg = (U8 *)App_Alloc(hWls, AppContext.MaxMsgSize);
714 unsigned TotalSize = 0;
721 printf("No memory for App_Alloc()\n");
725 flags = rand() & 0xff;
727 for(i = 0; i < AppContext.MaxMsgSize; i++)
728 pOriginMsg[i] = (flags + i) & 0xff;
730 // scatter original message among several blocks
731 for(i = 0; i < n; i++)
733 U32 size = (rand() % (AppContext.MaxMsgSize / n));
735 if (size < AppContext.MinMsgSize)
736 size = AppContext.MinMsgSize;
739 AppContext.TxMessageSizes[i] = size;
740 //printf("size%d=%lu\n", i, size);
743 // adjust size of the last block
744 if (TotalSize < AppContext.MaxMsgSize)
746 AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize;
748 else if (TotalSize > AppContext.MaxMsgSize)
750 printf("error: size of the scatted blocks exceeding size of the original message\n");
754 for(i = 0; i < n; i++)
756 // copy data into the scattered blocks
757 pMsg = AppContext.TxMessages[i];
758 memcpy(pMsg, p, AppContext.TxMessageSizes[i]);
759 p += AppContext.TxMessageSizes[i];
762 // transmit original message first
763 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0)
765 printf("could not send the message_%p\n", pOriginMsg);
766 if (App_Free(hWls, pOriginMsg) != 0)
767 printf("could not release the message_%p\n", pOriginMsg);
771 AppContext.nTxOctets += AppContext.MaxMsgSize;
772 AppContext.nTxMsgs += 1;
776 if (App_Free(hWls, pOriginMsg) != 0)
777 printf("could not release the message_%p\n", pMsg);
780 printf("pOriginMsg is NULL \n");
782 // transmit scattered messages following their creation order
785 pMsg = AppContext.TxMessages[cnt];
787 flags = WLS_SG_FIRST;
793 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0)
795 printf("could not send the message_%p\n", pMsg);
796 if (App_Free(hWls, pMsg) != 0)
797 printf("could not release the message_%p\n", pMsg);
802 AppContext.nTxOctets += AppContext.TxMessageSizes[cnt];
803 AppContext.nTxMsgs += 1;
807 printf("inorrect sent %d alloc %d \n", k, alloc);
812 pMsg = AppContext.TxMessages[cnt++];
814 if (App_Free(hWls, pMsg) != 0)
815 printf("could not release the message_%p\n", pMsg);
818 printf("pMsg is NULL [%d]\n", cnt);
821 printf("inorrect free sent %d free %d \n", k, cnt);
826 *******************************************************************************
828 * @fn app_SanityTestReceiver
829 * @brief default sanity checking receiver used in multiple tests.
831 * @param[h] hWls - app thread WLS handle
835 * The routine takes received messages and checks the sanity incremental
836 * counter to confirm the order. In case the counter does not correspond to
837 * expected counter (misordered message or incorrect message) an error is
843 * @ingroup icc_service_unit_test
845 ******************************************************************************/
846 static void app_SanityTestReceiver(HANDLE hWls)
854 unsigned short MsgTypeID;
855 unsigned short Flags;
856 U32 nBlocksSlave = 0;
858 // handle RX receiver
859 while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
860 pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
862 if (pMsgVa == NULL) {
863 printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
869 if (((U64) pMsg & 0x3) == 0) {
871 CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
873 // misaligned message
874 printf("Unaligned message\n");
875 MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize;
876 memcpy(TempBuf, pMsg, MsgSize);
877 // handle received message
878 CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize);
880 App_Free(AppContext.hWls, pMsg);
881 AppContext.nRxOcters += MsgSize;
882 AppContext.nRxMsgs += 1;
884 if (AppContext.master) {
886 /* allocate blocks for Slave to Master transmittion */
888 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
890 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
894 App_Free(AppContext.hWls, pBlock);
905 *******************************************************************************
907 * @fn app_ScatterGatherReceiver
908 * @brief scatter gather test receiver
910 * @param[h] hWls - app thread WLS handle
914 * The routine takes received messages and checks the sanity incremental
915 * counter to confirm the order. In case the counter does not correspond to
916 * expected counter (misordered message or incorrect message) an error is
922 * @ingroup icc_service_unit_test
924 ******************************************************************************/
925 static void app_ScatterGatherReceiver(HANDLE hWls)
934 unsigned short MsgTypeID;
935 unsigned short Flags;
937 // handle RX receiver
938 while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)
940 pMsgVa = (U8 *)WlsPaToVa(pMsgPa);
944 AppContext.nRxOcters += MsgSize;
945 AppContext.nRxMsgs += 1;
947 if (!AppContext.pLastRx)
949 AppContext.pLastRx = pMsg;
950 AppContext.LastRxSize = MsgSize;
952 else // compare with received and release both
955 if (AppContext.LastRxSize != MsgSize)
956 printf("received wrong size, unsync? try to re-run app both clusters\n");
959 if (size > AppContext.LastRxSize)
960 size = AppContext.LastRxSize;
962 for(i = 0; i < size; i++)
964 if (pMsg[i] != AppContext.pLastRx[i])
966 // error content doesn't match
974 printf("content verification failed, scatter-gather test FAIL\n");
976 AppContext.Receive = NULL;
977 AppContext.Transmit = NULL;
978 App_Free(AppContext.hWls, pMsg);
979 App_Free(AppContext.hWls, AppContext.pLastRx);
983 App_Free(AppContext.hWls, pMsg);
984 App_Free(AppContext.hWls, AppContext.pLastRx);
985 AppContext.pLastRx = NULL;
993 static U32 app_GetTime(void)
997 if (gettimeofday(&tv, NULL) == 0)
998 time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1003 /******************************************************************************
1005 * Application common routines *
1007 ******************************************************************************/
1010 *******************************************************************************
1012 * @fn app_UpdateStatistics
1013 * @brief is used to update RX and TX statistics
1019 * The routine prints out the statistics of received and transmitted
1025 * @ingroup icc_service_unit_test
1027 ******************************************************************************/
1029 static void app_UpdateStatistics(void)
1031 AppContext.Cycles += 1;
1033 if (AppContext.Debug || AppContext.Cycles % 1000 == 0) {
1034 printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10);
1035 printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10);
1041 *******************************************************************************
1044 * @brief prints app help content
1050 * The routine is used to print help content to stdout.
1055 * @ingroup icc_service_unit_test
1057 ******************************************************************************/
1058 static void app_Help(void)
1060 char help_content[] = \
1061 "WLS test application\n\n"\
1062 "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\
1063 "supports the following parameters:\n\n"
1064 "-c | --testcase <test number> 0 - default sanity test\n"\
1065 " 1 - misaligned pointers test\n"\
1066 " 2 - aligned 4 pointers test\n"\
1067 " 3 - random pools test\n"\
1068 " 4 - ping-pong (ZBC test)\n"\
1069 " 5 - invalid messages test\n\n"\
1070 "--trusted switches WLS to trusted mode\n"\
1071 "-r | --rxid <id> used to specify RxTypeID\n"\
1072 "-t | --txid <id> used to specify TxTypeID\n"\
1073 "-n | --msgcount <count> used to specify number of messages per timeframe\n"\
1074 "-l | --minsize <size> specifies MIN message size in bytes\n"\
1075 "-s | --maxsize <size> specifies MAX message size in bytes\n"\
1076 "--crc enables CRC generation and checking\n"\
1077 "--debug increases sleep interval to 1 second\n"\
1078 "-m | --master set predefined rxid and txid\n";
1080 printf("%s", help_content);
1084 *******************************************************************************
1087 * @brief is used to parse incoming app args
1089 * @param[i] argc - app arg count
1090 * @param[i] argv - array of args
1091 * @param[o] params - app startup params filled basing on args parse
1092 * @return number of parsed args
1095 * The routine is parse input args and convert them into app startup params
1100 * @ingroup icc_service_unit_test
1102 ******************************************************************************/
1103 static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
1109 struct option long_options[] = {
1110 {"wlsdev", required_argument, 0, 'w'},
1111 {"affinity", required_argument, 0, 'a'},
1112 {"testcase", required_argument, 0, 'c'},
1113 {"rxid", required_argument, 0, 'r'},
1114 {"txid", required_argument, 0, 't'},
1115 {"msgcount", required_argument, 0, 'n'},
1116 {"maxsize", required_argument, 0, 's'},
1117 {"minsize", required_argument, 0, 'l'},
1118 {"master", no_argument, 0, 'm'},
1119 {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/
1120 {"icount", required_argument, 0, 'i'},
1121 {"crc", no_argument, 0, 1},
1122 {"trusted", no_argument, 0, 2},
1123 {"help", no_argument, 0, 'h'},
1127 memset(params, 0, sizeof (*params));
1129 // set default values here
1130 params->interface_count = 1;
1133 //int this_option_optind = optind ? optind : 1;
1134 int option_index = 0;
1136 c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
1145 case 'a': // test Case selection
1146 pInt = ¶ms->aff_core;
1148 case 'c': // test Case selection
1149 pInt = ¶ms->test_id;
1151 case 'r': // rx id selection
1152 pInt = ¶ms->rx_id;
1154 case 't': // tx id selection
1155 pInt = ¶ms->tx_id;
1157 case 's': // select message size
1158 pInt = ¶ms->max_size;
1160 case 'l': // select message size
1161 pInt = ¶ms->min_size;
1163 case 'n': // select number of messages
1164 pInt = ¶ms->n_messages;
1166 case 'i': // select number of interfaces to register
1167 pInt = ¶ms->interface_count;
1170 params->master = TRUE;
1173 params->debug = TRUE;
1176 params->wls_dev_name = optarg;
1182 params->trusted = TRUE;
1184 case 1: // crc checking enabled
1189 if (pInt && optarg) {
1191 if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
1192 sscanf(optarg, "%x", (unsigned *) pInt);
1194 *pInt = atoi(optarg);
1201 static int app_set_affinity(int coreNum)
1206 /* set main thread affinity mask to CPU7 */
1209 CPU_SET(coreNum, &cpuset);
1211 rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1213 perror("pthread_setaffinity_np failed");
1214 printf("pthread_setaffinity_np failed: %d", rc);
1217 /* check the actual affinity mask assigned to the thread */
1221 rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1224 perror("pthread_getaffinity_np failed");
1225 printf("pthread_getaffinity_np failed: %d", rc);
1228 printf("set affinity: ");
1229 for (i = 0; i < CPU_SETSIZE; i++)
1230 if (CPU_ISSET(i, &cpuset))
1231 printf(" CPU %d\n", i);
1233 if (!CPU_ISSET(coreNum, &cpuset)) {
1234 printf("affinity failed");
1238 A new thread created by pthread_create(3) inherits a copy of its
1239 creator's CPU affinity mask. */
1245 *******************************************************************************
1247 * @fn app_ApplyParams
1248 * @brief is used to apply application startup parameters
1250 * @param[i] params - app startup params
1254 * The applies startup parameters
1259 * @ingroup icc_service_unit_test
1261 ******************************************************************************/
1262 static void app_ApplyParams(PAPP_PARAMS params)
1265 printf("selected test case %d - ", params->test_id);
1266 switch (params->test_id) {
1267 case APP_TC_SANITY_TEST:
1269 printf("NON-BLOCKING SANITY TEST\n");
1270 AppContext.Receive = app_SanityTestReceiver;
1271 AppContext.Transmit = app_SanityTestTransmitter;
1275 AppContext.wls_put = WLS_Put;
1276 AppContext.wls_get = WLS_Get;
1277 AppContext.wls_wget = WLS_WGet;
1279 AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS;
1280 AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE;
1281 AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE;
1282 AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE);
1284 if (params->master) {
1285 printf("WLS test app (supposed to run as MEMORY MASTER)\n");
1286 AppContext.master = TRUE;
1287 AppContext.RxID = 1;
1288 AppContext.TxID = 2;
1290 AppContext.master = FALSE;
1291 AppContext.RxID = 2;
1292 AppContext.TxID = 1;
1296 AppContext.RxID = params->rx_id;
1299 AppContext.TxID = params->tx_id;
1301 if (params->n_messages && params->n_messages < MAX_MESSAGES)
1302 AppContext.MsgPerMs = params->n_messages;
1304 if (params->min_size && params->min_size >= 4)
1305 AppContext.MinMsgSize = params->min_size;
1307 // default is 1 RX interface
1308 printf("if count = %u\n", params->interface_count);
1309 AppContext.nInterfaces = 1;
1310 if (params->interface_count == 0) {
1311 printf("WLS test app started as simple data source, no RX ID will be specified\n");
1312 AppContext.nInterfaces = 0;
1313 AppContext.RxID = 0; // override RxID
1314 } else if (params->interface_count <= 7) {
1315 AppContext.nInterfaces = params->interface_count;
1319 AppContext.TrustedDataSource = params->trusted;
1322 if (AppContext.MinMsgSize < 8)
1323 AppContext.MinMsgSize = 8;
1325 AppContext.wls_put = app_PutMessageCRC;
1326 AppContext.wls_get = app_GetMessageCRC;
1327 AppContext.wls_wget = app_WGetMessageCRC;
1329 AppContext.AppSanityMsgSize += 4; // + sizeof CRC
1332 if (params->max_size && params->max_size <= 16 * K)
1333 AppContext.MaxMsgSize = params->max_size;
1335 if (params->max_size < params->min_size)
1336 params->max_size = params->min_size;
1338 AppContext.Debug = params->debug;
1340 if (params->aff_core) {
1341 AppContext.core = params->aff_core;
1342 app_set_affinity(AppContext.core);
1345 printf("The application started with:\n");
1346 printf("Core ................ %d\n", AppContext.core);
1347 printf("Rx interface count .. %d\n", AppContext.nInterfaces);
1348 printf("RxID ................ %d\n", AppContext.RxID);
1349 printf("TxID ................ %d\n", AppContext.TxID);
1350 if (AppContext.Debug)
1351 printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs);
1353 printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs);
1354 printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize);
1355 printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize);
1356 printf("Number of threads ... 1\n");
1357 printf("CRC checking ........ ");
1359 printf("ENABLED\n");
1361 printf("DISABLED\n");
1365 *******************************************************************************
1367 * @fn app_ReleaseAllocatedBuffers
1368 * @brief releases ICC buffers allocated by the application
1374 * In process of making some tests when signal to close the application
1375 * happens the app may keep some allocated buffers from the ICC pools. This
1376 * routine does release these buffers back to ICC.
1381 * @ingroup icc_service_unit_test
1383 ******************************************************************************/
1384 static void app_ReleaseAllocatedBuffers(void)
1386 if (AppContext.TxMsgCnt && AppContext.master)
1388 AppContext.TxMsgCnt -= 1;
1389 App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
1390 } while (AppContext.TxMsgCnt != 0);
1394 *******************************************************************************
1397 * @brief ICC test application main routine
1403 * Contains logic of the test (one RX/TX thread)
1408 * @ingroup icc_service_unit_test
1410 ****************************************************************************/
1411 int main(int argc, char* argv[])
1416 signal(SIGINT, App_SigExitCallback);
1418 memset(&AppContext, 0, sizeof (AppContext));
1419 memset(¶ms, 0, sizeof (params));
1422 int ret = rte_eal_init(argc, argv);
1424 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1430 app_ParseArgs(argc, argv, ¶ms);
1431 app_ApplyParams(¶ms);
1433 AppContext.InitQueueSize = APP_QUEUE_SIZE;
1435 AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE);
1437 if (!AppContext.hWls) {
1438 printf("could not register WLS client\n");
1441 printf("WLS has been registered\n");
1444 AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
1446 if (AppContext.shm_memory == NULL) {
1447 if (AppContext.master)
1448 printf("could not create WLS shared memory\n");
1450 printf("could not attach WLS shared memory\n");
1455 if (AppContext.master) {
1456 if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) {
1457 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1458 WLS_Close(AppContext.hWls);
1464 // APPLICATION MAIN LOOP
1465 while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) {
1466 if (AppContext.Receive)
1467 AppContext.Receive(AppContext.hWls);
1469 if (AppContext.Debug)
1470 //usleep(10000); // 1 sec delay
1471 sleep(1); // 1 sec delay
1473 usleep(1000); // 1 ms delay
1475 if (AppContext.Transmit)
1476 AppContext.Transmit(AppContext.hWls);
1478 app_UpdateStatistics();
1481 app_ReleaseAllocatedBuffers();
1482 printf("deregistering WLS (TxTotal_%llu, RxTotal_%llu)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs);
1483 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1484 WLS_Close(AppContext.hWls);