Initialization script now passes signal to xapp process
[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 = 1;
86    int action_type = config_ref->report_mode_only ? 0:1;
87    int subsequent_action = 0; // continue
88    int time_to_wait = 4; // 10ms
89  
90    int message_type = 1;
91    int procedure_code = 27;
92    std::string egnb_id = "Testgnb";
93    std::string plmn_id = "Testplmn";
94
95    unsigned char event_buf[128];
96    size_t event_buf_len = 128;
97    bool res;
98
99
100    e2sm_event_trigger_helper trigger_data;
101    e2sm_event_trigger event_trigger;
102   
103    trigger_data.egNB_id = egnb_id;
104    trigger_data.plmn_id = plmn_id;
105    trigger_data.egNB_id_type = 2;
106    trigger_data.interface_direction = 1;
107    trigger_data.procedure_code = procedure_code;
108    trigger_data.message_type = message_type;
109    //======================================================
110    
111    // Encode the event trigger definition 
112    res = event_trigger.encode_event_trigger(&event_buf[0], &event_buf_len, trigger_data);
113    if (!res){
114      mdclog_write(MDCLOG_ERR, "Error : %s, %d: Could not encode subscription Request. Reason = %s\n", __FILE__, __LINE__, event_trigger.get_error().c_str());
115      exit(0);
116    }
117    mdclog_write(MDCLOG_INFO, "Encoded event trigger definition into PDU of size %lu bytes\n", event_buf_len);  
118
119    // create the subscription
120    subscription_helper sgnb_add_subscr_req;
121    subscription_response_helper subscr_response;
122   
123    sgnb_add_subscr_req.clear();
124    sgnb_add_subscr_req.set_request(request_id, req_seq);
125    sgnb_add_subscr_req.set_function_id(function_id);
126    sgnb_add_subscr_req.add_action(action_id, action_type, "", subsequent_action, time_to_wait);
127    
128    sgnb_add_subscr_req.set_event_def(&event_buf[0], event_buf_len);
129
130
131    //======================================================
132    // Purely for testing purposes ... write subscription ASN binary to file 
133    // FILE *pfile;
134    // pfile = fopen("event_trigger.pr", "wb");
135    // fwrite(event_buf, 1, event_buf_len,  pfile);
136    // fclose(pfile);
137    //======================================================
138   
139
140    // for each gNodeB, try MAX_SUBSCRIPTION_ATTEMPTS
141    // record gNodeBs for which we could not subscribe.
142    // note that there could be multiple subscriptions for each gNodeB.
143    // for AC xAPP we are doing just one ...
144    std::vector<std::string> failed_gNodeBs;
145
146    for(auto &it: config_ref->gNodeB_list){
147      int attempt = 0;
148      int subscr_result = -1;
149      
150      while(1){
151
152        if(!run_program){
153          std::cout <<"Shutdown signal received during subscription process. Quitting ....." << std::endl;
154          break;
155        }
156        
157        mdclog_write(MDCLOG_INFO, "Sending subscription request for %s ... Attempt number = %d\n", it.c_str(), attempt);
158        subscr_result = add_subscription(sub_handler_ref, xapp_ref,  sgnb_add_subscr_req, subscr_response, it);
159        if (subscr_result == SUBSCR_SUCCESS){
160          break;
161        }
162        sleep(5);
163        attempt ++;
164        if (attempt > MAX_SUBSCRIPTION_ATTEMPTS){
165          break;
166        }
167      }
168      
169      if(subscr_result == SUBSCR_SUCCESS){
170        mdclog_write(MDCLOG_INFO, "Successfully subscribed for gNodeB %s", (it).c_str());
171      }
172      else{
173        failed_gNodeBs.push_back(it);
174      }
175    }
176    
177    if (failed_gNodeBs.size() == 0){
178      std::cout <<"SUBSCRIPTION REQUEST :: Successfully subscribed to events for all gNodeBs " << std::endl;
179    }
180    else{
181      std::cerr <<"SUBSCRIPTION REQUEST :: Failed to subscribe for following gNodeBs" << std::endl;
182      for(const auto &e: failed_gNodeBs){
183        std::cerr <<"Failed to subscribe for gNodeB " << e << std::endl;
184      }
185    }
186    
187    
188 }
189
190
191 // Main handle to delete subscription requests
192 // Called upon shutdown
193 void init::shutdown_subscribe_deletes(){
194   std::vector<subscription_identifier> sub_ids;
195
196   subscription_helper sub_helper;
197   subscription_response_helper subscr_response;
198   
199   // get list of subscriptions
200   sub_handler_ref->get_subscription_keys(sub_ids);
201   
202   // send delete for each one ..
203   // this is synchronous, hence will block ...
204   for(auto & id: sub_ids){
205     std::string gnodeb_id = std::get<0>(id);
206     subscription_response_helper * sub_info = sub_handler_ref->get_subscription(id);
207     int subscr_result = -1;
208     if(sub_info != NULL){
209       sub_helper.set_request(0, 0); // requirement of subscription manager ... ?
210       sub_helper.set_function_id(sub_info->get_function_id());
211       mdclog_write(MDCLOG_INFO, "Sending subscription delete for gNodeB %s\n", gnodeb_id.c_str());
212       subscr_result = delete_subscription(sub_handler_ref, xapp_ref,  sub_helper, subscr_response, gnodeb_id);
213       if(subscr_result == SUBSCR_SUCCESS){
214         mdclog_write(MDCLOG_INFO, "Successfully deleted subscription for %s, %d\n", gnodeb_id.c_str(), sub_helper.get_function_id());
215       }
216       else{
217         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);
218       }
219     }
220     else{
221       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));
222     }
223   }
224   
225 }
226
227
228 //Request policies on start up
229 // This is async : once query is sent. responses from A1 are handled on RMR threads
230 // Ideally this should be done on a per-plugin basis (but for now hard-coded :) ) 
231 // Should match the same policy type in schemas/rate-control-policy.json
232 void init::startup_get_policies(void){
233
234   int policy_id = RATE_CONTROL_POLICY_ID;
235
236   // we simply create json from scratch for now since it is quite simple
237   std::string policy_query = "{\"policy_id\":" + std::to_string(policy_id) + "}";
238   unsigned char * message = (unsigned char *)calloc(policy_query.length(), sizeof(unsigned char));
239   memcpy(message, policy_query.c_str(),  policy_query.length());
240   mdclog_write(MDCLOG_INFO, "Sending request for policy id %d\n", policy_id);
241   xapp_ref->Send(A1_POLICY_QUERY, policy_query.length(), message, link_types::HIGH_RELIABILITY);
242   free(message);
243   
244 }
245
246
247 // start up subroutines go hear
248 void init::startup(void){
249   startup_subscribe_requests();
250   startup_get_policies();
251   
252 }
253
254 // shutdown subroutines go here
255 void init::shutdown(void ){
256   std::cout <<"Initiating shutdown subroutines ..." << std::endl;
257   shutdown_subscribe_deletes();
258 }
259