[Epic-ID: ODUHIGH-402][Task-ID: ODUHIGH-418] Harq feature changes
[o-du/l2.git] / src / 5gnrmac / mac_rach.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 /* header include files (.h) */
19 #include "common_def.h"
20 #include "lrg.h"
21 #include "lrg.x"
22 #include "du_app_mac_inf.h"
23 #include "mac_sch_interface.h"
24 #include "lwr_mac_upr_inf.h"
25 #include "mac.h"
26 #include "mac_utils.h"
27
28 /* Function pointer for sending rach ind from MAC to SCH */
29 MacSchRachIndFunc macSchRachIndOpts[]=
30 {
31    packMacSchRachInd,   /* packing for loosely coupled */
32    MacSchRachInd,       /* packing for tightly coupled */ 
33    packMacSchRachInd    /* packing for light weight loosely coupled */
34 };
35
36 /* Function pointer for sending RACH resource request from MAC to SCH */
37 MacSchRachRsrcReqFunc macSchRachRsrcReqOpts[] = 
38 {
39    packMacSchRachRsrcReq,   /* packing for loosely coupled */
40    MacSchRachRsrcReq,       /* packing for tightly coupled */
41    packMacSchRachRsrcReq    /* packing for light weight loosely coupled */
42 };
43
44 /* Function pointer for sending RACH resource response from MAC to DU APP */
45 MacDuRachRsrcRspFunc macDuRachRsrcRspOpts[] =
46 {
47    packDuMacRachRsrcRsp,   /* packing for loosely coupled */
48    DuProcMacRachRsrcRsp,   /* packing for tightly coupled */
49    packDuMacRachRsrcRsp    /* packing for light weight loosly coupled */
50 };
51
52 /* Function pointer for sending RACH resource release from MAC to SCH */
53 MacSchRachRsrcRelFunc macSchRachRsrcRelOpts[] =
54 {
55    packMacSchRachRsrcRel,   /* packing for loosely coupled */
56    MacSchRachRsrcRel,       /* packing for tightly coupled */
57    packMacSchRachRsrcRel    /* packing for light weight loosely coupled */
58 };
59
60 /*******************************************************************
61  *
62  * @brief Sends RACH indication to SCH
63  *
64  * @details
65  *
66  *    Function : sendRachIndMacToSch
67  *
68  *    Functionality:
69  *     Sends RACH indication to SCH
70  *
71  * @params[in] RACH indication info
72  * @return ROK     - success
73  *         RFAILED - failure
74  *
75  * ****************************************************************/
76 uint8_t sendRachIndMacToSch(RachIndInfo *rachInd)
77 {
78    Pst pst;
79
80    FILL_PST_MAC_TO_SCH(pst, EVENT_RACH_IND_TO_SCH);
81    return(*macSchRachIndOpts[pst.selector])(&pst, rachInd); 
82 }
83
84 /*******************************************************************
85  *
86  * @brief Adds an entry in list of RA Cb and fills RACH ind info
87  *
88  * @details
89  *
90  *    Function : createMacRaCb
91  *
92  *    Functionality:
93  *     Adds an entry in list of RA Cb and fills RACH ind info
94  *
95  * @params[in] Pointer to cellCB,
96  *             Pointer to RACH Indication information
97  * @return ROK - SUCCESS
98  *         RFAILED - FAILURE
99  *
100  * ****************************************************************/
101 uint8_t createMacRaCb(MacCellCb *cellCb, RachIndInfo *rachIndInfo)
102 {
103    int8_t ueIdx = -1;
104    uint8_t  ssbIdx = 0;
105    uint16_t crnti = 0;
106    MacUeCb  *ueCb = NULLP;
107
108    /* Search if a UE CB is already present to which the incoming preamble index was dedicated */
109    for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) 
110    {
111       /* Check if ueCb has a crnti alloted to it. If not, it means this ueIdx
112        * has no UE context stored in it, hence searching for preamble index in
113        * this ueCb is not required */
114       if(cellCb->ueCb[ueIdx].crnti)
115       {
116          for(ssbIdx = 0; ssbIdx < cellCb->ueCb[ueIdx].cfraResource.numSsb; ssbIdx++)
117          {
118             if(cellCb->ueCb[ueIdx].cfraResource.ssbResource[ssbIdx].raPreambleIdx == rachIndInfo->preambleIdx)
119             {
120                ueCb = &cellCb->ueCb[ueIdx];
121                break;
122             }
123          }
124          if(ueCb)
125             break;
126       }
127    }
128
129    if(ueCb)
130    {
131       /* If UE context is already present as in case of handover, fetch CRNTI from
132        * UE CB allocated during UE context creation */
133       crnti = ueCb->crnti;
134    }
135    else
136    {
137       /* If UE context not present, assign CRNTI to this UE */
138       ueIdx = getFreeBitFromUeBitMap(rachIndInfo->cellId);
139       if(ueIdx == -1)
140       {
141          DU_LOG("\nERROR  -->  MAC : Failed to find free UE Idx in UE bit map of cell Id [%d]", rachIndInfo->cellId);
142          return RFAILED;
143       }
144
145       /* Calculate CRNTI from UE Index */
146       GET_CRNTI(crnti, ueIdx+1);
147
148       /* Store in raCb */
149       memset(&cellCb->macRaCb[ueIdx], 0, sizeof(MacRaCbInfo));
150       cellCb->macRaCb[ueIdx].cellId = rachIndInfo->cellId;
151       cellCb->macRaCb[ueIdx].crnti  = crnti;
152
153      /* Initialize MSG4 HARQ PROC CB */
154      cellCb->macRaCb[ueIdx].msg4HqInfo.procId = MAX_NUM_HARQ_PROC;
155
156    }
157
158    /* Store in Rach Indication message to be sent to SCH */
159    rachIndInfo->crnti  = crnti;
160    return ROK;
161 }
162
163 /*******************************************************************
164  *
165  * @brief Processes RACH indication from PHY
166  *
167  * @details
168  *
169  *    Function : fapiMacRachInd
170  *
171  *    Functionality:
172  *      Processes RACH indication from PHY
173  *
174  * @params[in] Post structure
175  *             Rach indication message
176  * @return ROK     - success
177  *         RFAILED - failure
178  *
179  * ****************************************************************/ 
180 uint8_t fapiMacRachInd(Pst *pst, RachInd *rachInd)
181 {
182    uint8_t      ret = ROK;
183    uint8_t      pduIdx = 0;
184    uint8_t      preambleIdx = 0;
185    uint16_t     cellIdx = 0;  
186    RachIndInfo  *rachIndInfo = NULLP;
187    MacCellCb    *cellCb = NULLP;
188
189    DU_LOG("\nINFO  -->  MAC : Received RACH indication");
190    /* Considering one pdu and one preamble */
191    pduIdx = 0;
192    preambleIdx = 0;
193
194    /* Validate cell Id */
195    GET_CELL_IDX(rachInd->cellId, cellIdx);
196    if(macCb.macCell[cellIdx] && (macCb.macCell[cellIdx]->cellId == rachInd->cellId))
197          cellCb = macCb.macCell[cellIdx];
198
199    if(!cellCb)
200    {
201       DU_LOG("\nERROR  --> MAC : Invalid Cell ID [%d] received in RACH Indication", rachInd->cellId);
202       return RFAILED;
203    }
204
205    MAC_ALLOC(rachIndInfo, sizeof(RachIndInfo));
206    if(!rachIndInfo)
207    {
208       DU_LOG("\nERROR  --> MAC : Memory allocation failure in fapiMacRachInd");
209       MAC_FREE_SHRABL_BUF(pst->region, pst->pool, rachInd, sizeof(RachInd));
210       return RFAILED;
211    }
212
213    rachIndInfo->cellId = rachInd->cellId;
214    rachIndInfo->timingInfo.sfn = rachInd->timingInfo.sfn;
215    rachIndInfo->timingInfo.slot = rachInd->timingInfo.slot;
216    rachIndInfo->slotIdx = rachInd->rachPdu[pduIdx].slotIdx;
217    rachIndInfo->symbolIdx = rachInd->rachPdu[pduIdx].symbolIdx;
218    rachIndInfo->freqIdx = rachInd->rachPdu[pduIdx].freqIdx;
219    rachIndInfo->preambleIdx = rachInd->rachPdu[pduIdx].preamInfo[preambleIdx].preamIdx;
220    rachIndInfo->timingAdv = rachInd->rachPdu[pduIdx].preamInfo[preambleIdx].timingAdv;
221
222    /* Store the value in macRaCb */
223    if((ret = createMacRaCb(cellCb, rachIndInfo)) == ROK)
224    {
225       /* Send RACH Indication to SCH */
226       ret = sendRachIndMacToSch(rachIndInfo);
227    }
228
229    /* Free sharable buffer used to send RACH Indication from lower MAC to MAC */
230    MAC_FREE_SHRABL_BUF(pst->region, pst->pool, rachInd, sizeof(RachInd));
231
232    return ret;
233 }
234
235 /*******************************************************************
236  *
237  * @brief Processes RACH Resource request from DU APP
238  *
239  * @details
240  *
241  *    Function : MacProcRachRsrcReq
242  *
243  *    Functionality: Processes RACH resource request from DU APP.
244  *      Fills and sends RACH resource request towards SCH.
245  *
246  * @params[in] Post structure
247  *             RACH resource request
248  * @return ROK     - success
249  *         RFAILED - failure
250  *
251  * ****************************************************************/
252 uint8_t MacProcRachRsrcReq(Pst *pst, MacRachRsrcReq *rachRsrcReq)
253 {
254    uint8_t   ret = RFAILED;
255    uint16_t  cellIdx = 0;
256    Pst       schPst;
257    MacCellCb *cellCb = NULLP;
258    MacUeCb   *ueCb = NULLP;
259    SchRachRsrcReq *schRachRsrcReq = NULLP;
260
261    DU_LOG("\nINFO  -->  MAC : Recieved RACH Resource Request for Cell ID [%d] UE ID [%d]",\
262          rachRsrcReq->cellId, rachRsrcReq->ueId);
263
264    /* Fetch Cell Cb */
265    GET_CELL_IDX(rachRsrcReq->cellId, cellIdx);
266    if(macCb.macCell[cellIdx] && (macCb.macCell[cellIdx]->cellId == rachRsrcReq->cellId))
267    {
268       cellCb = macCb.macCell[cellIdx];
269
270       /* Fetch UE Cb */
271       if(cellCb->ueCb[rachRsrcReq->ueId-1].ueId == rachRsrcReq->ueId)
272       {
273          ueCb = &cellCb->ueCb[rachRsrcReq->ueId-1];
274          /* Allocate memory to RACH resource request to be sent to SCH */
275          MAC_ALLOC(schRachRsrcReq, sizeof(SchRachRsrcReq));
276          if(schRachRsrcReq)
277          {
278             /* Fill SCH RACH resource request from information received from DU APP to MAC */
279             schRachRsrcReq->cellId = rachRsrcReq->cellId;
280             schRachRsrcReq->crnti = ueCb->crnti;
281             schRachRsrcReq->numSsb = rachRsrcReq->numSsb;
282             memcpy(schRachRsrcReq->ssbIdx, rachRsrcReq->ssbIdx, sizeof(schRachRsrcReq->ssbIdx));
283
284             /* Send RACH resource request from MAC to SCH */
285             FILL_PST_MAC_TO_SCH(schPst, EVENT_RACH_RESOURCE_REQUEST_TO_SCH);
286             ret = (*macSchRachRsrcReqOpts[schPst.selector])(&schPst, schRachRsrcReq);
287          }
288          else
289             DU_LOG("\nERROR  -->  MAC : Memory allocation failed for RACH resource request to SCH");
290       }
291       else
292          DU_LOG("\nERROR  -->  MAC : UE ID [%d] not found", rachRsrcReq->ueId);
293    }
294    else
295       DU_LOG("\nERROR  -->  MAC : Cell ID [%d] not found", rachRsrcReq->cellId);
296
297    /* Free sharable buffer used to send RACH reource request from DU APP to MAC */
298    MAC_FREE_SHRABL_BUF(pst->region, pst->pool, rachRsrcReq, sizeof(MacRachRsrcReq));
299    return ret;
300 }
301
302 /*******************************************************************
303  *
304  * @brief Processes RACH Resource response from SCH
305  *
306  * @details
307  *
308  *    Function : MacProcSchRachRsrcRsp
309  *
310  *    Functionality: Processes RACH resource response from SCH
311  *      Fills and sends RACH resource response towards DU APP
312  *
313  * @params[in] Post structure
314  *             RACH resource response
315  * @return ROK     - success
316  *         RFAILED - failure
317  *
318  * ****************************************************************/
319 uint8_t MacProcSchRachRsrcRsp(Pst *pst, SchRachRsrcRsp *schRachRsrcRsp)
320 {
321    uint16_t cellIdx = 0;
322    Pst rspPst;
323    MacRachRsrcRsp *rachRsrcRsp = NULLP;
324    MacCellCb *cellCb = NULLP;
325    MacUeCb   *ueCb = NULLP;
326
327    DU_LOG("\nINFO  -->  MAC : Received RACH resource response from SCH : Cell ID [%d] CRNTI [%d]", \
328          schRachRsrcRsp->cellId, schRachRsrcRsp->crnti);
329
330    /* Fill RACH resource response to send to DU APP */
331    MAC_ALLOC_SHRABL_BUF(rachRsrcRsp, sizeof(MacRachRsrcRsp));
332    if(!rachRsrcRsp)
333    {
334       DU_LOG("\nERROR  -->  MAC : Memory allocation failed for RACH resource response");
335       MAC_FREE(schRachRsrcRsp, sizeof(SchRachRsrcRsp));
336       return RFAILED;
337    }
338    rachRsrcRsp->cellId = schRachRsrcRsp->cellId;
339    GET_UE_ID(schRachRsrcRsp->crnti, rachRsrcRsp->ueId);
340    rachRsrcRsp->result = MAC_DU_APP_RSP_OK;
341
342    /* Fill Pst structure to send RACH resource response from MAC to DU APP */
343    FILL_PST_MAC_TO_DUAPP(rspPst, EVENT_MAC_RACH_RESOURCE_RSP);
344
345    /* If negative response is received from SCH, send it further to DU APP */ 
346    if(schRachRsrcRsp->result == RSP_NOK)
347    {
348       DU_LOG("\nINFO  -->  MAC : RACH Resource response from SCH : Result [FAILURE]");
349       rachRsrcRsp->result = MAC_DU_APP_RSP_NOK;
350    }
351    else
352    {
353       DU_LOG("\nINFO  -->  MAC : RACH Resource response from SCH : Result [SUCCESS]");
354       
355       /* Fetch Cell Cb */
356       GET_CELL_IDX(schRachRsrcRsp->cellId, cellIdx);
357       if(macCb.macCell[cellIdx] && (macCb.macCell[cellIdx]->cellId == schRachRsrcRsp->cellId))
358       {   
359          cellCb = macCb.macCell[cellIdx];
360
361          /* Fetch UE Cb */
362          if(cellCb->ueCb[rachRsrcRsp->ueId-1].crnti == schRachRsrcRsp->crnti)
363             ueCb = &cellCb->ueCb[rachRsrcRsp->ueId-1];
364          else
365          {
366             DU_LOG("\nERROR  -->  MAC : CRNTI [%d] not found", schRachRsrcRsp->crnti);
367             rachRsrcRsp->result = MAC_DU_APP_RSP_NOK;
368          }   
369       }   
370       else
371       {   
372          DU_LOG("\nERROR  -->  MAC : Cell ID [%d] not found", schRachRsrcRsp->cellId);
373          rachRsrcRsp->result = MAC_DU_APP_RSP_NOK;
374       }   
375    }
376
377    /* Fill SSB RACH resource info if SCH has sent a positive response and 
378     * processing of SCH RACH resource response at MAC has been successful so far */
379    if(rachRsrcRsp->result == MAC_DU_APP_RSP_OK)
380    {
381       rachRsrcRsp->newCrnti = ueCb->crnti; 
382       rachRsrcRsp->cfraResource.numSsb = schRachRsrcRsp->cfraResource.numSsb;
383       memcpy(rachRsrcRsp->cfraResource.ssbResource, schRachRsrcRsp->cfraResource.ssbResource, \
384          rachRsrcRsp->cfraResource.numSsb * sizeof(MacCfraSsbResource));
385
386       /* Copy resources to UE CB in MAC */
387       memcpy(&ueCb->cfraResource, &rachRsrcRsp->cfraResource, sizeof(MacCfraResource));
388    }
389
390    /* Free SCH RACH resource response */
391    MAC_FREE(schRachRsrcRsp, sizeof(SchRachRsrcRsp));
392
393    /* Send RACH resource response to DU APP */
394    FILL_PST_MAC_TO_DUAPP(rspPst, EVENT_MAC_RACH_RESOURCE_RSP);
395    return (*macDuRachRsrcRspOpts[rspPst.selector])(&rspPst, rachRsrcRsp);
396 }
397
398
399 /*******************************************************************
400  *
401  * @brief Processes RACH Resource release from DU APP
402  *
403  * @details
404  *
405  *    Function : MacProcRachRsrcRel
406  *
407  *    Functionality: Processes RACH resource release from DU APP.
408  *      Fills and sends RACH resource release towards SCH.
409  *
410  * @params[in] Post structure
411  *             RACH resource release
412  * @return ROK     - success
413  *         RFAILED - failure
414  *
415  * ****************************************************************/
416 uint8_t MacProcRachRsrcRel(Pst *pst, MacRachRsrcRel *rachRsrcRel)
417 {
418    uint8_t   ret = RFAILED;
419    uint16_t  cellIdx = 0;
420    Pst       schPst;
421    MacCellCb *cellCb = NULLP;
422    MacUeCb   *ueCb = NULLP;
423    SchRachRsrcRel *schRachRsrcRel = NULLP;
424
425    DU_LOG("\nINFO  -->  MAC : Recieved RACH Resource Release for Cell ID [%d] UE ID [%d]",\
426          rachRsrcRel->cellId, rachRsrcRel->ueId);
427
428    /* Fetch Cell Cb */
429    GET_CELL_IDX(rachRsrcRel->cellId, cellIdx);
430    if(macCb.macCell[cellIdx] && (macCb.macCell[cellIdx]->cellId == rachRsrcRel->cellId))
431    {
432       cellCb = macCb.macCell[cellIdx];
433
434       /* Fetch UE Cb */
435       if(cellCb->ueCb[rachRsrcRel->ueId-1].ueId == rachRsrcRel->ueId)
436       {
437          ueCb = &cellCb->ueCb[rachRsrcRel->ueId-1];
438          /* Allocate memory to RACH resource release to be sent to SCH */
439          MAC_ALLOC(schRachRsrcRel, sizeof(SchRachRsrcRel));
440          if(schRachRsrcRel)
441          {
442             /* Fill SCH RACH resource release from information received from DU APP to MAC */
443             memset(schRachRsrcRel, 0, sizeof(SchRachRsrcRel));
444             schRachRsrcRel->cellId = rachRsrcRel->cellId;
445             schRachRsrcRel->crnti = ueCb->crnti;
446             memcpy(&schRachRsrcRel->cfraResource, &ueCb->cfraResource, sizeof(schRachRsrcRel->cfraResource));
447             
448             /* Release RACH resources at MAC */
449             memset(&ueCb->cfraResource, 0, sizeof(MacCfraResource));
450
451             /* Send RACH resource release from MAC to SCH */
452             FILL_PST_MAC_TO_SCH(schPst, EVENT_RACH_RESOURCE_RELEASE_TO_SCH);
453             ret = (*macSchRachRsrcRelOpts[schPst.selector])(&schPst, schRachRsrcRel);
454          }
455          else
456             DU_LOG("\nERROR  -->  MAC : Memory allocation failed for RACH resource release to SCH");
457       }
458       else
459          DU_LOG("\nERROR  -->  MAC : UE ID [%d] not found", rachRsrcRel->ueId);
460    }
461    else
462       DU_LOG("\nERROR  -->  MAC : Cell ID [%d] not found", rachRsrcRel->cellId);
463
464    /* Free sharable buffer used to send RACH reource release from DU APP to MAC */
465    MAC_FREE_SHRABL_BUF(pst->region, pst->pool, rachRsrcRel, sizeof(MacRachRsrcRel));
466    return ret;
467 }
468
469 /* spec-38.211 Table 6.3.3.1-7 */
470 uint8_t UnrestrictedSetNcsTable[MAX_ZERO_CORR_CFG_IDX] = 
471 {0, 2, 4, 6, 8, 10, 12, 13, 15, 17, 19, 23, 27, 34, 46, 69};
472
473 /*******************************************************************
474  *
475  * @brief Processes UL scheduling info from SCH
476  *
477  * @details
478  *
479  *    Function : MacProcUlSchInfo
480  *
481  *    Functionality: Processes UL scheduling info from SCH
482  *
483  * @params[in] Post structure
484  *             UL scheduling info
485  * @return ROK     - success
486  *         RFAILED - failure
487  *
488  * ****************************************************************/
489 uint8_t MacProcUlSchInfo(Pst *pst, UlSchedInfo *ulSchedInfo)
490 {
491    uint16_t  cellIdx;
492
493 #ifdef CALL_FLOW_DEBUG_LOG
494    DU_LOG("\nCall Flow: ENTSCH -> ENTMAC : EVENT_UL_SCH_INFO\n");
495 #endif
496
497    GET_CELL_IDX(ulSchedInfo->cellId, cellIdx);
498    if(ulSchedInfo != NULLP)
499    {
500       MacUlSlot *currUlSlot = 
501          &macCb.macCell[cellIdx]->ulSlot[ulSchedInfo->slotIndInfo.slot % MAX_SLOTS];
502       memcpy(&currUlSlot->ulInfo, ulSchedInfo, sizeof(UlSchedInfo)); 
503    }
504    return ROK;
505 }
506
507 /**********************************************************************
508   End of file
509  **********************************************************************/
510