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 ==================================================================================
21 #include "admission_policy.hpp"
22 admission::admission (std::string policy_schema_file, std::string samples_file, std::string metrics_schema_file, unsigned int num_instances, bool report_only){
25 if (num_instances == 0){
26 throw std::runtime_error("Error ! Number of instances of admission_policy protector pluging must be > 0");
31 std::string error_string;
33 std::vector<TrieNode> config_schema_path;
35 config_schema_path.clear();
37 // path to node in schema to process policy request
38 config_schema_path.emplace_back("controls");
39 config_schema_path.emplace_back((int)0);
40 config_schema_path.emplace_back("message_receives_payload_schema");
41 config_schema_path[0].add_child(&config_schema_path[1]);
42 config_schema_path[1].add_child(&config_schema_path[2]);
44 set_policy_req_obj.load_schema(policy_schema_file, &config_schema_path[0]);
45 // mdclog_write(MDCLOG_INFO, "Loaded schema for set Policy request");
47 //path to node in schema to process policy response
48 config_schema_path.clear();
49 config_schema_path.emplace_back("controls");
50 config_schema_path.emplace_back(0);
51 config_schema_path.emplace_back("message_sends_payload_schema");
52 config_schema_path[0].add_child(&config_schema_path[1]);
53 config_schema_path[1].add_child(&config_schema_path[2]);
55 set_policy_resp_obj.load_schema(policy_schema_file, &config_schema_path[0]);
56 mdclog_write(MDCLOG_INFO, "Loaded schema for set Policy response");
58 // load sample response
59 config_schema_path.clear();
60 config_schema_path.emplace_back("message_sends_example");
62 set_policy_resp_obj.load_buffer(samples_file, &config_schema_path[0]);
64 // verify that our sample conforms to the schema ...
65 buffer = set_policy_resp_obj.get_buffer();
66 if (! set_policy_resp_obj.is_valid(buffer.c_str(), buffer.length(), response)){
68 ss << "Error ! Sample loaded for SET policy response = " << buffer << " from file " << samples_file << " not valid. Reason = " << response;
69 throw std::runtime_error(ss.str());
71 mdclog_write(MDCLOG_INFO, "Verified sample for set Policy response");
73 // path to node in schema to respond to get policy (current same as set policy)
74 config_schema_path.clear();
75 config_schema_path.emplace_back("controls");
76 config_schema_path.emplace_back(0);
77 config_schema_path.emplace_back("message_receives_payload_schema");
78 config_schema_path[0].add_child(&config_schema_path[1]);
79 config_schema_path[1].add_child(&config_schema_path[2]);
81 get_policy_resp_obj.load_schema(policy_schema_file, &config_schema_path[0]);
82 mdclog_write(MDCLOG_INFO, "Loaded schema for get Policy response");
85 // sample to respond to get policy
86 config_schema_path.clear();
87 config_schema_path.emplace_back("message_receives_example");
89 get_policy_resp_obj.load_buffer(samples_file, &config_schema_path[0]);
91 // verify that our sample conforms to schema
92 buffer = get_policy_resp_obj.get_buffer();
93 if (! get_policy_resp_obj.is_valid(buffer.c_str(), buffer.length(), response)){
95 ss << "Error ! Sample loaded for GET policy response = " << buffer << " from file " << samples_file << " not valid. Reason = " << response;
96 throw std::runtime_error(ss.str());
100 mdclog_write(MDCLOG_INFO, "Verified sample for get Policy response");
102 // schema & sample for metrics
103 metrics_obj.load_schema(metrics_schema_file);
104 mdclog_write(MDCLOG_INFO, "Loaded schema for ves metrics");
106 config_schema_path.clear();
107 config_schema_path.emplace_back("metrics");
109 metrics_obj.load_buffer(samples_file, &config_schema_path[0]);
111 // verify sample conforms to schema
112 buffer = metrics_obj.get_buffer();
113 if (! metrics_obj.is_valid(buffer.c_str(), buffer.length(), response)){
114 std::stringstream ss;
115 ss << "Error ! Sample loaded for VES = " << buffer << " from file " << samples_file << " not valid. Reason = " << response;
116 throw std::runtime_error(ss.str());
119 mdclog_write(MDCLOG_INFO, "Verified sample for metrics");
124 //instantiate the core policy object
125 for(unsigned int i = 0; i < num_instances; i++){
126 instantiate_protector_plugin(report_only);
131 void admission::instantiate_protector_plugin(bool mode){
132 _plugin_instances.emplace_back(bool(current_config["enforce"]), current_config["window_length"], current_config["trigger_threshold"], current_config["blocking_rate"], mode);
135 admission::~admission(void){
139 set_policy_response.clear();
140 get_policy_response.clear();
141 metric_responses.clear();
142 policy_pointer.clear();
146 std::string admission::getName(void){
147 return std::string("admission control policy");
150 void admission::setPolicyVars(void){
153 // keys in request to set policy
154 policy_vars.emplace_back("enforce");
155 policy_vars.emplace_back("window_length");
156 policy_vars.emplace_back("blocking_rate");
157 policy_vars.emplace_back("trigger_threshold");
160 // keys in response to set policy
161 set_policy_response.emplace_back("status");
162 set_policy_response.emplace_back("message");
165 policy_pointer.push_back(&policy_vars[0]);
166 policy_pointer.push_back(&policy_vars[1]);
167 policy_pointer.push_back(&policy_vars[2]);
168 policy_pointer.push_back(&policy_vars[3]);
171 // keys in metric response
172 metric_responses.emplace_back("event"); // 0
173 metric_responses.emplace_back("commonEventHeader"); // 1
174 metric_responses.emplace_back("measurementFields"); // 2
175 metric_responses.emplace_back("additionalFields"); // 3
176 metric_responses.emplace_back("SgNB Request Rate"); // 4
177 metric_responses.emplace_back("SgNB Accept Rate"); // 5
178 metric_responses.emplace_back("startEpochMicrosec"); // 6
179 metric_responses.emplace_back("measurementInterval"); // 7
180 metric_responses.emplace_back("lastEpochMicrosec");//8
181 //metric_responses.emplace_back("TS"); //9
183 metric_responses[0].add_child(&metric_responses[1]);
184 metric_responses[0].add_child(&metric_responses[2]);
186 metric_responses[1].add_child(&metric_responses[6]);
187 metric_responses[1].add_child(&metric_responses[8]);
189 metric_responses[2].add_child(&metric_responses[3]);
190 metric_responses[2].add_child(&metric_responses[7]);
192 metric_responses[3].add_child(&metric_responses[4]);
193 metric_responses[3].add_child(&metric_responses[5]);
194 //metric_responses[3].add_child(&metric_responses[9]);
196 // default config map for the policy object
197 current_config.insert(std::pair<std::string, int>("enforce", 1));
198 current_config.insert(std::pair<std::string, int>("window_length", 60));
199 current_config.insert(std::pair<std::string, int>("blocking_rate", 1));
200 current_config.insert(std::pair<std::string, int>("trigger_threshold", 1));
202 prev_config = current_config;
204 auto ts = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
205 auto epoch = ts.time_since_epoch();
206 auto val = std::chrono::duration_cast<std::chrono::microseconds>(epoch);
207 prev_time_stamp = val.count();
208 prev_values.push_back(0);
209 prev_values.push_back(0);
210 curr_values = prev_values;
213 protector * admission::get_protector_instance(unsigned int index){
214 if (index > _plugin_instances.size() -1){
215 mdclog_write(MDCLOG_ERR, "%s, %d: Error . Requested index %u exceeds number of plugin instances %u", __FILE__, __LINE__, index, _plugin_instances.size());
219 return &_plugin_instances[index];
225 bool admission::setPolicy(const char * message, int message_length, std::string & response){
227 // Get the configuration
228 std::vector<TrieNode*> available_keys;
229 std::vector<TrieNode*> roots;
232 std::vector<TrieNode*>resp_pointer;
233 resp_pointer.push_back(&set_policy_response[0]);
234 resp_pointer.push_back(&set_policy_response[1]);
236 std::string local_response;
237 for(unsigned int i = 0; i < policy_vars.size(); i++){
238 int res = set_policy_req_obj.get_values(message, message_length, local_response, &policy_vars[i], available_keys);
240 setError(local_response);
241 set_policy_response[0].set_value("FAIL");
242 set_policy_response[1].set_value(local_response);
243 set_policy_resp_obj.set_values(response, resp_pointer);
249 if ( available_keys.size() == 0){
250 local_response = "No Keys were found";
251 setError(local_response);
252 set_policy_response[0].set_value("FAIL");
253 set_policy_response[1].set_value(local_response);
255 set_policy_resp_obj.set_values(response,resp_pointer);
261 prev_config = current_config;
263 for(std::vector<TrieNode *>::iterator it = available_keys.begin(); it != available_keys.end(); ++it){
264 DataContainer const * id = (*it)->get_id();
265 DataContainer const * val = (*it)->get_value();
266 auto e = current_config.find(id->value.s.c_str());
267 if (e != current_config.end()){
268 e->second = val->value.i;
273 // Note : xapp schema specifies window be in 'minutes'. Sliding window implementation maintains in seconds, hence multiply by 60
274 current_config["window_length"] *= 60;
278 for(std::vector<protector>::iterator it_p = _plugin_instances.begin(); it_p != _plugin_instances.end(); ++it_p){
280 res = (*it_p).configure( bool(current_config["enforce"]), current_config["window_length"], current_config["trigger_threshold"], current_config["blocking_rate"]);
282 mdclog_write(MDCLOG_ERR, "Error ::%s, %d :: Could not configure plugin\n", __FILE__, __LINE__);
283 set_policy_response[0].set_value("FAIL");
284 set_policy_response[1].set_value("Could not apply configuration");
290 set_policy_response[0].set_value("SUCCESS");
291 set_policy_response[1].set_value("configuration applied");
294 set_policy_resp_obj.set_values(response,resp_pointer);
299 bool admission::getPolicy(const char * message, int message_length, std::string & response){
301 // Note : by same token, when returning sliding window length : translate to
303 policy_vars[0].set_value(bool(current_config["enforce"]));
304 policy_vars[1].set_value((int)( (double)current_config["window_length"]/60.0));
305 policy_vars[2].set_value(current_config["blocking_rate"]);
306 policy_vars[3].set_value(current_config["trigger_threshold"]);
308 int res = get_policy_resp_obj.set_values(response, policy_pointer);
314 int admission::getMetrics(std::string & response){
315 std::vector<TrieNode *> metric_pointers;
316 metric_pointers.push_back(&metric_responses[0]);
318 auto ts = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
319 auto epoch = ts.time_since_epoch();
320 auto val_ms = std::chrono::duration_cast<std::chrono::microseconds>(epoch);
321 auto val_s = std::chrono::duration_cast<std::chrono::seconds>(epoch);
323 long int current_time_stamp = val_ms.count();
324 long int current_time = val_s.count();
325 long int interval = current_time_stamp - prev_time_stamp;
328 curr_values[0] = _plugin_instances[0].get_requests();
329 curr_values[1] = _plugin_instances[0].get_rejects();
331 //curr_values[0] = rand()%100 + prev_values[0];
332 //curr_values[1] = rand()%20 + prev_values[1];
334 //std::cout <<" Accept counter = " << curr_values[0]<< " Reject counter = " << curr_values[1] << " Request Count = " << (curr_values[0] - prev_values[0]) << " Reject count = " << curr_values[1] - prev_values[1] << std::endl;
336 metric_responses[4].set_value(std::to_string(curr_values[0] - prev_values[0]));
337 metric_responses[5].set_value(std::to_string((curr_values[0] - prev_values[0]) - (curr_values[1] - prev_values[1])));
338 metric_responses[6].set_value(prev_time_stamp);
339 metric_responses[8].set_value(current_time_stamp);
340 metric_responses[7].set_value(interval);
341 //metric_responses[9].set_value(current_time);
343 prev_values = curr_values;
344 prev_time_stamp = current_time_stamp;
345 int res = metrics_obj.set_values(response, metric_pointers);