version 4.0.7
[ric-plt/e2.git] / RIC-E2-TERMINATION / sctpThread.cpp
index 9b391a9..f9a56dd 100644 (file)
 
 
 
+#include <3rdparty/oranE2/RANfunctions-List.h>
 #include "sctpThread.h"
 #include "BuildRunName.h"
 
+#include "3rdparty/oranE2SM/E2SM-gNB-NRT-RANfunction-Definition.h"
+
+#include "pugixml/src/pugixml.hpp"
+
 using namespace std;
 //using namespace std::placeholders;
 using namespace boost::filesystem;
@@ -233,8 +238,8 @@ int buildConfiguration(sctp_params_t &sctpParams) {
     jsonTrace = sctpParams.trace;
 
     sctpParams.ka_message_length = snprintf(sctpParams.ka_message, KA_MESSAGE_SIZE, "{\"address\": \"%s:%d\","
-                                                                         "\"fqdn\": \"%s\","
-                                                                         "\"pod_name\": \"%s\"}",
+                                                                                    "\"fqdn\": \"%s\","
+                                                                                    "\"pod_name\": \"%s\"}",
                                             (const char *)sctpParams.myIP.c_str(),
                                             sctpParams.rmrPort,
                                             sctpParams.fqdn.c_str(),
@@ -277,6 +282,8 @@ int buildConfiguration(sctp_params_t &sctpParams) {
     return 0;
 }
 
+
+
 int main(const int argc, char **argv) {
     sctp_params_t sctpParams;
 
@@ -363,6 +370,9 @@ int main(const int argc, char **argv) {
         }
     }
 
+    auto statFlag = false;
+    auto statThread = std::thread(statColectorThread, (void *)&statFlag);
+
     //loop over term_init until first message from xApp
     handleTermInit(sctpParams);
 
@@ -370,6 +380,9 @@ int main(const int argc, char **argv) {
         t.join();
     }
 
+    statFlag = true;
+    statThread.join();
+
     return 0;
 }
 
@@ -465,12 +478,12 @@ int buildInotify(sctp_params_t &sctpParams) {
     }
 
     sctpParams.inotifyWD = inotify_add_watch(sctpParams.inotifyFD,
-                                              (const char *)sctpParams.configFilePath.c_str(),
+                                             (const char *)sctpParams.configFilePath.c_str(),
                                              (unsigned)IN_OPEN | (unsigned)IN_CLOSE_WRITE | (unsigned)IN_CLOSE_NOWRITE); //IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
     if (sctpParams.inotifyWD == -1) {
         mdclog_write(MDCLOG_ERR, "Failed to add directory : %s to  inotify (inotify_add_watch) %s",
-                sctpParams.configFilePath.c_str(),
-                strerror(errno));
+                     sctpParams.configFilePath.c_str(),
+                     strerror(errno));
         close(sctpParams.inotifyFD);
         return -1;
     }
@@ -539,10 +552,12 @@ void listener(sctp_params_t *params) {
 
     ReportingMessages_t message {};
 
-    for (int i = 0; i < MAX_RMR_BUFF_ARRY; i++) {
-        rmrMessageBuffer.rcvBufferedMessages[i] = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
-        rmrMessageBuffer.sendBufferedMessages[i] = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
-    }
+//    for (int i = 0; i < MAX_RMR_BUFF_ARRY; i++) {
+//        rmrMessageBuffer.rcvBufferedMessages[i] = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
+//        rmrMessageBuffer.sendBufferedMessages[i] = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, RECEIVE_XAPP_BUFFER_SIZE);
+//    }
+
+    message.statCollector = StatCollector::GetInstance();
 
     while (true) {
         if (mdclog_level_get() >= MDCLOG_DEBUG) {
@@ -573,6 +588,9 @@ void listener(sctp_params_t *params) {
             } else if (events[i].events & EPOLLOUT) {
                 handleEinprogressMessages(events[i], message, rmrMessageBuffer, params);
             } else if (params->listenFD == events[i].data.fd) {
+                if (mdclog_level_get() >= MDCLOG_INFO) {
+                    mdclog_write(MDCLOG_INFO, "New connection request from sctp network\n");
+                }
                 // new connection is requested from RAN  start build connection
                 while (true) {
                     struct sockaddr in_addr {};
@@ -599,8 +617,8 @@ void listener(sctp_params_t *params) {
                         break;
                     }
                     auto  ans = getnameinfo(&in_addr, in_len,
-                            peerInfo->hostName, NI_MAXHOST,
-                            peerInfo->portNumber, NI_MAXSERV, (signed )((unsigned)NI_NUMERICHOST | NI_NUMERICSERV));
+                                            peerInfo->hostName, NI_MAXHOST,
+                                            peerInfo->portNumber, NI_MAXSERV, (unsigned )((unsigned int)NI_NUMERICHOST | (unsigned int)NI_NUMERICSERV));
                     if (ans < 0) {
                         mdclog_write(MDCLOG_ERR, "Failed to get info on connection request. %s\n", strerror(errno));
                         close(peerInfo->fileDescriptor);
@@ -618,6 +636,7 @@ void listener(sctp_params_t *params) {
                                    0) != 0) {
                         break;
                     }
+                    break;
                 }
             } else if (params->rmrListenFd == events[i].data.fd) {
                 // got message from XAPP
@@ -626,8 +645,7 @@ void listener(sctp_params_t *params) {
                 if (mdclog_level_get() >= MDCLOG_DEBUG) {
                     mdclog_write(MDCLOG_DEBUG, "new message from RMR");
                 }
-                if (receiveXappMessages(params->epoll_fd,
-                                        params->sctpMap,
+                if (receiveXappMessages(params->sctpMap,
                                         rmrMessageBuffer,
                                         message.message.time) != 0) {
                     mdclog_write(MDCLOG_ERR, "Error handling Xapp message");
@@ -700,12 +718,16 @@ void handleConfigChange(sctp_params_t *sctpParams) {
                 // not the directory
             }
             if (event->len) {
-                if (!(sctpParams->configFileName.compare(event->name))) {
+                auto  retVal = strcmp(sctpParams->configFileName.c_str(), event->name);
+                if (retVal != 0) {
                     continue;
                 }
             }
             // only the file we want
             if (event->mask & (uint32_t)IN_CLOSE_WRITE) {
+                if (mdclog_level_get() >= MDCLOG_INFO) {
+                    mdclog_write(MDCLOG_INFO, "Configuration file changed");
+                }
                 if (exists(p)) {
                     const int size = 2048;
                     auto fileSize = file_size(p);
@@ -869,6 +891,7 @@ void handlepoll_error(struct epoll_event &event,
         }
 
         close(peerInfo->fileDescriptor);
+        params->sctpMap->erase(peerInfo->enodbName);
         cleanHashEntry((ConnectedCU_t *) event.data.ptr, params->sctpMap);
     } else {
         mdclog_write(MDCLOG_ERR, "epoll error, events %0x on RMR FD", event.events);
@@ -953,14 +976,14 @@ int sendSctpMsg(ConnectedCU_t *peerInfo, ReportingMessages_t &message, Sctp_Map_
             if (loglevel >= MDCLOG_DEBUG) {
                 mdclog_write(MDCLOG_DEBUG, "remove key = %s from %s at line %d", key, __FUNCTION__, __LINE__);
             }
-           auto tmp = m->find(key);
+            auto tmp = m->find(key);
             if (tmp) {
                 free(tmp);
             }
             m->erase(key);
             return -1;
         }
-        peerInfo->sentMesgs++;
+        message.statCollector->incSentMessage(string(message.message.enodbName));
         message.message.direction = 'D';
         // send report.buffer of size
         buildJsonMessage(message);
@@ -1018,7 +1041,7 @@ int receiveDataFromSctp(struct epoll_event *events,
     // get the identity of the interface
     message.peerInfo = (ConnectedCU_t *)events->data.ptr;
 
-
+    message.statCollector = StatCollector::GetInstance();
     struct timespec start{0, 0};
     struct timespec decodestart{0, 0};
     struct timespec end{0, 0};
@@ -1038,10 +1061,11 @@ int receiveDataFromSctp(struct epoll_event *events,
 
         if (loglevel >= MDCLOG_DEBUG) {
             mdclog_write(MDCLOG_DEBUG, "Finish Read from SCTP %d fd message length = %ld",
-                    message.peerInfo->fileDescriptor, message.message.asnLength);
+                         message.peerInfo->fileDescriptor, message.message.asnLength);
         }
-        message.peerInfo->rcvMsgs++;
+
         memcpy(message.message.enodbName, message.peerInfo->enodbName, sizeof(message.peerInfo->enodbName));
+        message.statCollector->incRecvMessage(string(message.message.enodbName));
         message.message.direction = 'U';
         message.message.time.tv_nsec = ts.tv_nsec;
         message.message.time.tv_sec = ts.tv_sec;
@@ -1069,7 +1093,6 @@ int receiveDataFromSctp(struct epoll_event *events,
             break;
         }
 
-        asn_dec_rval_t rval;
         if (loglevel >= MDCLOG_DEBUG) {
             char printBuffer[4096]{};
             char *tmp = printBuffer;
@@ -1086,11 +1109,12 @@ int receiveDataFromSctp(struct epoll_event *events,
             clock_gettime(CLOCK_MONOTONIC, &decodestart);
         }
 
-        rval = asn_decode(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, (void **) &pdu,
+        auto rval = asn_decode(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, (void **) &pdu,
                           message.message.asndata, message.message.asnLength);
         if (rval.code != RC_OK) {
             mdclog_write(MDCLOG_ERR, "Error %d Decoding (unpack) E2AP PDU from RAN : %s", rval.code,
                          message.peerInfo->enodbName);
+            //todo may need reset to pdu
             break;
         }
 
@@ -1108,15 +1132,15 @@ int receiveDataFromSctp(struct epoll_event *events,
 
         switch (pdu->present) {
             case E2AP_PDU_PR_initiatingMessage: {//initiating message
-                asnInitiatingRequest(pdu, message, rmrMessageBuffer);
+                asnInitiatingRequest(pdu, sctpMap,message, rmrMessageBuffer);
                 break;
             }
             case E2AP_PDU_PR_successfulOutcome: { //successful outcome
-                asnSuccsesfulMsg(pdu, message,  rmrMessageBuffer);
+                asnSuccsesfulMsg(pdu, sctpMap, message,  rmrMessageBuffer);
                 break;
             }
             case E2AP_PDU_PR_unsuccessfulOutcome: { //Unsuccessful Outcome
-                asnUnSuccsesfulMsg(pdu, message, rmrMessageBuffer);
+                asnUnSuccsesfulMsg(pdu, sctpMap, message, rmrMessageBuffer);
                 break;
             }
             default:
@@ -1134,17 +1158,18 @@ int receiveDataFromSctp(struct epoll_event *events,
         //break;
         if (pdu != nullptr) {
             //TODO need to test ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, pdu); to get better performance
-            //ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, pdu);
-            ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
-            pdu = nullptr;
+            ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, pdu);
+            //ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+            //pdu = nullptr;
         }
         //clock_gettime(CLOCK_MONOTONIC, &start);
     }
     // in case of break to avoid memory leak
-    if (pdu != nullptr) {
-        ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
-        pdu = nullptr;
-    }
+//    if (pdu != nullptr) {
+//        //ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
+//        ASN_STRUCT_RESET(asn_DEF_E2AP_PDU, pdu);
+//        //pdu = nullptr;
+//    }
 
     if (done) {
         if (loglevel >= MDCLOG_INFO) {
@@ -1152,9 +1177,9 @@ int receiveDataFromSctp(struct epoll_event *events,
         }
         message.message.asnLength = rmrMessageBuffer.sendMessage->len =
                 snprintf((char *)rmrMessageBuffer.sendMessage->payload,
-                        256,
-                        "%s|CU disconnected unexpectedly",
-                        message.peerInfo->enodbName);
+                         256,
+                         "%s|CU disconnected unexpectedly",
+                         message.peerInfo->enodbName);
         message.message.asndata = rmrMessageBuffer.sendMessage->payload;
 
         if (sendRequestToXapp(message,
@@ -1177,38 +1202,89 @@ int receiveDataFromSctp(struct epoll_event *events,
 }
 
 static void buildAndsendSetupRequest(ReportingMessages_t &message,
-                                     E2setupRequestIEs_t *ie,
                                      RmrMessagesBuffer_t &rmrMessageBuffer,
-                                     E2AP_PDU_t *pdu) {
+                                     E2AP_PDU_t *pdu,
+                                     vector<string> repValues) {
     auto logLevel = mdclog_level_get();
 
-
-    if (buildRanName(message.peerInfo->enodbName, ie) < 0) {
-        mdclog_write(MDCLOG_ERR, "Bad param in E2setupRequestIEs GlobalE2node_ID.\n");
-    } else {
-        memcpy(message.message.enodbName, message.peerInfo->enodbName, strlen(message.peerInfo->enodbName));
-    }
     // now we can send the data to e2Mgr
-    auto buffer_size = RECEIVE_SCTP_BUFFER_SIZE;
+    auto buffer_size = RECEIVE_SCTP_BUFFER_SIZE * 2;
 
     auto *rmrMsg = rmr_alloc_msg(rmrMessageBuffer.rmrCtx, buffer_size);
     // add addrees to message
-    auto j = snprintf((char *)rmrMsg->payload, 256, "%s:%d|", message.peerInfo->sctpParams->myIP.c_str(), message.peerInfo->sctpParams->rmrPort);
 
 
-    unsigned char *buffer = &rmrMsg->payload[j];
+    // unsigned char *buffer = &rmrMsg->payload[j];
+    unsigned char buffer[RECEIVE_SCTP_BUFFER_SIZE * 2];
     // encode to xml
-    asn_enc_rval_t er;
-    er = asn_encode_to_buffer(nullptr, ATS_BASIC_XER, &asn_DEF_E2AP_PDU, pdu, buffer, buffer_size - j);
+    auto er = asn_encode_to_buffer(nullptr, ATS_BASIC_XER, &asn_DEF_E2AP_PDU, pdu, buffer, buffer_size);
     if (er.encoded == -1) {
         mdclog_write(MDCLOG_ERR, "encoding of %s failed, %s", asn_DEF_E2AP_PDU.name, strerror(errno));
     } else if (er.encoded > (ssize_t) buffer_size) {
-        mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s",
+        mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s, at %s line %d",
                      (int) buffer_size,
-                     asn_DEF_E2AP_PDU.name);
+                     asn_DEF_E2AP_PDU.name, __func__, __LINE__);
     } else {
+        // we have the XML
+        pugi::xml_document doc;
+        pugi::xml_parse_result result = doc.load_string((const char *)buffer);
+        if (result) {
+            unsigned int index = 0;
+            for (auto tool : doc.child("E2AP-PDU")
+                    .child("initiatingMessage")
+                    .child("value")
+                    .child("E2setupRequest")
+                    .child("protocolIEs")
+                    .children("E2setupRequestIEs")) {
+                for (auto n : tool.child("value").child("RANfunctions-List").child(
+                        "ProtocolIE-SingleContainer").children()) {
+                    //ProtocolIE-SingleContainer
+                    //cout << "\t1 " << n.name() << endl;
+                    if (strcmp(n.name(), "value") == 0) {
+                        for (auto l : tool.child("value").children()) {
+                            //cout << "\t\t2 " << l.name() << endl;
+                            for (auto f : l.children()) {
+                                //cout << "\t\t\t3 " << f.name() << endl;
+                                for (auto g : f.child("value").children()) {
+                                    //cout << "\t\t\t\t4 " << g.name() << endl;
+                                    for (auto a : g.children()) {
+                                        if (strcmp(a.name(), "ranFunctionDefinition") == 0) {
+                                            if (repValues.size() > index) {
+                                                a.remove_children();
+                                                string val = repValues.at(index++);
+                                                // here we get vector with counter
+                                                a.append_child(pugi::node_pcdata).set_value(val.c_str());
+
+                                            }
+                                        }
+                                        //cout << "\t\t\t\t\t5 " << a.name() << " " << a.child_value() << endl;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+//            memstream strinBuf(buffer, RECEIVE_SCTP_BUFFER_SIZE * 2);
+//
+//            strinBuf.read(, RECEIVE_SCTP_BUFFER_SIZE * 2);
+
+            streambuf *oldCout = cout.rdbuf();
+            ostringstream memCout;
+            // create new cout
+            cout.rdbuf(memCout.rdbuf());
+            doc.save(std::cout);
+            //return to the normal cout
+            cout.rdbuf(oldCout);
+            memcpy(buffer, memCout.str().c_str(), memCout.str().length());
+        }
+        rmrMsg->len = snprintf((char *)rmrMsg->payload, RECEIVE_SCTP_BUFFER_SIZE * 2, "%s:%d|%s",
+                               message.peerInfo->sctpParams->myIP.c_str(),
+                               message.peerInfo->sctpParams->rmrPort,
+                               buffer);
         if (logLevel >= MDCLOG_DEBUG) {
-            mdclog_write(MDCLOG_DEBUG, "Buffer of size %d, data = %s", (int) er.encoded, buffer);
+            mdclog_write(MDCLOG_DEBUG, "Setup request of size %d :\n %s\n", rmrMsg->len, rmrMsg->payload);
         }
         // send to RMR
         message.message.messageType = rmrMsg->mtype = RIC_E2_SETUP_REQ;
@@ -1248,6 +1324,9 @@ static void buildAndsendSetupRequest(ReportingMessages_t &message,
         }
         message.peerInfo->gotSetup = true;
         buildJsonMessage(message);
+        if (rmrMsg != nullptr) {
+            rmr_free_msg(rmrMsg);
+        }
     }
 
 }
@@ -1258,6 +1337,7 @@ static void buildAndsendSetupRequest(ReportingMessages_t &message,
  * @param rmrMessageBuffer
  */
 void asnInitiatingRequest(E2AP_PDU_t *pdu,
+                          Sctp_Map_t *sctpMap,
                           ReportingMessages_t &message,
                           RmrMessagesBuffer_t &rmrMessageBuffer) {
     auto logLevel = mdclog_level_get();
@@ -1271,16 +1351,114 @@ void asnInitiatingRequest(E2AP_PDU_t *pdu,
                 mdclog_write(MDCLOG_DEBUG, "Got E2setup\n");
             }
 
+            // first get the message as XML buffer
+            auto setup_xml_buffer_size = RECEIVE_SCTP_BUFFER_SIZE * 2;
+            unsigned char setup_xml_buffer[RECEIVE_SCTP_BUFFER_SIZE * 2];
+            //unsigned char *tmp_buff_cursor = setup_xml_buffer;
+
+            auto er = asn_encode_to_buffer(nullptr, ATS_BASIC_XER, &asn_DEF_E2AP_PDU, pdu, setup_xml_buffer, setup_xml_buffer_size);
+            if (er.encoded == -1) {
+                mdclog_write(MDCLOG_ERR, "encoding of %s failed, %s", asn_DEF_E2AP_PDU.name, strerror(errno));
+            } else if (er.encoded > (ssize_t) setup_xml_buffer_size) {
+                mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s, at %s line %d",
+                             (int)setup_xml_buffer_size,
+                             asn_DEF_E2AP_PDU.name, __func__, __LINE__);
+            }
+            std::string xmlString(setup_xml_buffer_size,  setup_xml_buffer_size + er.encoded);
+
+            vector <string> runFunDEFXML_v;
+            runFunDEFXML_v.clear();
+            string runFuncStr = {};
+            auto failed = false;
             memset(message.peerInfo->enodbName, 0 , MAX_ENODB_NAME_SIZE);
             for (auto i = 0; i < pdu->choice.initiatingMessage->value.choice.E2setupRequest.protocolIEs.list.count; i++) {
                 auto *ie = pdu->choice.initiatingMessage->value.choice.E2setupRequest.protocolIEs.list.array[i];
                 if (ie->id == ProtocolIE_ID_id_GlobalE2node_ID) {
+                    // get the ran name for meid
                     if (ie->value.present == E2setupRequestIEs__value_PR_GlobalE2node_ID) {
-                        buildAndsendSetupRequest(message, ie, rmrMessageBuffer, pdu);
-                        break;
+                        if (buildRanName(message.peerInfo->enodbName, ie) < 0) {
+                            mdclog_write(MDCLOG_ERR, "Bad param in E2setupRequestIEs GlobalE2node_ID.\n");
+                            // no mesage will be sent
+                            break;
+                        }
+                        memcpy(message.message.enodbName, message.peerInfo->enodbName, strlen(message.peerInfo->enodbName));
+                        sctpMap->setkey(message.message.enodbName, message.peerInfo);
+                    }
+                }
+                // reformat RANFUNCTION Definition to XML
+                if (ie->id == ProtocolIE_ID_id_RANfunctionsAdded) {
+                    if (ie->value.present == E2setupRequestIEs__value_PR_RANfunctions_List) {
+                        for (auto j = 0; i < ie->value.choice.RANfunctions_List.list.count; i++) {
+                            auto *raNfunctionItemIEs = (RANfunction_ItemIEs_t *)ie->value.choice.RANfunctions_List.list.array[j];
+                            if (raNfunctionItemIEs->id == ProtocolIE_ID_id_RANfunction_Item &&
+                                    (raNfunctionItemIEs->value.present == RANfunction_ItemIEs__value_PR_RANfunction_Item)) {
+                                // encode to xml
+                                E2SM_gNB_NRT_RANfunction_Definition_t *ranFunDef = nullptr;
+                                auto rval = asn_decode(nullptr, ATS_ALIGNED_BASIC_PER,
+                                        &asn_DEF_E2SM_gNB_NRT_RANfunction_Definition,
+                                        (void **)&ranFunDef,
+                                        raNfunctionItemIEs->value.choice.RANfunction_Item.ranFunctionDefinition.buf,
+                                        raNfunctionItemIEs->value.choice.RANfunction_Item.ranFunctionDefinition.size);
+                                if (rval.code != RC_OK) {
+                                    mdclog_write(MDCLOG_ERR, "Error %d Decoding (unpack) E2SM message from : %s",
+                                                 rval.code,
+                                                 asn_DEF_E2SM_gNB_NRT_RANfunction_Definition.name);
+                                    failed = true;
+                                    break;
+                                }
+
+                                if (mdclog_level_get() >= MDCLOG_DEBUG) {
+                                    char *printBuffer;
+                                    size_t size;
+                                    FILE *stream = open_memstream(&printBuffer, &size);
+                                    asn_fprint(stream, &asn_DEF_E2SM_gNB_NRT_RANfunction_Definition, ranFunDef);
+                                    mdclog_write(MDCLOG_DEBUG, "Encoding E2SM %s PDU past : %s",
+                                                 asn_DEF_E2SM_gNB_NRT_RANfunction_Definition.name,
+                                                 printBuffer);
+                                }
+                                auto xml_buffer_size = RECEIVE_SCTP_BUFFER_SIZE * 2;
+                                unsigned char xml_buffer[RECEIVE_SCTP_BUFFER_SIZE * 2];
+                                // encode to xml
+                                er = asn_encode_to_buffer(nullptr,
+                                                          ATS_BASIC_XER,
+                                                          &asn_DEF_E2SM_gNB_NRT_RANfunction_Definition,
+                                                          ranFunDef,
+                                                          xml_buffer,
+                                                          xml_buffer_size);
+                                if (er.encoded == -1) {
+                                    mdclog_write(MDCLOG_ERR, "encoding of %s failed, %s",
+                                                 asn_DEF_E2SM_gNB_NRT_RANfunction_Definition.name,
+                                                 strerror(errno));
+                                } else if (er.encoded > (ssize_t)xml_buffer_size) {
+                                    mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s, at %s line %d",
+                                                 (int) xml_buffer_size,
+                                                 asn_DEF_E2SM_gNB_NRT_RANfunction_Definition.name, __func__, __LINE__);
+                                } else {
+                                    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+                                        mdclog_write(MDCLOG_DEBUG, "Encoding E2SM %s PDU past : %s",
+                                                     asn_DEF_E2SM_gNB_NRT_RANfunction_Definition.name,
+                                                     xml_buffer);
+                                    }
+                                    //TODO replace the ranFunctionDefinition with the XML
+                                    string runFuncs = (char *)(xml_buffer);
+                                    runFunDEFXML_v.emplace_back(runFuncs);
+                                }
+
+                            }
+                        }
+                        if (failed) {
+                            break;
+                        }
                     }
                 }
             }
+            if (failed) {
+                break;
+            }
+
+            //build all parts and send the XML (need to copy the XML with the header to the rmrMessageBuffer payload
+            //TODO replace with new function
+            buildAndsendSetupRequest(message, rmrMessageBuffer, pdu, runFunDEFXML_v);
             break;
         }
         case ProcedureCode_id_ErrorIndication: {
@@ -1392,7 +1570,10 @@ void asnInitiatingRequest(E2AP_PDU_t *pdu,
  * @param message
  * @param rmrMessageBuffer
  */
-void asnSuccsesfulMsg(E2AP_PDU_t *pdu, ReportingMessages_t &message, RmrMessagesBuffer_t &rmrMessageBuffer) {
+void asnSuccsesfulMsg(E2AP_PDU_t *pdu,
+                      Sctp_Map_t *sctpMap,
+                      ReportingMessages_t &message,
+                      RmrMessagesBuffer_t &rmrMessageBuffer) {
     auto procedureCode = pdu->choice.successfulOutcome->procedureCode;
     auto logLevel = mdclog_level_get();
     if (logLevel >= MDCLOG_INFO) {
@@ -1553,6 +1734,7 @@ void asnSuccsesfulMsg(E2AP_PDU_t *pdu, ReportingMessages_t &message, RmrMessages
  * @param rmrMessageBuffer
  */
 void asnUnSuccsesfulMsg(E2AP_PDU_t *pdu,
+                        Sctp_Map_t *sctpMap,
                         ReportingMessages_t &message,
                         RmrMessagesBuffer_t &rmrMessageBuffer) {
     auto procedureCode = pdu->choice.unsuccessfulOutcome->procedureCode;
@@ -1773,16 +1955,47 @@ void getRmrContext(sctp_params_t &pSctpParams) {
     }
 }
 
+int BuildPERSetupResponseMessaeFromXML(ReportingMessages_t &message, RmrMessagesBuffer_t &rmrMessageBuffer) {
+    E2AP_PDU_t *pdu;
+
+    if (mdclog_level_get() >= MDCLOG_DEBUG) {
+        mdclog_write(MDCLOG_DEBUG, "got xml setup response \n %s\n", rmrMessageBuffer.rcvMessage->payload);
+    }
+    auto rval = asn_decode(nullptr, ATS_BASIC_XER, &asn_DEF_E2AP_PDU, (void **) &pdu,
+                           rmrMessageBuffer.rcvMessage->payload, rmrMessageBuffer.rcvMessage->len);
+    if (rval.code != RC_OK) {
+        mdclog_write(MDCLOG_ERR, "Error %d Decoding (unpack) setup response  from E2MGR : %s",
+                     rval.code,
+                     message.message.enodbName);
+        return -1;
+    }
+
+    int buff_size = RECEIVE_XAPP_BUFFER_SIZE;
+    auto er = asn_encode_to_buffer(nullptr, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, pdu,
+                                   rmrMessageBuffer.rcvMessage->payload, buff_size);
+    if (er.encoded == -1) {
+        mdclog_write(MDCLOG_ERR, "encoding of %s failed, %s", asn_DEF_E2AP_PDU.name, strerror(errno));
+        return -1;
+    } else if (er.encoded > (ssize_t)buff_size) {
+        mdclog_write(MDCLOG_ERR, "Buffer of size %d is to small for %s, at %s line %d",
+                     (int)rmrMessageBuffer.rcvMessage->len,
+                     asn_DEF_E2AP_PDU.name,
+                     __func__,
+                     __LINE__);
+        return -1;
+    }
+    rmrMessageBuffer.rcvMessage->len = er.encoded;
+    return 0;
+}
+
 /**
  *
- * @param epoll_fd
  * @param sctpMap
  * @param rmrMessageBuffer
  * @param ts
  * @return
  */
-int receiveXappMessages(int epoll_fd,
-                        Sctp_Map_t *sctpMap,
+int receiveXappMessages(Sctp_Map_t *sctpMap,
                         RmrMessagesBuffer_t &rmrMessageBuffer,
                         struct timespec &ts) {
     if (rmrMessageBuffer.rcvMessage == nullptr) {
@@ -1811,8 +2024,13 @@ int receiveXappMessages(int epoll_fd,
         mdclog_write(MDCLOG_ERR, "RMR Receving message with stat = %d", rmrMessageBuffer.rcvMessage->state);
         return -1;
     }
+    rmr_get_meid(rmrMessageBuffer.rcvMessage, (unsigned char *)message.message.enodbName);
     switch (rmrMessageBuffer.rcvMessage->mtype) {
         case RIC_E2_SETUP_RESP : {
+            if (BuildPERSetupResponseMessaeFromXML(message, rmrMessageBuffer) != 0) {
+                break;
+            }
+
             if (sendDirectionalSctpMsg(rmrMessageBuffer, message, 0, sctpMap) != 0) {
                 mdclog_write(MDCLOG_ERR, "Failed to send RIC_E2_SETUP_RESP");
                 return -6;
@@ -1820,6 +2038,9 @@ int receiveXappMessages(int epoll_fd,
             break;
         }
         case RIC_E2_SETUP_FAILURE : {
+            if (BuildPERSetupResponseMessaeFromXML(message, rmrMessageBuffer) != 0) {
+                break;
+            }
             if (sendDirectionalSctpMsg(rmrMessageBuffer, message, 0, sctpMap) != 0) {
                 mdclog_write(MDCLOG_ERR, "Failed to send RIC_E2_SETUP_FAILURE");
                 return -6;
@@ -1908,9 +2129,9 @@ int receiveXappMessages(int epoll_fd,
 
                     message.message.asnLength = rmrMessageBuffer.sendMessage->len =
                             snprintf((char *)rmrMessageBuffer.sendMessage->payload,
-                                                                   256,
-                                                                   "%s|RIC_SCTP_CLEAR_ALL",
-                                                                   peerInfo->enodbName);
+                                     256,
+                                     "%s|RIC_SCTP_CLEAR_ALL",
+                                     peerInfo->enodbName);
                     message.message.asndata = rmrMessageBuffer.sendMessage->payload;
                     mdclog_write(MDCLOG_INFO, "%s", message.message.asndata);
                     if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer) != 0) {
@@ -1927,8 +2148,8 @@ int receiveXappMessages(int epoll_fd,
         case E2_TERM_KEEP_ALIVE_REQ: {
             // send message back
             rmr_bytes2payload(rmrMessageBuffer.sendMessage,
-                    (unsigned char *)rmrMessageBuffer.ka_message,
-                    rmrMessageBuffer.ka_message_len);
+                              (unsigned char *)rmrMessageBuffer.ka_message,
+                              rmrMessageBuffer.ka_message_len);
             rmrMessageBuffer.sendMessage->mtype = E2_TERM_KEEP_ALIVE_RESP;
             rmrMessageBuffer.sendMessage->state = 0;
             static unsigned char tx[32];
@@ -1940,9 +2161,9 @@ int receiveXappMessages(int epoll_fd,
                 mdclog_write(MDCLOG_ERR, "Failed to send E2_TERM_KEEP_ALIVE_RESP RMR message returned NULL");
             } else if (rmrMessageBuffer.sendMessage->state != 0)  {
                 mdclog_write(MDCLOG_ERR, "Failed to send E2_TERM_KEEP_ALIVE_RESP, on RMR state = %d ( %s)",
-                        rmrMessageBuffer.sendMessage->state, translateRmrErrorMessages(rmrMessageBuffer.sendMessage->state).c_str());
-            } else if (mdclog_level_get() >= MDCLOG_INFO) {
-                mdclog_write(MDCLOG_INFO, "Got Keep Alive Request send : %s", rmrMessageBuffer.ka_message);
+                             rmrMessageBuffer.sendMessage->state, translateRmrErrorMessages(rmrMessageBuffer.sendMessage->state).c_str());
+            } else if (mdclog_level_get() >= MDCLOG_DEBUG) {
+                mdclog_write(MDCLOG_DEBUG, "Got Keep Alive Request send : %s", rmrMessageBuffer.ka_message);
             }
 
             break;
@@ -2122,7 +2343,7 @@ int modifyToEpoll(int epoll_fd,
         if (mdclog_level_get() >= MDCLOG_DEBUG) {
             mdclog_write(MDCLOG_DEBUG, "remove key = %s from %s at line %d", key, __FUNCTION__, __LINE__);
         }
-       auto tmp = sctpMap->find(key);
+        auto tmp = sctpMap->find(key);
         if (tmp) {
             free(tmp);
         }
@@ -2192,19 +2413,19 @@ void buildJsonMessage(ReportingMessages_t &message) {
         }
 
         snprintf(message.buffer, sizeof(message.buffer),
-                                     "{\"header\": {\"ts\": \"%ld.%09ld\","
-                                     "\"ranName\": \"%s\","
-                                     "\"messageType\": %d,"
-                                     "\"direction\": \"%c\"},"
-                                     "\"base64Length\": %d,"
-                                     "\"asnBase64\": \"%s\"}",
-                                     message.message.time.tv_sec,
-                                     message.message.time.tv_nsec,
-                                     message.message.enodbName,
-                                     message.message.messageType,
-                                     message.message.direction,
-                                     (int) message.outLen,
-                                     message.base64Data);
+                 "{\"header\": {\"ts\": \"%ld.%09ld\","
+                 "\"ranName\": \"%s\","
+                 "\"messageType\": %d,"
+                 "\"direction\": \"%c\"},"
+                 "\"base64Length\": %d,"
+                 "\"asnBase64\": \"%s\"}",
+                 message.message.time.tv_sec,
+                 message.message.time.tv_nsec,
+                 message.message.enodbName,
+                 message.message.messageType,
+                 message.message.direction,
+                 (int) message.outLen,
+                 message.base64Data);
         static src::logger_mt &lg = my_logger::get();
 
         BOOST_LOG(lg) << message.buffer;