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