FAPI TM, WLS_LIB and ODULOW documentation
[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 #define _GNU_SOURCE
26 #include <stdio.h>   // for printf
27 #include <string.h>  // for memset
28 #include <signal.h>  // for SIGINT
29 #include <unistd.h>  // for usleep
30 #include <stdlib.h>  // for rand
31 #include <getopt.h>  // for getopt
32 #include <sys/time.h>
33 #include <pthread.h>
34 #include <sched.h>
35 #include "ttypes.h"
36 #include "wls_lib.h"
37 #include "pool.h"
38
39 #define HANDLE  PVOID
40
41
42 #define K                       1024
43 #define M                       (K*K)
44
45 #define   DEFAULT_TEST_MEMORY_SIZE      256*M
46 #define   DEFAUTL_TEST_BLOCK_SIZE       16*K
47
48 #define   DEFAULT_MESSAGE_COUNT_PER_MS  10
49 #define   DEFAULT_MAX_MESSAGE_SIZE      2000
50 #define   DEFUALT_MIN_MESSAGE_SIZE      100
51
52 #define   APP_QUEUE_SIZE   255   /* number of elements each queue of the WLS  being registered will have */
53 #define   MAX_MESSAGES  1000   /* per ms */
54
55
56 #ifndef TRUE
57 #define TRUE  1
58 #endif
59
60 #ifndef FALSE
61 #define FALSE 0
62 #endif
63
64 typedef enum {
65     APP_TC_SANITY_TEST = 0,
66 } APP_TEST_CASES;
67
68 typedef struct tagAPP_PARAMS {
69     char *wls_dev_name;
70     int aff_core;
71     int test_id;
72     int rx_id;
73     int tx_id;
74     int n_messages;
75     int max_size;
76     int min_size;
77     int interface_count;
78     U8 master;
79     U8 debug;
80     U8 crc;
81     U8 trusted;
82 } APP_PARAMS, *PAPP_PARAMS;
83
84 typedef struct tagAPP_MESSAGE {
85     U32 id;
86 } APP_MESSAGE, *PAPP_MESSAGE;
87
88 typedef struct tagAPP_CONTEXT {
89     V32 ExitStatus;
90     HANDLE hWls;
91
92     U32 master;
93
94     PVOID shm_memory;
95
96     POOL Pool; // The pool descriptor
97     void* PoolStrPtr; // The pool storage pointer to keep indexes
98
99     U16 RxID;
100     U16 TxID;
101
102     U16 nInterfaces; // number of RX identifiers used by the APP
103     //
104     U16 InitQueueSize; // for invalid messages test (to trigger WLS  blocking)
105
106     //
107     U32 MsgPerMs;
108     U32 MaxMsgSize;
109     U32 MinMsgSize;
110
111     U32 TxCnt;
112     U32 RxCnt;
113
114     U64 nTxMsgs; // Messages transmitted
115     U64 nTxOctets; // Octets transmitted
116     U64 nRxMsgs; // Messages received
117     U64 nRxOcters; // Octets received
118     U64 Cycles; // number of 1ms cycles
119
120     int AppSanityMsgSize; // 4 or 8 depending on CRC feature
121     U8 Debug; // when TRUE app cycle is 1 sec, otherwise 1ms
122     U8 TrustedDataSource; // for trusted data sources ICC service removes msg validity checking.
123
124     void (*Receive)(HANDLE h);
125     void (*Transmit)(HANDLE h);
126
127     void (*ThreadReceive)(HANDLE h);
128     void (*ThreadTransmit)(HANDLE h);
129
130     int (*wls_put)(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags);
131     unsigned long long (*wls_get)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
132     unsigned long long (*wls_wget)(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags);
133
134     U8 *pLastRx; // used for scatter-gather test
135     U32 LastRxSize; // used for scatter-gather test
136
137     U32 *pServiceBuffer;
138
139     U32 TxMsgCnt;
140     PVOID TxMessages[MAX_MESSAGES];
141     U32 TxMessageSizes[MAX_MESSAGES]; // <-- required for Ping-Pong test to store received sizes
142     int core;
143
144 } APP_CONTEXT, *PAPP_CONTEXT;
145
146 APP_CONTEXT AppContext;
147
148 static int pool_alloc = 0;
149 static int pool_free = 0;
150
151 static void ShowData(void* ptr, unsigned int size)
152 {
153     U8 *d = ptr;
154     unsigned int i;
155
156     for (i = 0; i < size; i++) {
157         if (!(i & 0xf))
158             printf("\n");
159         printf("%02x ", d[i]);
160     }
161     printf("\n");
162 }
163
164 static void App_SigExitCallback(int signum)
165 {
166     (void) signum;
167     AppContext.ExitStatus = TRUE;
168 }
169
170 static void* WlsVaToPa(void * ptr)
171 {
172     PAPP_CONTEXT pCtx = &AppContext;
173     return (void*) WLS_VA2PA(pCtx->hWls, ptr);
174 }
175
176 static void* WlsPaToVa(void * ptr)
177 {
178     PAPP_CONTEXT pCtx = &AppContext;
179     return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
180 }
181
182 static void* App_Alloc(void* h, unsigned long size)
183 {
184     (void) h;
185     (void) size;
186     void * retval = NULL;
187     if (AppContext.master) {
188         retval = PoolAlloc(&(AppContext.Pool));
189         //printf("pPool->FreeGet  %d == pPool->FreePut %d\n", AppContext.Pool.FreeGet, AppContext.Pool.FreePut);
190     } else {
191         retval = (void*) WLS_DequeueBlock(AppContext.hWls);
192         if (retval)
193             retval = (void*) WlsPaToVa(retval);
194         else
195             printf("WLS_DequeueBlock returned null\n");
196     }
197
198     if (retval == NULL) {
199         printf("no memory %d %d\n", pool_alloc, pool_free);
200         exit(-1);
201     } else
202         pool_alloc++;
203
204     return retval;
205 }
206
207 static int App_Free(void* h, void* pMsg)
208 {
209     (void) h;
210     if (AppContext.master)
211         if (pMsg) {
212             pool_free++;
213             return (PoolFree(&(AppContext.Pool), pMsg) == 1 ? 0 : -1);
214         } else {
215             printf("Free Null pointer\n");
216             exit(-1);
217         } else
218         return 0;
219 }
220
221 static int App_MemoryInit(void* h, unsigned long size, U32 BlockSize)
222 {
223     int ret = 0;
224     unsigned long long* pUsed;
225     unsigned long long* pFree;
226     PAPP_CONTEXT pCtx = &AppContext;
227     U32 nBlocksSlave = 0;
228
229     U32 nElmNum = size / BlockSize - 1;
230
231     // We need to allocate the memory for indexes and to initialize the
232     // pool descriptor, (x+1) is used to prevent queues overflow
233
234     pCtx->PoolStrPtr = malloc((nElmNum + 1) * 4 * sizeof (unsigned long long));
235
236     if (pCtx->PoolStrPtr == NULL)
237         return -1;
238
239     pFree = (unsigned long long*) pCtx->PoolStrPtr;
240     pUsed = pFree + (nElmNum + 1);
241
242     ret = PoolInit(&pCtx->Pool, h, nElmNum, BlockSize, pFree, pUsed);
243
244     if (ret == 0) {
245
246         if (AppContext.master) {
247             int res = TRUE;
248             /* allocate blocks for Slave to Master transmittion */
249             while (res) {
250                 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
251                 if (pBlock) {
252                     res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
253                     if (res)
254                         nBlocksSlave++;
255                     else
256                         App_Free(AppContext.hWls, pBlock);
257                 } else
258                     res = FALSE;
259             }
260             printf("Slave has %d free blocks\n", nBlocksSlave);
261         }
262     }
263
264     return ret;
265 }
266
267 /********************************/
268
269 #define FAST_CRC16    1
270
271 #if (FAST_CRC16)
272 const U8 mb_table_level1[] = {
273     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
274     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
275     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
276     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
277     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
278     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
279     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
280     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
281     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
282     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
283     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
284     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
285     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
286     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
287     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
288     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
289     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
290     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
291     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
292     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
293     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
294     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
295     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
296     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
297     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
298     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
299     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
300     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
301     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
302     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
303     0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
304     0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
305 };
306
307 const U8 mb_table_level2[] = {
308     0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2,
309     0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
310     0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
311     0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
312     0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
313     0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
314     0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6,
315     0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
316     0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
317     0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
318     0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE,
319     0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
320     0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA,
321     0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C,
322     0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
323     0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
324     0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62,
325     0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
326     0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE,
327     0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
328     0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
329     0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
330     0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76,
331     0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
332     0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
333     0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
334     0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
335     0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98,
336     0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A,
337     0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
338     0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86,
339     0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
340 };
341
342 #if 0
343 // big endian CPU
344
345 U16
346 crc16(U16 crc, U8 data)
347 {
348     U8 index;
349     U8 crc_Low = crc & 0xFF;
350     U8 crc_High = crc >> 8;
351
352     index = (crc_High ^ data) & 0xFF;
353     crc_High = crc_Low ^ mb_table_level1[ index ];
354     crc_Low = mb_table_level2[ index ];
355
356     return (crc_High << 8) | crc_Low;
357 }
358 #else
359 // little endian CPU
360 #if 0
361 static U16 CRC16_Update(U16 crc, U8 data)
362 {
363     U8 index;
364     U8 crc_High = crc >> 8;
365     U8 crc_Low = crc & 0xFF;
366
367     index = crc_Low ^ data;
368     crc_Low = crc_High ^ mb_table_level1[ index ];
369     crc_High = mb_table_level2[ index ];
370
371     return (crc_High << 8) | crc_Low;
372 }
373 #endif
374 #endif
375
376 #if 0
377 /***********************************************
378  * CRC16  polynomial : X16 + X15 + X2 + 1       *
379  * FAST CRC16 routine                           *
380  * ---> pData - msg to be protected             *
381  * ---> size - msg size in bytes                *
382  * ---> aCRC - initializer (0xFFFF for 1st page)*
383  * <--- crc16                                   *
384  ***********************************************/
385 static U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
386 {
387
388     if (!size)
389         return aCRC;
390     else {
391         U8 index;
392         U8 crc_High = aCRC >> 8;
393         U8 crc_Low = aCRC & 0xFF;
394
395         do {
396             index = crc_Low ^ *pData++;
397             crc_Low = crc_High ^ mb_table_level1[ index ];
398             crc_High = mb_table_level2[ index ];
399         } while (--size);
400
401         return (crc_High << 8) | crc_Low;
402     }
403 }
404 #endif
405
406 #else // SLOW (canonic CRC16 calculation)
407
408 /***********************************************
409  * CRC16  polynomial : X16 + X15 + X2 + 1       *
410  * ---> pData - msg to be protected             *
411  * ---> size - msg size in bytes                *
412  * ---> aCRC - initializer (0xFFFF for 1st page)*
413  * <--- crc16                                   *
414  ***********************************************/
415 U16 CRC16_NoInit(U16 aCRC, U8 *pData, U16 size)
416 {
417     U8 i, tmp;
418
419     if (!size)
420         return aCRC;
421
422     do {
423         aCRC ^= *pData++;
424         for (i = 0; i < 8; i++) {
425             tmp = aCRC & 0x01;
426             aCRC >>= 1;
427             if (tmp) {
428                 aCRC ^= CRC16_DIVISOR;
429             }
430         }
431     } while (--size);
432     return aCRC;
433 }
434
435 #endif // FAST_CRC16
436
437
438 #define CRC32_INIT_VAL  0xFFFFFFFF
439 #define CRC32_DIVISOR   0xA0000001
440
441 static U32 ICC_CRC32(U8 *pData, U32 size)
442 {
443     U32 retval = CRC32_INIT_VAL;
444     U8 i, tmp;
445
446     if (!size)
447         return CRC32_INIT_VAL; // mean CRC error
448     do {
449         retval ^= *pData++;
450         for (i = 8; i > 0; --i) {
451             tmp = retval & 0x01;
452             retval >>= 1;
453             if (tmp) {
454                 retval ^= CRC32_DIVISOR;
455             }
456         }
457     } while (--size);
458     return retval;
459 }
460
461 #if 0
462
463 static U16 ICC_CRC16(U8 *pData, U16 size)
464 {
465 #define CRC16_ERROR (0xffff)
466     return CRC16_NoInit(CRC16_ERROR, pData, size); // use 0xFFFF as first initializer
467 }
468 #endif
469
470 static int app_PutMessageCRC(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags)
471 {
472     U8 *p;
473     U64 pMsgVa = (U64) WlsPaToVa((void*) pMsg);
474
475     if (pMsgVa == 0)
476     {
477         return 0;
478     }
479     p = (U8 *) pMsgVa;
480 #if 1
481     U32 crc = ICC_CRC32((U8 *) pMsgVa, MsgSize - sizeof (crc));
482     // CRC32
483     p[MsgSize - 4] = (crc >> 0) & 0xff;
484     p[MsgSize - 3] = (crc >> 8) & 0xff;
485     p[MsgSize - 2] = (crc >> 16) & 0xff;
486     p[MsgSize - 1] = (crc >> 24) & 0xff;
487 #else
488     U16 crc = ICC_CRC16((U8 *) pMsg, MsgSize - sizeof (crc));
489     // CRC16
490     p[MsgSize - 2] = (crc >> 0) & 0xff;
491     p[MsgSize - 1] = (crc >> 8) & 0xff;
492 #endif
493
494     return WLS_Put(h, (unsigned long long) pMsg, MsgSize, MsgTypeID, Flags);
495 }
496
497 static unsigned long long app_GetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
498 {
499     U64 pMsgPa = WLS_Get(h, MsgSize, MsgTypeID, Flags);
500     U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
501
502     if (pMsg) {
503         U32 size = *MsgSize;
504 #if 1
505         U32 crc = ICC_CRC32((U8*) pMsg, size);
506 #else
507         U16 crc = ICC_CRC16((U8*) pMsg, size);
508 #endif
509
510         if (crc != 0) {
511             printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
512             ShowData((U8*) pMsg, size);
513         }
514     }
515     return pMsgPa;
516 }
517
518 static unsigned long long app_WGetMessageCRC(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags)
519 {
520     U64 pMsgPa = WLS_WGet(h, MsgSize, MsgTypeID, Flags);
521     U64 pMsg = (U64) WlsPaToVa((void*) pMsgPa);
522
523     if (pMsg) {
524         U32 size = *MsgSize;
525 #if 1
526         U32 crc = ICC_CRC32((U8*) pMsg, size);
527 #else
528         U16 crc = ICC_CRC16((U8*) pMsg, size);
529 #endif
530
531         if (crc != 0) {
532             printf("CRC error detected for message %p, size_%lu\n", (void*) pMsg, (long) size);
533             ShowData((U8*) pMsg, size);
534         }
535     }
536     return pMsgPa;
537 }
538
539 static void CreateMessage(PAPP_MESSAGE p, U32 size)
540 {
541     (void) size;
542     p->id = AppContext.TxCnt++;
543 }
544
545 static void CheckMessage(PAPP_MESSAGE p, U32 size)
546 {
547     if (AppContext.RxCnt && p->id != AppContext.RxCnt) {
548         //              char buf[8*K];
549         printf("rx message(id_%llu)_%lx error expected_%lu, received_%lu\n", (long long) AppContext.nRxMsgs, (U64) p, (long) AppContext.RxCnt, (long) p->id);
550         ShowData(p, size);
551         //              if (TL_GetStatistics(AppContext.hWls, buf, sizeof(buf)))
552         //              printf("%s", buf);
553     }
554
555     AppContext.RxCnt = p->id;
556     AppContext.RxCnt += 1;
557 }
558
559 /**
560  *******************************************************************************
561  *
562  * @fn    app_AllocMultiple
563  * @brief used to allocate multiple blocks of the same size from the WLS
564  *
565  * @param[h]  hWls - app thread WLS  handle
566  * @param[o]  pMsgs - ptr to beginning of array of points to allocated blocks
567  * @param[o]  pMsgSizes - array to write size for each allocated blocks
568  * @param[i]  nMsgs - number of blocks to allocate
569  * @return    U32 - number of allocated blocks
570  *
571  * @description
572  *    The routine is used allocate multiple blocks from the ICC service,
573  * the blocks are supposed to be same size blocks, satisfying
574  * appContext.MaxMsgSize parameter.
575  *    In case the service is unable to provide requested number of blocks,
576  * smaller count is allocated. The routine returns actual number of allocated
577  * blocks
578  *
579  * @references
580  * MS-111070-SP
581  *
582  * @ingroup icc_service_unit_test
583  *
584  ******************************************************************************/
585 static U32 app_AllocMultiple(HANDLE hWls, PVOID *pMsgs, U32 *pMsgSizes, U32 nMsgs)
586 {
587     unsigned n = 0;
588     unsigned i, j;
589
590     memset(pMsgs, 0x00, sizeof (PVOID) * nMsgs);
591
592     while (nMsgs--) {
593         pMsgs[n] = App_Alloc(hWls, AppContext.MaxMsgSize);
594         pMsgSizes[n] = AppContext.MaxMsgSize;
595         if (!pMsgs[n]) {
596             printf("empty pool allocated_%u out of %lu\n", n, (long) AppContext.MsgPerMs);
597             break;
598         }
599         n += 1;
600     }
601
602     // check for duplicated pointers
603     for (i = 0; i < n; i++) {
604         for (j = i + 1; j < n; j++) {
605             if (pMsgs[i] == pMsgs[j]) {
606                 printf("duplicated pointer %p (msg_id1_%u, msg_id2_%u)\n", pMsgs[i], i, j);
607                 break;
608             }
609         }
610     }
611
612     return n;
613     //ShowData(TxMessages, sizeof(TxMessages));
614 }
615
616 /**
617  *******************************************************************************
618  *
619  * @fn    app_SanityTestTransmitter
620  * @brief transmitter of default test case (0).
621  *
622  * @param[h]  hWls - app thread WLS  handle
623  * @return    void
624  *
625  * @description
626  *    The routine is used in test case 0 (non-blocking sanity unit test)
627  * The transmitter does allocate multiple blocks of the same size from the ICC
628  * service. Then it fills each block with incremental counter and transfers
629  * to other application specified by parameter TxID.
630  *
631  * @references
632  * MS-111070-SP
633  *
634  * @ingroup icc_service_unit_test
635  *
636  ******************************************************************************/
637 static void app_SanityTestTransmitter(HANDLE hWls)
638 {
639     U8 *pMsg;
640     unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs);
641     unsigned fn = n;
642     unsigned cnt = 0;
643     unsigned k = 0;
644     unsigned alloc = n;
645
646     // lets transmit some message for test
647     while (n--) {
648         pMsg = AppContext.TxMessages[cnt++];
649         if (pMsg) {
650             U32 size = (rand() % AppContext.MaxMsgSize);
651
652             if (size < AppContext.MinMsgSize)
653                 size = AppContext.MinMsgSize;
654
655             memset(pMsg, cnt, size);
656             CreateMessage((PAPP_MESSAGE) pMsg, size);
657             if ((AppContext.wls_put(hWls, (U64) WlsVaToPa(pMsg), size, AppContext.TxID, 0) != 0)) {
658                 printf("could not send the message_%p\n", pMsg);
659                 break;
660             } else {
661                 k++;
662             }
663             AppContext.nTxOctets += size;
664             AppContext.nTxMsgs += 1;
665         }
666     }
667
668     if (alloc != k)
669         printf("inorrect sent %d alloc %d \n", k, alloc);
670
671     cnt = 0;
672     while (fn--) {
673         pMsg = AppContext.TxMessages[cnt++];
674         if (pMsg) {
675             if (App_Free(hWls, pMsg) != 0)
676                 printf("could not release the message_%p\n", pMsg);
677         } else
678             printf("pMsg is NULL [%d]\n", cnt);
679     }
680     if (cnt != k) {
681         printf("inorrect free sent %d free %d \nQuiting...\n", k, cnt);
682         AppContext.ExitStatus = 1;
683     }
684 }
685
686 #if 0
687 /**
688  *******************************************************************************
689  *
690  * @fn    app_ScatterGatherTransmitter
691  * @brief transmitter of default test case (15/16).
692  *
693  * @param[h]  hWls - app thread WLS  handle
694  * @return    void
695  *
696  * @description
697  *    The routine is used in test case 0 (non-blocking sanity unit test)
698  * The transmitter does allocate multiple blocks of the same size from the ICC
699  * service. Then it fills each block with incremental counter and transfers
700  * to other application specified by parameter TxID.
701  *
702  * @references
703  * MS-111070-SP
704  *
705  * @ingroup icc_service_unit_test
706  *
707  ******************************************************************************/
708 static void app_ScatterGatherTransmitter(HANDLE hWls)
709 {
710         U8 *pMsg;
711         unsigned n = app_AllocMultiple(hWls, AppContext.TxMessages, AppContext.TxMessageSizes, AppContext.MsgPerMs + 2);
712         unsigned i, cnt = 0, flags = 0;
713         U8 *p, *pOriginMsg = (U8 *)App_Alloc(hWls, AppContext.MaxMsgSize);
714         unsigned TotalSize = 0;
715
716     unsigned fn  = n;
717     unsigned k = 0;
718     unsigned alloc = n;
719
720         if (!pOriginMsg) {
721                 printf("No memory for App_Alloc()\n");
722                 return;
723         }
724
725         flags = rand() & 0xff;
726
727         for(i = 0; i < AppContext.MaxMsgSize; i++)
728                 pOriginMsg[i] = (flags + i) & 0xff;
729
730         // scatter original message among several blocks
731         for(i = 0; i < n; i++)
732         {
733                 U32 size = (rand() % (AppContext.MaxMsgSize / n));
734
735                 if (size < AppContext.MinMsgSize)
736                         size = AppContext.MinMsgSize;
737
738                 TotalSize += size;
739                 AppContext.TxMessageSizes[i] = size;
740                 //printf("size%d=%lu\n", i, size);
741         }
742
743         // adjust size of the last block
744         if (TotalSize < AppContext.MaxMsgSize)
745         {
746                 AppContext.TxMessageSizes[n - 1] += AppContext.MaxMsgSize - TotalSize;
747         }
748         else if (TotalSize > AppContext.MaxMsgSize)
749         {
750                 printf("error: size of the scatted blocks exceeding size of the original message\n");
751         }
752
753         p = pOriginMsg;
754         for(i = 0; i < n; i++)
755         {
756                 // copy data into the scattered blocks
757                 pMsg = AppContext.TxMessages[i];
758                 memcpy(pMsg, p, AppContext.TxMessageSizes[i]);
759                 p += AppContext.TxMessageSizes[i];
760         }
761
762         // transmit original message first
763         if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pOriginMsg), AppContext.MaxMsgSize, AppContext.TxID, 0) != 0)
764         {
765                 printf("could not send the message_%p\n", pOriginMsg);
766                 if (App_Free(hWls, pOriginMsg) != 0)
767                         printf("could not release the message_%p\n", pOriginMsg);
768         }
769         else
770         {
771                 AppContext.nTxOctets += AppContext.MaxMsgSize;
772                 AppContext.nTxMsgs += 1;
773         }
774
775     if(pOriginMsg){
776         if (App_Free(hWls, pOriginMsg) != 0)
777             printf("could not release the message_%p\n", pMsg);
778     }
779     else
780         printf("pOriginMsg is NULL \n");
781
782         // transmit scattered messages following their creation order
783         while (n--)
784         {
785                 pMsg = AppContext.TxMessages[cnt];
786                 if (!cnt)
787                         flags = WLS_SG_FIRST;
788                 else if (n == 0)
789                         flags = WLS_SG_LAST;
790                 else
791                         flags = WLS_SG_NEXT;
792
793                 if (AppContext.wls_put(hWls, (U64)WlsVaToPa(pMsg), AppContext.TxMessageSizes[cnt], AppContext.TxID, flags) != 0)
794                 {
795                         printf("could not send the message_%p\n", pMsg);
796                         if (App_Free(hWls, pMsg) != 0)
797                                 printf("could not release the message_%p\n", pMsg);
798                 }
799         else
800             k++;
801
802                 AppContext.nTxOctets += AppContext.TxMessageSizes[cnt];
803                 AppContext.nTxMsgs += 1;
804                 cnt++;
805         }
806     if(alloc != k)
807         printf("inorrect sent %d alloc %d \n", k, alloc);
808
809     cnt = 0;
810     while (fn--)
811     {
812         pMsg = AppContext.TxMessages[cnt++];
813         if(pMsg){
814             if (App_Free(hWls, pMsg) != 0)
815                 printf("could not release the message_%p\n", pMsg);
816         }
817         else
818             printf("pMsg is NULL [%d]\n", cnt);
819     }
820     if(cnt != k)
821         printf("inorrect free sent %d free %d \n", k, cnt);
822 }
823 #endif
824
825 /**
826  *******************************************************************************
827  *
828  * @fn    app_SanityTestReceiver
829  * @brief default sanity checking receiver used in multiple tests.
830  *
831  * @param[h]  hWls - app thread WLS  handle
832  * @return    void
833  *
834  * @description
835  *    The routine takes received messages and checks the sanity incremental
836  * counter to confirm the order. In case the counter does not correspond to
837  * expected counter (misordered message or incorrect message) an error is
838  * printed to STDOUT.
839  *
840  * @references
841  * MS-111070-SP
842  *
843  * @ingroup icc_service_unit_test
844  *
845  ******************************************************************************/
846 static void app_SanityTestReceiver(HANDLE hWls)
847 {
848     (void) hWls;
849     U32 MsgSize;
850     U8 *pMsg;
851     U8 *pMsgPa;
852     U8 *pMsgVa;
853     U8 TempBuf[16 * K];
854     unsigned short MsgTypeID;
855     unsigned short Flags;
856     U32 nBlocksSlave = 0;
857
858     // handle RX receiver
859     while (((pMsgPa = (U8 *) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)) {
860         pMsgVa = (U8 *) WlsPaToVa(pMsgPa);
861
862         if (pMsgVa == NULL) {
863             printf("va: %lx pa: %lx\n", (long) pMsgVa, (long) pMsgPa);
864             continue;
865         }
866
867         pMsg = pMsgVa;
868
869         if (((U64) pMsg & 0x3) == 0) {
870             // aligned message
871             CheckMessage((PAPP_MESSAGE) pMsg, MsgSize);
872         } else {
873             // misaligned message
874             printf("Unaligned message\n");
875             MsgSize = (MsgSize > sizeof (TempBuf)) ? sizeof (TempBuf) : MsgSize;
876             memcpy(TempBuf, pMsg, MsgSize);
877             // handle received message
878             CheckMessage((PAPP_MESSAGE) TempBuf, MsgSize);
879         }
880         App_Free(AppContext.hWls, pMsg);
881         AppContext.nRxOcters += MsgSize;
882         AppContext.nRxMsgs += 1;
883
884         if (AppContext.master) {
885             int res = TRUE;
886             /* allocate blocks for Slave to Master transmittion */
887             while (res) {
888                 void* pBlock = App_Alloc(AppContext.hWls, DEFAUTL_TEST_BLOCK_SIZE);
889                 if (pBlock) {
890                     res = WLS_EnqueueBlock(AppContext.hWls, (U64) WlsVaToPa(pBlock));
891                     if (res)
892                         nBlocksSlave++;
893                     else
894                         App_Free(AppContext.hWls, pBlock);
895                 } else
896                     res = FALSE;
897             }
898         }
899
900     }
901 }
902
903 #if 0
904 /**
905  *******************************************************************************
906  *
907  * @fn    app_ScatterGatherReceiver
908  * @brief scatter gather test receiver
909  *
910  * @param[h]  hWls - app thread WLS  handle
911  * @return    void
912  *
913  * @description
914  *    The routine takes received messages and checks the sanity incremental
915  * counter to confirm the order. In case the counter does not correspond to
916  * expected counter (misordered message or incorrect message) an error is
917  * printed to STDOUT.
918  *
919  * @references
920  * MS-111070-SP
921  *
922  * @ingroup icc_service_unit_test
923  *
924  ******************************************************************************/
925 static void app_ScatterGatherReceiver(HANDLE hWls)
926 {
927         (void)hWls;
928         U32 MsgSize;
929         U8  *pMsg;
930     U8  *pMsgPa;
931     U8  *pMsgVa;
932         U32 size;
933         U8 err = 0;
934     unsigned short MsgTypeID;
935     unsigned short Flags;
936
937         // handle RX receiver
938         while ((pMsgPa = (U8*) AppContext.wls_get(AppContext.hWls, &MsgSize, &MsgTypeID, &Flags)) != NULL)
939         {
940         pMsgVa = (U8  *)WlsPaToVa(pMsgPa);
941
942         pMsg = pMsgVa;
943
944                 AppContext.nRxOcters += MsgSize;
945                 AppContext.nRxMsgs += 1;
946
947                 if (!AppContext.pLastRx)
948                 {
949                         AppContext.pLastRx = pMsg;
950                         AppContext.LastRxSize = MsgSize;
951                 }
952                 else // compare with received and release both
953                 {
954                         U32 i;
955                         if (AppContext.LastRxSize != MsgSize)
956                                 printf("received wrong size, unsync? try to re-run app both clusters\n");
957
958                         size = MsgSize;
959                         if (size > AppContext.LastRxSize)
960                                 size = AppContext.LastRxSize;
961
962                         for(i = 0; i < size; i++)
963                         {
964                                 if (pMsg[i] != AppContext.pLastRx[i])
965                                 {
966                                         // error content doesn't match
967                                         err = TRUE;
968                                         break;
969                                 }
970                         }
971
972                         if (err)
973                         {
974                                 printf("content verification failed, scatter-gather test FAIL\n");
975                                 // terminate
976                                 AppContext.Receive = NULL;
977                                 AppContext.Transmit = NULL;
978                                 App_Free(AppContext.hWls, pMsg);
979                                 App_Free(AppContext.hWls, AppContext.pLastRx);
980                                 return;
981                         }
982
983                         App_Free(AppContext.hWls, pMsg);
984                         App_Free(AppContext.hWls, AppContext.pLastRx);
985                         AppContext.pLastRx = NULL;
986                 }
987
988         }
989 }
990
991
992
993 static U32 app_GetTime(void)
994 {
995         struct timeval tv;
996         U32 time_ms = 0;
997         if (gettimeofday(&tv, NULL) == 0)
998                 time_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
999         return time_ms;
1000 }
1001 #endif
1002
1003 /******************************************************************************
1004  *                                                                             *
1005  *                       Application common routines                           *
1006  *                                                                             *
1007  ******************************************************************************/
1008
1009 /**
1010  *******************************************************************************
1011  *
1012  * @fn    app_UpdateStatistics
1013  * @brief is used to update RX and TX statistics
1014  *
1015  * @param[n]  void
1016  * @return    void
1017  *
1018  * @description
1019  *    The routine prints out the statistics of received and transmitted
1020  * messages.
1021  *
1022  * @references
1023  * MS-111070-SP
1024  *
1025  * @ingroup icc_service_unit_test
1026  *
1027  ******************************************************************************/
1028
1029 static void app_UpdateStatistics(void)
1030 {
1031     AppContext.Cycles += 1;
1032
1033     if (AppContext.Debug || AppContext.Cycles % 1000 == 0) {
1034         printf("Rx(id_%u) (%llu) - (%llu KiB)\n", AppContext.RxID, (long long) AppContext.nRxMsgs, (long long) AppContext.nRxOcters >> 10);
1035         printf("Tx(id_%u) (%llu) - (%llu KiB)\n", AppContext.TxID, (long long) AppContext.nTxMsgs, (long long) AppContext.nTxOctets >> 10);
1036     }
1037
1038 }
1039
1040 /**
1041  *******************************************************************************
1042  *
1043  * @fn    app_Help
1044  * @brief prints app help content
1045  *
1046  * @param[n]  void
1047  * @return    void
1048  *
1049  * @description
1050  *    The routine is used to print help content to stdout.
1051  *
1052  * @references
1053  * MS-111070-SP
1054  *
1055  * @ingroup icc_service_unit_test
1056  *
1057  ******************************************************************************/
1058 static void app_Help(void)
1059 {
1060     char help_content[] =  \
1061                         "WLS test application\n\n"\
1062                         "Usage: testapp [-c <test>] [-r <rxid>] [-t <txid>] [-n <msgcount>]\n\n"\
1063                         "supports the following parameters:\n\n"
1064                         "-c | --testcase <test number>     0 - default sanity test\n"\
1065                         "                                  1 - misaligned pointers test\n"\
1066                         "                                  2 - aligned 4 pointers test\n"\
1067                         "                                  3 - random pools test\n"\
1068                         "                                  4 - ping-pong (ZBC test)\n"\
1069                         "                                  5 - invalid messages test\n\n"\
1070                         "--trusted                    switches WLS  to trusted mode\n"\
1071                         "-r | --rxid <id>             used to specify RxTypeID\n"\
1072                         "-t | --txid <id>             used to specify TxTypeID\n"\
1073                         "-n | --msgcount <count>      used to specify number of messages per timeframe\n"\
1074                         "-l | --minsize  <size>       specifies MIN message size in bytes\n"\
1075                         "-s | --maxsize  <size>       specifies MAX message size in bytes\n"\
1076                         "--crc                        enables CRC generation and checking\n"\
1077                         "--debug                      increases sleep interval to 1 second\n"\
1078                         "-m | --master                set predefined rxid and txid\n";
1079
1080     printf("%s", help_content);
1081 }
1082
1083 /**
1084  *******************************************************************************
1085  *
1086  * @fn    app_ParseArgs
1087  * @brief is used to parse incoming app args
1088  *
1089  * @param[i]  argc - app arg count
1090  * @param[i]  argv - array of args
1091  * @param[o]  params - app startup params filled basing on args parse
1092  * @return    number of parsed args
1093  *
1094  * @description
1095  *    The routine is parse input args and convert them into app startup params
1096  *
1097  * @references
1098  * MS-111070-SP
1099  *
1100  * @ingroup icc_service_unit_test
1101  *
1102  ******************************************************************************/
1103 static int app_ParseArgs(int argc, char ** argv, PAPP_PARAMS params)
1104 {
1105     int c;
1106     int *pInt;
1107     int cnt = 0;
1108
1109     struct option long_options[] = {
1110         {"wlsdev", required_argument, 0, 'w'},
1111         {"affinity", required_argument, 0, 'a'},
1112         {"testcase", required_argument, 0, 'c'},
1113         {"rxid", required_argument, 0, 'r'},
1114         {"txid", required_argument, 0, 't'},
1115         {"msgcount", required_argument, 0, 'n'},
1116         {"maxsize", required_argument, 0, 's'},
1117         {"minsize", required_argument, 0, 'l'},
1118         {"master", no_argument, 0, 'm'},
1119         {"debug", no_argument, 0, 'd'}, /* slow down the app cycle from 1ms to 1s*/
1120         {"icount", required_argument, 0, 'i'},
1121         {"crc", no_argument, 0, 1},
1122         {"trusted", no_argument, 0, 2},
1123         {"help", no_argument, 0, 'h'},
1124         {0, 0, 0, 0}
1125     };
1126
1127     memset(params, 0, sizeof (*params));
1128
1129     // set default values here
1130     params->interface_count = 1;
1131
1132     while (1) {
1133         //int this_option_optind = optind ? optind : 1;
1134         int option_index = 0;
1135
1136         c = getopt_long(argc, argv, "a:w:c:r:t:n:s:l:mdi:h", long_options, &option_index);
1137
1138         if (c == -1)
1139             break;
1140
1141         cnt += 1;
1142         pInt = NULL;
1143
1144         switch (c) {
1145             case 'a': // test Case selection
1146                 pInt = &params->aff_core;
1147                 break;
1148             case 'c': // test Case selection
1149                 pInt = &params->test_id;
1150                 break;
1151             case 'r': // rx id selection
1152                 pInt = &params->rx_id;
1153                 break;
1154             case 't': // tx id selection
1155                 pInt = &params->tx_id;
1156                 break;
1157             case 's': // select message size
1158                 pInt = &params->max_size;
1159                 break;
1160             case 'l': // select message size
1161                 pInt = &params->min_size;
1162                 break;
1163             case 'n': // select number of messages
1164                 pInt = &params->n_messages;
1165                 break;
1166             case 'i': // select number of interfaces to register
1167                 pInt = &params->interface_count;
1168                 break;
1169             case 'm':
1170                 params->master = TRUE;
1171                 break;
1172             case 'd':
1173                 params->debug = TRUE;
1174                 break;
1175             case 'w':
1176                 params->wls_dev_name = optarg;
1177                 break;
1178             case 'h':
1179                 app_Help();
1180                 exit(0);
1181             case 2:
1182                 params->trusted = TRUE;
1183                 break;
1184             case 1: // crc checking enabled
1185                 params->crc = TRUE;
1186                 break;
1187         }
1188
1189         if (pInt && optarg) {
1190             // get int arg
1191             if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
1192                 sscanf(optarg, "%x", (unsigned *) pInt);
1193             } else {
1194                 *pInt = atoi(optarg);
1195             }
1196         }
1197     }
1198     return cnt;
1199 }
1200
1201 static int app_set_affinity(int coreNum)
1202 {
1203     cpu_set_t cpuset;
1204     int i, rc;
1205
1206     /* set main thread affinity mask to CPU7 */
1207
1208     CPU_ZERO(&cpuset);
1209     CPU_SET(coreNum, &cpuset);
1210
1211     rc = pthread_setaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1212     if (rc) {
1213         perror("pthread_setaffinity_np failed");
1214         printf("pthread_setaffinity_np failed: %d", rc);
1215     }
1216
1217     /* check the actual affinity mask assigned to the thread */
1218
1219     CPU_ZERO(&cpuset);
1220
1221     rc = pthread_getaffinity_np(pthread_self(), sizeof (cpu_set_t), &cpuset);
1222
1223     if (rc) {
1224         perror("pthread_getaffinity_np failed");
1225         printf("pthread_getaffinity_np failed: %d", rc);
1226     }
1227
1228     printf("set affinity: ");
1229     for (i = 0; i < CPU_SETSIZE; i++)
1230         if (CPU_ISSET(i, &cpuset))
1231             printf("    CPU %d\n", i);
1232
1233     if (!CPU_ISSET(coreNum, &cpuset)) {
1234         printf("affinity failed");
1235     }
1236
1237     /**
1238        A new thread created by pthread_create(3) inherits a copy of its
1239        creator's CPU affinity mask. */
1240
1241     return rc;
1242 }
1243
1244 /**
1245  *******************************************************************************
1246  *
1247  * @fn    app_ApplyParams
1248  * @brief is used to apply application startup parameters
1249  *
1250  * @param[i]  params - app startup params
1251  * @return    void
1252  *
1253  * @description
1254  *    The applies startup parameters
1255  *
1256  * @references
1257  * MS-111070-SP
1258  *
1259  * @ingroup icc_service_unit_test
1260  *
1261  ******************************************************************************/
1262 static void app_ApplyParams(PAPP_PARAMS params)
1263 {
1264     // apply parameters
1265     printf("selected test case %d - ", params->test_id);
1266     switch (params->test_id) {
1267         case APP_TC_SANITY_TEST:
1268         default:
1269             printf("NON-BLOCKING SANITY TEST\n");
1270             AppContext.Receive = app_SanityTestReceiver;
1271             AppContext.Transmit = app_SanityTestTransmitter;
1272             break;
1273     }
1274
1275     AppContext.wls_put = WLS_Put;
1276     AppContext.wls_get = WLS_Get;
1277     AppContext.wls_wget = WLS_WGet;
1278
1279     AppContext.MsgPerMs = DEFAULT_MESSAGE_COUNT_PER_MS;
1280     AppContext.MaxMsgSize = DEFAULT_MAX_MESSAGE_SIZE;
1281     AppContext.MinMsgSize = DEFUALT_MIN_MESSAGE_SIZE;
1282     AppContext.AppSanityMsgSize = sizeof (APP_MESSAGE);
1283
1284     if (params->master) {
1285         printf("WLS test app (supposed to run as MEMORY MASTER)\n");
1286         AppContext.master = TRUE;
1287         AppContext.RxID = 1;
1288         AppContext.TxID = 2;
1289     } else {
1290         AppContext.master = FALSE;
1291         AppContext.RxID = 2;
1292         AppContext.TxID = 1;
1293     }
1294
1295     if (params->rx_id)
1296         AppContext.RxID = params->rx_id;
1297
1298     if (params->tx_id)
1299         AppContext.TxID = params->tx_id;
1300
1301     if (params->n_messages && params->n_messages < MAX_MESSAGES)
1302         AppContext.MsgPerMs = params->n_messages;
1303
1304     if (params->min_size && params->min_size >= 4)
1305         AppContext.MinMsgSize = params->min_size;
1306
1307     // default is 1 RX interface
1308     printf("if count = %u\n", params->interface_count);
1309     AppContext.nInterfaces = 1;
1310     if (params->interface_count == 0) {
1311         printf("WLS test app started as simple data source, no RX ID will be specified\n");
1312         AppContext.nInterfaces = 0;
1313         AppContext.RxID = 0; // override RxID
1314     } else if (params->interface_count <= 7) {
1315         AppContext.nInterfaces = params->interface_count;
1316     }
1317
1318
1319     AppContext.TrustedDataSource = params->trusted;
1320
1321     if (params->crc) {
1322         if (AppContext.MinMsgSize < 8)
1323             AppContext.MinMsgSize = 8;
1324
1325         AppContext.wls_put = app_PutMessageCRC;
1326         AppContext.wls_get = app_GetMessageCRC;
1327         AppContext.wls_wget = app_WGetMessageCRC;
1328
1329         AppContext.AppSanityMsgSize += 4; // + sizeof CRC
1330     }
1331
1332     if (params->max_size && params->max_size <= 16 * K)
1333         AppContext.MaxMsgSize = params->max_size;
1334
1335     if (params->max_size < params->min_size)
1336         params->max_size = params->min_size;
1337
1338     AppContext.Debug = params->debug;
1339
1340     if (params->aff_core) {
1341         AppContext.core = params->aff_core;
1342         app_set_affinity(AppContext.core);
1343     }
1344
1345     printf("The application started with:\n");
1346     printf("Core ................ %d\n", AppContext.core);
1347     printf("Rx interface count .. %d\n", AppContext.nInterfaces);
1348     printf("RxID ................ %d\n", AppContext.RxID);
1349     printf("TxID ................ %d\n", AppContext.TxID);
1350     if (AppContext.Debug)
1351         printf("Generating .......... %lu Messages per second (DEBUG MODE)\n", (long) AppContext.MsgPerMs);
1352     else
1353         printf("Generating .......... %lu Messages per ms\n", (long) AppContext.MsgPerMs);
1354     printf("Max Message Size .... %lu bytes\n", (long) AppContext.MaxMsgSize);
1355     printf("Min Message Size .... %lu bytes\n", (long) AppContext.MinMsgSize);
1356     printf("Number of threads ... 1\n");
1357     printf("CRC checking ........ ");
1358     if (params->crc)
1359         printf("ENABLED\n");
1360     else
1361         printf("DISABLED\n");
1362 }
1363
1364 /**
1365  *******************************************************************************
1366  *
1367  * @fn    app_ReleaseAllocatedBuffers
1368  * @brief releases ICC buffers allocated by the application
1369  *
1370  * @param[n]  void
1371  * @return    void
1372  *
1373  * @description
1374  *    In process of making some tests when signal to close the application
1375  * happens the app may keep some allocated buffers from the ICC pools. This
1376  * routine does release these buffers back to ICC.
1377  *
1378  * @references
1379  * MS-111070-SP
1380  *
1381  * @ingroup icc_service_unit_test
1382  *
1383  ******************************************************************************/
1384 static void app_ReleaseAllocatedBuffers(void)
1385 {
1386     if (AppContext.TxMsgCnt && AppContext.master)
1387         do {
1388             AppContext.TxMsgCnt -= 1;
1389             App_Free(AppContext.hWls, AppContext.TxMessages[ AppContext.TxMsgCnt ]);
1390         } while (AppContext.TxMsgCnt != 0);
1391 }
1392
1393 /**
1394  *******************************************************************************
1395  *
1396  * @fn    main
1397  * @brief ICC test application main routine
1398  *
1399  * @param[n]  void
1400  * @return    void
1401  *
1402  * @description
1403  *    Contains logic of the test (one RX/TX thread)
1404  *
1405  * @references
1406  * MS-111070-SP
1407  *
1408  * @ingroup icc_service_unit_test
1409  *
1410  ****************************************************************************/
1411 int main(int argc, char* argv[])
1412 {
1413     int retval = 0;
1414     APP_PARAMS params;
1415
1416     signal(SIGINT, App_SigExitCallback);
1417
1418     memset(&AppContext, 0, sizeof (AppContext));
1419     memset(&params, 0, sizeof (params));
1420
1421 #ifdef DPDK_WLS
1422     int ret = rte_eal_init(argc, argv);
1423     if (ret < 0)
1424         rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1425
1426     argc -= ret;
1427     argv += ret;
1428 #endif
1429
1430     app_ParseArgs(argc, argv, &params);
1431     app_ApplyParams(&params);
1432
1433     AppContext.InitQueueSize = APP_QUEUE_SIZE;
1434
1435     AppContext.hWls = WLS_Open(params.wls_dev_name, AppContext.master, DEFAULT_TEST_MEMORY_SIZE);
1436
1437     if (!AppContext.hWls) {
1438         printf("could not register WLS client\n");
1439         return 1;
1440     } else {
1441         printf("WLS has been registered\n");
1442     }
1443
1444     AppContext.shm_memory = WLS_Alloc(AppContext.hWls, DEFAULT_TEST_MEMORY_SIZE);
1445
1446     if (AppContext.shm_memory == NULL) {
1447         if (AppContext.master)
1448             printf("could not create WLS shared memory\n");
1449         else
1450             printf("could not attach WLS shared memory\n");
1451
1452         return -1;
1453     }
1454
1455     if (AppContext.master) {
1456         if (App_MemoryInit(AppContext.shm_memory, DEFAULT_TEST_MEMORY_SIZE, DEFAUTL_TEST_BLOCK_SIZE) != 0) {
1457             WLS_Free(AppContext.hWls, AppContext.shm_memory);
1458             WLS_Close(AppContext.hWls);
1459             exit(1);
1460         }
1461
1462     }
1463
1464     // APPLICATION MAIN LOOP
1465     while (!AppContext.ExitStatus && (AppContext.Receive || AppContext.Transmit)) {
1466         if (AppContext.Receive)
1467             AppContext.Receive(AppContext.hWls);
1468
1469         if (AppContext.Debug)
1470             //usleep(10000); // 1 sec delay
1471             sleep(1); // 1 sec delay
1472         else
1473             usleep(1000); // 1 ms delay
1474
1475         if (AppContext.Transmit)
1476             AppContext.Transmit(AppContext.hWls);
1477
1478         app_UpdateStatistics();
1479     }
1480
1481     app_ReleaseAllocatedBuffers();
1482     printf("deregistering WLS  (TxTotal_%llu, RxTotal_%llu)\n", (long long) AppContext.nTxMsgs, (long long) AppContext.nRxMsgs);
1483     WLS_Free(AppContext.hWls, AppContext.shm_memory);
1484     WLS_Close(AppContext.hWls);
1485     return retval;
1486 }