1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /* This file handles slot indication */
21 #include "common_def.h"
22 #include "phy_stub_utils.h"
24 #include "nr5g_fapi_internal.h"
25 #include "fapi_vendor_extension.h"
28 #include "mac_sch_interface.h"
33 extern uint16_t l1BuildAndSendBSR(uint8_t ueIdx, BsrType bsrType,\
34 LcgBufferSize lcgBsIdx[MAX_NUM_LOGICAL_CHANNEL_GROUPS]);
37 bool slotIndicationStarted;
39 /*******************************************************************
41 * @brief Generates slot indications
45 * Function : GenerateTicks
47 * Functionality: Generates slot indications
50 * @return ROK - success
53 * ****************************************************************/
57 float milisec = 0.5; /* 0.5ms */
59 float milisec = 1; /* 1ms */
61 struct timespec req = {0};
64 slotIndicationStarted = true;
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;
73 DU_LOG("\nPHY_STUB : GenerateTicks : Starting to generate slot indications");
75 while(slotIndicationStarted)
77 clock_nanosleep(CLOCK_REALTIME, 0, &req, NULL);
78 /* Send Slot indication indication to lower mac */
79 if(l1BuildAndSendSlotIndication() != ROK)
81 DU_LOG("\nERROR --> PHY_STUB : GenerateTicks(): Failed to build and send Slot Indication");
86 DU_LOG("\nINFO --> PHY_STUB : Slot indication stopped");
88 /* Initialize all global variables */
91 memset(&phyDb.ueDb, 0, sizeof(UeDb));
93 /* Send Stop indication to MAC */
95 l1BuildAndSendStopInd();
98 /*******************************************************************
100 * @brief Create/cancel thread for generating slot indication
104 * Function : l1HdlSlotIndicaion
106 * Functionality: Create/cancel thread for generating slot indication
109 * @return ROK - success
112 * ****************************************************************/
113 void l1HdlSlotIndicaion(bool stopSlotInd)
116 Buffer *mBuf = NULLP;
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);
128 slotIndicationStarted = false;
132 /*******************************************************************
134 * @brief Handles Console input
138 * Function : l1ConsoleHandler
140 * Functionality: Handles Console input
143 * @return ROK - success
146 * ****************************************************************/
147 void *l1ConsoleHandler(void *args)
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;
159 /* Send UL user data to DU when user enters 'd' on console */
165 /* Start Pumping data from PHY stub to DU */
166 for(ueIdx=0; ueIdx < phyDb.ueDb.numActvUe; ueIdx++)
168 for(drbIdx = 0; drbIdx < NUM_DRB_TO_PUMP_DATA; drbIdx++) //Number of DRB times the loop will run
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 */
182 /* Send Control PDU from PHY stub to DU */
183 DU_LOG("\nDEBUG --> PHY STUB: Sending Status PDU");
188 memset(lcgBS, 0, (MAX_NUM_LOGICAL_CHANNEL_GROUPS * sizeof(LcgBufferSize)));
189 /* Send Control PDU from PHY stub to DU */
191 for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
195 for(lcgIdx = 0; lcgIdx < NUM_DRB_TO_PUMP_DATA; lcgIdx++)
197 lcgBS[lcgIdx].lcgId = MIN_DRB_LCID + lcgIdx;
198 lcgBS[lcgIdx].bsIdx = lcgIdx + 1;
200 l1BuildAndSendBSR(ueIdx, LONG_BSR, lcgBS);
206 lcgBS[lcgIdx].lcgId = MIN_DRB_LCID + lcgIdx;
207 lcgBS[lcgIdx].bsIdx = lcgIdx + 1;
208 l1BuildAndSendBSR(ueIdx, SHORT_BSR, lcgBS);
214 /* Trigger RACH Indication towards DU */
215 if(phyDb.ueDb.ueCb[phyDb.ueDb.numActvUe].rachIndSent == false)
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++;
229 /*******************************************************************
231 * @brief Creates thread for handling console input
235 * Function : l1StartConsoleHandler
237 * Functionality: Creates thread for handling console input
240 * @return ROK - success
243 * ****************************************************************/
244 void l1StartConsoleHandler()
246 uint8_t retVal, threadIdx;
247 pthread_t conThrdId[NUM_THREADS];
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++)
259 retVal = pthread_create(&conThrdId[threadIdx], &attr, l1ConsoleHandler, NULLP);
263 retVal = pthread_create(&conThrdId[threadIdx], &attr, establishConnectionWithPeerL1, NULLP);
268 DU_LOG("\nERROR --> PHY STUB : Thread creation failed. Cause %d", retVal);
271 pthread_attr_destroy(&attr);
274 /*******************************************************************
276 * @brief function reads the recevied information send by peer PHY
280 * Function : receiveMsgFromPeerL1
282 * Functionality: This function reads the recevied information
283 * and prints at console
286 * @return ROK - success
289 * ****************************************************************/
290 void receiveMsgFromPeerL1()
294 char buffer[1024] = {0};
296 if(read(socket_fd, buffer, 1024)>0)
299 DU_LOG("%s\n",buffer);
300 if (strncmp("HANDOVER_IN_PROGRESS", buffer, 19) == 0)
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
309 /*******************************************************************
311 * @brief function build the message which need to send to target PHY
317 * Functionality: function build the message which need to send
320 * @return ROK - success
323 * ****************************************************************/
326 char *msgToDestinationPhy = "HANDOVER_IN_PROGRESS";
328 send(socket_fd, msgToDestinationPhy , strlen(msgToDestinationPhy) , 0 );
331 /*******************************************************************
333 * @brief This function handles the server functionalities like
334 * binding socket, listen and accept
338 * Function : startL1AsServer
340 * Functionality: This function handles the server functionalities like
341 * binding socket, listen and accept
343 * @params[in] struct sockaddr_in serverPhy, struct sockaddr_in
345 * @return ROK - success
348 * ****************************************************************/
349 int8_t startL1AsServer(struct sockaddr_in serverPhy, struct sockaddr_in clientPhy)
351 int addrlen= sizeof(struct sockaddr_in);
353 if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in))<0)
355 DU_LOG("\nERROR --> PHY_STUB : bind failed");
358 if (listen(socket_fd, 3) < 0)
360 DU_LOG("\nERROR --> PHY_STUB : listen failed");
365 if ((socket_fd = accept(socket_fd, (struct sockaddr *)&clientPhy,
366 (socklen_t*)&addrlen))<0)
368 DU_LOG("\nINFO --> PHY_STUB : Server is waiting");
372 DU_LOG("\nINFO --> PHY_STUB : Server Connected");
379 /*******************************************************************
381 * @brief this function includes all the functionalities of client side
382 * like binding the client side socket and connecting to the server
386 * Function : startL1AsClient
388 * Functionality: this function includes all the functionalities of client
389 * side like binding the client side socket and connecting to the server
392 * @return ROK - success
395 * ****************************************************************/
396 int8_t startL1AsClient(struct sockaddr_in serverPhy, struct sockaddr_in destinationPhy)
398 if (bind(socket_fd, (struct sockaddr *)&serverPhy, sizeof(struct sockaddr_in ))<0)
400 DU_LOG("\nERROR --> PHY_STUB : bind failed");
406 if (connect(socket_fd, (struct sockaddr *)&destinationPhy, sizeof(struct sockaddr_in)) < 0)
408 DU_LOG("\nERROR --> PHY_STUB : Connection Failed");
412 DU_LOG("\nINFO --> PHY_STUB : Client connected to sever");
420 /*******************************************************************
422 * @brief this function creates the socket for commincation between source and
427 * Function : establishConnectionWithPeerL1
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
434 * @return ROK - success
437 * ****************************************************************/
438 void *establishConnectionWithPeerL1(void *args)
441 struct sockaddr_in sourcePhy, destinationPhy;
443 if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
445 DU_LOG("\nERROR --> PHY_STUB : socket failed");
449 sourcePhy.sin_family = AF_INET;
450 sourcePhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
451 sourcePhy.sin_addr.s_addr = phyDb.ipCfgInfo.sourceDu;
453 destinationPhy.sin_family = AF_INET;
454 destinationPhy.sin_port = htons(phyDb.ipCfgInfo.portNumber);
455 destinationPhy.sin_addr.s_addr = phyDb.ipCfgInfo.destinationDu;
459 if(startL1AsServer(sourcePhy, destinationPhy) != ROK)
461 DU_LOG("\nERROR --> PHY_STUB : Failed to start server");
467 if(startL1AsClient(sourcePhy, destinationPhy) != ROK)
469 DU_LOG("\nERROR --> PHY_STUB : Failed to start client");
474 DU_LOG("\nINFO --> PHY_STUB : Connection established");
475 receiveMsgFromPeerL1();
478 /**********************************************************************
480 **********************************************************************/