# 1 June - 5 June 2020
###### tags: `Study Note`
## Monday, 1 June 2020
- Continue drawing the MSC (until DU activity tasks)
- Understand how the F1AP messages handled in the DU
### F1AP handler code
:::spoiler
```
/*******************************************************************
*
* @brief Handles received F1AP message and sends back response
*
* @details
*
* Function : F1InmsgHdlr
*
* Functionality:
* - Decodes received F1AP control message
* - Prepares response message, encodes and sends to SCTP
*
* @params[in]
* @return ROK - success
* RFAILED - failure
*
* ****************************************************************/
void F1InmsgHdlr(Buffer *mBuf)
{
int i,j;
char *recvBuf;
char *finalBuf;
MsgLen copyCnt;
MsgLen recvBufLen;
F1AP_PDU_t *f1apmsg;
asn_dec_rval_t rval; /* Decoder return value */
F1AP_PDU_t f1apasnmsg ;
Buffer *respBuf;
printf("\nReceived F1AP message buffer");
SPrntMsg(mBuf, 0,0);
/* Copy mBuf into char array to decode it */
SFndLenMsg(mBuf, &recvBufLen);
if(SGetSBuf(1, 1, (Data **)&recvBuf, (Size)recvBufLen) != ROK)
{
printf("Memory allocation failed");
return;
}
if(SCpyMsgFix(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK)
{
printf("\nFailed while copying %d", copyCnt);
return;
}
printf("\nReceived flat buffer to be decoded : ");
for(i=0; i< recvBufLen; i++)
{
printf("%x",recvBuf[i]);
}
/* Decoding flat buffer into F1AP messsage */
f1apmsg = &f1apasnmsg;
memset(f1apmsg, 0, sizeof(F1AP_PDU_t));
rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apmsg, recvBuf, recvBufLen, 0, 0);
SPutSBuf(1, 1, (Data *)recvBuf, (Size)recvBufLen);
if(rval.code == RC_FAIL || rval.code == RC_WMORE)
{
printf("\nASN decode failed");
return;
}
printf("\n");
xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apmsg);
switch(f1apmsg->present)
{
case F1AP_PDU_PR_initiatingMessage:
{
switch(f1apmsg->choice.initiatingMessage->value.present)
{
case InitiatingMessage__value_PR_F1SetupRequest:
{
printf("\nF1 setup request received");
BuildF1SetupRsp();
/* Reversing the encoded string */
if(SGetSBuf(1, 1, (Data **)&finalBuf, (Size)encBufSize) != ROK)
{
printf("Memory allocation failed");
return;
}
for(i = 0, j = encBufSize-1; i<encBufSize; i++, j--)
{
finalBuf[j] = encBuf[i];
}
if(SGetMsg(1, 1, &respBuf) == ROK)
{
if(SCpyFixMsg((Data *)finalBuf, respBuf, 0, encBufSize, ©Cnt) == ROK)
{
printf("\nSending F1 setup response");
SPrntMsg(respBuf, 0,0);
if(sctpOutMsgSend(respBuf) != ROK)
{
printf("\nFailed Sending");
}
SPutMsg(respBuf);
}
}
else
{
printf("\nFailed to allocate memory");
return;
}
break;
}
case InitiatingMessage__value_PR_GNBDUConfigurationUpdate:
{
printf("\nGNB-DU config update received");
BuildDUUpdateAck();
/* Reversing the encoded string */
if(SGetSBuf(1, 1, (Data **)&finalBuf, (Size)encBufSize) != ROK)
{
printf("Memory allocation failed");
return;
}
for(i = 0, j = encBufSize-1; i<encBufSize; i++, j--)
{
finalBuf[j] = encBuf[i];
}
if(SGetMsg(1, 1, &respBuf) == ROK)
{
if(SCpyFixMsg((Data *)finalBuf, respBuf, 0, encBufSize, ©Cnt) == ROK)
{
printf("\nSending GNB-DU Config Update Acknowledgement");
SPrntMsg(respBuf, 0,0);
if(sctpOutMsgSend(respBuf) != ROK)
{
printf("\nFailed Sending");
}
SPutMsg(respBuf);
}
}
else
{
printf("\nFailed to allocate memory");
return;
}
break;
}
default:
{
printf("\nInvalid type of intiating message [%d]",f1apmsg->choice.initiatingMessage->value.present);
return;
}
}/* End of switch(initiatingMessage) */
break;
}
case F1AP_PDU_PR_successfulOutcome:
{
switch(f1apmsg->choice.successfulOutcome->value.present)
{
case SuccessfulOutcome__value_PR_F1SetupResponse:
{
F1SetupResponse_t *f1SetRspMsg;
F1SetupRsp f1SetRspDb;
GNB_CU_Name_t *cuName;
RRC_Version_t *rrc_Ver;
printf("\nF1 Setup Response");
/* Store the received info in local database */
f1SetRspMsg = &f1apmsg->choice.successfulOutcome->value.choice.F1SetupResponse;
cuName = &f1SetRspMsg->protocolIEs.list.array[1]->value.choice.GNB_CU_Name;
rrc_Ver = &f1SetRspMsg->protocolIEs.list.array[2]->value.choice.RRC_Version;
f1SetRspDb.transId = f1SetRspMsg->protocolIEs.list.array[0]->value.choice.TransactionID;
strcpy(f1SetRspDb.cuName, cuName->buf);
//strcpy(f1SetRspDb.rrcVersion.rrcVer, rrc_Ver->latest_RRC_Version.buf[0]);
/* TODO :Check the deallocation */
#if 0
SPutSBuf(DU_APP_MEM_REGION, DU_POOL,(Data *)&(f1SetupRsp->protocolIEs.list.array),\
(Size)elementCnt * sizeof(F1SetupResponseIEs_t *));
SPutSBuf(DU_APP_MEM_REGION, DU_POOL,(Data *)&(f1apMsg->choice.successfulOutcome),\
(Size)sizeof(SuccessfulOutcome_t));
SPutSBuf(DU_APP_MEM_REGION, DU_POOL,(Data *)&f1apMsg,(Size)sizeof(F1AP_PDU_t));
#endif
/* Build and send GNB-DU config update */
BuildDUConfigUpdate();
/* Reversing the encoded string */
if(SGetSBuf(1, 1, (Data **)&finalBuf, (Size)encBufSize) != ROK)
{
printf("Memory allocation failed");
return;
}
for(i = 0, j = encBufSize-1; i<encBufSize; i++, j--)
{
finalBuf[j] = encBuf[i];
}
if(SGetMsg(1, 1, &respBuf) == ROK)
{
if(SCpyFixMsg((Data *)finalBuf, respBuf, 0, encBufSize, ©Cnt) == ROK)
{
printf("\nSending GNB-DU Config Update");
SPrntMsg(respBuf, 0,0);
if(sctpOutMsgSend(respBuf) != ROK)
{
printf("\nFailed Sending");
}
SPutMsg(respBuf);
}
}
else
{
printf("\nFailed to allocate memory");
return;
}
break;
}
case SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge:
{
F1GnbDuCfgUpdAck duCfgUpdAckDb;
GNBDUConfigurationUpdateAcknowledge_t *gnbDuCfgUpdAckMsg;
printf("\nGNB-DU config update acknowledgment received");
/* Store the received info in local database */
gnbDuCfgUpdAckMsg = &f1apmsg->choice.successfulOutcome->value.choice.GNBDUConfigurationUpdateAcknowledge;
duCfgUpdAckDb.transId = gnbDuCfgUpdAckMsg->protocolIEs.list.array[0]->value.choice.TransactionID;
/* TODO :Check the deallocation */
#if 0
SPutSBuf(DU_APP_MEM_REGION,DU_POOL,(Data *)&(gNBDuCfgAck->protocolIEs.list.array),\
(Size)elementCnt * sizeof(GNBDUConfigurationUpdateAcknowledgeIEs_t *));
SPutSBuf(DU_APP_MEM_REGION,DU_POOL,(Data *)&(f1apMsg->choice.successfulOutcome),\
(Size)sizeof(SuccessfulOutcome_t));
SPutSBuf(DU_APP_MEM_REGION,DU_POOL,(Data *)&f1apMsg,(Size)sizeof(F1AP_PDU_t));
#endif
break;
}
default:
{
printf("\nInvalid type of successful outcome [%d]", f1apmsg->choice.successfulOutcome->value.present);
return;
}
}/* End of switch(successfulOutcome) */
break;
}
default:
{
printf("\nInvalie type of f1apMsg->present [%d]",f1apmsg->present);
return;
}
}/* End of switch(f1apmsg->present) */
} /* End of F1InmsgHdlr */
```
:::
### How it works?
F1AP PDU contains several things.
first, the function decode the messages and make sure that the information received is F1AP messages with no deffect.
then the function decide is the code is initiating messages or succesfull messages? *not handling unsecessfull messages now, maybe will added later*
as describe in [O-RAN F1 messages release](/@OranDocs/SJdw_Yp7L), the function only able to respond to these messages
- F1 Setup Request
- F1 Setup Response
- GNB DU Config Update
- GNB DU Config Update Ack
### notes for the F1AP handler code
- unsuccessfull outcome messages not implemented yet
- only 4 messages/reponse supported
- Maybe if we need to add F1AP messages to the code, we can try to inject it here.
- list of messages could be found at these structs or enum: F1AP_PDU, F1AP_PDU_PR, and F1AP asn folder
## Tuesday, 2 June 2020
Daily Report Tuesday (2/6)
- Continue drawing the MSC (duActvInit finished)
https://hackmd.io/@OranDocs/HkaMnmToL
## Wednesday, 3 June 2020
- Finisihing the DU MSC
- Drawing the MSC for F1 Setup Request
Problems:

Why this function appear both on DU and CU?