2 ==================================================================================
4 Copyright (c) 2018-2019 AT&T Intellectual Property.
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
10 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
19 /* Author : Ashwin Sridharan
25 holds all functionality related to message exchange upon startup
26 - subscription requests
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
35 #include "adm-ctrl-xapp.hpp"
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
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';
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));
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
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';
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));
67 init::init (XaPP & xapp, subscription_handler & sub_handler, configuration & my_config){
69 sub_handler_ref = &sub_handler;
70 config_ref = &my_config;
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
77 void init::startup_subscribe_requests(void ){
79 //======================================================
80 // sgnb Subscription spec
82 int request_id = 2; // will be over-written by subscription handler
86 int action_type = config_ref->report_mode_only ? 0:1;
87 int subsequent_action = 0; // continue
88 int time_to_wait = 4; // 10ms
91 int procedure_code = 27;
92 std::string egnb_id = "Testgnb";
93 std::string plmn_id = "Testplmn";
95 unsigned char event_buf[128];
96 size_t event_buf_len = 128;
100 e2sm_event_trigger_helper trigger_data;
101 e2sm_event_trigger event_trigger;
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 //======================================================
111 // Encode the event trigger definition
112 res = event_trigger.encode_event_trigger(&event_buf[0], &event_buf_len, trigger_data);
114 mdclog_write(MDCLOG_ERR, "Error : %s, %d: Could not encode subscription Request. Reason = %s\n", __FILE__, __LINE__, event_trigger.get_error().c_str());
117 mdclog_write(MDCLOG_INFO, "Encoded event trigger definition into PDU of size %lu bytes\n", event_buf_len);
119 // create the subscription
120 subscription_helper sgnb_add_subscr_req;
121 subscription_response_helper subscr_response;
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);
128 sgnb_add_subscr_req.set_event_def(&event_buf[0], event_buf_len);
131 //======================================================
132 // Purely for testing purposes ... write subscription ASN binary to file
134 // pfile = fopen("event_trigger.pr", "wb");
135 // fwrite(event_buf, 1, event_buf_len, pfile);
137 //======================================================
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;
146 for(auto &it: config_ref->gNodeB_list){
148 int subscr_result = -1;
153 std::cout <<"Shutdown signal received during subscription process. Quitting ....." << std::endl;
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){
164 if (attempt > MAX_SUBSCRIPTION_ATTEMPTS){
169 if(subscr_result == SUBSCR_SUCCESS){
170 mdclog_write(MDCLOG_INFO, "Successfully subscribed for gNodeB %s", (it).c_str());
173 failed_gNodeBs.push_back(it);
177 if (failed_gNodeBs.size() == 0){
178 std::cout <<"SUBSCRIPTION REQUEST :: Successfully subscribed to events for all gNodeBs " << std::endl;
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;
191 // Main handle to delete subscription requests
192 // Called upon shutdown
193 void init::shutdown_subscribe_deletes(){
194 std::vector<subscription_identifier> sub_ids;
196 subscription_helper sub_helper;
197 subscription_response_helper subscr_response;
199 // get list of subscriptions
200 sub_handler_ref->get_subscription_keys(sub_ids);
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());
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);
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));
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){
234 int policy_id = RATE_CONTROL_POLICY_ID;
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);
247 // start up subroutines go hear
248 void init::startup(void){
249 startup_subscribe_requests();
250 startup_get_policies();
254 // shutdown subroutines go here
255 void init::shutdown(void ){
256 std::cout <<"Initiating shutdown subroutines ..." << std::endl;
257 shutdown_subscribe_deletes();