1 /******************************************************************************
3 * Copyright (c) 2021 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
41 #include <rte_config.h>
42 #include <rte_common.h>
52 #define DEFAULT_TEST_MEMORY_SIZE 256*M
53 #define DEFAUTL_TEST_BLOCK_SIZE 16*K
55 #define DEFAULT_MESSAGE_COUNT_PER_MS 10
56 #define DEFAULT_MAX_MESSAGE_SIZE 2000
57 #define DEFUALT_MIN_MESSAGE_SIZE 100
59 #define APP_QUEUE_SIZE 255 /* number of elements each queue of the WLS being registered will have */
60 #define MAX_MESSAGES 1000 /* per ms */
74 APP_TC_SANITY_TEST = 0,
77 typedef struct tagAPP_PARAMS {
91 } APP_PARAMS, *PAPP_PARAMS;
93 typedef struct tagAPP_MESSAGE {
95 } APP_MESSAGE, *PAPP_MESSAGE;
97 typedef struct tagAPP_CONTEXT {
105 POOL Pool; // The pool descriptor
106 void* PoolStrPtr; // The pool storage pointer to keep indexes
111 U16 nInterfaces; // number of RX identifiers used by the APP
113 U16 InitQueueSize; // for invalid messages test (to trigger WLS blocking)
123 U64 nTxMsgs; // Messages transmitted
124 U64 nTxOctets; // Octets transmitted
125 U64 nRxMsgs; // Messages received
126 U64 nRxOcters; // Octets received
127 U64 Cycles; // number of 1ms cycles
129 int AppSanityMsgSize; // 4 or 8 depending on CRC feature
130 U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms
131 U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking.
133 void (*Receive)(HANDLE h);
134 void (*Transmit)(HANDLE h);
136 void (*ThreadReceive)(HANDLE h);
137 void (*ThreadTransmit)(HANDLE h);
139 int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
140 unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
141 unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
143 U8 *pLastRx; // used for scatter-gather test
144 U32 LastRxSize; // used for scatter-gather test
149 PVOID TxMessages[MAX_MESSAGES];
150 U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
153 } APP_CONTEXT, *PAPP_CONTEXT;
155 APP_CONTEXT AppContext;
157 static int pool_alloc = 0;
158 static int pool_free = 0;
160 static void ShowData(void* ptr, unsigned int size)
165 for (i = 0; i < size; i++) {
168 printf("%02x ", d[i]);
173 static void App_SigExitCallback(int signum)
176 AppContext.ExitStatus = TRUE;
179 static void* WlsVaToPa(void * ptr)
181 PAPP_CONTEXT pCtx = &AppContext;
182 return (void*) WLS_VA2PA(pCtx->hWls, ptr);
185 static void* WlsPaToVa(void * ptr)
187 PAPP_CONTEXT pCtx = &AppContext;
188 return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
191 static void* App_Alloc(void* h, unsigned long size)
195 void * retval = NULL;
196 if (AppContext.master) {
197 retval = PoolAlloc(&(AppContext.Pool));
198 //printf("pPool->FreeGet %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut);
200 retval = (void*) WLS_DequeueBlock(AppContext.hWls);
202 retval = (void*) WlsPaToVa(retval);
204 printf("WLS_DequeueBlock returned null\n");
207 if (retval == NULL) {
208 printf("no memory %d %d\n", pool_alloc, pool_free);
216 static int App_Free(void* h, void* pMsg)
219 if (AppContext.master)
222 return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
224 printf("Free Null pointer\n");
230 static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
233 unsigned long long* pUsed;
234 unsigned long long* pFree;
235 PAPP_CONTEXT pCtx = &AppContext;
236 U32 nBlocksSlave = 0;
238 U32 nElmNum = size / BlockSize - 1;
240 // We need to allocate the memory for indexes and to initialize the
241 // pool descriptor, (x+1) is used to prevent queues overflow
243 pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
245 if (pCtx->PoolStrPtr == NULL)
248 pFree = (unsigned long long*) pCtx->PoolStrPtr;
249 pUsed = pFree + (nElmNum + 1);
251 ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
255 if (AppContext.master) {
257 /* allocate blocks for Slave to Master transmittion */
259 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
261 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
265 App_Free(AppContext.hWls, pBlock);
269 printf("Slave has %d free blocks\n", nBlocksSlave);
276 /********************************/
278 const U8 mb_table_level1[] = {
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 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
284 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
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 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
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 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
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 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
298 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
299 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
300 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
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,
305 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
306 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
307 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
308 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
309 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
310 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
313 const U8 mb_table_level2[] = {
314 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
315 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
316 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
317 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
318 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
319 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
320 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
321 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
322 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
323 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
324 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
325 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
326 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
327 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
328 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
329 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
330 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
331 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
332 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
333 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
334 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
335 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
336 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
337 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
338 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
339 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
340 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
341 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
342 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
343 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
344 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
345 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
348 #define CRC32_INIT_VAL 0xFFFFFFFF
349 #define CRC32_DIVISOR 0xA0000001
351 static U32 ICC_CRC32(U8 *pData, U32 size)
353 U32 retval = CRC32_INIT_VAL;
357 return CRC32_INIT_VAL; // mean CRC error
360 for (i = 8; i > 0; --i) {
364 retval ^= CRC32_DIVISOR;
372 static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
375 U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
383 U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
386 p[MsgSize - 4] = (crc >> 0) & 0xff;
387 p[MsgSize - 3] = (crc >> 8) & 0xff;
388 p[MsgSize - 2] = (crc >> 16) & 0xff;
389 p[MsgSize - 1] = (crc >> 24) & 0xff;
391 return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
394 static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
396 U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
399 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
403 U32 crc = ICC_CRC32((U8*) pMsg, size);
407 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
408 ShowData((U8*) pMsg, size);
411 if (nCRC_Pass == 0) {
412 printf("Example of Msg Size and Content being sent: %d\n", size);
413 ShowData((U8*) pMsg, size);
422 static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
424 U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
427 U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
431 U32 crc = ICC_CRC32((U8*) pMsg, size);
435 printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
436 ShowData((U8*) pMsg, size);
439 if (nCRC_Pass == 0) {
440 printf("Example of Msg Size and Content being sent: %d\n", size);
441 ShowData((U8*) pMsg, size);
450 static void CreateMessage(PAPP_MESSAGE p, U32 size)
453 p->id = AppContext.TxCnt++;
456 static void CheckMessage(PAPP_MESSAGE p, U32 size)
458 if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
460 printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id);
462 // if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
463 // printf("%s", buf);
466 AppContext.RxCnt = p->id;
467 AppContext.RxCnt += 1;
471 *******************************************************************************
473 * @fn app_AllocMultiple
474 * @brief used to allocate multiple blocks of the same size from the WLS
476 * @param[h] hWls - app thread WLS handle
477 * @param[o] pMsgs - ptr to beginning of array of points to allocated blocks
478 * @param[o] pMsgSizes - array to write size for each allocated blocks
479 * @param[i] nMsgs - number of blocks to allocate
480 * @return U32 - number of allocated blocks
483 * The routine is used allocate multiple blocks from the ICC service,
484 * the blocks are supposed to be same size blocks, satisfying
485 * appContext.MaxMsgSize parameter.
486 * In case the service is unable to provide requested number of blocks,
487 * smaller count is allocated. The routine returns actual number of allocated
493 * @ingroup icc_service_unit_test
495 ******************************************************************************/
496 static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
501 memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
504 pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
505 pMsgSizes[n] = AppContext.MaxMsgSize;
507 printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
513 // check for duplicated pointers
514 for (i = 0; i < n; i++) {
515 for (j = i + 1; j < n; j++) {
516 if (pMsgs[i] == pMsgs[j]) {
517 printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j);
524 //ShowData(TxMessages, sizeof(TxMessages));
528 *******************************************************************************
530 * @fn app_SanityTestTransmitter
531 * @brief transmitter of default test case (0).
533 * @param[h] hWls - app thread WLS handle
537 * The routine is used in test case 0 (non-blocking sanity unit test)
538 * The transmitter does allocate multiple blocks of the same size from the ICC
539 * service. Then it fills each block with incremental counter and transfers
540 * to other application specified by parameter TxID.
545 * @ingroup icc_service_unit_test
547 ******************************************************************************/
548 static void app_SanityTestTransmitter(HANDLE hWls)
551 unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
557 // lets transmit some message for test
559 pMsg = AppContext.TxMessages[cnt++];
561 U32 size = (rand() % AppContext.MaxMsgSize);
563 if (size < AppContext.MinMsgSize)
564 size = AppContext.MinMsgSize;
566 memset(pMsg, cnt, size);
567 CreateMessage((PAPP_MESSAGE) pMsg, size);
568 if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) {
569 printf("could not send the message_%p\n", pMsg);
574 AppContext.nTxOctets += size;
575 AppContext.nTxMsgs += 1;
580 printf("inorrect sent %d alloc %d \n", k, alloc);
584 pMsg = AppContext.TxMessages[cnt++];
586 if (App_Free(hWls, pMsg) != 0)
587 printf("could not release the message_%p\n", pMsg);
589 printf("pMsg is NULL [%d]\n", cnt);
592 printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
593 AppContext.ExitStatus = 1;
599 *******************************************************************************
601 * @fn app_SanityTestReceiver
602 * @brief default sanity checking receiver used in multiple tests.
604 * @param[h] hWls - app thread WLS handle
608 * The routine takes received messages and checks the sanity incremental
609 * counter to confirm the order. In case the counter does not correspond to
610 * expected counter (misordered message or incorrect message) an error is
616 * @ingroup icc_service_unit_test
618 ******************************************************************************/
619 static void app_SanityTestReceiver(HANDLE hWls)
627 unsigned short MsgTypeID;
628 unsigned short Flags;
629 U32 nBlocksSlave = 0;
631 // handle RX receiver
632 while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
633 pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
635 if (pMsgVa == NULL) {
636 printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
642 if (((U64) pMsg & 0x3) == 0) {
644 CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
646 // misaligned message
647 printf("Unaligned message\n");
648 MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize;
649 memcpy(TempBuf, pMsg, MsgSize);
650 // handle received message
651 CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize);
653 App_Free(AppContext.hWls, pMsg);
654 AppContext.nRxOcters += MsgSize;
655 AppContext.nRxMsgs += 1;
657 if (AppContext.master) {
659 /* allocate blocks for Slave to Master transmittion */
661 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
663 res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
667 App_Free(AppContext.hWls, pBlock);
677 /******************************************************************************
679 * Application common routines *
681 ******************************************************************************/
684 *******************************************************************************
686 * @fn app_UpdateStatistics
687 * @brief is used to update RX and TX statistics
693 * The routine prints out the statistics of received and transmitted
699 * @ingroup icc_service_unit_test
701 ******************************************************************************/
703 static void app_UpdateStatistics(void)
705 AppContext.Cycles += 1;
707 if (AppContext.Debug || AppContext.Cycles % 1000 == 0) {
708 printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10);
709 printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10);
715 *******************************************************************************
718 * @brief prints app help content
724 * The routine is used to print help content to stdout.
729 * @ingroup icc_service_unit_test
731 ******************************************************************************/
732 static void app_Help(void)
734 char help_content[] = \
735 "WLS test application\n\n"\
736 "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\
737 "supports the following parameters:\n\n"
738 "-c | --testcase <test number> 0 - default sanity test\n"\
739 " 1 - misaligned pointers test\n"\
740 " 2 - aligned 4 pointers test\n"\
741 " 3 - random pools test\n"\
742 " 4 - ping-pong (ZBC test)\n"\
743 " 5 - invalid messages test\n\n"\
744 "--trusted switches WLS to trusted mode\n"\
745 "-r | --rxid <id> used to specify RxTypeID\n"\
746 "-t | --txid <id> used to specify TxTypeID\n"\
747 "-n | --msgcount <count> used to specify number of messages per timeframe\n"\
748 "-l | --minsize <size> specifies MIN message size in bytes\n"\
749 "-s | --maxsize <size> specifies MAX message size in bytes\n"\
750 "--crc enables CRC generation and checking\n"\
751 "--debug increases sleep interval to 1 second\n"\
752 "-m | --master set predefined rxid and txid\n";
754 printf("%s", help_content);
758 *******************************************************************************
761 * @brief is used to parse incoming app args
763 * @param[i] argc - app arg count
764 * @param[i] argv - array of args
765 * @param[o] params - app startup params filled basing on args parse
766 * @return number of parsed args
769 * The routine is parse input args and convert them into app startup params
774 * @ingroup icc_service_unit_test
776 ******************************************************************************/
777 static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
783 struct option long_options[] = {
784 {"wlsdev", required_argument, 0, 'w'},
785 {"affinity", required_argument, 0, 'a'},
786 {"testcase", required_argument, 0, 'c'},
787 {"rxid", required_argument, 0, 'r'},
788 {"txid", required_argument, 0, 't'},
789 {"msgcount", required_argument, 0, 'n'},
790 {"maxsize", required_argument, 0, 's'},
791 {"minsize", required_argument, 0, 'l'},
792 {"master", no_argument, 0, 'm'},
793 {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/
794 {"icount", required_argument, 0, 'i'},
795 {"crc", no_argument, 0, 1},
796 {"trusted", no_argument, 0, 2},
797 {"help", no_argument, 0, 'h'},
801 memset(params, 0, sizeof (*params));
803 // set default values here
804 params->interface_count = 1;
807 //int this_option_optind = optind ? optind : 1;
808 int option_index = 0;
810 c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
819 case 'a': // test Case selection
820 pInt = ¶ms->aff_core;
822 case 'c': // test Case selection
823 pInt = ¶ms->test_id;
825 case 'r': // rx id selection
826 pInt = ¶ms->rx_id;
828 case 't': // tx id selection
829 pInt = ¶ms->tx_id;
831 case 's': // select message size
832 pInt = ¶ms->max_size;
834 case 'l': // select message size
835 pInt = ¶ms->min_size;
837 case 'n': // select number of messages
838 pInt = ¶ms->n_messages;
840 case 'i': // select number of interfaces to register
841 pInt = ¶ms->interface_count;
844 params->master = TRUE;
847 params->debug = TRUE;
850 params->wls_dev_name = optarg;
856 params->trusted = TRUE;
858 case 1: // crc checking enabled
863 if (pInt && optarg) {
865 if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
866 sscanf(optarg, "%x", (unsigned *) pInt);
868 *pInt = atoi(optarg);
875 static int app_set_affinity(int coreNum)
880 /* set main thread affinity mask to CPU7 */
883 CPU_SET(coreNum, &cpuset);
885 rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
887 perror("pthread_setaffinity_np failed");
888 printf("pthread_setaffinity_np failed: %d", rc);
891 /* check the actual affinity mask assigned to the thread */
895 rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
898 perror("pthread_getaffinity_np failed");
899 printf("pthread_getaffinity_np failed: %d", rc);
902 printf("set affinity: ");
903 for (i = 0; i < CPU_SETSIZE; i++)
904 if (CPU_ISSET(i, &cpuset))
905 printf(" CPU %d\n", i);
907 if (!CPU_ISSET(coreNum, &cpuset)) {
908 printf("affinity failed");
912 A new thread created by pthread_create(3) inherits a copy of its
913 creator's CPU affinity mask. */
919 *******************************************************************************
921 * @fn app_ApplyParams
922 * @brief is used to apply application startup parameters
924 * @param[i] params - app startup params
928 * The applies startup parameters
933 * @ingroup icc_service_unit_test
935 ******************************************************************************/
936 static void app_ApplyParams(PAPP_PARAMS params)
939 printf("selected test case %d - ", params->test_id);
940 switch (params->test_id) {
941 case APP_TC_SANITY_TEST:
943 printf("NON-BLOCKING SANITY TEST\n");
944 AppContext.Receive = app_SanityTestReceiver;
945 AppContext.Transmit = app_SanityTestTransmitter;
949 AppContext.wls_put = WLS_Put;
950 AppContext.wls_get = WLS_Get;
951 AppContext.wls_wget = WLS_WGet;
953 AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS;
954 AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE;
955 AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE;
956 AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE);
958 if (params->master) {
959 printf("WLS test app (supposed to run as MEMORY MASTER)\n");
960 AppContext.master = TRUE;
964 AppContext.master = FALSE;
970 AppContext.RxID = params->rx_id;
973 AppContext.TxID = params->tx_id;
975 if (params->n_messages && params->n_messages < MAX_MESSAGES)
976 AppContext.MsgPerMs = params->n_messages;
978 if (params->min_size && params->min_size >= 4)
979 AppContext.MinMsgSize = params->min_size;
981 // default is 1 RX interface
982 printf("if count = %u\n", params->interface_count);
983 AppContext.nInterfaces = 1;
984 if (params->interface_count == 0) {
985 printf("WLS test app started as simple data source, no RX ID will be specified\n");
986 AppContext.nInterfaces = 0;
987 AppContext.RxID = 0; // override RxID
988 } else if (params->interface_count <= 7) {
989 AppContext.nInterfaces = params->interface_count;
993 AppContext.TrustedDataSource = params->trusted;
996 if (AppContext.MinMsgSize < 8)
997 AppContext.MinMsgSize = 8;
999 AppContext.wls_put = app_PutMessageCRC;
1000 AppContext.wls_get = app_GetMessageCRC;
1001 AppContext.wls_wget = app_WGetMessageCRC;
1003 AppContext.AppSanityMsgSize += 4; // + sizeof CRC
1006 if (params->max_size && params->max_size <= 16 * K)
1007 AppContext.MaxMsgSize = params->max_size;
1009 if (params->max_size < params->min_size)
1010 params->max_size = params->min_size;
1012 AppContext.Debug = params->debug;
1014 if (params->aff_core) {
1015 AppContext.core = params->aff_core;
1016 app_set_affinity(AppContext.core);
1019 printf("The application started with:\n");
1020 printf("Core ................ %d\n", AppContext.core);
1021 printf("Rx interface count .. %d\n", AppContext.nInterfaces);
1022 printf("RxID ................ %d\n", AppContext.RxID);
1023 printf("TxID ................ %d\n", AppContext.TxID);
1024 if (AppContext.Debug)
1025 printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs);
1027 printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs);
1028 printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize);
1029 printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize);
1030 printf("Number of threads ... 1\n");
1031 printf("CRC checking ........ ");
1033 printf("ENABLED\n");
1035 printf("DISABLED\n");
1039 *******************************************************************************
1041 * @fn app_ReleaseAllocatedBuffers
1042 * @brief releases ICC buffers allocated by the application
1048 * In process of making some tests when signal to close the application
1049 * happens the app may keep some allocated buffers from the ICC pools. This
1050 * routine does release these buffers back to ICC.
1055 * @ingroup icc_service_unit_test
1057 ******************************************************************************/
1058 static void app_ReleaseAllocatedBuffers(void)
1060 if (AppContext.TxMsgCnt && AppContext.master)
1062 AppContext.TxMsgCnt -= 1;
1063 App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
1064 } while (AppContext.TxMsgCnt != 0);
1068 *******************************************************************************
1071 * @brief ICC test application main routine
1077 * Contains logic of the test (one RX/TX thread)
1082 * @ingroup icc_service_unit_test
1084 ****************************************************************************/
1085 int main(int argc, char* argv[])
1089 uint64_t nWlsMacMemorySize = DEFAULT_TEST_MEMORY_SIZE, nWlsPhyMemorySize = 0;
1090 uint32_t nLoop = 30000;
1091 uint32_t nNumBlks = 0;
1093 signal(SIGINT, App_SigExitCallback);
1095 memset(&AppContext, 0, sizeof (AppContext));
1096 memset(¶ms, 0, sizeof (params));
1101 int ret = rte_eal_init(argc, argv);
1103 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1108 app_ParseArgs(argc, argv, ¶ms);
1109 app_ApplyParams(¶ms);
1111 AppContext.InitQueueSize = APP_QUEUE_SIZE;
1113 AppContext.hWls = WLS_Open(params.wls_dev_name, !AppContext.master, &nWlsMacMemorySize, &nWlsPhyMemorySize);
1115 if (!AppContext.hWls) {
1116 printf("could not register WLS client\n");
1119 printf("WLS has been registered\n");
1122 WLS_SetMode(AppContext.hWls, AppContext.master);
1123 AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
1125 if (AppContext.shm_memory == NULL) {
1126 if (AppContext.master)
1127 printf("could not create WLS shared memory\n");
1129 printf("could not attach WLS shared memory\n");
1134 if (AppContext.master) {
1135 if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) {
1136 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1137 WLS_Close(AppContext.hWls);
1143 ret = WLS_Ready(AppContext.hWls);
1145 printf("wls not ready\n");
1149 nNumBlks = WLS_Check(AppContext.hWls);
1150 printf("There are %d blocks in queue from WLS_Check\n", nNumBlks);
1152 nNumBlks = WLS_NumBlocks(AppContext.hWls);
1153 printf("There are %d blocks in queue from WLS_NumBlocks\n", nNumBlks);
1155 // APPLICATION MAIN LOOP
1156 while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit) && nLoop) {
1157 if (AppContext.Receive)
1158 AppContext.Receive(AppContext.hWls);
1160 if (AppContext.Debug)
1161 //usleep(10000); // 1 sec delay
1162 sleep(1); // 1 sec delay
1164 usleep(1000); // 1 ms delay
1166 if (AppContext.Transmit)
1167 AppContext.Transmit(AppContext.hWls);
1169 app_UpdateStatistics();
1173 app_ReleaseAllocatedBuffers();
1174 printf("deregistering WLS (TxTotal_%lld, RxTotal_%lld)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs);
1177 printf("Number of CRC Pass %d\n", nCRC_Pass);
1178 printf("Number of CRC Fail %d\n", nCRC_Fail);
1179 printf("Total Message sent: %d\n", (nCRC_Pass + nCRC_Fail));
1181 WLS_Free(AppContext.hWls, AppContext.shm_memory);
1182 WLS_Close(AppContext.hWls);