[ Jira id - ODUHIGH-593 ] Pack and unpack function nomenclature correction
[o-du/l2.git] / src / phy_stub / phy_stub_thread_hdl.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
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 /* This file handles slot indication */
20
21 #include "common_def.h"
22 #include "phy_stub_utils.h"
23 #ifdef INTEL_FAPI
24 #include "nr5g_fapi_internal.h"
25 #include "fapi_vendor_extension.h"
26 #endif
27 #include "phy_stub.h"
28 #include "mac_sch_interface.h"
29
30 uint16_t sfnValue;
31 uint16_t slotValue;
32 PhyDb phyDb;
33 extern uint16_t l1BuildAndSendBSR(uint8_t ueIdx, BsrType bsrType,\
34              LcgBufferSize lcgBsIdx[MAX_NUM_LOGICAL_CHANNEL_GROUPS]);
35 pthread_t thread = 0;
36 int socket_fd =0;
37 bool     slotIndicationStarted;
38
39 /*******************************************************************
40  *
41  * @brief Generates slot indications
42  *
43  * @details
44  *
45  *    Function : GenerateTicks
46  *
47  *    Functionality: Generates slot indications
48  *
49  * @params[in] 
50  * @return ROK     - success
51  *         RFAILED - failure
52  *
53  * ****************************************************************/
54 void GenerateTicks()
55 {
56 #ifdef NR_TDD
57    float     milisec = 0.5;        /* 0.5ms */
58 #else
59    float     milisec = 1;          /* 1ms */
60 #endif
61    struct timespec req = {0};
62    uint8_t ratio = 2;
63
64    slotIndicationStarted = true;
65    req.tv_sec = 0;
66
67    /* Currently the code takes longer that one slot indication to execute.
68     * Hence, multiplying slot time interval by 2 in order to give enough time 
69     * for L2 to complete one slot processing.
70     * The ratio must be removed once code optimization is complete */
71    req.tv_nsec = milisec * 1000000L * ratio;
72
73    DU_LOG("\nPHY_STUB : GenerateTicks : Starting to generate slot indications");
74
75    while(slotIndicationStarted)
76    {
77       clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL); 
78       /* Send Slot indication indication to lower mac */
79       if(l1BuildAndSendSlotIndication() != ROK)
80       {
81          DU_LOG("\nERROR  --> PHY_STUB : GenerateTicks(): Failed to build and send Slot Indication");
82          return;
83       }
84    }
85
86    DU_LOG("\nINFO  --> PHY_STUB : Slot indication stopped");
87
88    /* Initialize all global variables */
89    sfnValue = 0;
90    slotValue = 0;
91    memset(&phyDb.ueDb, 0, sizeof(UeDb));
92
93    /* Send Stop indication to MAC */
94    sleep(1);
95    l1BuildAndSendStopInd();
96 }
97
98 /*******************************************************************
99  *
100  * @brief Create/cancel thread for generating slot indication 
101  *
102  * @details
103  *
104  *    Function : l1HdlSlotIndicaion
105  *
106  *    Functionality: Create/cancel thread for generating slot indication
107  *
108  * @params[in] 
109  * @return ROK     - success
110  *         RFAILED - failure
111  *
112  * ****************************************************************/
113 void l1HdlSlotIndicaion(bool stopSlotInd)
114 {
115    Pst pst;
116    Buffer *mBuf = NULLP;
117
118    if(!stopSlotInd)
119    {
120       DU_LOG("\nPHY_STUB: Sending start slot indication event to self");
121       memset(&pst, 0, sizeof(Pst));
122       FILL_PST_PHY_TO_PHY(pst, EVT_PHY_START_SLOT_IND);
123       ODU_GET_MSG_BUF(pst.region, pst.pool, &mBuf);
124       ODU_POST_TASK(&pst, mBuf);
125    }
126    else
127    {
128       slotIndicationStarted = false;
129    }
130 }
131
132 /*******************************************************************
133  *
134  * @brief Handles Console input
135  *
136  * @details
137  *
138  *    Function : l1ConsoleHandler
139  *
140  *    Functionality: Handles Console input
141  *
142  * @params[in]
143  * @return ROK     - success
144  *         RFAILED - failure
145  *
146  * ****************************************************************/
147 void *l1ConsoleHandler(void *args)
148 {
149    char ch, ch1;
150    uint8_t drbIdx = 0, lcgIdx = 0, ueIdx = 0;
151    LcgBufferSize lcgBS[MAX_NUM_LOGICAL_CHANNEL_GROUPS];
152    /* The below variable is taken for sending specific number of UL Packets  
153     * For sendind 4500 Ul packets for three UEs the calculation of
154     * [counter * NUM_DRB_TO_PUMP_DATA * MAX_NUM_UE * NUM_UL_PACKETS] must be equal to 4500 */
155    uint32_t counter=500; 
156
157    while(true)
158    {
159       /* Send UL user data to DU when user enters 'd' on console */
160       ch = getchar();
161       if(ch == 'd')
162       {
163          while(counter)
164          {
165             /* Start Pumping data from PHY stub to DU */
166             for(ueIdx=0; ueIdx < phyDb.ueDb.numActvUe; ueIdx++)
167             {
168                for(drbIdx = 0; drbIdx < NUM_DRB_TO_PUMP_DATA; drbIdx++) //Number of DRB times the loop will run
169                {
170                   DU_LOG("\nDEBUG  --> PHY STUB: Sending UL User Data[DrbId:%d] for UEIdx %d\n",drbIdx,ueIdx);
171                   l1SendUlUserData(drbIdx,ueIdx);
172                   /* TODO :- sleep(1) will be removed once we will be able to
173                    * send continuous data packet */
174                   sleep(1);
175                }
176             }
177             counter--;
178          }
179       }
180       else if(ch =='c')
181       {
182          /* Send Control PDU from PHY stub to DU */
183          DU_LOG("\nDEBUG  --> PHY STUB: Sending Status PDU");
184          l1SendStatusPdu();
185       }
186       else if(ch == 'b')
187       {
188          memset(lcgBS, 0, (MAX_NUM_LOGICAL_CHANNEL_GROUPS * sizeof(LcgBufferSize)));
189          /* Send Control PDU from PHY stub to DU */
190          ch1 = getchar();
191          for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
192          {
193             if(ch1 == 'l')
194             {
195                for(lcgIdx = 0; lcgIdx < NUM_DRB_TO_PUMP_DATA; lcgIdx++)
196                {
197                   lcgBS[lcgIdx].lcgId = MIN_DRB_LCID + lcgIdx;
198                   lcgBS[lcgIdx].bsIdx = lcgIdx + 1;
199                }
200                l1BuildAndSendBSR(ueIdx, LONG_BSR, lcgBS);
201             }
202             else if(ch1 == 's')
203             {
204                lcgIdx = 0;
205
206                lcgBS[lcgIdx].lcgId = MIN_DRB_LCID + lcgIdx;
207                lcgBS[lcgIdx].bsIdx = lcgIdx + 1;
208                l1BuildAndSendBSR(ueIdx, SHORT_BSR, lcgBS);
209             }
210          }
211       }
212       else if(ch == 'r')
213       {
214          /* Trigger RACH Indication towards DU */
215          if(phyDb.ueDb.ueCb[phyDb.ueDb.numActvUe].rachIndSent == false)
216          {
217             phyDb.ueDb.ueCb[phyDb.ueDb.numActvUe].rachIndSent = true;
218             phyDb.ueDb.ueCb[phyDb.ueDb.numActvUe].isCFRA = true;
219             l1BuildAndSendRachInd(slotValue, sfnValue, CF_RA_PREAMBLE_IDX);
220             phyDb.ueDb.numActvUe++;
221          }
222
223       }
224       DU_LOG("\n");
225       continue;
226    }
227 }
228
229 /*******************************************************************
230  *
231  * @brief Creates thread for handling console input 
232  *
233  * @details
234  *
235  *    Function : l1StartConsoleHandler
236  *
237  *    Functionality: Creates thread for handling console input
238  *
239  * @params[in] 
240  * @return ROK     - success
241  *         RFAILED - failure
242  *
243  * ****************************************************************/
244 void l1StartConsoleHandler()
245 {
246    uint8_t retVal, threadIdx;
247    pthread_t conThrdId[NUM_THREADS];
248    pthread_attr_t attr;
249
250    /* Start thread to receive console input */
251    pthread_attr_init(&attr);
252    pthread_attr_setstacksize(&attr, (size_t)NULLD);
253    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
254    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
255    for(threadIdx =0 ; threadIdx <NUM_THREADS; threadIdx++)
256    {
257       if(threadIdx == 0)
258       {
259          retVal = pthread_create(&conThrdId[threadIdx], &attr, l1ConsoleHandler, NULLP);
260       }
261       else
262       {
263          retVal = pthread_create(&conThrdId[threadIdx], &attr, establishConnectionWithPeerL1, NULLP);
264       }
265       
266       if(retVal != 0)
267       {
268          DU_LOG("\nERROR  -->  PHY STUB : Thread creation failed. Cause %d", retVal);
269       }
270    }
271    pthread_attr_destroy(&attr);
272 }
273
274 /*******************************************************************
275  *
276  * @brief function reads the recevied information send by peer PHY 
277  *
278  * @details
279  *
280  *    Function : receiveMsgFromPeerL1
281  *
282  *    Functionality: This function reads the recevied information 
283  *    and prints at console
284  *
285  * @params[in] 
286  * @return ROK     - success
287  *         RFAILED - failure
288  *
289  * ****************************************************************/
290 void receiveMsgFromPeerL1()
291 {
292    while(true)
293    {
294       char buffer[1024] = {0};
295       
296       if(read(socket_fd, buffer, 1024)>0)
297       {
298          DU_LOG("\n");
299          DU_LOG("%s\n",buffer);
300          if (strncmp("HANDOVER_IN_PROGRESS", buffer, 19) == 0) 
301          {
302             DU_LOG("\nINFO  --> PHY_STUB : Communication completed in between the source and destination PHY\n");
303             //TODO: Trigger for other handover process in target PHY
304          }
305       }
306    }
307 }
308
309 /*******************************************************************
310  *
311  * @brief function build the message which need to send to target PHY 
312  *
313  * @details
314  *
315  *    Function : sendMsg
316  *
317  *    Functionality: function build the message which need to send 
318  *
319  * @params[in] 
320  * @return ROK     - success
321  *         RFAILED - failure
322  *
323  * ****************************************************************/
324 void sendMsg()
325 {
326    char *msgToDestinationPhy = "HANDOVER_IN_PROGRESS";
327
328    send(socket_fd, msgToDestinationPhy , strlen(msgToDestinationPhy) , 0 );
329 }
330
331 /*******************************************************************
332  *
333  * @brief This function handles the server functionalities like 
334  * binding socket, listen and accept
335  *
336  * @details
337  *
338  *    Function : startL1AsServer
339  *
340  *    Functionality: This function handles the server functionalities like
341  *     binding socket, listen and accept
342  *
343  * @params[in] struct sockaddr_in serverPhy, struct sockaddr_in
344  * clientPhy
345  * @return ROK     - success
346  *         RFAILED - failure
347  *
348  * ****************************************************************/
349 int8_t startL1AsServer(struct sockaddr_in serverPhy, struct sockaddr_in clientPhy)
350 {
351    int addrlen= sizeof(struct sockaddr_in);
352
353    if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in))<0)
354    {
355       DU_LOG("\nERROR  --> PHY_STUB : bind failed");
356       return RFAILED;
357    }
358    if (listen(socket_fd, 3) < 0)
359    {
360       DU_LOG("\nERROR  --> PHY_STUB : listen failed");
361       return RFAILED;
362    }
363    while(true)
364    {
365       if ((socket_fd = accept(socket_fd, (struct sockaddr *)&clientPhy,
366                   (socklen_t*)&addrlen))<0)
367       {
368          DU_LOG("\nINFO  --> PHY_STUB : Server is waiting");
369       }
370       else
371       {
372          DU_LOG("\nINFO  --> PHY_STUB : Server Connected");
373          break;
374       }
375    }
376    return ROK;
377 }
378
379 /*******************************************************************
380  *
381  * @brief this function includes all the functionalities of client side
382  * like binding the client side socket and connecting to the server
383  *
384  * @details
385  *
386  *    Function : startL1AsClient
387  *
388  *    Functionality: this function includes all the functionalities of client
389  *    side like binding the client side socket and connecting to the server
390  *
391  * @params[in] 
392  * @return ROK     - success
393  *         RFAILED - failure
394  *
395  * ****************************************************************/
396 int8_t startL1AsClient(struct sockaddr_in serverPhy, struct sockaddr_in  destinationPhy)
397 {
398    if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in ))<0)
399    {
400       DU_LOG("\nERROR  --> PHY_STUB : bind failed");
401       return RFAILED;
402    }
403
404    while(true)
405    {
406       if (connect(socket_fd, (struct sockaddr *)&destinationPhy, sizeof(struct sockaddr_in)) < 0)
407       {
408          DU_LOG("\nERROR  --> PHY_STUB : Connection Failed");
409       }
410       else
411       {
412          DU_LOG("\nINFO  --> PHY_STUB : Client connected to sever");
413          break;
414       }
415    }
416    return ROK;
417
418 }
419
420 /*******************************************************************
421  *
422  * @brief this function creates the socket for commincation between source and 
423  * target phy
424  *
425  * @details
426  *
427  *    Function : establishConnectionWithPeerL1
428  *
429  *    Functionality: creates the socket for commincation between source and
430  *    target PHY, allocated the ip addresses and sends the request for connection
431  *    establisshement and sends the information to each other
432  *
433  * @params[in] 
434  * @return ROK     - success
435  *         RFAILED - failure
436  *
437  * ****************************************************************/
438 void *establishConnectionWithPeerL1(void *args)
439 {
440    void *ret = NULLP;
441    struct sockaddr_in sourcePhy, destinationPhy;
442
443    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
444    {
445       DU_LOG("\nERROR  --> PHY_STUB : socket failed");
446       return ret; 
447    }
448    
449    sourcePhy.sin_family = AF_INET;
450    sourcePhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
451    sourcePhy.sin_addr.s_addr = phyDb.ipCfgInfo.sourceDu;
452    
453    destinationPhy.sin_family = AF_INET;
454    destinationPhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
455    destinationPhy.sin_addr.s_addr = phyDb.ipCfgInfo.destinationDu;
456    
457    if(phyDb.isServer)
458    {
459       if(startL1AsServer(sourcePhy, destinationPhy) != ROK)
460       {
461          DU_LOG("\nERROR  --> PHY_STUB : Failed to start server");
462          return ret;
463       }
464    }
465    else
466    {
467       if(startL1AsClient(sourcePhy, destinationPhy) != ROK)
468       {
469          DU_LOG("\nERROR  --> PHY_STUB : Failed to start client");
470          return ret;
471       }
472    }
473
474    DU_LOG("\nINFO  --> PHY_STUB : Connection established");
475    receiveMsgFromPeerL1();
476    return ROK;
477 }
478 /**********************************************************************
479          End of file
480 **********************************************************************/