[Epic-ID: ODUHIGH-405][Task-ID: ODUHIGH-437] Establishing communication between Sourc...
[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       DU_LOG("\n");
209       continue;
210    }
211 }
212
213 /*******************************************************************
214  *
215  * @brief Creates thread for handling console input 
216  *
217  * @details
218  *
219  *    Function : l1StartConsoleHandler
220  *
221  *    Functionality: Creates thread for handling console input
222  *
223  * @params[in] 
224  * @return ROK     - success
225  *         RFAILED - failure
226  *
227  * ****************************************************************/
228 void l1StartConsoleHandler()
229 {
230    uint8_t retVal, threadIdx;
231    pthread_t conThrdId[NUM_THREADS];
232    pthread_attr_t attr;
233
234    /* Start thread to receive console input */
235    pthread_attr_init(&attr);
236    pthread_attr_setstacksize(&attr, (size_t)NULLD);
237    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
238    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
239    for(threadIdx =0 ; threadIdx <NUM_THREADS; threadIdx++)
240    {
241       if(threadIdx == 0)
242       {
243          retVal = pthread_create(&conThrdId[threadIdx], &attr, l1ConsoleHandler, NULLP);
244       }
245       else
246       {
247          retVal = pthread_create(&conThrdId[threadIdx], &attr, establishConnectionWithPeerL1, NULLP);
248       }
249       
250       if(retVal != 0)
251       {
252          DU_LOG("\nERROR  -->  PHY STUB : Thread creation failed. Cause %d", retVal);
253       }
254    }
255    pthread_attr_destroy(&attr);
256 }
257
258 /*******************************************************************
259  *
260  * @brief function reads the recevied information send by peer PHY 
261  *
262  * @details
263  *
264  *    Function : receiveMsgFromPeerL1
265  *
266  *    Functionality: This function reads the recevied information 
267  *    and prints at console
268  *
269  * @params[in] 
270  * @return ROK     - success
271  *         RFAILED - failure
272  *
273  * ****************************************************************/
274 void receiveMsgFromPeerL1()
275 {
276    while(true)
277    {
278       char buffer[1024] = {0};
279       
280       if(read(socket_fd, buffer, 1024)>0)
281       {
282          DU_LOG("\n");
283          DU_LOG("%s\n",buffer);
284          if (strncmp("HANDOVER_IN_PROGRESS", buffer, 19) == 0) 
285          {
286             DU_LOG("\nINFO  --> PHY_STUB : Communication completed in between the source and destination PHY\n");
287             //TODO: Trigger for other handover process in target PHY
288          }
289       }
290    }
291 }
292
293 /*******************************************************************
294  *
295  * @brief function build the message which need to send to target PHY 
296  *
297  * @details
298  *
299  *    Function : sendMsg
300  *
301  *    Functionality: function build the message which need to send 
302  *
303  * @params[in] 
304  * @return ROK     - success
305  *         RFAILED - failure
306  *
307  * ****************************************************************/
308 void sendMsg()
309 {
310    char *msgToDestinationPhy = "HANDOVER_IN_PROGRESS";
311
312    send(socket_fd, msgToDestinationPhy , strlen(msgToDestinationPhy) , 0 );
313 }
314
315 /*******************************************************************
316  *
317  * @brief This function handles the server functionalities like 
318  * binding socket, listen and accept
319  *
320  * @details
321  *
322  *    Function : startL1AsServer
323  *
324  *    Functionality: This function handles the server functionalities like
325  *     binding socket, listen and accept
326  *
327  * @params[in] struct sockaddr_in serverPhy, struct sockaddr_in
328  * clientPhy
329  * @return ROK     - success
330  *         RFAILED - failure
331  *
332  * ****************************************************************/
333 int8_t startL1AsServer(struct sockaddr_in serverPhy, struct sockaddr_in clientPhy)
334 {
335    int addrlen= sizeof(struct sockaddr_in);
336
337    if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in))<0)
338    {
339       DU_LOG("\nERROR  --> PHY_STUB : bind failed");
340       return RFAILED;
341    }
342    if (listen(socket_fd, 3) < 0)
343    {
344       DU_LOG("\nERROR  --> PHY_STUB : listen failed");
345       return RFAILED;
346    }
347    while(true)
348    {
349       if ((socket_fd = accept(socket_fd, (struct sockaddr *)&clientPhy,
350                   (socklen_t*)&addrlen))<0)
351       {
352          DU_LOG("\nINFO  --> PHY_STUB : Server is waiting");
353       }
354       else
355       {
356          DU_LOG("\nINFO  --> PHY_STUB : Server Connected");
357          break;
358       }
359    }
360    return ROK;
361 }
362
363 /*******************************************************************
364  *
365  * @brief this function includes all the functionalities of client side
366  * like binding the client side socket and connecting to the server
367  *
368  * @details
369  *
370  *    Function : startL1AsClient
371  *
372  *    Functionality: this function includes all the functionalities of client
373  *    side like binding the client side socket and connecting to the server
374  *
375  * @params[in] 
376  * @return ROK     - success
377  *         RFAILED - failure
378  *
379  * ****************************************************************/
380 int8_t startL1AsClient(struct sockaddr_in serverPhy, struct sockaddr_in  destinationPhy)
381 {
382    if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in ))<0)
383    {
384       DU_LOG("\nERROR  --> PHY_STUB : bind failed");
385       return RFAILED;
386    }
387
388    while(true)
389    {
390       if (connect(socket_fd, (struct sockaddr *)&destinationPhy, sizeof(struct sockaddr_in)) < 0)
391       {
392          DU_LOG("\nERROR  --> PHY_STUB : Connection Failed");
393       }
394       else
395       {
396          DU_LOG("\nINFO  --> PHY_STUB : Client connected to sever");
397          break;
398       }
399    }
400    return ROK;
401
402 }
403
404 /*******************************************************************
405  *
406  * @brief this function creates the socket for commincation between source and 
407  * target phy
408  *
409  * @details
410  *
411  *    Function : establishConnectionWithPeerL1
412  *
413  *    Functionality: creates the socket for commincation between source and
414  *    target PHY, allocated the ip addresses and sends the request for connection
415  *    establisshement and sends the information to each other
416  *
417  * @params[in] 
418  * @return ROK     - success
419  *         RFAILED - failure
420  *
421  * ****************************************************************/
422 void *establishConnectionWithPeerL1(void *args)
423 {
424    void *ret = NULLP;
425    struct sockaddr_in sourcePhy, destinationPhy;
426
427    if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
428    {
429       DU_LOG("\nERROR  --> PHY_STUB : socket failed");
430       return ret; 
431    }
432    
433    sourcePhy.sin_family = AF_INET;
434    sourcePhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
435    sourcePhy.sin_addr.s_addr = phyDb.ipCfgInfo.sourceDu;
436    
437    destinationPhy.sin_family = AF_INET;
438    destinationPhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
439    destinationPhy.sin_addr.s_addr = phyDb.ipCfgInfo.destinationDu;
440    
441    if(phyDb.isServer)
442    {
443       if(startL1AsServer(sourcePhy, destinationPhy) != ROK)
444       {
445          DU_LOG("\nERROR  --> PHY_STUB : Failed to start server");
446          return ret;
447       }
448    }
449    else
450    {
451       if(startL1AsClient(sourcePhy, destinationPhy) != ROK)
452       {
453          DU_LOG("\nERROR  --> PHY_STUB : Failed to start client");
454          return ret;
455       }
456    }
457
458    DU_LOG("\nINFO  --> PHY_STUB : Connection established");
459    receiveMsgFromPeerL1();
460    return ROK;
461 }
462 /**********************************************************************
463          End of file
464 **********************************************************************/