2 * Copyright 2019 AT&T Intellectual Property
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.
19 // Created by adi ENZEL on 6/17/19.
22 #include <mdclog/mdclog.h>
24 #include "asn/type_defs.h"
25 #include "asn/per/codec.hpp"
26 #include "asn/printer.hpp"
28 #include "X2AP-CommonDataTypes.hpp"
29 #include "X2AP-Containers.hpp"
30 #include "X2AP-Constants.hpp"
31 #include "X2AP-IEs.hpp"
32 #include "X2AP-PDU-Contents.hpp"
34 #include "E2AP-Constants.hpp"
35 #include "E2AP-IEs.hpp"
36 #include "E2AP-PDU-Contents.hpp"
37 #include "E2AP-PDU-Descriptions.hpp"
47 #include <rmr/RIC_message_types.h>
51 // test X2SetUP request and response
56 int main(const int argc, char **argv) {
57 mdclog_severity_t loglevel = MDCLOG_INFO;
59 auto buff = new string("Subscription TEST");
60 init_log((char *)buff->c_str());
62 mdclog_level_set(loglevel);
65 mdclog_mdc_add("app", argv[0]);
66 mdclog_write(MDCLOG_ERR, "Usage ran <ran name> rmr <rmr address> [logLevel <debug/warning/info/error]");
70 char ranName[256] {0};
71 char rmrAddress[256] {0};
74 for (int i = 1; i < argc; i += 2) {
75 for (int j = 0; j < strlen(argv[i]); j++) {
76 str1[j] = (char)tolower(argv[i][j]);
78 str1[strlen(argv[i])] = 0;
79 if (strcmp("ran", str1) == 0) {
80 strcpy(ranName, argv[i + 1]);
81 } else if (strcmp("rmr", str1) == 0) {
82 strcpy(rmrAddress, argv[i + 1]);
83 } else if (strcmp("loglevel", str1) == 0) {
84 if (strcmp("debug", argv[i + 1]) == 0) {
85 loglevel = MDCLOG_DEBUG;
86 } else if (strcmp("info", argv[i + 1]) == 0) {
87 loglevel = MDCLOG_INFO;
88 } else if (strcmp("warning", argv[i + 1]) == 0) {
89 loglevel = MDCLOG_WARN;
90 } else if (strcmp("error", argv[i + 1]) == 0) {
91 loglevel = MDCLOG_ERR;
96 void *rmrCtx = rmr_init(rmrAddress, RMR_MAX_RCV_BYTES, RMRFL_NONE);
97 if (rmrCtx == nullptr ) {
98 mdclog_write(MDCLOG_ERR, "RMR failed to initialise : %s", strerror(errno));
102 // get the RMR fd for the epoll
103 auto rmrListenFd = rmr_get_rcvfd(rmrCtx);
105 auto epoll_fd = epoll_create1(0);
106 if (epoll_fd == -1) {
107 mdclog_write(MDCLOG_ERR,"failed to open epoll descriptor");
112 struct epoll_event event {};
113 event.events = EPOLLIN;
114 event.data.fd = rmrListenFd;
115 // add listening sctpPort to epoll
116 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, rmrListenFd, &event)) {
117 mdclog_write(MDCLOG_ERR, "Failed to add RMR descriptor to epoll");
124 // we need to find that routing table exist and we can run
125 if (mdclog_level_get() >= MDCLOG_INFO) {
126 mdclog_write(MDCLOG_INFO, "We are after RMR INIT wait for RMR_Ready");
132 if ((rmrReady = rmr_ready(rmrCtx)) == 0) {
136 if (count % 60 == 0) {
137 mdclog_write(MDCLOG_INFO, "waiting to RMR ready state for %d seconds", count);
140 mdclog_write(MDCLOG_ERR, "RMR not ready tried for 3 minutes ");
144 if (mdclog_level_get() >= MDCLOG_INFO) {
145 mdclog_write(MDCLOG_INFO, "RMR running");
148 E2AP_PDU cuAckPdu {};
149 auto &succ = cuAckPdu.select_successfulOutcome();
150 succ.ref_procedureCode().select_id_endcConfigurationUpdate();
151 succ.ref_criticality().select_id_endcConfigurationUpdate();
152 auto &endcConfAck = succ.ref_value().select_id_endcConfigurationUpdate();
153 auto &confAckIes = endcConfAck.ref_protocolIEs();
155 ENDCConfigurationUpdateAcknowledge::protocolIEs_t::value_type endcENB {};
156 endcENB.ref_id().select_id_RespondingNodeType_EndcConfigUpdate();
157 endcENB.ref_criticality().select_id_RespondingNodeType_EndcConfigUpdate();
159 auto &respondingNode = endcENB.ref_value().select_id_RespondingNodeType_EndcConfigUpdate();
161 auto &enb = respondingNode.select_respond_eNB();
164 confAckIes.push_back(endcENB);
169 auto &initiatingMsg = pdu.select_initiatingMessage();
170 initiatingMsg.ref_procedureCode().select_id_ricSubscription();
171 initiatingMsg.ref_criticality().select_id_ricSubscription();
172 auto &subscription = initiatingMsg.ref_value().select_id_ricSubscription();
174 auto &ies = subscription.ref_protocolIEs();
178 RICsubscriptionRequest::protocolIEs_t::value_type ranFuncId {};
179 ranFuncId.ref_id().select_id_RANfunctionID();
180 ranFuncId.ref_criticality().select_id_RANfunctionID();
181 ranFuncId.ref_value().select_id_RANfunctionID().set(28);
182 ies.push_back(ranFuncId);
184 RICsubscriptionRequest::protocolIEs_t::value_type ricRequestId {};
185 ricRequestId.ref_id().select_id_RICrequestID();
186 ricRequestId.ref_criticality().select_id_RICrequestID();
187 ricRequestId.ref_value().select_id_RICrequestID().ref_ricRequestorID().set(44);
188 ricRequestId.ref_value().select_id_RICrequestID().ref_ricRequestSequenceNumber().set(55);
189 ies.push_back(ricRequestId);
191 RICsubscriptionRequest::protocolIEs_t::value_type ricSubId {};
192 ricSubId.ref_id().select_id_RICsubscription();
193 ricSubId.ref_criticality().select_id_RICsubscription();
195 //E2SM_gNB_X2_eventTriggerDefinition_t evt;
196 uint8_t v1[] = {0x02, 0xf8, 0x29, 0x88};
198 RICeventTriggerDefinition eventTriggerDef {}; // octet string in E2AP but struct in E2SM
199 eventTriggerDef.set(4, v1);
204 // RICaction_Admitted_List::value_type actbl {};
205 // actbl.ref_id().select_id_RICaction_Admitted_Item();
206 // actbl.ref_criticality().select_id_RICaction_Admitted_Item();
209 // RICaction_ToBeSetup_Item actb1{};
211 // actbl.ref_value().select_id_RICaction_Admitted_Item().ref_ricActionID().set(actb1);
212 // ricSubId.ref_value().select_id_RICsubscription().ref_ricAction_ToBeSetup_List().set(actbl);
215 ies.push_back(ricSubId);
219 ies.push_back(ranFuncId);
221 X2SetupRequest::protocolIEs_t::value_type sc {};
224 sc.ref_id().select_id_ServedCells();
225 sc.ref_criticality().select_id_ServedCells();
227 ServedCells::value_type sce;
228 sc.ref_value().select_id_ServedCells().push_back(sce);
230 sce.ref_servedCellInfo().ref_pCI().set(0x1F7);
231 uint8_t v3[] = {0x1, 0x2};
232 sce.ref_servedCellInfo().ref_tAC().set(2,v3);
233 sce.ref_servedCellInfo().ref_cellId().ref_pLMN_Identity().set(3, v1);
234 uint8_t v4[] = {0x00, 0x07, 0xab, ((unsigned)0x50) >> (unsigned)4};
235 sce.ref_servedCellInfo().ref_cellId().ref_eUTRANcellIdentifier().set_buffer(28, v4);
237 BroadcastPLMNs_Item::value_type bpe;
238 sce.ref_servedCellInfo().ref_broadcastPLMNs().push_back(bpe);
241 sce.ref_servedCellInfo().ref_eUTRA_Mode_Info().select_fDD().ref_uL_EARFCN().set(0x1);
242 sce.ref_servedCellInfo().ref_eUTRA_Mode_Info().select_fDD().ref_dL_EARFCN().set(0x1);
243 sce.ref_servedCellInfo().ref_eUTRA_Mode_Info().select_fDD().ref_uL_Transmission_Bandwidth().set(Transmission_Bandwidth::bw50);
244 sce.ref_servedCellInfo().ref_eUTRA_Mode_Info().select_fDD().ref_dL_Transmission_Bandwidth().set(Transmission_Bandwidth::bw50);
248 unsigned char s_buffer[64 * 1024];
249 asn::per::EncoderCtx ctx{s_buffer, sizeof(s_buffer)};
250 std::cout << asn::get_printed(pdu) << std::endl;
251 if (!asn::per::pack(pdu, ctx)) {
252 std::cout << ctx.refErrorCtx().toString() << std::endl;
255 size_t packed_buf_size;
256 packed_buf_size = static_cast<size_t>(ctx.refBuffer().getBytesUsed());
260 //auto delimiter = (const char) '|';
261 sprintf(data, "%s/0", ctx.refBuffer().getBytes(packed_buf_size));
263 rmr_mbuf_t *msg = rmr_alloc_msg(rmrCtx, int(strlen(data)));
264 rmr_bytes2meid(msg, (unsigned char const*)ranName, strlen(ranName));
265 rmr_bytes2payload(msg, (unsigned char const*)data, strlen(data));
266 rmr_bytes2xact(msg, (unsigned char const*)ranName, strlen(ranName));
267 msg->mtype = RIC_SUB_REQ;
270 msg = rmr_send_msg(rmrCtx, msg);
271 if (msg->state != 0) {
272 mdclog_write(MDCLOG_ERR, "Message state %d while sending RIC_X2_SETUP to %s", msg->state, ranName);
280 unsigned char allocBuffer[64*1024] {0};
281 auto *events = (struct epoll_event *)calloc(MAXEVENTS, sizeof(event));
285 auto numOfEvents = epoll_wait(epoll_fd, events, MAXEVENTS, -1);
286 if (numOfEvents < 0) {
287 mdclog_write(MDCLOG_ERR, "Epoll wait failed, errno = %s", strerror(errno));
291 for (auto i = 0; i < numOfEvents; i++) {
292 if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) {
293 mdclog_write(MDCLOG_ERR, "epoll error");
294 } else if (rmrListenFd == events[i].data.fd) {
295 msg = rmr_alloc_msg(rmrCtx, 4096);
296 if (msg == nullptr) {
297 mdclog_write(MDCLOG_ERR, "RMR Allocation message, %s", strerror(errno));
302 msg = rmr_rcv_msg(rmrCtx, msg);
303 if (msg == nullptr) {
304 mdclog_write(MDCLOG_ERR, "RMR Receving message, %s", strerror(errno));
308 memset(allocBuffer, 0, 64*1024);
309 switch (msg->mtype) {
311 mdclog_write(MDCLOG_INFO, "RMR receiveing message type %d", msg->mtype);
312 asn::per::DecoderCtx dCtx{msg->payload, (size_t) msg->len, allocBuffer, sizeof(allocBuffer)};
314 if (!asn::per::unpack(opdu, dCtx)) {
315 mdclog_write(MDCLOG_ERR, "Failed to unpack ASN message, %s", dCtx.refErrorCtx().toString());
320 switch (opdu.get_index()) {
321 case 1: { //initiating message
322 mdclog_write(MDCLOG_INFO, "ASN initiating message type %ld",
323 opdu.get_initiatingMessage()->ref_procedureCode().ref_value().get());
326 case 2: { //successful message
327 mdclog_write(MDCLOG_INFO, "ASN initiating message type %ld",
328 opdu.get_successfulOutcome()->ref_procedureCode().ref_value().get());
331 case 3: { //unsuccessesful message
332 mdclog_write(MDCLOG_INFO, "ASN initiating message type %ld",
333 opdu.get_unsuccessfulOutcome()->ref_procedureCode().ref_value().get());
338 mdclog_write(MDCLOG_INFO, "RMR receiveing message from E2 terminator, %d",