blob: 1bd9a84e1d1620b13f40c88d166dc6c388a69e18 [file] [log] [blame]
Luis Farias9d66fca2020-05-28 19:01:58 -07001/******************************************************************************
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
64typedef enum {
65 APP_TC_SANITY_TEST = 0,
66} APP_TEST_CASES;
67
68typedef 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
84typedef struct tagAPP_MESSAGE {
85 U32 id;
86} APP_MESSAGE, *PAPP_MESSAGE;
87
88typedef 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
146APP_CONTEXT AppContext;
147
148static int pool_alloc = 0;
149static int pool_free = 0;
150
151static 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
164static void App_SigExitCallback(int signum)
165{
166 (void) signum;
167 AppContext.ExitStatus = TRUE;
168}
169
170static void* WlsVaToPa(void * ptr)
171{
172 PAPP_CONTEXT pCtx = &AppContext;
173 return (void*) WLS_VA2PA(pCtx->hWls, ptr);
174}
175
176static void* WlsPaToVa(void * ptr)
177{
178 PAPP_CONTEXT pCtx = &AppContext;
179 return (void*) WLS_PA2VA(pCtx->hWls, (U64) ptr);
180}
181
182static 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
207static 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
221static 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)
272const 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
307const 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
345U16
346crc16(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
361static 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 ***********************************************/
385static 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 ***********************************************/
415U16 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
441static 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
463static 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
470static 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
497static 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
518static 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
539static void CreateMessage(PAPP_MESSAGE p, U32 size)
540{
541 (void) size;
542 p->id = AppContext.TxCnt++;
543}
544
545static 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 ******************************************************************************/
585static 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 ******************************************************************************/
637static 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 ******************************************************************************/
708static 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 ******************************************************************************/
846static 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 ******************************************************************************/
925static 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
993static 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
1029static 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 ******************************************************************************/
1058static 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 ******************************************************************************/
1103static 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
1201static 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 ******************************************************************************/
1262static 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 ******************************************************************************/
1384static 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 ****************************************************************************/
1411int 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}