First release
[sim/ns3-o-ran-e2.git] / model / oran-interface.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2022 Northeastern University
4  * Copyright (c) 2022 Sapienza, University of Rome
5  * Copyright (c) 2022 University of Padova
6  *
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;
10  *
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.
15  *
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
19  *
20  * Author: Andrea Lacava <thecave003@gmail.com>
21  *                 Tommaso Zugno <tommasozugno@gmail.com>
22  *                 Michele Polese <michele.polese@gmail.com>
23  */
24
25 #include <ns3/oran-interface.h>
26 #include <ns3/asn1c-types.h>
27  
28 #include <ns3/log.h>
29 #include <thread>
30 #include "encode_e2apv1.hpp"
31
32 extern "C" {
33   #include "RICsubscriptionRequest.h"
34   #include "RICactionType.h"
35   #include "ProtocolIE-Field.h"
36   #include "InitiatingMessage.h"
37 }
38
39 namespace ns3 {
40
41 NS_LOG_COMPONENT_DEFINE ("E2Termination");
42
43 NS_OBJECT_ENSURE_REGISTERED (E2Termination);
44
45 TypeId E2Termination::GetTypeId ()
46 {
47   static TypeId tid = TypeId ("ns3::E2Termination")
48     .SetParent<Object>()
49     .AddConstructor<E2Termination>();
50   return tid;
51 }
52
53 E2Termination::E2Termination ()
54 {
55   NS_FATAL_ERROR("Do not use the default constructor");
56 }
57
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),
64     m_ricPort (ricPort),
65     m_clientPort (clientPort),
66     m_gnbId (gnbId),
67     m_plmnId(plmnId)
68 {
69   NS_LOG_FUNCTION (this);
70   m_e2sim = new E2Sim;
71   
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");
75   // fclose (f);
76 }
77
78 void
79 E2Termination::RegisterFunctionDescToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription)
80 {
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);
86
87   m_e2sim->register_e2sm (ranFunctionId, rfdBuf);
88 }
89
90 void
91 E2Termination::RegisterKpmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription,
92                              SubscriptionCallback sbCb)
93 {
94   RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
95   m_e2sim->register_subscription_callback (ranFunctionId, sbCb);
96 }
97
98 void
99 E2Termination::RegisterSmCallbackToE2Sm (long ranFunctionId, Ptr<FunctionDescription> ranFunctionDescription, SmCallback smCb)
100 {
101   RegisterFunctionDescToE2Sm (ranFunctionId,ranFunctionDescription);
102   m_e2sim->register_sm_callback (ranFunctionId, smCb);
103 }
104
105 void E2Termination::Start ()
106 {
107   NS_LOG_FUNCTION (this);
108
109   NS_ABORT_MSG_IF(m_ricAddress.empty(), "Set the RIC information first");
110   
111   // create a thread to host e2sim execution
112   std::thread e2simThread (&E2Termination::DoStart, this);
113   e2simThread.detach ();
114 }
115
116 void E2Termination::DoStart ()
117 {
118   NS_LOG_FUNCTION (this);
119   
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 ());
131
132   NS_LOG_INFO ("In ns3::E2Term:  GNB" << m_gnbId << ", clientPort " << m_clientPort << ", ricPort "
133                                  << m_ricPort <<  ", PlmnID "
134                                  << m_plmnId);
135
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);
138 }
139
140 E2Termination::~E2Termination ()
141 {
142   NS_LOG_FUNCTION (this);
143   delete m_e2sim;
144 }
145
146 E2Termination::RicSubscriptionRequest_rval_s 
147 E2Termination::ProcessRicSubscriptionRequest (E2AP_PDU_t* sub_req_pdu)
148 {
149   //Record RIC Request ID
150   //Go through RIC action to be Setup List
151   //Find first entry with REPORT action Type
152   //Record ricActionID
153   //Encode subscription response
154
155   RICsubscriptionRequest_t orig_req = sub_req_pdu->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
156
157   // RICsubscriptionResponse_IEs_t *ricreqid = (RICsubscriptionResponse_IEs_t*)calloc(1, sizeof(RICsubscriptionResponse_IEs_t));
158            
159   int count = orig_req.protocolIEs.list.count;
160   int size = orig_req.protocolIEs.list.size;
161
162   RICsubscriptionRequest_IEs_t **ies = (RICsubscriptionRequest_IEs_t**)orig_req.protocolIEs.list.array;
163
164   NS_LOG_DEBUG ("Number of IEs " << count);
165   NS_LOG_DEBUG ("Size of IEs " << size);
166
167   RICsubscriptionRequest_IEs__value_PR pres;
168   
169   uint16_t reqRequestorId {};
170   uint16_t reqInstanceId {};
171   uint16_t ranFuncionId {};
172   uint8_t reqActionId {};
173   
174   std::vector<long> actionIdsAccept;
175   std::vector<long> actionIdsReject;
176   
177   // iterate over the IEs
178   for (int i = 0; i < count; i++) 
179   {
180     RICsubscriptionRequest_IEs_t *next_ie = ies[i];
181     pres = next_ie->value.present; // value of the current IE
182       
183     switch(pres) 
184     {
185       // IE containing the RIC Request ID
186       case RICsubscriptionRequest_IEs__value_PR_RICrequestID:
187         {
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);
194           break;
195         }
196       // IE containing the RAN Function ID
197       case RICsubscriptionRequest_IEs__value_PR_RANfunctionID:
198         {
199           NS_LOG_DEBUG ("Processing RAN Function ID field");    
200           ranFuncionId = next_ie->value.choice.RANfunctionID;
201           NS_LOG_DEBUG ("RAN Function ID " << ranFuncionId);
202           break;
203         }
204       case RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails:
205         {
206           NS_LOG_DEBUG ("Processing RIC Subscription Details field");
207           RICsubscriptionDetails_t subDetails = next_ie->value.choice.RICsubscriptionDetails;
208           
209           // RIC Event Trigger Definition
210           RICeventTriggerDefinition_t triggerDef = subDetails.ricEventTriggerDefinition;
211
212           // TODO How to decode this field?
213           uint8_t size = 20;  
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));
217                     
218           // Sequence of actions
219           RICactions_ToBeSetup_List_t actionList = subDetails.ricAction_ToBeSetup_List;
220           // TODO We are ignoring the trigger definition
221   
222           int actionCount = actionList.list.count;
223           NS_LOG_DEBUG ("Number of actions " << actionCount);
224   
225           auto **item_array = actionList.list.array;
226           bool foundAction = false;
227   
228           for (int i = 0; i < actionCount; i++) 
229           {
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;
233                         
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))
237             {
238               reqActionId = actionId;
239               actionIdsAccept.push_back(reqActionId);
240               NS_LOG_DEBUG ("Action ID " << actionId << " accepted");
241               foundAction = true;
242             } 
243             else 
244             {
245               reqActionId = actionId;
246               NS_LOG_DEBUG ("Action ID " << actionId << " rejected");
247               // actionIdsReject.push_back(reqActionId);
248             }
249           }
250           break;
251         }
252       default:
253         {
254           NS_LOG_DEBUG ("in case default");     
255           break;
256         }      
257       }
258   }
259   
260   NS_LOG_DEBUG ("Create RIC Subscription Response");
261   
262   E2AP_PDU *e2ap_pdu = (E2AP_PDU*)calloc(1,sizeof(E2AP_PDU));
263
264   long *accept_array = &actionIdsAccept[0];
265   long *reject_array = &actionIdsReject[0];
266   int accept_size = actionIdsAccept.size();
267   int reject_size = actionIdsReject.size();
268
269   encoding::generate_e2apv1_subscription_response_success(e2ap_pdu, accept_array, reject_array, accept_size, reject_size, reqRequestorId, reqInstanceId);
270
271   NS_LOG_DEBUG ("Send RIC Subscription Response");
272   m_e2sim->encode_and_send_sctp_data(e2ap_pdu);
273
274   RicSubscriptionRequest_rval_s reqParams;
275   reqParams.requestorId = reqRequestorId;
276   reqParams.instanceId = reqInstanceId;
277   reqParams.ranFuncionId = ranFuncionId;
278   reqParams.actionId = reqActionId;
279   return reqParams;
280 }
281
282 void
283 E2Termination::SendE2Message (E2AP_PDU* pdu)
284 {
285   m_e2sim->encode_and_send_sctp_data (pdu);
286 }
287
288 }