4958343c56306e2d1f57b355fe9c05bf4554b644
[ric-app/admin.git] / src / admission_init_routines.cc
1 /*
2 ==================================================================================
3
4         Copyright (c) 2018-2019 AT&T Intellectual Property.
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19 /* Author : Ashwin Sridharan
20    Date    : Dec 2019
21 */
22
23
24 /* 
25    holds all functionality related to message exchange upon startup
26    - subscription requests
27    - policy requests
28
29    NOTE : This module only sends out requests. Responses are assumed to be
30    handled on RMR listening threads that are expected to already running in 
31    main
32
33 */
34
35 #include "adm-ctrl-xapp.hpp"
36
37
38 // function to call to add subscriptions
39 // Note 1 : it is synchronous. will block till it succeeds or fails
40 // Note 2:  we bind and pass the xapp tx function to separate out RMR from subscription process
41
42 int add_subscription(subscription_handler *sub_handler_ref, XaPP * xapp_ref, subscription_helper & he, subscription_response_helper he_resp, std::string & gNodeB){
43   unsigned char node_buffer[32];
44   std::copy(gNodeB.begin(), gNodeB.end(), node_buffer);
45   node_buffer[gNodeB.length()] = '\0';
46
47   int res = sub_handler_ref->request_subscription(he, he_resp,  gNodeB, RIC_SUB_REQ, std::bind(static_cast<bool (XaPP::*)(int, size_t, void *, unsigned char const*,  link_types, tx_types)>( &XaPP::Send), xapp_ref, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, node_buffer, link_types::HIGH_RELIABILITY, tx_types::ROUTE));
48   return res;
49 };
50
51
52 // function to call to delete subscription
53 // Note 1 : it is synchronous. will block till it succeeds or fails
54 // Note 2:  we bind and pass the xapp tx function to separate out RMR from subscription process
55
56 int delete_subscription(subscription_handler *sub_handler_ref, XaPP * xapp_ref, subscription_helper & he, subscription_response_helper  he_resp, std::string & gNodeB){
57   unsigned char node_buffer[32];
58   std::copy(gNodeB.begin(), gNodeB.end(), node_buffer);
59   node_buffer[gNodeB.length()] = '\0';
60   
61   int res = sub_handler_ref->request_subscription_delete(he, he_resp, gNodeB, RIC_SUB_DEL_REQ, std::bind(static_cast<bool (XaPP::*)(int, size_t, void *, unsigned char const*, link_types, tx_types)>(&XaPP::Send), xapp_ref, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, node_buffer, link_types::HIGH_RELIABILITY, tx_types::ROUTE));
62   return res;
63 };
64
65
66
67 init::init (XaPP & xapp, subscription_handler & sub_handler, configuration & my_config){
68   xapp_ref = &xapp;
69   sub_handler_ref = &sub_handler;
70   config_ref = &my_config;
71 }
72
73
74 // Main handle to subscribe to requests
75 // AC xAPP basically subscribes to just one  subscription (SgNB Addition Request), but can be extended to subscribe to
76 // multiple too.
77 void init::startup_subscribe_requests(void ){
78   
79   //======================================================
80   // sgnb Subscription spec
81   
82    int request_id = 2; // will be over-written by subscription handler
83    int req_seq = 1;
84    int function_id = 0;
85    int action_id = 4;
86    int action_type = config_ref->report_mode_only ? 0:1;
87    
88    int message_type = 1;
89    int procedure_code = 27;
90    std::string egnb_id = "Testgnb";
91    std::string plmn_id = "Testplmn";
92
93    unsigned char event_buf[128];
94    size_t event_buf_len = 128;
95    bool res;
96
97
98    e2sm_event_trigger_helper trigger_data;
99    e2sm_event_trigger event_trigger;
100   
101    trigger_data.egNB_id = egnb_id;
102    trigger_data.plmn_id = plmn_id;
103    trigger_data.egNB_id_type = 2;
104    trigger_data.interface_direction = 1;
105    trigger_data.procedure_code = procedure_code;
106    trigger_data.message_type = message_type;
107    //======================================================
108    
109    // Encode the event trigger definition 
110    res = event_trigger.encode_event_trigger(&event_buf[0], &event_buf_len, trigger_data);
111    if (!res){
112      mdclog_write(MDCLOG_ERR, "Error : %s, %d: Could not encode subscription Request. Reason = %s\n", __FILE__, __LINE__, event_trigger.get_error().c_str());
113      exit(0);
114    }
115    mdclog_write(MDCLOG_INFO, "Encoded event trigger definition into PDU of size %lu bytes\n", event_buf_len);  
116
117    // create the subscription
118    subscription_helper sgnb_add_subscr_req;
119    subscription_response_helper subscr_response;
120   
121    sgnb_add_subscr_req.clear();
122    sgnb_add_subscr_req.set_request(request_id, req_seq);
123    sgnb_add_subscr_req.set_function_id(function_id);
124    sgnb_add_subscr_req.add_action(action_id, action_type);
125    
126    sgnb_add_subscr_req.set_event_def(&event_buf[0], event_buf_len);
127
128
129    //======================================================
130    // Purely for testing purposes ... write subscription ASN binary to file 
131    // FILE *pfile;
132    // pfile = fopen("event_trigger.pr", "wb");
133    // fwrite(event_buf, 1, event_buf_len,  pfile);
134    // fclose(pfile);
135    //======================================================
136   
137
138    // for each gNodeB, try MAX_SUBSCRIPTION_ATTEMPTS
139    // record gNodeBs for which we could not subscribe.
140    // note that there could be multiple subscriptions for each gNodeB.
141    // for AC xAPP we are doing just one ...
142    std::vector<std::string> failed_gNodeBs;
143
144    for(auto &it: config_ref->gNodeB_list){
145      int attempt = 0;
146      int subscr_result = -1;
147      
148      while(1){
149
150        if(!run_program){
151          std::cout <<"Shutdown signal received during subscription process. Quitting ....." << std::endl;
152          break;
153        }
154        
155        mdclog_write(MDCLOG_INFO, "Sending subscription request for %s ... Attempt number = %d\n", it.c_str(), attempt);
156        subscr_result = add_subscription(sub_handler_ref, xapp_ref,  sgnb_add_subscr_req, subscr_response, it);
157        if (subscr_result == SUBSCR_SUCCESS){
158          break;
159        }
160        sleep(5);
161        attempt ++;
162        if (attempt > MAX_SUBSCRIPTION_ATTEMPTS){
163          break;
164        }
165      }
166      
167      if(subscr_result == SUBSCR_SUCCESS){
168        mdclog_write(MDCLOG_INFO, "Successfully subscribed for gNodeB %s", (it).c_str());
169      }
170      else{
171        failed_gNodeBs.push_back(it);
172      }
173    }
174    
175    if (failed_gNodeBs.size() == 0){
176      std::cout <<"SUBSCRIPTION REQUEST :: Successfully subscribed to events for all gNodeBs " << std::endl;
177    }
178    else{
179      std::cerr <<"SUBSCRIPTION REQUEST :: Failed to subscribe for following gNodeBs" << std::endl;
180      for(const auto &e: failed_gNodeBs){
181        std::cerr <<"Failed to subscribe for gNodeB " << e << std::endl;
182      }
183    }
184    
185    
186 }
187
188
189 // Main handle to delete subscription requests
190 // Called upon shutdown
191 void init::shutdown_subscribe_deletes(){
192   std::vector<subscription_identifier> sub_ids;
193
194   subscription_helper sub_helper;
195   subscription_response_helper subscr_response;
196   
197   // get list of subscriptions
198   sub_handler_ref->get_subscription_keys(sub_ids);
199   
200   // send delete for each one ..
201   // this is synchronous, hence will block ...
202   for(auto & id: sub_ids){
203     std::string gnodeb_id = std::get<0>(id);
204     subscription_response_helper * sub_info = sub_handler_ref->get_subscription(id);
205     int subscr_result = -1;
206     if(sub_info != NULL){
207       sub_helper.set_request(0, 0); // requirement of subscription manager ... ?
208       sub_helper.set_function_id(sub_info->get_function_id());
209       mdclog_write(MDCLOG_INFO, "Sending subscription delete for gNodeB %s\n", gnodeb_id.c_str());
210       subscr_result = delete_subscription(sub_handler_ref, xapp_ref,  sub_helper, subscr_response, gnodeb_id);
211       if(subscr_result == SUBSCR_SUCCESS){
212         mdclog_write(MDCLOG_INFO, "Successfully deleted subscription for %s, %d\n", gnodeb_id.c_str(), sub_helper.get_function_id());
213       }
214       else{
215         mdclog_write(MDCLOG_ERR, "Error : %s, %d. Could not delete subcription  for %s, %d. Reason = %d\n", __FILE__, __LINE__, gnodeb_id.c_str(), sub_helper.get_function_id(), subscr_result);
216       }
217     }
218     else{
219       mdclog_write(MDCLOG_ERR, "Error : %s, %d. Could not get subscription for %s, %d\n", __FILE__, __LINE__, std::get<0>(id).c_str(), std::get<1>(id));
220     }
221   }
222   
223 }
224
225
226 //Request policies on start up
227 // This is async : once query is sent. responses from A1 are handled on RMR threads
228 void init::startup_get_policies(void){
229
230   int policy_id = 21000;
231
232   // we simply create json from scratch for now since it is quite simple
233   std::string policy_query = "{\"policy_id\":" + std::to_string(policy_id) + "}";
234   unsigned char * message = (unsigned char *)calloc(policy_query.length(), sizeof(unsigned char));
235   memcpy(message, policy_query.c_str(),  policy_query.length());
236   mdclog_write(MDCLOG_INFO, "Sending request for policy id %d\n", policy_id);
237   xapp_ref->Send(A1_POLICY_QUERY, policy_query.length(), message, link_types::HIGH_RELIABILITY);
238   free(message);
239   
240 }
241
242
243 // start up subroutines go hear
244 void init::startup(void){
245   startup_subscribe_requests();
246   startup_get_policies();
247   
248 }
249
250 // shutdown subroutines go here
251 void init::shutdown(void ){
252   std::cout <<"Initiating shutdown subroutines ..." << std::endl;
253   shutdown_subscribe_deletes();
254 }
255