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 contains message handling functionality for DU APP */
20 #include "common_def.h"
26 #include "du_app_mac_inf.h"
30 #include "du_f1ap_msg_hdl.h"
31 #include "du_ue_mgr.h"
34 #include "lphy_stub.h"
44 extern DuCfgParams duCfgParam;
45 extern S16 cmPkLkwCfgReq(Pst *pst, KwMngmt *cfg);
46 extern S16 cmPkLkwCntrlReq(Pst *pst, KwMngmt *cfg);
47 extern S16 cmPkLrgCfgReq(Pst *pst, RgMngmt *cfg);
48 extern S16 BuildAndSendE2SetupReq();
49 extern S16 egtpHdlDatInd(EgtpMsg egtpMsg);
50 extern uint8_t BuildAndSendDUConfigUpdate();
51 extern U16 getTransId();
52 extern S16 cmPkLrgSchCfgReq(Pst * pst,RgMngmt * cfg);
54 packMacCellCfgReq packMacCellCfgOpts[] =
56 packMacCellCfg, /* packing for loosely coupled */
57 MacProcCellCfgReq, /* packing for tightly coupled */
58 packMacCellCfg, /* packing for light weight loosly coupled */
61 DuMacCellStartReq packMacCellStartReqOpts[] =
63 packMacCellStartReq, /* Loose coupling */
64 MacProcCellStartReq, /* TIght coupling */
65 packMacCellStartReq /* Light weight-loose coupling */
68 DuMacCellStopReq packMacCellStopReqOpts[] =
70 packMacCellStopReq, /* Loose coupling */
71 MacProcCellStopReq, /* TIght coupling */
72 packMacCellStopReq /* Light weight-loose coupling */
75 /**************************************************************************
76 * @brief Function to fill configs required by RLC
80 * Function : duBuildRlcCfg
83 * Initiates general Configs towards RLC
85 * @param[in] Inst Specifies if RLC UL or RLC DL instance
86 * @return ROK - success
89 ***************************************************************************/
90 S16 duBuildRlcCfg(Inst inst)
93 KwGenCfg *genCfg = NULLP;
96 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
97 DU_SET_ZERO(&pst, sizeof(Pst));
99 genCfg = &(kwMngmt.t.cfg.s.gen);
101 /*----------- Fill General Configuration Parameters ---------*/
102 genCfg->maxUe = duCfgParam.maxUe;
103 genCfg->maxKwuSaps = 2;
104 genCfg->maxUdxSaps = 1;
105 genCfg->rlcMode = (inst == RLC_UL_INST) ?
106 LKW_RLC_MODE_UL : LKW_RLC_MODE_DL;
108 genCfg->maxRguSaps = DEFAULT_CELLS;
110 /*----------- Fill lmPst
111 * Parameters ---------*/
112 genCfg->lmPst.dstProcId = DU_PROC;
113 genCfg->lmPst.srcProcId = DU_PROC;
114 genCfg->lmPst.dstEnt = ENTDUAPP;
115 genCfg->lmPst.dstInst = DU_INST;
116 genCfg->lmPst.srcEnt = ENTKW;
117 genCfg->lmPst.srcInst = inst;
118 genCfg->lmPst.prior = PRIOR0;
119 genCfg->lmPst.route = RTESPEC;
120 genCfg->lmPst.region = (inst == RLC_UL_INST) ?
121 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
122 genCfg->lmPst.pool = RLC_POOL;
123 genCfg->lmPst.selector = ODU_SELECTOR_LC;
126 kwMngmt.hdr.msgType = TCFG;
127 kwMngmt.hdr.msgLen = 0;
128 kwMngmt.hdr.entId.ent = ENTKW;
129 kwMngmt.hdr.entId.inst = (Inst)0;
130 kwMngmt.hdr.elmId.elmnt = STGEN;
131 kwMngmt.hdr.seqNmb = 0;
132 kwMngmt.hdr.version = 0;
133 kwMngmt.hdr.transId = 0;
134 kwMngmt.hdr.response.prior = PRIOR0;
135 kwMngmt.hdr.response.route = RTESPEC;
136 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
137 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
138 kwMngmt.hdr.response.mem.pool = DU_POOL;
139 kwMngmt.hdr.response.selector = ODU_SELECTOR_LC;
142 pst.selector = ODU_SELECTOR_LC;
143 pst.srcEnt = ENTDUAPP;
146 pst.dstProcId = DU_PROC;
147 pst.srcProcId = DU_PROC;
148 pst.region = duCb.init.region;
150 DU_LOG("\nDU_APP : RLC Gen Cfg Req sent for inst %d", inst);
152 /* Send the request to RLC */
153 cmPkLkwCfgReq(&pst, &kwMngmt);
158 /**************************************************************************
159 * @brief Function to fill configs required by RLC
163 * Function : duBuildRlcLsapCfg
166 * Initiates general Configs towards RLC
168 * @param[in] Inst Specifies if RLC UL or RLC DL instance
169 * @return ROK - success
172 ***************************************************************************/
173 S16 duBuildRlcLsapCfg(Ent ent, Inst inst, U8 lsapInst)
177 KwSapCfg *lSap = NULLP;
180 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
181 DU_SET_ZERO(&pst, sizeof(Pst));
184 kwMngmt.hdr.msgType = TCFG;
185 kwMngmt.hdr.entId.ent = ENTKW;
186 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
187 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
189 kwMngmt.hdr.response.mem.pool = RLC_POOL;
192 pst.selector = ODU_SELECTOR_LC;
193 pst.srcEnt = ENTDUAPP;
195 pst.dstProcId = DU_PROC;
197 pst.srcProcId = DU_PROC;
198 pst.region = duCb.init.region;
199 lSap = &(kwMngmt.t.cfg.s.sap);
201 lSap->mem.region = (inst == RLC_UL_INST) ?
202 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
203 lSap->mem.pool = RLC_POOL;
205 lSap->bndTmrIntvl = 10;
206 lSap->priority = PRIOR0;
207 lSap->route = RTESPEC;
210 lSap->procId = DU_PROC;
212 lSap->inst = lsapInst;
213 lSap->sapId = lsapInst; /* SapId will be stored as suId in MAC */
214 lSap->selector = (inst == RLC_UL_INST) ? ODU_SELECTOR_LWLC : ODU_SELECTOR_TC;
215 kwMngmt.hdr.elmId.elmnt = STRGUSAP;
216 DU_LOG("\nDU_APP : RLC MAC Lower Sap Cfg Req sent for inst %d", inst);
221 lSap->procId = DU_PROC;
223 lSap->inst = (inst == RLC_UL_INST) ?
224 RLC_DL_INST : RLC_UL_INST;
226 lSap->selector = ODU_SELECTOR_LC;
227 kwMngmt.hdr.elmId.elmnt = STUDXSAP;
228 DU_LOG("\nDU_APP : RLC DL/UL Lower Sap Cfg Req sent for inst %d", inst);
231 cmPkLkwCfgReq(&pst, &kwMngmt);
235 /**************************************************************************
236 * @brief Function to fill configs required by RLC
240 * Function : duBuildRlcUsapCfg
243 * Initiates general Configs towards RLC
245 * @param[in] Inst Specifies if RLC UL or RLC DL instance
246 * @return ROK - success
249 ***************************************************************************/
250 S16 duBuildRlcUsapCfg(U8 elemId, Ent ent, Inst inst)
253 KwSapCfg *uSap = NULLP;
256 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
257 DU_SET_ZERO(&pst, sizeof(Pst));
259 uSap = &(kwMngmt.t.cfg.s.sap);
261 uSap->selector = ODU_SELECTOR_LC;
262 uSap->mem.region = (inst == RLC_UL_INST) ?
263 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
264 uSap->mem.pool = RLC_POOL;
267 uSap->procId = DU_PROC;
271 uSap->inst = (inst == RLC_UL_INST) ?
272 RLC_DL_INST : RLC_UL_INST;
273 uSap->bndTmrIntvl = 1000;
274 uSap->priority = PRIOR0;
275 uSap->route = RTESPEC;
278 kwMngmt.hdr.msgType = TCFG;
279 kwMngmt.hdr.entId.ent = ENTKW;
280 kwMngmt.hdr.elmId.elmnt = STUDXSAP;
281 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
282 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
284 kwMngmt.hdr.response.mem.pool = RLC_POOL;
287 pst.selector = ODU_SELECTOR_LC;
288 pst.srcEnt = ENTDUAPP;
290 pst.dstProcId = DU_PROC;
292 pst.srcProcId = DU_PROC;
293 pst.region = duCb.init.region;
295 DU_LOG("\nDU_APP : RLC Kwu Upper Sap Cfg Req sent for inst %d", inst);
296 cmPkLkwCfgReq(&pst, &kwMngmt);
301 /**************************************************************************
302 * @brief Function to populate internal DS of DU APP
306 * Function : duProcCfgComplete
309 * Populates internal data structures of DU APP after
310 * receiving configurations.
313 * @return ROK - success
316 ***************************************************************************/
317 S16 duProcCfgComplete()
320 static U16 cellId = 0;
322 for(idx=0; idx< DEFAULT_CELLS; idx++)
324 DuCellCb *cell = NULLP;
325 DU_ALLOC(cell, sizeof(DuCellCb))
328 DU_LOG("\nDU_APP : Memory Allocation failed in duProcCfgComplete");
335 memset(cell, 0, sizeof(DuCellCb));
336 cell->cellId = ++cellId;
337 cell->cellInfo.nrEcgi.plmn.mcc[0] = PLMN_MCC0;
338 cell->cellInfo.nrEcgi.plmn.mcc[1] = PLMN_MCC1;
339 cell->cellInfo.nrEcgi.plmn.mcc[2] = PLMN_MCC2;
340 cell->cellInfo.nrEcgi.plmn.mnc[0] = PLMN_MNC0;
341 cell->cellInfo.nrEcgi.plmn.mnc[1] = PLMN_MNC1;
342 cell->cellInfo.nrEcgi.plmn.mnc[2] = PLMN_MNC2;
343 cell->cellInfo.nrEcgi.cellId = NR_CELL_ID;
344 cell->cellInfo.nrPci = NR_PCI;
345 cell->cellInfo.fiveGsTac = DU_TAC;
346 for(idx1=0; idx1<MAX_PLMN; idx1++)
348 cell->cellInfo.plmn[idx1].mcc[0] = PLMN_MCC0;
349 cell->cellInfo.plmn[idx1].mcc[1] = PLMN_MCC1;
350 cell->cellInfo.plmn[idx1].mcc[2] = PLMN_MCC2;
351 cell->cellInfo.plmn[idx1].mnc[0] = PLMN_MNC0;
352 cell->cellInfo.plmn[idx1].mnc[1] = PLMN_MNC1;
353 cell->cellInfo.plmn[idx1].mnc[2] = PLMN_MNC2;
355 cell->cellInfo.maxUe = duCfgParam.maxUe;
356 cell->cellStatus = CELL_OUT_OF_SERVICE;
357 nci = (U16)cell->cellInfo.nrEcgi.cellId;
359 duCb.cfgCellLst[nci-1] = cell;
365 //Start layer configs
366 ret = duSendRlcUlCfg();
370 /**************************************************************************
371 * @brief Function to invoke DU Layer Configs
375 * Function : duSendRlcUlCfg
378 * Initiates Configs towards layers of DU
381 * @return ROK - success
384 ***************************************************************************/
389 duBuildRlcCfg((Inst)RLC_UL_INST);
390 for(cellIdx = 0; cellIdx < DEFAULT_CELLS; cellIdx++)
392 duBuildRlcLsapCfg(ENTRG, (Inst)RLC_UL_INST, cellIdx);
394 duBuildRlcLsapCfg(ENTKW, (Inst)RLC_UL_INST, 0);
399 /**************************************************************************
400 * @brief Function to invoke DU Layer Configs
404 * Function : duSendRlcDlCfg
407 * Initiates Configs towards layers of DU
410 * @return ROK - success
413 ***************************************************************************/
418 duBuildRlcCfg((Inst)RLC_DL_INST);
419 duBuildRlcUsapCfg(STUDXSAP, ENTKW, (Inst)RLC_DL_INST);
420 for(cellIdx = 0; cellIdx < DEFAULT_CELLS; cellIdx++)
422 duBuildRlcLsapCfg(ENTRG, (Inst)RLC_DL_INST, cellIdx);
427 /**************************************************************************
428 * @brief Function to handle Config Confirm from RLC
432 * Function : duHdlRlcCfgComplete
435 * Handles Gen Config Confirm from RLC
437 * @param[in] Pst *pst, Post structure of the primitive.
438 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC
439 * @return ROK - success
442 ***************************************************************************/
443 S16 duHdlRlcCfgComplete(Pst *pst, KwMngmt *cfm)
446 if (pst->srcInst == RLC_UL_INST)
448 ret = duProcRlcUlCfgComplete(pst, cfm);
452 ret = duProcRlcDlCfgComplete(pst, cfm);
457 /**************************************************************************
458 * @brief Function to handle Control Config Confirm from RLC
462 * Function : duHdlRlcCntrlCfgComplete
465 * Handles Control Config Confirm from RLC
467 * @param[in] Pst *pst, Post structure of the primitive.
468 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC
469 * @return ROK - success
472 ***************************************************************************/
473 S16 duHdlRlcCntrlCfgComplete(Pst *pst, KwMngmt *cntrl)
477 if (cntrl->cfm.status == LCM_PRIM_OK)
479 switch (cntrl->hdr.elmId.elmnt)
483 if (pst->srcInst == RLC_DL_INST)
485 DU_LOG("\nDU_APP : BIND OF RLC DL TO MAC (RGU) SAP SUCCESSFUL");
487 if(macCfgInst < DEFAULT_CELLS)
490 duBindUnbindRlcToMacSap((Inst) RLC_DL_INST, ABND);
494 duBindUnbindRlcToMacSap((Inst) RLC_UL_INST, ABND);
499 DU_LOG("\nDU_APP : BIND OF RLC UL TO MAC (RGU) SAP SUCCESSFUL");
501 if(macCfgInst < DEFAULT_CELLS)
503 duBindUnbindRlcToMacSap((Inst) RLC_UL_INST, ABND);
517 /**************************************************************************
518 * @brief Function to handle Config Confirm from RLC UL
522 * Function : duHdlRlcUlCfgComplete
525 * Handles Config Confirm from RLC UL
527 * @param[in] Pst *pst, Post structure of the primitive.
528 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC UL
529 * @return ROK - success
532 ***************************************************************************/
533 S16 duProcRlcUlCfgComplete(Pst *pst, KwMngmt *cfm)
537 DU_LOG("\nDU_APP : RLC UL Cfg Status %d", cfm->cfm.status);
538 if (cfm->cfm.status == LCM_PRIM_OK)
540 switch(cfm->hdr.elmId.elmnt)
544 rlcUlCfg |= RLC_GEN_CFG;
550 if(numRlcMacSaps == DEFAULT_CELLS)
552 rlcUlCfg |= RLC_MAC_SAP_CFG;
559 rlcUlCfg |= RLC_UDX_SAP_CFG;
566 DU_LOG("\nDU_APP : RLC UL Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
567 if(rlcUlCfg == DU_RLC_UL_CONFIGURED)
571 //Start configuration of RLC DL
578 DU_LOG("\nDU_APP : Config confirm NOK from RLC UL");
584 /**************************************************************************
585 * @brief Function to handle Config Confirm from RLC DL
589 * Function : duHdlRlcDlCfgComplete
592 * Handles Config Confirm from RLC DL
594 * @param[in] Pst *pst, Post structure of the primitive.
595 * @param[in] KwMngmt *cfm, Unpacked primitive info received from RLC DL
596 * @return ROK - success
599 ***************************************************************************/
600 S16 duProcRlcDlCfgComplete(Pst *pst, KwMngmt *cfm)
602 DU_LOG("\nDU_APP : RLC DL Cfg Status %d", cfm->cfm.status);
603 if (cfm->cfm.status == LCM_PRIM_OK)
605 switch(cfm->hdr.elmId.elmnt)
609 rlcDlCfg |= RLC_GEN_CFG;
615 if(numRlcMacSaps == DEFAULT_CELLS)
617 rlcDlCfg |= RLC_MAC_SAP_CFG;
624 rlcDlCfg |= RLC_UDX_SAP_CFG;
632 DU_LOG("\nDU_APP : RLC DL Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
633 if(rlcDlCfg == DU_RLC_DL_CONFIGURED)
636 //Start configuration of MAC
643 DU_LOG("\nDU_APP : Config confirm NOK from RLC DL");
648 /**************************************************************************
649 * @brief Function to send configs to MAC
653 * Function : duSendMacCfg
656 * Initiates Configs towards MAC layer
659 * @return ROK - success
662 ***************************************************************************/
666 duBuildMacUsapCfg(RLC_UL_INST);
667 duBuildMacUsapCfg(RLC_DL_INST);
672 /**************************************************************************
673 * @brief Function to fill gen config required by MAC
677 * Function : duBuildMacGenCfg
680 * Initiates general Configs towards MAC
683 * @return ROK - success
686 ***************************************************************************/
687 S16 duBuildMacGenCfg()
690 RgGenCfg *genCfg=NULLP;
693 DU_SET_ZERO(&pst, sizeof(Pst));
694 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
696 genCfg = &(rgMngmt.t.cfg.s.genCfg);
698 /*----------- Fill General Configuration Parameters ---------*/
699 genCfg->mem.region = MAC_MEM_REGION;
700 genCfg->mem.pool = MAC_POOL;
702 genCfg->numRguSaps = 2;
704 genCfg->lmPst.dstProcId = DU_PROC;
705 genCfg->lmPst.srcProcId = DU_PROC;
706 genCfg->lmPst.dstEnt = ENTDUAPP;
707 genCfg->lmPst.dstInst = 0;
708 genCfg->lmPst.srcEnt = ENTRG;
709 genCfg->lmPst.srcInst = macCfgInst;
710 genCfg->lmPst.prior = PRIOR0;
711 genCfg->lmPst.route = RTESPEC;
712 genCfg->lmPst.region = MAC_MEM_REGION;
713 genCfg->lmPst.pool = MAC_POOL;
714 genCfg->lmPst.selector = ODU_SELECTOR_LC;
717 rgMngmt.hdr.msgType = TCFG;
718 rgMngmt.hdr.msgLen = 0;
719 rgMngmt.hdr.entId.ent = ENTRG;
720 rgMngmt.hdr.entId.inst = (Inst)0;
721 rgMngmt.hdr.elmId.elmnt = STGEN;
722 rgMngmt.hdr.seqNmb = 0;
723 rgMngmt.hdr.version = 0;
724 rgMngmt.hdr.transId = 0;
726 rgMngmt.hdr.response.prior = PRIOR0;
727 rgMngmt.hdr.response.route = RTESPEC;
728 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
729 rgMngmt.hdr.response.mem.pool = MAC_POOL;
730 rgMngmt.hdr.response.selector = ODU_SELECTOR_LC;
733 pst.selector = ODU_SELECTOR_LC;
734 pst.srcEnt = ENTDUAPP;
736 pst.dstInst = macCfgInst;
737 pst.dstProcId = DU_PROC;
738 pst.srcProcId = DU_PROC;
739 pst.region = duCb.init.region;
741 DU_LOG("\nDU_APP : MAC Gen Cfg Req sent");
743 /* Send the request to MAC */
744 cmPkLrgCfgReq(&pst, &rgMngmt);
749 /**************************************************************************
750 * @brief Function to fill USAP config required by MAC
754 * Function : duBuildMacUsapCfg
757 * Initiates USAP Configs towards MAC
759 * @param[in] SpId Specifies if RLC UL or RLC DL instance
760 * @return ROK - success
763 ***************************************************************************/
764 S16 duBuildMacUsapCfg(SpId sapId)
767 RgUpSapCfg *uSap = NULLP;
770 DU_SET_ZERO(&pst, sizeof(Pst));
771 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
773 uSap = &(rgMngmt.t.cfg.s.rguSap);
775 uSap->mem.region = MAC_MEM_REGION;
776 uSap->mem.pool = MAC_POOL;
779 uSap->procId = DU_PROC;
782 uSap->prior = PRIOR0;
783 uSap->route = RTESPEC;
784 uSap->selector = ODU_SELECTOR_LC ;
787 rgMngmt.hdr.msgType = TCFG;
788 rgMngmt.hdr.entId.ent = ENTRG;
789 rgMngmt.hdr.entId.inst = (Inst)0;
790 rgMngmt.hdr.elmId.elmnt = STRGUSAP;
791 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
792 rgMngmt.hdr.response.mem.pool = MAC_POOL;
795 pst.selector = ODU_SELECTOR_LC;
796 pst.srcEnt = ENTDUAPP;
798 pst.dstInst = macCfgInst;
799 pst.dstProcId = DU_PROC;
800 pst.srcProcId = DU_PROC;
801 pst.region = duCb.init.region;
803 DU_LOG("\nDU_APP : MAC Rgu USap Cfg Req sent");
805 /* Send the request to MAC */
806 cmPkLrgCfgReq(&pst, &rgMngmt);
811 /**************************************************************************
812 * @brief Function to handle Config Confirm from MAC
816 * Function : duHdlMacCfgComplete
819 * Handles Gen Config Confirm from MAC
821 * @param[in] Pst *pst, Post structure of the primitive.
822 * @param[in] RgMngmt *cfm, Unpacked primitive info received from MAC
823 * @return ROK - success
826 ***************************************************************************/
827 S16 duHdlMacCfgComplete(Pst *pst, RgMngmt *cfm)
831 if (cfm->cfm.status == LCM_PRIM_OK)
833 switch (cfm->hdr.elmId.elmnt)
837 macCfg |= MAC_GEN_CFG;
842 macCfg |= MAC_SAP_CFG;
849 DU_LOG("\nDU_APP : MAC Cfg Cfm received for the element %d ",cfm->hdr.elmId.elmnt);
850 if(macCfg == MAC_CONFIGURED && numRlcMacSaps == MAX_MAC_SAP)
853 DU_LOG("\nDU_APP : Completed sending Configs");
855 duBindUnbindRlcToMacSap(RLC_DL_INST, ABND);
861 DU_LOG("\nDU_APP : Config confirm NOK from MAC");
867 /**************************************************************************
868 * @brief Function to bind/unbind RLC to MAC SAP
872 * Function : duBindUnbindRlcToMacSap
875 * Initiates Bind/Unbind from RLC to MAC
877 * @param[in] Inst Specifies if RLC UL or RLC DL instance
878 * @param[in] action Specifies if action is bind or unbind
879 * @return ROK - success
882 ***************************************************************************/
883 S16 duBindUnbindRlcToMacSap(U8 inst, U8 action)
885 KwCntrl *cntrl = NULLP;
889 TRC2(smBindKwToRguSap)
891 DU_SET_ZERO(&kwMngmt, sizeof(KwMngmt));
892 DU_SET_ZERO(&pst, sizeof(Pst));
896 DU_LOG("\nDU_APP : Cntrl Req to RLC inst %d to bind MAC sap", inst);
900 DU_LOG("\nDU_APP : Cntrl Req to RLC inst %d to unbind MAC sap", inst);
902 cntrl = &(kwMngmt.t.cntrl);
904 cntrl->action = action;
905 cntrl->subAction = DU_ZERO_VAL;
906 cntrl->s.sapCntrl.suId = macCfgInst;
907 cntrl->s.sapCntrl.spId = inst;
910 kwMngmt.hdr.msgType = TCNTRL;
911 kwMngmt.hdr.entId.ent = ENTKW;
912 kwMngmt.hdr.entId.inst = inst;
913 kwMngmt.hdr.elmId.elmnt = 186; /* ambiguous defines in lkw.h and lrg.h so direct hardcoded*/
914 kwMngmt.hdr.response.mem.region = (inst == RLC_UL_INST) ?
915 RLC_UL_MEM_REGION:RLC_DL_MEM_REGION;
916 kwMngmt.hdr.response.mem.pool = RLC_POOL;
919 pst.selector = ODU_SELECTOR_LC;
920 pst.srcEnt = ENTDUAPP;
922 pst.dstProcId = DU_PROC;
924 pst.srcProcId = DU_PROC;
925 pst.region = duCb.init.region;
927 cmPkLkwCntrlReq(&pst, &kwMngmt);
931 /*******************************************************************
933 * @brief Handles SCTP notifications
937 * Function : duSctpNtfyHdl
940 * Handles SCTP notification
942 * @params[in] Message Buffer
945 * @return ROK - success
948 * ****************************************************************/
950 S16 duSctpNtfyHdl(Buffer *mBuf, CmInetSctpNotification *ntfy)
952 if(f1Params.assocId == ntfy->u.assocChange.assocId)
954 if(BuildAndSendF1SetupReq() != ROK)
959 else if(ricParams.assocId == ntfy->u.assocChange.assocId)
961 if(BuildAndSendE2SetupReq() != ROK)
968 DU_LOG("\nDU_APP : Invalid assocId %d received", ntfy->u.assocChange.assocId);
974 /*******************************************************************
976 * @brief Fills Pst struct for ENTEGTP
980 * Function : duFillEgtpPst
983 * Fills Pst struct for ENTEGTP
986 * @return ROK - success
989 * ****************************************************************/
990 S16 duFillEgtpPst(Pst *pst, Event event)
992 cmMemset((U8 *)pst, 0, sizeof(Pst));
993 pst->srcEnt = (Ent)ENTDUAPP;
994 pst->srcInst = (Inst)DU_INST;
995 pst->srcProcId = DU_PROC;
996 pst->dstEnt = (Ent)ENTEGTP;
997 pst->dstInst = (Inst)EGTP_INST;
998 pst->dstProcId = pst->srcProcId;
1000 pst->selector = ODU_SELECTOR_LC;
1007 /*******************************************************************
1009 * @brief Function to configure EGTP
1013 * Function : duBuildEgtpCfgReq
1016 * Function to configure EGTP
1019 * @return ROK - success
1022 * ****************************************************************/
1024 S16 duBuildEgtpCfgReq()
1029 DU_LOG("\nDU_APP : Sending EGTP config request");
1031 cmMemset((U8 *)&egtpCfg, 0, sizeof(EgtpConfig));
1032 cmMemcpy((U8 *)&egtpCfg, (U8 *)&duCfgParam.egtpParams, (PTR)sizeof(EgtpConfig));
1034 duFillEgtpPst(&pst, EVTCFGREQ);
1035 packEgtpCfgReq(&pst, egtpCfg);
1040 /*******************************************************************
1042 * @brief Function to configure EGTP
1046 * Function : duBuildEgtpCfgReq
1049 * Function to configure EGTP
1052 * @return ROK - success
1055 * ****************************************************************/
1056 S16 duHdlEgtpCfgComplete(CmStatus cfm)
1060 if(cfm.status == LCM_PRIM_OK)
1062 DU_LOG("\nDU_APP : EGTP configuraton complete");
1064 duSendEgtpSrvOpenReq();
1069 DU_LOG("\nDU_APP : EGTP configuraton failed");
1076 /*******************************************************************
1078 * @brief Sends server open request to EGTP
1082 * Function : duSendEgtpSrvOpenReq
1085 * Sends server open request to EGTP
1088 * @return ROK - success
1091 * ****************************************************************/
1093 S16 duSendEgtpSrvOpenReq()
1097 DU_LOG("\nDU_APP : Sending EGTP server open request");
1099 duFillEgtpPst(&pst, EVTSRVOPENREQ);
1100 packEgtpSrvOpenReq(&pst);
1105 /*******************************************************************
1107 * @brief Handles server open confirmation
1111 * Function : duHdlEgtpSrvOpenComplete
1114 * Handles server open confirmation
1117 * @return ROK - success
1120 *****************************************************************/
1122 S16 duHdlEgtpSrvOpenComplete(CmStatus cfm)
1126 if(cfm.status == LCM_PRIM_OK)
1128 DU_LOG("\nDU_APP : EGTP server opened successfully");
1130 duSendEgtpTnlMgmtReq(EGTP_TNL_MGMT_ADD, EGTP_LCL_TEID, EGTP_REM_TEID);
1135 DU_LOG("\nDU_APP : EGTP server opening failed");
1142 /*******************************************************************
1144 * @brief Sends tunnel management request
1148 * Function : duSendEgtpTnlMgmtReq
1151 * Builds and sends tunnel management request to EGTP
1153 * @params[in] Action
1154 * Local tunnel endpoint id
1155 * Remote tunnel endpoint id
1156 * @return ROK - success
1159 * ****************************************************************/
1161 S16 duSendEgtpTnlMgmtReq(U8 action, U32 lclTeid, U32 remTeid)
1166 tnlEvt.action = action;
1167 tnlEvt.lclTeid = lclTeid;
1168 tnlEvt.remTeid = remTeid;
1170 DU_LOG("\nDU_APP : Sending EGTP tunnel management request");
1172 duFillEgtpPst(&pst, EVTTNLMGMTREQ);
1173 packEgtpTnlMgmtReq(&pst, tnlEvt);
1178 /*******************************************************************
1180 * @brief Handles Tunnel management confirm
1184 * Function : duHdlEgtpTnlMgmtCfm
1187 * Handles tunnel management confirm received from Egtp
1189 * @params[in] Tunnel Event
1190 * @return ROK - success
1193 * ****************************************************************/
1194 S16 duHdlEgtpTnlMgmtCfm(EgtpTnlEvt tnlEvtCfm)
1198 if(tnlEvtCfm.cfmStatus.status == LCM_PRIM_OK)
1200 DU_LOG("\nDU_APP : Tunnel management confirm OK");
1203 duSendUeCreateReqToRlc();
1205 duSendEgtpTestData();
1210 DU_LOG("\nDU_APP : Tunnel management failed");
1217 S16 duSendEgtpDatInd(Buffer *mBuf)
1221 /* Fill EGTP header */
1222 egtpMsg.msgHdr.msgType = EGTPU_MSG_GPDU;
1223 egtpMsg.msgHdr.nPdu.pres = FALSE;
1224 egtpMsg.msgHdr.seqNum.pres = FALSE;
1225 egtpMsg.msgHdr.extHdr.udpPort.pres = FALSE;
1226 egtpMsg.msgHdr.extHdr.pdcpNmb.pres = FALSE;
1227 egtpMsg.msgHdr.teId = 1;
1230 egtpHdlDatInd(egtpMsg);
1237 /*******************************************************************
1239 * @brief Simulate UL Data for intial test
1243 * Function : duSendEgtpTestData
1246 * Simulate UL data for initial test
1249 * @return ROK - success
1252 * ****************************************************************/
1253 S16 duSendEgtpTestData()
1255 char data[30] = "This is EGTP data from DU";
1260 if(SGetMsg(DU_APP_MEM_REGION, DU_POOL, &mBuf) == ROK)
1262 if(SAddPstMsgMult((Data *)data, datSize, mBuf) != ROK)
1264 DU_LOG("\nDU_APP : SAddPstMsgMult failed");
1271 DU_LOG("\nDU_APP : Failed to allocate memory");
1275 /* filling IPv4 header */
1280 SFndLenMsg(mBuf, &mLen);
1282 cmMemset((U8 *)&ipv4Hdr, 0, sizeof(CmIpv4Hdr));
1283 ipv4Hdr.length = CM_IPV4_HDRLEN + mLen;
1284 ipv4Hdr.hdrVer = 0x45;
1286 ipv4Hdr.srcAddr = CM_INET_NTOH_U32(duCfgParam.egtpParams.localIp.ipV4Addr);
1287 ipv4Hdr.destAddr = CM_INET_NTOH_U32(duCfgParam.egtpParams.destIp.ipV4Addr);
1289 /* Packing IPv4 header into buffer */
1291 Data revPkArray[CM_IPV4_HDRLEN];
1292 Data pkArray[CM_IPV4_HDRLEN];
1294 /* initialize locals */
1296 cmMemset(revPkArray, 0, CM_IPV4_HDRLEN);
1297 cmMemset(pkArray, 0, CM_IPV4_HDRLEN);
1299 /* Pack Header Version */
1300 pkArray[cnt++] = ipv4Hdr.hdrVer;
1303 pkArray[cnt++] = ipv4Hdr.tos;
1305 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.length);
1306 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.length);
1309 pkArray[cnt++] = (Data) GetHiByte(ipv4Hdr.id);
1310 pkArray[cnt++] = (Data) GetLoByte(ipv4Hdr.id);
1313 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.off);
1314 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.off);
1317 pkArray[cnt++] = ipv4Hdr.ttl;
1320 pkArray[cnt++] = ipv4Hdr.proto;
1323 pkArray[cnt++] = (Data)GetHiByte(ipv4Hdr.chkSum);
1324 pkArray[cnt++] = (Data)GetLoByte(ipv4Hdr.chkSum);
1326 /* Pack Source Address */
1327 pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.srcAddr));
1328 pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.srcAddr));
1329 pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.srcAddr));
1330 pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.srcAddr));
1332 /* Pack Destination Address */
1333 pkArray[cnt++] = (Data)GetHiByte(GetHiWord(ipv4Hdr.destAddr));
1334 pkArray[cnt++] = (Data)GetLoByte(GetHiWord(ipv4Hdr.destAddr));
1335 pkArray[cnt++] = (Data)GetHiByte(GetLoWord(ipv4Hdr.destAddr));
1336 pkArray[cnt++] = (Data)GetLoByte(GetLoWord(ipv4Hdr.destAddr));
1338 for (idx = 0; idx < CM_IPV4_HDRLEN; idx++)
1339 revPkArray[idx] = pkArray[CM_IPV4_HDRLEN - idx -1];
1341 /* this function automatically reverses revPkArray */
1342 ret = SAddPreMsgMult(revPkArray, (MsgLen)cnt, mBuf);
1344 duSendEgtpDatInd(mBuf);
1348 #endif /* EGTP_TEST */
1351 /**************************************************************************
1352 * @brief Function to send configs to SCH
1356 * Function : duSendSchCfg
1359 * Sends general config to Scheduler via MAC layer
1362 * @return ROK - success
1365 ***************************************************************************/
1369 RgSchInstCfg *cfg = NULLP;
1372 DU_SET_ZERO(&pst, sizeof(Pst));
1373 DU_SET_ZERO(&rgMngmt, sizeof(RgMngmt));
1375 cfg = &(rgMngmt.t.cfg.s.schInstCfg);
1377 /* Filling of Instance Id */
1378 cfg->instId = DEFAULT_CELLS + 1;
1379 /* Filling of Gen config */
1380 cfg->genCfg.mem.region = MAC_MEM_REGION;
1381 cfg->genCfg.mem.pool = MAC_POOL;
1382 cfg->genCfg.tmrRes = 10;
1385 cfg->genCfg.forceCntrlSrbBoOnPCel = FALSE;
1386 cfg->genCfg.isSCellActDeactAlgoEnable = TRUE;
1388 cfg->genCfg.startCellId = 1;
1389 cfg->genCfg.lmPst.dstProcId = DU_PROC;
1390 cfg->genCfg.lmPst.srcProcId = DU_PROC;
1391 cfg->genCfg.lmPst.dstEnt = ENTDUAPP;
1392 cfg->genCfg.lmPst.dstInst = DU_INST;
1393 cfg->genCfg.lmPst.srcEnt = ENTRG;
1394 cfg->genCfg.lmPst.srcInst = DEFAULT_CELLS + 1;
1395 cfg->genCfg.lmPst.prior = PRIOR0;
1396 cfg->genCfg.lmPst.route = RTESPEC;
1397 cfg->genCfg.lmPst.region = MAC_MEM_REGION;
1398 cfg->genCfg.lmPst.pool = MAC_POOL;
1399 cfg->genCfg.lmPst.selector = ODU_SELECTOR_LC;
1402 rgMngmt.hdr.msgType = TCFG;
1403 rgMngmt.hdr.entId.ent = ENTRG;
1404 rgMngmt.hdr.entId.inst = DU_INST;
1405 rgMngmt.hdr.elmId.elmnt = STSCHINST;
1406 rgMngmt.hdr.response.mem.region = MAC_MEM_REGION;
1407 rgMngmt.hdr.response.mem.pool = MAC_POOL;
1410 pst.selector = ODU_SELECTOR_LC;
1411 pst.srcEnt = ENTDUAPP;
1413 pst.dstProcId = DU_PROC;
1414 pst.srcProcId = DU_PROC;
1415 pst.srcInst = DU_INST;
1417 pst.region = duCb.init.region;
1418 pst.event = (Event) EVTMACSCHGENCFGREQ;
1420 DU_LOG("\nDU_APP : MAC Sch Cfg sent");
1422 /* Send the request to MAC */
1423 cmPkLrgSchCfgReq(&pst, &rgMngmt);
1429 /**************************************************************************
1430 * @brief Function to configure SCTP params and
1431 * responsible for F1 and E2 interfaces
1435 * Function : duLayerConfigComplete
1438 * Configures SCTP Params and responsible for handling
1439 * F1 and E2 interface.
1442 * @return ROK - success
1445 ***************************************************************************/
1446 S16 duLayerConfigComplete()
1450 DU_LOG("\nDU_APP : Configuring all Layer is complete");
1452 if((ret = duSctpCfgReq(duCfgParam.sctpParams)) != ROK)
1454 DU_LOG("\nDU_APP : Failed configuring Sctp Params");
1457 if((ret = duSctpAssocReq(F1_INTERFACE)) != ROK)
1459 DU_LOG("\nDU_APP : Failed to send AssocReq F1");
1462 if((ret = duSctpAssocReq(E2_INTERFACE)) != ROK)
1464 DU_LOG("\nDU_APP : Failed to send AssocReq E2");
1471 /**************************************************************************
1472 * @brief Function to handle SCH Config Confirm from MAC
1476 * Function : duHdlSchCfgComplete
1479 * Handles Scheduler Gen Config Confirm from MAC
1481 * @param[in] Pst *pst, Post structure of the primitive.
1482 * @param[in] RgMngmt *cfm, Unpacked primitive info received from MAC
1483 * @return ROK - success
1486 ***************************************************************************/
1487 S16 duHdlSchCfgComplete(Pst *pst, RgMngmt *cfm)
1489 if (cfm->cfm.status == LCM_PRIM_OK)
1491 switch (cfm->hdr.elmId.elmnt)
1495 DU_LOG("\nDU_APP : Received SCH CFG CFM at DU APP");
1502 duLayerConfigComplete();
1503 duBuildEgtpCfgReq();
1507 /*******************************************************************
1509 * @brief Sends Slot indication to EGTP
1513 * Function : duSendEgtpSlotInd
1516 * Sends Slot indication to EGTP
1519 * @return ROK - success
1522 * ****************************************************************/
1523 S16 duSendEgtpSlotInd()
1527 duFillEgtpPst(&pst, EVTSLOTIND);
1528 packEgtpSlotInd(&pst);
1534 /**************************************************************************
1535 * @brief Function to fill and send MacCellconfig
1539 * Function : duBuildAndSendMacCellCfg
1542 * Initiates MAC Configs towards MAC
1545 * @return ROK - success
1548 ***************************************************************************/
1549 S16 duBuildAndSendMacCellCfg()
1552 DU_SET_ZERO(&pst, sizeof(Pst));
1553 MacCellCfg *duMacCellCfg = NULLP;
1555 DU_ALLOC_SHRABL_BUF(duMacCellCfg, sizeof(MacCellCfg));
1556 if(duMacCellCfg == NULLP)
1561 /* store the address in the duCb so that we can free on confirm msg */
1562 duCb.duMacCellCfg = duMacCellCfg;
1564 /* copy the mac config structure from duCfgParams */
1565 memcpy(duMacCellCfg,&duCfgParam.macCellCfg,sizeof(MacCellCfg));
1568 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_CONFIG_REQ);
1570 /* Send MAC cell config to MAC */
1571 return (*packMacCellCfgOpts[pst.selector])(&pst, duMacCellCfg);
1574 /**************************************************************************
1575 * @brief Function to Handle MAC cell config confirm
1579 * Function : duHandleMacCellCfgCfm
1582 * Initiates general Configs towards MAC
1585 * @return ROK - success
1588 ***************************************************************************/
1589 uint8_t duHandleMacCellCfgCfm(Pst *pst, MacCellCfgCfm *macCellCfgCfm)
1591 uint8_t actvCellIdx = 0;
1594 if(macCellCfgCfm->rsp == ROK)
1596 for(actvCellIdx = 0 ; actvCellIdx <duCb.numActvCells ; actvCellIdx++)
1598 if(macCellCfgCfm->cellId == duCb.actvCellLst[actvCellIdx]->cellId)
1600 duCb.duMacCellCfg = NULLP;
1601 /* Build and send GNB-DU config update */
1602 ret = BuildAndSendDUConfigUpdate();
1604 /* TODO: Trigger cell start req once cell up slot ind is received*/
1605 /* Build and Send Cell Start Req to MAC */
1606 ret = duBuildAndSendMacCellStartReq();
1613 DU_LOG("\nMac cell cfg failed");
1619 /*******************************************************************
1621 * @brief Handles slot indication from MAC
1625 * Function : duHandleSlotInd
1628 * Handles slot indication from MAC
1630 * @params[in] Post structure pointer
1632 * @return ROK - success
1635 * ****************************************************************/
1636 uint8_t duHandleSlotInd(Pst *pst, SlotIndInfo *slotInfo)
1639 DU_LOG("\nDU APP : Slot Indication received");
1641 if(slotInfo->cellId <=0 || slotInfo->cellId > MAX_NUM_CELL)
1643 DU_LOG("\nDU APP : Invalid Cell Id %d", slotInfo->cellId);
1645 if(!duCb.actvCellLst[slotInfo->cellId-1]->firstSlotIndRcvd)
1647 duCb.actvCellLst[slotInfo->cellId-1]->firstSlotIndRcvd = true;
1648 if((duCb.actvCellLst[slotInfo->cellId-1] != NULL) && \
1649 (duCb.actvCellLst[slotInfo->cellId-1]->cellStatus == \
1650 ACTIVATION_IN_PROGRESS))
1652 DU_LOG("\nDU APP : 5G-NR Cell %d is UP", slotInfo->cellId);
1653 duCb.actvCellLst[slotInfo->cellId-1]->cellStatus = ACTIVATED;
1658 /* TODO : Slot Indication to be moved out of EGTP_TEST when
1659 * data path is established */
1661 duSendEgtpSlotInd();
1664 if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
1665 DU_FREE_SHRABL_BUF(MAC_MEM_REGION, pst->pool, slotInfo, sizeof(SlotIndInfo));
1670 /*******************************************************************
1672 * @brief Builds and sends cell start request to MAC
1676 * Function : duBuildAndSendMacCellStartReq
1679 * Builds and sends cell start request to MAC
1682 * @return ROK - success
1685 * ****************************************************************/
1686 uint8_t duBuildAndSendMacCellStartReq()
1689 MacCellStartInfo *cellStartInfo = NULL;
1691 DU_LOG("\nDU APP : Building and Sending cell start request to MAC");
1693 /* Send Cell Start Request to MAC */
1694 DU_ALLOC_SHRABL_BUF(cellStartInfo, sizeof(MacCellStartInfo));
1697 DU_LOG("\nDU APP : Memory alloc failed while building cell start request");
1701 for(uint8_t id = 0; id < MAX_NUM_CELL; id++)
1703 if(duCb.actvCellLst[id])
1705 duCb.actvCellLst[id]->firstSlotIndRcvd = FALSE;
1706 cellStartInfo->cellId = duCb.actvCellLst[id]->cellInfo.nrEcgi.cellId;
1709 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_START_REQ);
1711 return (*packMacCellStartReqOpts[pst.selector])(&pst, cellStartInfo);
1717 /*******************************************************************
1719 * @brief Builds and sends cell stop request to MAC
1723 * Function : duBuildAndSendMacCellStopReq
1726 * Builds and sends cell stop request to MAC
1729 * @return ROK - success
1732 * ****************************************************************/
1733 uint8_t duBuildAndSendMacCellStopReq()
1736 MacCellStopInfo *cellStopInfo = NULL;
1738 DU_LOG("\nDU APP : Building and Sending cell stop request to MAC");
1740 /* Send Cell Stop Request to MAC */
1741 DU_ALLOC_SHRABL_BUF(cellStopInfo, sizeof(MacCellStopInfo));
1744 DU_LOG("\nDU APP : Memory alloc failed while building cell stop request");
1747 cellStopInfo->cellId = duCb.actvCellLst[0]->cellId;
1750 FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_CELL_STOP_REQ);
1752 return (*packMacCellStopReqOpts[pst.selector])(&pst, cellStopInfo);
1755 /*******************************************************************
1757 * @brief Handles stop indication from MAC
1761 * Function : duHandleStopInd
1764 * Handles stop indication from MAC
1766 * @params[in] Post structure pointer
1767 * @return ROK - success
1770 * ****************************************************************/
1771 uint8_t duHandleStopInd(Pst *pst, MacCellStopInfo *cellStopId)
1773 if(cellStopId->cellId <=0 || cellStopId->cellId > MAX_NUM_CELL)
1775 DU_LOG("\nDU APP : Invalid Cell Id %d", cellStopId->cellId);
1777 if(duCb.actvCellLst[cellStopId->cellId-1] != NULL)
1779 if(duCb.actvCellLst[cellStopId->cellId-1]->firstSlotIndRcvd)
1781 duCb.actvCellLst[cellStopId->cellId-1]->firstSlotIndRcvd = false;
1782 if((duCb.actvCellLst[cellStopId->cellId-1]->cellStatus == \
1785 DU_LOG("\nDU APP : 5G-NR Cell %d is DOWN", cellStopId->cellId);
1786 duCb.actvCellLst[cellStopId->cellId-1]->cellStatus = DELETION_IN_PROGRESS;
1790 if((pst->selector == ODU_SELECTOR_LWLC) || (pst->selector == ODU_SELECTOR_TC))
1791 DU_FREE_SHRABL_BUF(MAC_MEM_REGION, pst->pool, cellStopId, sizeof(MacCellStopInfo));
1796 /*******************************************************************
1798 * @brief Handles slot indication from MAC
1802 * Function : duHandleUlCcchInd
1805 * Handles UL CCCH indication from MAC
1807 * @params[in] Post structure pointer
1808 * UL CCCH Ind pointer
1809 * @return ROK - success
1812 * ****************************************************************/
1813 uint8_t duHandleUlCcchInd(Pst *pst, UlCcchIndInfo *ulCcchIndInfo)
1816 DU_LOG("\nDU APP : UL CCCH Indication received");
1818 return (duProcUlCcchInd(ulCcchIndInfo));
1822 /**********************************************************************
1824 **********************************************************************/