1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2022 Northeastern University
4 * Copyright (c) 2022 Sapienza, University of Rome
5 * Copyright (c) 2022 University of Padova
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation;
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Author: Andrea Lacava <thecave003@gmail.com>
21 * Tommaso Zugno <tommasozugno@gmail.com>
22 * Michele Polese <michele.polese@gmail.com>
25 #include <ns3/oran-interface.h>
26 #include <ns3/asn1c-types.h>
30 #include "encode_e2apv1.hpp"
33 #include "RICsubscriptionRequest.h"
34 #include "RICactionType.h"
35 #include "ProtocolIE-Field.h"
36 #include "InitiatingMessage.h"
41 NS_LOG_COMPONENT_DEFINE ("E2Termination");
43 NS_OBJECT_ENSURE_REGISTERED (E2Termination);
45 TypeId E2Termination::GetTypeId ()
47 static TypeId tid = TypeId ("ns3::E2Termination")
49 .AddConstructor<E2Termination>();
53 E2Termination::E2Termination ()
55 NS_FATAL_ERROR("Do not use the default constructor");
58 E2Termination::E2Termination(const std::string ricAddress,
59 const uint16_t ricPort,
60 const uint16_t clientPort,
61 const std::string gnbId,
62 const std::string plmnId)
63 : m_ricAddress (ricAddress),
65 m_clientPort (clientPort),
69 NS_LOG_FUNCTION (this);
72 // create a new file which will be used to trace the encoded messages
73 // TODO create an appropriate log class to handle these messages
74 // FILE* f = fopen ("messages.txt", "w");
79 E2Termination::RegisterFunctionDescToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription)
81 // create an octet string and copy the e2smbuffer
82 OCTET_STRING_t *rfdBuf = (OCTET_STRING_t *) calloc (1, sizeof (OCTET_STRING_t));
83 rfdBuf->buf = (uint8_t *) calloc (1, ranFunctionDescription->m_size);
84 rfdBuf->size = ranFunctionDescription->m_size;
85 memcpy (rfdBuf->buf, ranFunctionDescription->m_buffer, ranFunctionDescription->m_size);
87 m_e2sim->register_e2sm (ranFunctionId, rfdBuf);
91 E2Termination::RegisterKpmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription,
92 SubscriptionCallback sbCb)
94 RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
95 m_e2sim->register_subscription_callback (ranFunctionId, sbCb);
99 E2Termination::RegisterSmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription, SmCallback smCb)
101 RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
102 m_e2sim->register_sm_callback (ranFunctionId, smCb);
105 void E2Termination::Start ()
107 NS_LOG_FUNCTION (this);
109 NS_ABORT_MSG_IF(m_ricAddress.empty(), "Set the RIC information first");
111 // create a thread to host e2sim execution
112 std::thread e2simThread (&E2Termination::DoStart, this);
113 e2simThread.detach ();
116 void E2Termination::DoStart ()
118 NS_LOG_FUNCTION (this);
120 // start e2sim main loop
121 // char second[14]; // RIC ADDRESS
122 // std::strcpy (second, m_ricAddress.c_str ());
123 // char third[6]; // RIC PORT
124 // std::strcpy (third, std::to_string (m_ricPort).c_str ());
125 // char fourth[5]; // GNB ID value
126 // std::strncpy (fourth, m_gnbId.c_str (), 4);
127 // char fifth[6]; // CLIENT PORT
128 // std::strcpy (fifth, std::to_string (m_clientPort).c_str ());
129 // char sixth[4]; //PLMN ID
130 // std::strcpy (sixth, m_plmnId.c_str ());
132 NS_LOG_INFO ("In ns3::E2Term: GNB" << m_gnbId << ", clientPort " << m_clientPort << ", ricPort "
133 << m_ricPort << ", PlmnID "
136 // char* argv [] = {nullptr, &second [0], &third [0], &fourth[0], &fifth[0],&sixth[0]};
137 m_e2sim->run_loop (m_ricAddress, m_ricPort, m_clientPort, m_gnbId, m_plmnId);
140 E2Termination::~E2Termination ()
142 NS_LOG_FUNCTION (this);
146 E2Termination::RicSubscriptionRequest_rval_s
147 E2Termination::ProcessRicSubscriptionRequest (E2AP_PDU_t* sub_req_pdu)
149 //Record RIC Request ID
150 //Go through RIC action to be Setup List
151 //Find first entry with REPORT action Type
153 //Encode subscription response
155 RICsubscriptionRequest_t orig_req = sub_req_pdu->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
157 // RICsubscriptionResponse_IEs_t *ricreqid = (RICsubscriptionResponse_IEs_t*)calloc(1, sizeof(RICsubscriptionResponse_IEs_t));
159 int count = orig_req.protocolIEs.list.count;
160 int size = orig_req.protocolIEs.list.size;
162 RICsubscriptionRequest_IEs_t **ies = (RICsubscriptionRequest_IEs_t**)orig_req.protocolIEs.list.array;
164 NS_LOG_DEBUG ("Number of IEs " << count);
165 NS_LOG_DEBUG ("Size of IEs " << size);
167 RICsubscriptionRequest_IEs__value_PR pres;
169 uint16_t reqRequestorId {};
170 uint16_t reqInstanceId {};
171 uint16_t ranFuncionId {};
172 uint8_t reqActionId {};
174 std::vector<long> actionIdsAccept;
175 std::vector<long> actionIdsReject;
177 // iterate over the IEs
178 for (int i = 0; i < count; i++)
180 RICsubscriptionRequest_IEs_t *next_ie = ies[i];
181 pres = next_ie->value.present; // value of the current IE
185 // IE containing the RIC Request ID
186 case RICsubscriptionRequest_IEs__value_PR_RICrequestID:
188 NS_LOG_DEBUG ("Processing RIC Request ID field");
189 RICrequestID_t reqId = next_ie->value.choice.RICrequestID;
190 reqRequestorId = reqId.ricRequestorID;
191 reqInstanceId = reqId.ricInstanceID;
192 NS_LOG_DEBUG ( "RIC Requestor ID " << reqRequestorId);
193 NS_LOG_DEBUG ( "RIC Instance ID " << reqInstanceId);
196 // IE containing the RAN Function ID
197 case RICsubscriptionRequest_IEs__value_PR_RANfunctionID:
199 NS_LOG_DEBUG ("Processing RAN Function ID field");
200 ranFuncionId = next_ie->value.choice.RANfunctionID;
201 NS_LOG_DEBUG ("RAN Function ID " << ranFuncionId);
204 case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails:
206 NS_LOG_DEBUG ("Processing RIC Subscription Details field");
207 RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
209 // RIC Event Trigger Definition
210 RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
212 // TODO How to decode this field?
214 uint8_t *buf = (uint8_t *)calloc(1,size);
215 memcpy(buf, &triggerDef, size);
216 NS_LOG_DEBUG ("RIC Event Trigger Definition " << std::to_string (*buf));
218 // Sequence of actions
219 RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
220 // TODO We are ignoring the trigger definition
222 int actionCount = actionList.list.count;
223 NS_LOG_DEBUG ("Number of actions " << actionCount);
225 auto **item_array = actionList.list.array;
226 bool foundAction = false;
228 for (int i = 0; i < actionCount; i++)
230 auto *next_item = item_array[i];
231 RICactionID_t actionId = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionID;
232 RICactionType_t actionType = ((RICaction_ToBeSetup_ItemIEs*)next_item)->value.choice.RICaction_ToBeSetup_Item.ricActionType;
234 //We identify the first action whose type is REPORT
235 //That is the only one accepted; all others are rejected
236 if (!foundAction && (actionType == RICactionType_report || actionType == RICactionType_insert))
238 reqActionId = actionId;
239 actionIdsAccept.push_back(reqActionId);
240 NS_LOG_DEBUG ("Action ID " << actionId << " accepted");
245 reqActionId = actionId;
246 NS_LOG_DEBUG ("Action ID " << actionId << " rejected");
247 // actionIdsReject.push_back(reqActionId);
254 NS_LOG_DEBUG ("in case default");
260 NS_LOG_DEBUG ("Create RIC Subscription Response");
262 E2AP_PDU *e2ap_pdu = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
264 long *accept_array = &actionIdsAccept[0];
265 long *reject_array = &actionIdsReject[0];
266 int accept_size = actionIdsAccept.size();
267 int reject_size = actionIdsReject.size();
269 encoding::generate_e2apv1_subscription_response_success(e2ap_pdu, accept_array, reject_array, accept_size, reject_size, reqRequestorId, reqInstanceId);
271 NS_LOG_DEBUG ("Send RIC Subscription Response");
272 m_e2sim->encode_and_send_sctp_data(e2ap_pdu);
274 RicSubscriptionRequest_rval_s reqParams;
275 reqParams.requestorId = reqRequestorId;
276 reqParams.instanceId = reqInstanceId;
277 reqParams.ranFuncionId = ranFuncionId;
278 reqParams.actionId = reqActionId;
283 E2Termination::SendE2Message (E2AP_PDU* pdu)
285 m_e2sim->encode_and_send_sctp_data (pdu);