Updated wls_lib to remove driver non dpdk option
[o-du/phy.git] / wls_lib / testapp / testapp.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
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
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 *******************************************************************************/
18
19 /**
20  * WLS interface test application
21  * (contains functional unit tests and diagnostics to test wls
22  *  supported by WLS interface)
23  */
24
25 #ifndef _GNU_SOURCE
26 #define _GNU_SOURCE
27 #endif
28
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
35 #include <sys/time.h>
36 #include <pthread.h>
37 #include <sched.h>
38 #include "ttypes.h"
39 #include "wls_lib.h"
40 #include "pool.h"
41
42 #define HANDLE  PVOID
43
44
45 #define K                       1024
46 #define M                       (K*K)
47
48 #define   DEFAULT_TEST_MEMORY_SIZE      256*M
49 #define   DEFAUTL_TEST_BLOCK_SIZE       16*K
50
51 #define   DEFAULT_MESSAGE_COUNT_PER_MS  10
52 #define   DEFAULT_MAX_MESSAGE_SIZE      2000
53 #define   DEFUALT_MIN_MESSAGE_SIZE      100
54
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 */
57
58
59 #ifndef TRUE
60 #define TRUE  1
61 #endif
62
63 #ifndef FALSE
64 #define FALSE 0
65 #endif
66
67 typedef enum {
68     APP_TC_SANITY_TEST = 0,
69 } APP_TEST_CASES;
70
71 typedef struct tagAPP_PARAMS {
72     char *wls_dev_name;
73     int aff_core;
74     int test_id;
75     int rx_id;
76     int tx_id;
77     int n_messages;
78     int max_size;
79     int min_size;
80     int interface_count;
81     U8 master;
82     U8 debug;
83     U8 crc;
84     U8 trusted;
85 } APP_PARAMS, *PAPP_PARAMS;
86
87 typedef struct tagAPP_MESSAGE {
88     U32 id;
89 } APP_MESSAGE, *PAPP_MESSAGE;
90
91 typedef struct tagAPP_CONTEXT {
92     V32 ExitStatus;
93     HANDLE hWls;
94
95     U32 master;
96
97     PVOID shm_memory;
98
99     POOL Pool; // The pool descriptor
100     void* PoolStrPtr; // The pool storage pointer to keep indexes
101
102     U16 RxID;
103     U16 TxID;
104
105     U16 nInterfaces; // number of RX identifiers used by the APP
106     //
107     U16 InitQueueSize; // for invalid messages test (to trigger WLS  blocking)
108
109     //
110     U32 MsgPerMs;
111     U32 MaxMsgSize;
112     U32 MinMsgSize;
113
114     U32 TxCnt;
115     U32 RxCnt;
116
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
122
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.
126
127     void (*Receive)(HANDLE h);
128     void (*Transmit)(HANDLE h);
129
130     void (*ThreadReceive)(HANDLE h);
131     void (*ThreadTransmit)(HANDLE h);
132
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);
136
137     U8 *pLastRx; // used for scatter-gather test
138     U32 LastRxSize; // used for scatter-gather test
139
140     U32 *pServiceBuffer;
141
142     U32 TxMsgCnt;
143     PVOID TxMessages[MAX_MESSAGES];
144     U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
145     int core;
146
147 } APP_CONTEXT, *PAPP_CONTEXT;
148
149 APP_CONTEXT AppContext;
150
151 static int pool_alloc = 0;
152 static int pool_free = 0;
153
154 static void ShowData(void* ptr, unsigned int size)
155 {
156     U8 *d = ptr;
157     unsigned int i;
158
159     for (i = 0; i < size; i++) {
160         if (!(i & 0xf))
161             printf("\n");
162         printf("%02x ", d[i]);
163     }
164     printf("\n");
165 }
166
167 static void App_SigExitCallback(int signum)
168 {
169     (void) signum;
170     AppContext.ExitStatus = TRUE;
171 }
172
173 static void* WlsVaToPa(void * ptr)
174 {
175     PAPP_CONTEXT pCtx = &AppContext;
176     return (void*) WLS_VA2PA(pCtx->hWls, ptr);
177 }
178
179 static void* WlsPaToVa(void * ptr)
180 {
181     PAPP_CONTEXT pCtx = &AppContext;
182     return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
183 }
184
185 static void* App_Alloc(void* h, unsigned long size)
186 {
187     (void) h;
188     (void) 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);
193     } else {
194         retval = (void*) WLS_DequeueBlock(AppContext.hWls);
195         if (retval)
196             retval = (void*) WlsPaToVa(retval);
197         else
198             printf("WLS_DequeueBlock returned null\n");
199     }
200
201     if (retval == NULL) {
202         printf("no memory %d %d\n", pool_alloc, pool_free);
203         exit(-1);
204     } else
205         pool_alloc++;
206
207     return retval;
208 }
209
210 static int App_Free(void* h, void* pMsg)
211 {
212     (void) h;
213     if (AppContext.master)
214         if (pMsg) {
215             pool_free++;
216             return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
217         } else {
218             printf("Free Null pointer\n");
219             exit(-1);
220         } else
221         return 0;
222 }
223
224 static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
225 {
226     int ret = 0;
227     unsigned long long* pUsed;
228     unsigned long long* pFree;
229     PAPP_CONTEXT pCtx = &AppContext;
230     U32 nBlocksSlave = 0;
231
232     U32 nElmNum = size / BlockSize - 1;
233
234     // We need to allocate the memory for indexes and to initialize the
235     // pool descriptor, (x+1) is used to prevent queues overflow
236
237     pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
238
239     if (pCtx->PoolStrPtr == NULL)
240         return -1;
241
242     pFree = (unsigned long long*) pCtx->PoolStrPtr;
243     pUsed = pFree + (nElmNum + 1);
244
245     ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
246
247     if (ret == 0) {
248
249         if (AppContext.master) {
250             int res = TRUE;
251             /* allocate blocks for Slave to Master transmittion */
252             while (res) {
253                 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
254                 if (pBlock) {
255                     res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
256                     if (res)
257                         nBlocksSlave++;
258                     else
259                         App_Free(AppContext.hWls, pBlock);
260                 } else
261                     res = FALSE;
262             }
263             printf("Slave has %d free blocks\n", nBlocksSlave);
264         }
265     }
266
267     return ret;
268 }
269
270 /********************************/
271
272 #define FAST_CRC16    1
273
274 #if (FAST_CRC16)
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
308 };
309
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
343 };
344
345 #if 0
346 // big endian CPU
347
348 U16
349 crc16(U16 crc, U8 data)
350 {
351     U8 index;
352     U8 crc_Low = crc & 0xFF;
353     U8 crc_High = crc >> 8;
354
355     index = (crc_High ^ data) & 0xFF;
356     crc_High = crc_Low ^ mb_table_level1[ index ];
357     crc_Low = mb_table_level2[ index ];
358
359     return (crc_High << 8) | crc_Low;
360 }
361 #else
362 // little endian CPU
363 #if 0
364 static U16 CRC16_Update(U16 crc, U8 data)
365 {
366     U8 index;
367     U8 crc_High = crc >> 8;
368     U8 crc_Low = crc & 0xFF;
369
370     index = crc_Low ^ data;
371     crc_Low = crc_High ^ mb_table_level1[ index ];
372     crc_High = mb_table_level2[ index ];
373
374     return (crc_High << 8) | crc_Low;
375 }
376 #endif
377 #endif
378
379 #if 0
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)*
386  * <--- crc16                                   *
387  ***********************************************/
388 static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
389 {
390
391     if (!size)
392         return aCRC;
393     else {
394         U8 index;
395         U8 crc_High = aCRC >> 8;
396         U8 crc_Low = aCRC & 0xFF;
397
398         do {
399             index = crc_Low ^ *pData++;
400             crc_Low = crc_High ^ mb_table_level1[ index ];
401             crc_High = mb_table_level2[ index ];
402         } while (--size);
403
404         return (crc_High << 8) | crc_Low;
405     }
406 }
407 #endif
408
409 #else // SLOW (canonic CRC16 calculation)
410
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)*
416  * <--- crc16                                   *
417  ***********************************************/
418 U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
419 {
420     U8 i, tmp;
421
422     if (!size)
423         return aCRC;
424
425     do {
426         aCRC ^= *pData++;
427         for (i = 0; i < 8; i++) {
428             tmp = aCRC & 0x01;
429             aCRC >>= 1;
430             if (tmp) {
431                 aCRC ^= CRC16_DIVISOR;
432             }
433         }
434     } while (--size);
435     return aCRC;
436 }
437
438 #endif // FAST_CRC16
439
440
441 #define CRC32_INIT_VAL  0xFFFFFFFF
442 #define CRC32_DIVISOR   0xA0000001
443
444 static U32 ICC_CRC32(U8 *pData, U32 size)
445 {
446     U32 retval = CRC32_INIT_VAL;
447     U8 i, tmp;
448
449     if (!size)
450         return CRC32_INIT_VAL; // mean CRC error
451     do {
452         retval ^= *pData++;
453         for (i = 8; i > 0; --i) {
454             tmp = retval & 0x01;
455             retval >>= 1;
456             if (tmp) {
457                 retval ^= CRC32_DIVISOR;
458             }
459         }
460     } while (--size);
461     return retval;
462 }
463
464 #if 0
465
466 static U16 ICC_CRC16(U8 *pData, U16 size)
467 {
468 #define CRC16_ERROR (0xffff)
469     return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer
470 }
471 #endif
472
473 static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
474 {
475     U8 *p;
476     U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
477
478     if (pMsgVa == 0)
479     {
480         return 0;
481     }
482     p = (U8 *) pMsgVa;
483 #if 1
484     U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
485     // CRC32
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;
490 #else
491     U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc));
492     // CRC16
493     p[MsgSize - 2] = (crc >> 0) & 0xff;
494     p[MsgSize - 1] = (crc >> 8) & 0xff;
495 #endif
496
497     return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
498 }
499
500 static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
501 {
502     U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
503     U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
504
505     if (pMsg) {
506         U32 size = *MsgSize;
507 #if 1
508         U32 crc = ICC_CRC32((U8*) pMsg, size);
509 #else
510         U16 crc = ICC_CRC16((U8*) pMsg, size);
511 #endif
512
513         if (crc != 0) {
514             printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
515             ShowData((U8*) pMsg, size);
516         }
517     }
518     return pMsgPa;
519 }
520
521 static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
522 {
523     U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
524     U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
525
526     if (pMsg) {
527         U32 size = *MsgSize;
528 #if 1
529         U32 crc = ICC_CRC32((U8*) pMsg, size);
530 #else
531         U16 crc = ICC_CRC16((U8*) pMsg, size);
532 #endif
533
534         if (crc != 0) {
535             printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
536             ShowData((U8*) pMsg, size);
537         }
538     }
539     return pMsgPa;
540 }
541
542 static void CreateMessage(PAPP_MESSAGE p, U32 size)
543 {
544     (void) size;
545     p->id = AppContext.TxCnt++;
546 }
547
548 static void CheckMessage(PAPP_MESSAGE p, U32 size)
549 {
550     if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
551         //              char buf[8*K];
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);
553         ShowData(p, size);
554         //              if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
555         //              printf("%s", buf);
556     }
557
558     AppContext.RxCnt = p->id;
559     AppContext.RxCnt += 1;
560 }
561
562 /**
563  *******************************************************************************
564  *
565  * @fn    app_AllocMultiple
566  * @brief used to allocate multiple blocks of the same size from the WLS
567  *
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
573  *
574  * @description
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
580  * blocks
581  *
582  * @references
583  * MS-111070-SP
584  *
585  * @ingroup icc_service_unit_test
586  *
587  ******************************************************************************/
588 static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
589 {
590     unsigned n = 0;
591     unsigned i, j;
592
593     memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
594
595     while (nMsgs--) {
596         pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
597         pMsgSizes[n] = AppContext.MaxMsgSize;
598         if (!pMsgs[n]) {
599             printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
600             break;
601         }
602         n += 1;
603     }
604
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);
610                 break;
611             }
612         }
613     }
614
615     return n;
616     //ShowData(TxMessages, sizeof(TxMessages));
617 }
618
619 /**
620  *******************************************************************************
621  *
622  * @fn    app_SanityTestTransmitter
623  * @brief transmitter of default test case (0).
624  *
625  * @param[h]  hWls - app thread WLS  handle
626  * @return    void
627  *
628  * @description
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.
633  *
634  * @references
635  * MS-111070-SP
636  *
637  * @ingroup icc_service_unit_test
638  *
639  ******************************************************************************/
640 static void app_SanityTestTransmitter(HANDLE hWls)
641 {
642     U8 *pMsg;
643     unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
644     unsigned fn = n;
645     unsigned cnt = 0;
646     unsigned k = 0;
647     unsigned alloc = n;
648
649     // lets transmit some message for test
650     while (n--) {
651         pMsg = AppContext.TxMessages[cnt++];
652         if (pMsg) {
653             U32 size = (rand() % AppContext.MaxMsgSize);
654
655             if (size < AppContext.MinMsgSize)
656                 size = AppContext.MinMsgSize;
657
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);
662                 break;
663             } else {
664                 k++;
665             }
666             AppContext.nTxOctets += size;
667             AppContext.nTxMsgs += 1;
668         }
669     }
670
671     if (alloc != k)
672         printf("inorrect sent %d alloc %d \n", k, alloc);
673
674     cnt = 0;
675     while (fn--) {
676         pMsg = AppContext.TxMessages[cnt++];
677         if (pMsg) {
678             if (App_Free(hWls, pMsg) != 0)
679                 printf("could not release the message_%p\n", pMsg);
680         } else
681             printf("pMsg is NULL [%d]\n", cnt);
682     }
683     if (cnt != k) {
684         printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
685         AppContext.ExitStatus = 1;
686     }
687 }
688
689 #if 0
690 /**
691  *******************************************************************************
692  *
693  * @fn    app_ScatterGatherTransmitter
694  * @brief transmitter of default test case (15/16).
695  *
696  * @param[h]  hWls - app thread WLS  handle
697  * @return    void
698  *
699  * @description
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.
704  *
705  * @references
706  * MS-111070-SP
707  *
708  * @ingroup icc_service_unit_test
709  *
710  ******************************************************************************/
711 static void app_ScatterGatherTransmitter(HANDLE hWls)
712 {
713         U8 *pMsg;
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;
718
719     unsigned fn  = n;
720     unsigned k = 0;
721     unsigned alloc = n;
722
723         if (!pOriginMsg) {
724                 printf("No memory for App_Alloc()\n");
725                 return;
726         }
727
728         flags = rand() & 0xff;
729
730         for(i = 0; i < AppContext.MaxMsgSize; i++)
731                 pOriginMsg[i] = (flags + i) & 0xff;
732
733         // scatter original message among several blocks
734         for(i = 0; i < n; i++)
735         {
736                 U32 size = (rand() % (AppContext.MaxMsgSize / n));
737
738                 if (size < AppContext.MinMsgSize)
739                         size = AppContext.MinMsgSize;
740
741                 TotalSize += size;
742                 AppContext.TxMessageSizes[i] = size;
743                 //printf("size%d=%lu\n", i, size);
744         }
745
746         // adjust size of the last block
747         if (TotalSize < AppContext.MaxMsgSize)
748         {
749                 AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize;
750         }
751         else if (TotalSize > AppContext.MaxMsgSize)
752         {
753                 printf("error: size of the scatted blocks exceeding size of the original message\n");
754         }
755
756         p = pOriginMsg;
757         for(i = 0; i < n; i++)
758         {
759                 // copy data into the scattered blocks
760                 pMsg = AppContext.TxMessages[i];
761                 memcpy(pMsg, p, AppContext.TxMessageSizes[i]);
762                 p += AppContext.TxMessageSizes[i];
763         }
764
765         // transmit original message first
766         if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0)
767         {
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);
771         }
772         else
773         {
774                 AppContext.nTxOctets += AppContext.MaxMsgSize;
775                 AppContext.nTxMsgs += 1;
776         }
777
778     if(pOriginMsg){
779         if (App_Free(hWls, pOriginMsg) != 0)
780             printf("could not release the message_%p\n", pMsg);
781     }
782     else
783         printf("pOriginMsg is NULL \n");
784
785         // transmit scattered messages following their creation order
786         while (n--)
787         {
788                 pMsg = AppContext.TxMessages[cnt];
789                 if (!cnt)
790                         flags = WLS_SG_FIRST;
791                 else if (n == 0)
792                         flags = WLS_SG_LAST;
793                 else
794                         flags = WLS_SG_NEXT;
795
796                 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0)
797                 {
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);
801                 }
802         else
803             k++;
804
805                 AppContext.nTxOctets += AppContext.TxMessageSizes[cnt];
806                 AppContext.nTxMsgs += 1;
807                 cnt++;
808         }
809     if(alloc != k)
810         printf("inorrect sent %d alloc %d \n", k, alloc);
811
812     cnt = 0;
813     while (fn--)
814     {
815         pMsg = AppContext.TxMessages[cnt++];
816         if(pMsg){
817             if (App_Free(hWls, pMsg) != 0)
818                 printf("could not release the message_%p\n", pMsg);
819         }
820         else
821             printf("pMsg is NULL [%d]\n", cnt);
822     }
823     if(cnt != k)
824         printf("inorrect free sent %d free %d \n", k, cnt);
825 }
826 #endif
827
828 /**
829  *******************************************************************************
830  *
831  * @fn    app_SanityTestReceiver
832  * @brief default sanity checking receiver used in multiple tests.
833  *
834  * @param[h]  hWls - app thread WLS  handle
835  * @return    void
836  *
837  * @description
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
841  * printed to STDOUT.
842  *
843  * @references
844  * MS-111070-SP
845  *
846  * @ingroup icc_service_unit_test
847  *
848  ******************************************************************************/
849 static void app_SanityTestReceiver(HANDLE hWls)
850 {
851     (void) hWls;
852     U32 MsgSize;
853     U8 *pMsg;
854     U8 *pMsgPa;
855     U8 *pMsgVa;
856     U8 TempBuf[16 * K];
857     unsigned short MsgTypeID;
858     unsigned short Flags;
859     U32 nBlocksSlave = 0;
860
861     // handle RX receiver
862     while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
863         pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
864
865         if (pMsgVa == NULL) {
866             printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
867             continue;
868         }
869
870         pMsg = pMsgVa;
871
872         if (((U64) pMsg & 0x3) == 0) {
873             // aligned message
874             CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
875         } else {
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);
882         }
883         App_Free(AppContext.hWls, pMsg);
884         AppContext.nRxOcters += MsgSize;
885         AppContext.nRxMsgs += 1;
886
887         if (AppContext.master) {
888             int res = TRUE;
889             /* allocate blocks for Slave to Master transmittion */
890             while (res) {
891                 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
892                 if (pBlock) {
893                     res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
894                     if (res)
895                         nBlocksSlave++;
896                     else
897                         App_Free(AppContext.hWls, pBlock);
898                 } else
899                     res = FALSE;
900             }
901         }
902
903     }
904 }
905
906 #if 0
907 /**
908  *******************************************************************************
909  *
910  * @fn    app_ScatterGatherReceiver
911  * @brief scatter gather test receiver
912  *
913  * @param[h]  hWls - app thread WLS  handle
914  * @return    void
915  *
916  * @description
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
920  * printed to STDOUT.
921  *
922  * @references
923  * MS-111070-SP
924  *
925  * @ingroup icc_service_unit_test
926  *
927  ******************************************************************************/
928 static void app_ScatterGatherReceiver(HANDLE hWls)
929 {
930         (void)hWls;
931         U32 MsgSize;
932         U8  *pMsg;
933     U8  *pMsgPa;
934     U8  *pMsgVa;
935         U32 size;
936         U8 err = 0;
937     unsigned short MsgTypeID;
938     unsigned short Flags;
939
940         // handle RX receiver
941         while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)
942         {
943         pMsgVa = (U8  *)WlsPaToVa(pMsgPa);
944
945         pMsg = pMsgVa;
946
947                 AppContext.nRxOcters += MsgSize;
948                 AppContext.nRxMsgs += 1;
949
950                 if (!AppContext.pLastRx)
951                 {
952                         AppContext.pLastRx = pMsg;
953                         AppContext.LastRxSize = MsgSize;
954                 }
955                 else // compare with received and release both
956                 {
957                         U32 i;
958                         if (AppContext.LastRxSize != MsgSize)
959                                 printf("received wrong size, unsync? try to re-run app both clusters\n");
960
961                         size = MsgSize;
962                         if (size > AppContext.LastRxSize)
963                                 size = AppContext.LastRxSize;
964
965                         for(i = 0; i < size; i++)
966                         {
967                                 if (pMsg[i] != AppContext.pLastRx[i])
968                                 {
969                                         // error content doesn't match
970                                         err = TRUE;
971                                         break;
972                                 }
973                         }
974
975                         if (err)
976                         {
977                                 printf("content verification failed, scatter-gather test FAIL\n");
978                                 // terminate
979                                 AppContext.Receive = NULL;
980                                 AppContext.Transmit = NULL;
981                                 App_Free(AppContext.hWls, pMsg);
982                                 App_Free(AppContext.hWls, AppContext.pLastRx);
983                                 return;
984                         }
985
986                         App_Free(AppContext.hWls, pMsg);
987                         App_Free(AppContext.hWls, AppContext.pLastRx);
988                         AppContext.pLastRx = NULL;
989                 }
990
991         }
992 }
993
994
995
996 static U32 app_GetTime(void)
997 {
998         struct timeval tv;
999         U32 time_ms = 0;
1000         if (gettimeofday(&tv, NULL) == 0)
1001                 time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1002         return time_ms;
1003 }
1004 #endif
1005
1006 /******************************************************************************
1007  *                                                                             *
1008  *                       Application common routines                           *
1009  *                                                                             *
1010  ******************************************************************************/
1011
1012 /**
1013  *******************************************************************************
1014  *
1015  * @fn    app_UpdateStatistics
1016  * @brief is used to update RX and TX statistics
1017  *
1018  * @param[n]  void
1019  * @return    void
1020  *
1021  * @description
1022  *    The routine prints out the statistics of received and transmitted
1023  * messages.
1024  *
1025  * @references
1026  * MS-111070-SP
1027  *
1028  * @ingroup icc_service_unit_test
1029  *
1030  ******************************************************************************/
1031
1032 static void app_UpdateStatistics(void)
1033 {
1034     AppContext.Cycles += 1;
1035
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);
1039     }
1040
1041 }
1042
1043 /**
1044  *******************************************************************************
1045  *
1046  * @fn    app_Help
1047  * @brief prints app help content
1048  *
1049  * @param[n]  void
1050  * @return    void
1051  *
1052  * @description
1053  *    The routine is used to print help content to stdout.
1054  *
1055  * @references
1056  * MS-111070-SP
1057  *
1058  * @ingroup icc_service_unit_test
1059  *
1060  ******************************************************************************/
1061 static void app_Help(void)
1062 {
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";
1082
1083     printf("%s", help_content);
1084 }
1085
1086 /**
1087  *******************************************************************************
1088  *
1089  * @fn    app_ParseArgs
1090  * @brief is used to parse incoming app args
1091  *
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
1096  *
1097  * @description
1098  *    The routine is parse input args and convert them into app startup params
1099  *
1100  * @references
1101  * MS-111070-SP
1102  *
1103  * @ingroup icc_service_unit_test
1104  *
1105  ******************************************************************************/
1106 static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
1107 {
1108     int c;
1109     int *pInt;
1110     int cnt = 0;
1111
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'},
1127         {0, 0, 0, 0}
1128     };
1129
1130     memset(params, 0, sizeof (*params));
1131
1132     // set default values here
1133     params->interface_count = 1;
1134
1135     while (1) {
1136         //int this_option_optind = optind ? optind : 1;
1137         int option_index = 0;
1138
1139         c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
1140
1141         if (c == -1)
1142             break;
1143
1144         cnt += 1;
1145         pInt = NULL;
1146
1147         switch (c) {
1148             case 'a': // test Case selection
1149                 pInt = &params->aff_core;
1150                 break;
1151             case 'c': // test Case selection
1152                 pInt = &params->test_id;
1153                 break;
1154             case 'r': // rx id selection
1155                 pInt = &params->rx_id;
1156                 break;
1157             case 't': // tx id selection
1158                 pInt = &params->tx_id;
1159                 break;
1160             case 's': // select message size
1161                 pInt = &params->max_size;
1162                 break;
1163             case 'l': // select message size
1164                 pInt = &params->min_size;
1165                 break;
1166             case 'n': // select number of messages
1167                 pInt = &params->n_messages;
1168                 break;
1169             case 'i': // select number of interfaces to register
1170                 pInt = &params->interface_count;
1171                 break;
1172             case 'm':
1173                 params->master = TRUE;
1174                 break;
1175             case 'd':
1176                 params->debug = TRUE;
1177                 break;
1178             case 'w':
1179                 params->wls_dev_name = optarg;
1180                 break;
1181             case 'h':
1182                 app_Help();
1183                 exit(0);
1184             case 2:
1185                 params->trusted = TRUE;
1186                 break;
1187             case 1: // crc checking enabled
1188                 params->crc = TRUE;
1189                 break;
1190         }
1191
1192         if (pInt && optarg) {
1193             // get int arg
1194             if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
1195                 sscanf(optarg, "%x", (unsigned *) pInt);
1196             } else {
1197                 *pInt = atoi(optarg);
1198             }
1199         }
1200     }
1201     return cnt;
1202 }
1203
1204 static int app_set_affinity(int coreNum)
1205 {
1206     cpu_set_t cpuset;
1207     int i, rc;
1208
1209     /* set main thread affinity mask to CPU7 */
1210
1211     CPU_ZERO(&cpuset);
1212     CPU_SET(coreNum, &cpuset);
1213
1214     rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1215     if (rc) {
1216         perror("pthread_setaffinity_np failed");
1217         printf("pthread_setaffinity_np failed: %d", rc);
1218     }
1219
1220     /* check the actual affinity mask assigned to the thread */
1221
1222     CPU_ZERO(&cpuset);
1223
1224     rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1225
1226     if (rc) {
1227         perror("pthread_getaffinity_np failed");
1228         printf("pthread_getaffinity_np failed: %d", rc);
1229     }
1230
1231     printf("set affinity: ");
1232     for (i = 0; i < CPU_SETSIZE; i++)
1233         if (CPU_ISSET(i, &cpuset))
1234             printf("    CPU %d\n", i);
1235
1236     if (!CPU_ISSET(coreNum, &cpuset)) {
1237         printf("affinity failed");
1238     }
1239
1240     /**
1241        A new thread created by pthread_create(3) inherits a copy of its
1242        creator's CPU affinity mask. */
1243
1244     return rc;
1245 }
1246
1247 /**
1248  *******************************************************************************
1249  *
1250  * @fn    app_ApplyParams
1251  * @brief is used to apply application startup parameters
1252  *
1253  * @param[i]  params - app startup params
1254  * @return    void
1255  *
1256  * @description
1257  *    The applies startup parameters
1258  *
1259  * @references
1260  * MS-111070-SP
1261  *
1262  * @ingroup icc_service_unit_test
1263  *
1264  ******************************************************************************/
1265 static void app_ApplyParams(PAPP_PARAMS params)
1266 {
1267     // apply parameters
1268     printf("selected test case %d - ", params->test_id);
1269     switch (params->test_id) {
1270         case APP_TC_SANITY_TEST:
1271         default:
1272             printf("NON-BLOCKING SANITY TEST\n");
1273             AppContext.Receive = app_SanityTestReceiver;
1274             AppContext.Transmit = app_SanityTestTransmitter;
1275             break;
1276     }
1277
1278     AppContext.wls_put = WLS_Put;
1279     AppContext.wls_get = WLS_Get;
1280     AppContext.wls_wget = WLS_WGet;
1281
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);
1286
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;
1292     } else {
1293         AppContext.master = FALSE;
1294         AppContext.RxID = 2;
1295         AppContext.TxID = 1;
1296     }
1297
1298     if (params->rx_id)
1299         AppContext.RxID = params->rx_id;
1300
1301     if (params->tx_id)
1302         AppContext.TxID = params->tx_id;
1303
1304     if (params->n_messages && params->n_messages < MAX_MESSAGES)
1305         AppContext.MsgPerMs = params->n_messages;
1306
1307     if (params->min_size && params->min_size >= 4)
1308         AppContext.MinMsgSize = params->min_size;
1309
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;
1319     }
1320
1321
1322     AppContext.TrustedDataSource = params->trusted;
1323
1324     if (params->crc) {
1325         if (AppContext.MinMsgSize < 8)
1326             AppContext.MinMsgSize = 8;
1327
1328         AppContext.wls_put = app_PutMessageCRC;
1329         AppContext.wls_get = app_GetMessageCRC;
1330         AppContext.wls_wget = app_WGetMessageCRC;
1331
1332         AppContext.AppSanityMsgSize += 4; // + sizeof CRC
1333     }
1334
1335     if (params->max_size && params->max_size <= 16 * K)
1336         AppContext.MaxMsgSize = params->max_size;
1337
1338     if (params->max_size < params->min_size)
1339         params->max_size = params->min_size;
1340
1341     AppContext.Debug = params->debug;
1342
1343     if (params->aff_core) {
1344         AppContext.core = params->aff_core;
1345         app_set_affinity(AppContext.core);
1346     }
1347
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);
1355     else
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 ........ ");
1361     if (params->crc)
1362         printf("ENABLED\n");
1363     else
1364         printf("DISABLED\n");
1365 }
1366
1367 /**
1368  *******************************************************************************
1369  *
1370  * @fn    app_ReleaseAllocatedBuffers
1371  * @brief releases ICC buffers allocated by the application
1372  *
1373  * @param[n]  void
1374  * @return    void
1375  *
1376  * @description
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.
1380  *
1381  * @references
1382  * MS-111070-SP
1383  *
1384  * @ingroup icc_service_unit_test
1385  *
1386  ******************************************************************************/
1387 static void app_ReleaseAllocatedBuffers(void)
1388 {
1389     if (AppContext.TxMsgCnt && AppContext.master)
1390         do {
1391             AppContext.TxMsgCnt -= 1;
1392             App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
1393         } while (AppContext.TxMsgCnt != 0);
1394 }
1395
1396 /**
1397  *******************************************************************************
1398  *
1399  * @fn    main
1400  * @brief ICC test application main routine
1401  *
1402  * @param[n]  void
1403  * @return    void
1404  *
1405  * @description
1406  *    Contains logic of the test (one RX/TX thread)
1407  *
1408  * @references
1409  * MS-111070-SP
1410  *
1411  * @ingroup icc_service_unit_test
1412  *
1413  ****************************************************************************/
1414 int main(int argc, char* argv[])
1415 {
1416     int retval = 0;
1417     APP_PARAMS params;
1418
1419     signal(SIGINT, App_SigExitCallback);
1420
1421     memset(&AppContext, 0, sizeof (AppContext));
1422     memset(&params, 0, sizeof (params));
1423
1424     int ret = rte_eal_init(argc, argv);
1425     if (ret < 0)
1426         rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1427
1428     argc -= ret;
1429     argv += ret;
1430
1431     app_ParseArgs(argc, argv, &params);
1432     app_ApplyParams(&params);
1433
1434     AppContext.InitQueueSize = APP_QUEUE_SIZE;
1435
1436     AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE);
1437
1438     if (!AppContext.hWls) {
1439         printf("could not register WLS client\n");
1440         return 1;
1441     } else {
1442         printf("WLS has been registered\n");
1443     }
1444
1445     AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
1446
1447     if (AppContext.shm_memory == NULL) {
1448         if (AppContext.master)
1449             printf("could not create WLS shared memory\n");
1450         else
1451             printf("could not attach WLS shared memory\n");
1452
1453         return -1;
1454     }
1455
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);
1460             exit(1);
1461         }
1462
1463     }
1464
1465     // APPLICATION MAIN LOOP
1466     while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) {
1467         if (AppContext.Receive)
1468             AppContext.Receive(AppContext.hWls);
1469
1470         if (AppContext.Debug)
1471             //usleep(10000); // 1 sec delay
1472             sleep(1); // 1 sec delay
1473         else
1474             usleep(1000); // 1 ms delay
1475
1476         if (AppContext.Transmit)
1477             AppContext.Transmit(AppContext.hWls);
1478
1479         app_UpdateStatistics();
1480     }
1481
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);
1486     return retval;
1487 }