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)
29 #include <stdio.h> // for printf
30 #include <string.h> // for memset
31 #include <signal.h> // for SIGINT
32 #include <unistd.h> // for usleep
33 #include <stdlib.h> // for rand
34 #include <getopt.h> // for getopt
48 #define DEFAULT_TEST_MEMORY_SIZE 256*M
49 #define DEFAUTL_TEST_BLOCK_SIZE 16*K
51 #define DEFAULT_MESSAGE_COUNT_PER_MS 10
52 #define DEFAULT_MAX_MESSAGE_SIZE 2000
53 #define DEFUALT_MIN_MESSAGE_SIZE 100
55 #define APP_QUEUE_SIZE 255 /* number of elements each queue of the WLS being registered will have */
56 #define MAX_MESSAGES 1000 /* per ms */
68 APP_TC_SANITY_TEST = 0,
71 typedef struct tagAPP_PARAMS {
85 } APP_PARAMS, *PAPP_PARAMS;
87 typedef struct tagAPP_MESSAGE {
89 } APP_MESSAGE, *PAPP_MESSAGE;
91 typedef struct tagAPP_CONTEXT {
99 POOL Pool; // The pool descriptor
100 void* PoolStrPtr; // The pool storage pointer to keep indexes
105 U16 nInterfaces; // number of RX identifiers used by the APP
107 U16 InitQueueSize; // for invalid messages test (to trigger WLS blocking)
117 U64 nTxMsgs; // Messages transmitted
118 U64 nTxOctets; // Octets transmitted
119 U64 nRxMsgs; // Messages received
120 U64 nRxOcters; // Octets received
121 U64 Cycles; // number of 1ms cycles
123 int AppSanityMsgSize; // 4 or 8 depending on CRC feature
124 U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms
125 U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking.
127 void (*Receive)(HANDLE h);
128 void (*Transmit)(HANDLE h);
130 void (*ThreadReceive)(HANDLE h);
131 void (*ThreadTransmit)(HANDLE h);
133 int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
134 unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
135 unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
137 U8 *pLastRx; // used for scatter-gather test
138 U32 LastRxSize; // used for scatter-gather test
143 PVOID TxMessages[MAX_MESSAGES];
144 U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
147 } APP_CONTEXT, *PAPP_CONTEXT;
149 APP_CONTEXT AppContext;
151 static int pool_alloc = 0;
152 static int pool_free = 0;
154 static void ShowData(void* ptr, unsigned int size)
159 for (i = 0; i < size; i++) {
162 printf("%02x ", d[i]);
167 static void App_SigExitCallback(int signum)
170 AppContext.ExitStatus = TRUE;
173 static void* WlsVaToPa(void * ptr)
175 PAPP_CONTEXT pCtx = &AppContext;
176 return (void*) WLS_VA2PA(pCtx->hWls, ptr);
179 static void* WlsPaToVa(void * ptr)
181 PAPP_CONTEXT pCtx = &AppContext;
182 return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
185 static void* App_Alloc(void* h, unsigned long size)
189 void * retval = NULL;
190 if (AppContext.master) {
191 retval = PoolAlloc(&(AppContext.Pool));
192 //printf("pPool->FreeGet %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut);
194 retval = (void*) WLS_DequeueBlock(AppContext.hWls);
196 retval = (void*) WlsPaToVa(retval);
198 printf("WLS_DequeueBlock returned null\n");
201 if (retval == NULL) {
202 printf("no memory %d %d\n", pool_alloc, pool_free);
210 static int App_Free(void* h, void* pMsg)
213 if (AppContext.master)
216 return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
218 printf("Free Null pointer\n");
224 static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
227 unsigned long long* pUsed;
228 unsigned long long* pFree;
229 PAPP_CONTEXT pCtx = &AppContext;
230 U32 nBlocksSlave = 0;
232 U32 nElmNum = size / BlockSize - 1;
234 // We need to allocate the memory for indexes and to initialize the
235 // pool descriptor, (x+1) is used to prevent queues overflow
237 pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
239 if (pCtx->PoolStrPtr == NULL)
242 pFree = (unsigned long long*) pCtx->PoolStrPtr;
243 pUsed = pFree + (nElmNum + 1);
245 ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
249 if (AppContext.master) {
251 /* allocate blocks for Slave to Master transmittion */
253 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
255 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
259 App_Free(AppContext.hWls, pBlock);
263 printf("Slave has %d free blocks\n", nBlocksSlave);
270 /********************************/
275 const U8 mb_table_level1[] = {
276 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
277 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
278 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
279 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
280 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
281 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
282 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
283 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
284 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
285 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
286 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
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 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
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 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
295 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
296 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
297 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
298 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
299 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
300 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
301 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
302 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
303 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
304 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
305 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
306 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
307 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
310 const U8 mb_table_level2[] = {
311 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
312 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
313 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
314 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
315 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
316 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
317 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
318 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
319 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
320 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
321 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
322 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
323 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
324 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
325 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
326 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
327 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
328 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
329 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
330 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
331 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
332 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
333 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
334 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
335 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
336 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
337 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
338 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
339 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
340 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
341 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
342 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
349 crc16(U16 crc, U8 data)
352 U8 crc_Low = crc & 0xFF;
353 U8 crc_High = crc >> 8;
355 index = (crc_High ^ data) & 0xFF;
356 crc_High = crc_Low ^ mb_table_level1[ index ];
357 crc_Low = mb_table_level2[ index ];
359 return (crc_High << 8) | crc_Low;
364 static U16 CRC16_Update(U16 crc, U8 data)
367 U8 crc_High = crc >> 8;
368 U8 crc_Low = crc & 0xFF;
370 index = crc_Low ^ data;
371 crc_Low = crc_High ^ mb_table_level1[ index ];
372 crc_High = mb_table_level2[ index ];
374 return (crc_High << 8) | crc_Low;
380 /***********************************************
381 * CRC16 polynomial : X16 + X15 + X2 + 1 *
382 * FAST CRC16 routine *
383 * ---> pData - msg to be protected *
384 * ---> size - msg size in bytes *
385 * ---> aCRC - initializer (0xFFFF for 1st page)*
387 ***********************************************/
388 static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
395 U8 crc_High = aCRC >> 8;
396 U8 crc_Low = aCRC & 0xFF;
399 index = crc_Low ^ *pData++;
400 crc_Low = crc_High ^ mb_table_level1[ index ];
401 crc_High = mb_table_level2[ index ];
404 return (crc_High << 8) | crc_Low;
409 #else // SLOW (canonic CRC16 calculation)
411 /***********************************************
412 * CRC16 polynomial : X16 + X15 + X2 + 1 *
413 * ---> pData - msg to be protected *
414 * ---> size - msg size in bytes *
415 * ---> aCRC - initializer (0xFFFF for 1st page)*
417 ***********************************************/
418 U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
427 for (i = 0; i < 8; i++) {
431 aCRC ^= CRC16_DIVISOR;
441 #define CRC32_INIT_VAL 0xFFFFFFFF
442 #define CRC32_DIVISOR 0xA0000001
444 static U32 ICC_CRC32(U8 *pData, U32 size)
446 U32 retval = CRC32_INIT_VAL;
450 return CRC32_INIT_VAL; // mean CRC error
453 for (i = 8; i > 0; --i) {
457 retval ^= CRC32_DIVISOR;
466 static U16 ICC_CRC16(U8 *pData, U16 size)
468 #define CRC16_ERROR (0xffff)
469 return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer
473 static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
476 U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
484 U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
486 p[MsgSize - 4] = (crc >> 0) & 0xff;
487 p[MsgSize - 3] = (crc >> 8) & 0xff;
488 p[MsgSize - 2] = (crc >> 16) & 0xff;
489 p[MsgSize - 1] = (crc >> 24) & 0xff;
491 U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc));
493 p[MsgSize - 2] = (crc >> 0) & 0xff;
494 p[MsgSize - 1] = (crc >> 8) & 0xff;
497 return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
500 static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
502 U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
503 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
508 U32 crc = ICC_CRC32((U8*) pMsg, size);
510 U16 crc = ICC_CRC16((U8*) pMsg, size);
514 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
515 ShowData((U8*) pMsg, size);
521 static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
523 U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
524 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
529 U32 crc = ICC_CRC32((U8*) pMsg, size);
531 U16 crc = ICC_CRC16((U8*) pMsg, size);
535 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
536 ShowData((U8*) pMsg, size);
542 static void CreateMessage(PAPP_MESSAGE p, U32 size)
545 p->id = AppContext.TxCnt++;
548 static void CheckMessage(PAPP_MESSAGE p, U32 size)
550 if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
552 printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id);
554 // if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
555 // printf("%s", buf);
558 AppContext.RxCnt = p->id;
559 AppContext.RxCnt += 1;
563 *******************************************************************************
565 * @fn app_AllocMultiple
566 * @brief used to allocate multiple blocks of the same size from the WLS
568 * @param[h] hWls - app thread WLS handle
569 * @param[o] pMsgs - ptr to beginning of array of points to allocated blocks
570 * @param[o] pMsgSizes - array to write size for each allocated blocks
571 * @param[i] nMsgs - number of blocks to allocate
572 * @return U32 - number of allocated blocks
575 * The routine is used allocate multiple blocks from the ICC service,
576 * the blocks are supposed to be same size blocks, satisfying
577 * appContext.MaxMsgSize parameter.
578 * In case the service is unable to provide requested number of blocks,
579 * smaller count is allocated. The routine returns actual number of allocated
585 * @ingroup icc_service_unit_test
587 ******************************************************************************/
588 static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
593 memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
596 pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
597 pMsgSizes[n] = AppContext.MaxMsgSize;
599 printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
605 // check for duplicated pointers
606 for (i = 0; i < n; i++) {
607 for (j = i + 1; j < n; j++) {
608 if (pMsgs[i] == pMsgs[j]) {
609 printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j);
616 //ShowData(TxMessages, sizeof(TxMessages));
620 *******************************************************************************
622 * @fn app_SanityTestTransmitter
623 * @brief transmitter of default test case (0).
625 * @param[h] hWls - app thread WLS handle
629 * The routine is used in test case 0 (non-blocking sanity unit test)
630 * The transmitter does allocate multiple blocks of the same size from the ICC
631 * service. Then it fills each block with incremental counter and transfers
632 * to other application specified by parameter TxID.
637 * @ingroup icc_service_unit_test
639 ******************************************************************************/
640 static void app_SanityTestTransmitter(HANDLE hWls)
643 unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
649 // lets transmit some message for test
651 pMsg = AppContext.TxMessages[cnt++];
653 U32 size = (rand() % AppContext.MaxMsgSize);
655 if (size < AppContext.MinMsgSize)
656 size = AppContext.MinMsgSize;
658 memset(pMsg, cnt, size);
659 CreateMessage((PAPP_MESSAGE) pMsg, size);
660 if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) {
661 printf("could not send the message_%p\n", pMsg);
666 AppContext.nTxOctets += size;
667 AppContext.nTxMsgs += 1;
672 printf("inorrect sent %d alloc %d \n", k, alloc);
676 pMsg = AppContext.TxMessages[cnt++];
678 if (App_Free(hWls, pMsg) != 0)
679 printf("could not release the message_%p\n", pMsg);
681 printf("pMsg is NULL [%d]\n", cnt);
684 printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
685 AppContext.ExitStatus = 1;
691 *******************************************************************************
693 * @fn app_ScatterGatherTransmitter
694 * @brief transmitter of default test case (15/16).
696 * @param[h] hWls - app thread WLS handle
700 * The routine is used in test case 0 (non-blocking sanity unit test)
701 * The transmitter does allocate multiple blocks of the same size from the ICC
702 * service. Then it fills each block with incremental counter and transfers
703 * to other application specified by parameter TxID.
708 * @ingroup icc_service_unit_test
710 ******************************************************************************/
711 static void app_ScatterGatherTransmitter(HANDLE hWls)
714 unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs + 2);
715 unsigned i, cnt = 0, flags = 0;
716 U8 *p, *pOriginMsg = (U8 *)App_Alloc(hWls, AppContext.MaxMsgSize);
717 unsigned TotalSize = 0;
724 printf("No memory for App_Alloc()\n");
728 flags = rand() & 0xff;
730 for(i = 0; i < AppContext.MaxMsgSize; i++)
731 pOriginMsg[i] = (flags + i) & 0xff;
733 // scatter original message among several blocks
734 for(i = 0; i < n; i++)
736 U32 size = (rand() % (AppContext.MaxMsgSize / n));
738 if (size < AppContext.MinMsgSize)
739 size = AppContext.MinMsgSize;
742 AppContext.TxMessageSizes[i] = size;
743 //printf("size%d=%lu\n", i, size);
746 // adjust size of the last block
747 if (TotalSize < AppContext.MaxMsgSize)
749 AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize;
751 else if (TotalSize > AppContext.MaxMsgSize)
753 printf("error: size of the scatted blocks exceeding size of the original message\n");
757 for(i = 0; i < n; i++)
759 // copy data into the scattered blocks
760 pMsg = AppContext.TxMessages[i];
761 memcpy(pMsg, p, AppContext.TxMessageSizes[i]);
762 p += AppContext.TxMessageSizes[i];
765 // transmit original message first
766 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0)
768 printf("could not send the message_%p\n", pOriginMsg);
769 if (App_Free(hWls, pOriginMsg) != 0)
770 printf("could not release the message_%p\n", pOriginMsg);
774 AppContext.nTxOctets += AppContext.MaxMsgSize;
775 AppContext.nTxMsgs += 1;
779 if (App_Free(hWls, pOriginMsg) != 0)
780 printf("could not release the message_%p\n", pMsg);
783 printf("pOriginMsg is NULL \n");
785 // transmit scattered messages following their creation order
788 pMsg = AppContext.TxMessages[cnt];
790 flags = WLS_SG_FIRST;
796 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0)
798 printf("could not send the message_%p\n", pMsg);
799 if (App_Free(hWls, pMsg) != 0)
800 printf("could not release the message_%p\n", pMsg);
805 AppContext.nTxOctets += AppContext.TxMessageSizes[cnt];
806 AppContext.nTxMsgs += 1;
810 printf("inorrect sent %d alloc %d \n", k, alloc);
815 pMsg = AppContext.TxMessages[cnt++];
817 if (App_Free(hWls, pMsg) != 0)
818 printf("could not release the message_%p\n", pMsg);
821 printf("pMsg is NULL [%d]\n", cnt);
824 printf("inorrect free sent %d free %d \n", k, cnt);
829 *******************************************************************************
831 * @fn app_SanityTestReceiver
832 * @brief default sanity checking receiver used in multiple tests.
834 * @param[h] hWls - app thread WLS handle
838 * The routine takes received messages and checks the sanity incremental
839 * counter to confirm the order. In case the counter does not correspond to
840 * expected counter (misordered message or incorrect message) an error is
846 * @ingroup icc_service_unit_test
848 ******************************************************************************/
849 static void app_SanityTestReceiver(HANDLE hWls)
857 unsigned short MsgTypeID;
858 unsigned short Flags;
859 U32 nBlocksSlave = 0;
861 // handle RX receiver
862 while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
863 pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
865 if (pMsgVa == NULL) {
866 printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
872 if (((U64) pMsg & 0x3) == 0) {
874 CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
876 // misaligned message
877 printf("Unaligned message\n");
878 MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize;
879 memcpy(TempBuf, pMsg, MsgSize);
880 // handle received message
881 CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize);
883 App_Free(AppContext.hWls, pMsg);
884 AppContext.nRxOcters += MsgSize;
885 AppContext.nRxMsgs += 1;
887 if (AppContext.master) {
889 /* allocate blocks for Slave to Master transmittion */
891 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
893 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
897 App_Free(AppContext.hWls, pBlock);
908 *******************************************************************************
910 * @fn app_ScatterGatherReceiver
911 * @brief scatter gather test receiver
913 * @param[h] hWls - app thread WLS handle
917 * The routine takes received messages and checks the sanity incremental
918 * counter to confirm the order. In case the counter does not correspond to
919 * expected counter (misordered message or incorrect message) an error is
925 * @ingroup icc_service_unit_test
927 ******************************************************************************/
928 static void app_ScatterGatherReceiver(HANDLE hWls)
937 unsigned short MsgTypeID;
938 unsigned short Flags;
940 // handle RX receiver
941 while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)
943 pMsgVa = (U8 *)WlsPaToVa(pMsgPa);
947 AppContext.nRxOcters += MsgSize;
948 AppContext.nRxMsgs += 1;
950 if (!AppContext.pLastRx)
952 AppContext.pLastRx = pMsg;
953 AppContext.LastRxSize = MsgSize;
955 else // compare with received and release both
958 if (AppContext.LastRxSize != MsgSize)
959 printf("received wrong size, unsync? try to re-run app both clusters\n");
962 if (size > AppContext.LastRxSize)
963 size = AppContext.LastRxSize;
965 for(i = 0; i < size; i++)
967 if (pMsg[i] != AppContext.pLastRx[i])
969 // error content doesn't match
977 printf("content verification failed, scatter-gather test FAIL\n");
979 AppContext.Receive = NULL;
980 AppContext.Transmit = NULL;
981 App_Free(AppContext.hWls, pMsg);
982 App_Free(AppContext.hWls, AppContext.pLastRx);
986 App_Free(AppContext.hWls, pMsg);
987 App_Free(AppContext.hWls, AppContext.pLastRx);
988 AppContext.pLastRx = NULL;
996 static U32 app_GetTime(void)
1000 if (gettimeofday(&tv, NULL) == 0)
1001 time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1006 /******************************************************************************
1008 * Application common routines *
1010 ******************************************************************************/
1013 *******************************************************************************
1015 * @fn app_UpdateStatistics
1016 * @brief is used to update RX and TX statistics
1022 * The routine prints out the statistics of received and transmitted
1028 * @ingroup icc_service_unit_test
1030 ******************************************************************************/
1032 static void app_UpdateStatistics(void)
1034 AppContext.Cycles += 1;
1036 if (AppContext.Debug || AppContext.Cycles % 1000 == 0) {
1037 printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10);
1038 printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10);
1044 *******************************************************************************
1047 * @brief prints app help content
1053 * The routine is used to print help content to stdout.
1058 * @ingroup icc_service_unit_test
1060 ******************************************************************************/
1061 static void app_Help(void)
1063 char help_content[] = \
1064 "WLS test application\n\n"\
1065 "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\
1066 "supports the following parameters:\n\n"
1067 "-c | --testcase <test number> 0 - default sanity test\n"\
1068 " 1 - misaligned pointers test\n"\
1069 " 2 - aligned 4 pointers test\n"\
1070 " 3 - random pools test\n"\
1071 " 4 - ping-pong (ZBC test)\n"\
1072 " 5 - invalid messages test\n\n"\
1073 "--trusted switches WLS to trusted mode\n"\
1074 "-r | --rxid <id> used to specify RxTypeID\n"\
1075 "-t | --txid <id> used to specify TxTypeID\n"\
1076 "-n | --msgcount <count> used to specify number of messages per timeframe\n"\
1077 "-l | --minsize <size> specifies MIN message size in bytes\n"\
1078 "-s | --maxsize <size> specifies MAX message size in bytes\n"\
1079 "--crc enables CRC generation and checking\n"\
1080 "--debug increases sleep interval to 1 second\n"\
1081 "-m | --master set predefined rxid and txid\n";
1083 printf("%s", help_content);
1087 *******************************************************************************
1090 * @brief is used to parse incoming app args
1092 * @param[i] argc - app arg count
1093 * @param[i] argv - array of args
1094 * @param[o] params - app startup params filled basing on args parse
1095 * @return number of parsed args
1098 * The routine is parse input args and convert them into app startup params
1103 * @ingroup icc_service_unit_test
1105 ******************************************************************************/
1106 static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
1112 struct option long_options[] = {
1113 {"wlsdev", required_argument, 0, 'w'},
1114 {"affinity", required_argument, 0, 'a'},
1115 {"testcase", required_argument, 0, 'c'},
1116 {"rxid", required_argument, 0, 'r'},
1117 {"txid", required_argument, 0, 't'},
1118 {"msgcount", required_argument, 0, 'n'},
1119 {"maxsize", required_argument, 0, 's'},
1120 {"minsize", required_argument, 0, 'l'},
1121 {"master", no_argument, 0, 'm'},
1122 {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/
1123 {"icount", required_argument, 0, 'i'},
1124 {"crc", no_argument, 0, 1},
1125 {"trusted", no_argument, 0, 2},
1126 {"help", no_argument, 0, 'h'},
1130 memset(params, 0, sizeof (*params));
1132 // set default values here
1133 params->interface_count = 1;
1136 //int this_option_optind = optind ? optind : 1;
1137 int option_index = 0;
1139 c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
1148 case 'a': // test Case selection
1149 pInt = ¶ms->aff_core;
1151 case 'c': // test Case selection
1152 pInt = ¶ms->test_id;
1154 case 'r': // rx id selection
1155 pInt = ¶ms->rx_id;
1157 case 't': // tx id selection
1158 pInt = ¶ms->tx_id;
1160 case 's': // select message size
1161 pInt = ¶ms->max_size;
1163 case 'l': // select message size
1164 pInt = ¶ms->min_size;
1166 case 'n': // select number of messages
1167 pInt = ¶ms->n_messages;
1169 case 'i': // select number of interfaces to register
1170 pInt = ¶ms->interface_count;
1173 params->master = TRUE;
1176 params->debug = TRUE;
1179 params->wls_dev_name = optarg;
1185 params->trusted = TRUE;
1187 case 1: // crc checking enabled
1192 if (pInt && optarg) {
1194 if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
1195 sscanf(optarg, "%x", (unsigned *) pInt);
1197 *pInt = atoi(optarg);
1204 static int app_set_affinity(int coreNum)
1209 /* set main thread affinity mask to CPU7 */
1212 CPU_SET(coreNum, &cpuset);
1214 rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1216 perror("pthread_setaffinity_np failed");
1217 printf("pthread_setaffinity_np failed: %d", rc);
1220 /* check the actual affinity mask assigned to the thread */
1224 rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1227 perror("pthread_getaffinity_np failed");
1228 printf("pthread_getaffinity_np failed: %d", rc);
1231 printf("set affinity: ");
1232 for (i = 0; i < CPU_SETSIZE; i++)
1233 if (CPU_ISSET(i, &cpuset))
1234 printf(" CPU %d\n", i);
1236 if (!CPU_ISSET(coreNum, &cpuset)) {
1237 printf("affinity failed");
1241 A new thread created by pthread_create(3) inherits a copy of its
1242 creator's CPU affinity mask. */
1248 *******************************************************************************
1250 * @fn app_ApplyParams
1251 * @brief is used to apply application startup parameters
1253 * @param[i] params - app startup params
1257 * The applies startup parameters
1262 * @ingroup icc_service_unit_test
1264 ******************************************************************************/
1265 static void app_ApplyParams(PAPP_PARAMS params)
1268 printf("selected test case %d - ", params->test_id);
1269 switch (params->test_id) {
1270 case APP_TC_SANITY_TEST:
1272 printf("NON-BLOCKING SANITY TEST\n");
1273 AppContext.Receive = app_SanityTestReceiver;
1274 AppContext.Transmit = app_SanityTestTransmitter;
1278 AppContext.wls_put = WLS_Put;
1279 AppContext.wls_get = WLS_Get;
1280 AppContext.wls_wget = WLS_WGet;
1282 AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS;
1283 AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE;
1284 AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE;
1285 AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE);
1287 if (params->master) {
1288 printf("WLS test app (supposed to run as MEMORY MASTER)\n");
1289 AppContext.master = TRUE;
1290 AppContext.RxID = 1;
1291 AppContext.TxID = 2;
1293 AppContext.master = FALSE;
1294 AppContext.RxID = 2;
1295 AppContext.TxID = 1;
1299 AppContext.RxID = params->rx_id;
1302 AppContext.TxID = params->tx_id;
1304 if (params->n_messages && params->n_messages < MAX_MESSAGES)
1305 AppContext.MsgPerMs = params->n_messages;
1307 if (params->min_size && params->min_size >= 4)
1308 AppContext.MinMsgSize = params->min_size;
1310 // default is 1 RX interface
1311 printf("if count = %u\n", params->interface_count);
1312 AppContext.nInterfaces = 1;
1313 if (params->interface_count == 0) {
1314 printf("WLS test app started as simple data source, no RX ID will be specified\n");
1315 AppContext.nInterfaces = 0;
1316 AppContext.RxID = 0; // override RxID
1317 } else if (params->interface_count <= 7) {
1318 AppContext.nInterfaces = params->interface_count;
1322 AppContext.TrustedDataSource = params->trusted;
1325 if (AppContext.MinMsgSize < 8)
1326 AppContext.MinMsgSize = 8;
1328 AppContext.wls_put = app_PutMessageCRC;
1329 AppContext.wls_get = app_GetMessageCRC;
1330 AppContext.wls_wget = app_WGetMessageCRC;
1332 AppContext.AppSanityMsgSize += 4; // + sizeof CRC
1335 if (params->max_size && params->max_size <= 16 * K)
1336 AppContext.MaxMsgSize = params->max_size;
1338 if (params->max_size < params->min_size)
1339 params->max_size = params->min_size;
1341 AppContext.Debug = params->debug;
1343 if (params->aff_core) {
1344 AppContext.core = params->aff_core;
1345 app_set_affinity(AppContext.core);
1348 printf("The application started with:\n");
1349 printf("Core ................ %d\n", AppContext.core);
1350 printf("Rx interface count .. %d\n", AppContext.nInterfaces);
1351 printf("RxID ................ %d\n", AppContext.RxID);
1352 printf("TxID ................ %d\n", AppContext.TxID);
1353 if (AppContext.Debug)
1354 printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs);
1356 printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs);
1357 printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize);
1358 printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize);
1359 printf("Number of threads ... 1\n");
1360 printf("CRC checking ........ ");
1362 printf("ENABLED\n");
1364 printf("DISABLED\n");
1368 *******************************************************************************
1370 * @fn app_ReleaseAllocatedBuffers
1371 * @brief releases ICC buffers allocated by the application
1377 * In process of making some tests when signal to close the application
1378 * happens the app may keep some allocated buffers from the ICC pools. This
1379 * routine does release these buffers back to ICC.
1384 * @ingroup icc_service_unit_test
1386 ******************************************************************************/
1387 static void app_ReleaseAllocatedBuffers(void)
1389 if (AppContext.TxMsgCnt && AppContext.master)
1391 AppContext.TxMsgCnt -= 1;
1392 App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
1393 } while (AppContext.TxMsgCnt != 0);
1397 *******************************************************************************
1400 * @brief ICC test application main routine
1406 * Contains logic of the test (one RX/TX thread)
1411 * @ingroup icc_service_unit_test
1413 ****************************************************************************/
1414 int main(int argc, char* argv[])
1419 signal(SIGINT, App_SigExitCallback);
1421 memset(&AppContext, 0, sizeof (AppContext));
1422 memset(¶ms, 0, sizeof (params));
1424 int ret = rte_eal_init(argc, argv);
1426 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1431 app_ParseArgs(argc, argv, ¶ms);
1432 app_ApplyParams(¶ms);
1434 AppContext.InitQueueSize = APP_QUEUE_SIZE;
1436 AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE);
1438 if (!AppContext.hWls) {
1439 printf("could not register WLS client\n");
1442 printf("WLS has been registered\n");
1445 AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
1447 if (AppContext.shm_memory == NULL) {
1448 if (AppContext.master)
1449 printf("could not create WLS shared memory\n");
1451 printf("could not attach WLS shared memory\n");
1456 if (AppContext.master) {
1457 if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) {
1458 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1459 WLS_Close(AppContext.hWls);
1465 // APPLICATION MAIN LOOP
1466 while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) {
1467 if (AppContext.Receive)
1468 AppContext.Receive(AppContext.hWls);
1470 if (AppContext.Debug)
1471 //usleep(10000); // 1 sec delay
1472 sleep(1); // 1 sec delay
1474 usleep(1000); // 1 ms delay
1476 if (AppContext.Transmit)
1477 AppContext.Transmit(AppContext.hWls);
1479 app_UpdateStatistics();
1482 app_ReleaseAllocatedBuffers();
1483 printf("deregistering WLS (TxTotal_%llu, RxTotal_%llu)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs);
1484 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1485 WLS_Close(AppContext.hWls);