b3e82f3b7a499ee8fdc7dd9d578e92babf3f764f
[ric-app/admin.git] / src / protector-plugin / NetworkProtector.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
20
21 #include "NetworkProtector.h"
22
23
24 #include <mutex>          // std::mutex
25 #include <ctime>    // For time()
26 #include <cstdlib>  // For srand() and rand()
27
28
29 protector::protector(bool enforce,   int windowSize_, int threshold_, double blockRate_, bool report):  m_enforce(enforce),  m_windowSize(windowSize_), m_threshold(threshold_), m_blockRate(blockRate_), m_req(0), m_rej(0)
30 {       
31   m_counter = 0;
32   m_window_ref = std::make_unique<sliding_window>(m_windowSize);
33   m_access = std::make_unique<std::mutex>();
34   report_mode_only = report;
35 }
36
37
38 bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned char * buffer, size_t *buf_size )
39 {
40   
41   bool res = true;
42   
43   std::lock_guard<std::mutex> lck(*(m_access.get()));
44   
45   X2N_X2AP_PDU_t * x2ap_recv = 0;
46   asn_dec_rval_t dec_res;
47   
48   // /* Decode */
49   dec_res = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_X2N_X2AP_PDU, (void **)&x2ap_recv, msg_ref, msg_size);
50   
51   if (dec_res.code == RC_OK){
52     /* Is this an SgNB Addition request ? */
53     mdclog_write(MDCLOG_DEBUG, "Decoded X2AP PDU successfully. Processing X2 message fields to ascertain type etc ...\n");
54     if (x2ap_recv->present == X2N_X2AP_PDU_PR_initiatingMessage){
55       if (x2ap_recv->choice.initiatingMessage->procedureCode ==  X2N_ProcedureCode_id_sgNBAdditionPreparation ){
56         if (x2ap_recv->choice.initiatingMessage->value.present ==  X2N_InitiatingMessage__value_PR_SgNBAdditionRequest){
57           mdclog_write(MDCLOG_DEBUG, "Processing X2AP SgNB Addition Request message\n");
58           res = true;
59         }
60         else{
61           mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: X2AP Message (%d) not an SgNB Addition Request\n", __FILE__, __LINE__, x2ap_recv->choice.initiatingMessage->value.present);
62           res = false;
63         }
64       }
65       else{
66         mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: X2AP procedure code  %ld does not match required %ld\n", __FILE__, __LINE__, x2ap_recv->choice.initiatingMessage->procedureCode, X2N_ProcedureCode_id_sgNBAdditionPreparation);
67         res = false;
68       }
69     }
70     else{
71       mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: Not an X2AP initiating message. X2AP Message type %d\n", __FILE__, __LINE__, x2ap_recv->present);
72       res = false;
73     }
74   }
75   else{
76     mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: Could not decode X2AP PDU of size %lu bytes\n", __FILE__, __LINE__, msg_size);
77     res = false;
78   }
79   
80   if (res){
81
82     mdclog_write(MDCLOG_DEBUG, "Extracting SgNB Addition Request fields...");
83
84     //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
85     //xer_fprint(stdout,  &asn_DEF_X2AP_PDU, x2ap_recv);
86     //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
87
88     res = sgnb_req.get_fields(x2ap_recv->choice.initiatingMessage, sgnb_data);
89     if (!res){
90       mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: could not get  fields from SgNB Addition Request. Reason = %s\n", __FILE__, __LINE__, sgnb_req.get_error().c_str());
91     }
92     
93     if (res){
94       mdclog_write(MDCLOG_DEBUG, "Decoded and extracted X2AP PDU data. Number of erabs = %u\n", sgnb_data.get_list()->size());
95       mdclog_write(MDCLOG_DEBUG, "Applying admission control logic ...");
96
97       // Admission control  
98       m_req ++;
99
100       // update sliding window
101       m_window_ref.get()->update_window(1);
102       if ( m_enforce && m_window_ref.get()->net_events  > m_threshold){
103         res = selectiveBlock();
104       }
105       else{
106         res = true;
107       }
108
109       if (!res){
110           m_rej ++;
111       }
112       
113       mdclog_write(MDCLOG_DEBUG, "Plugin decision for sgnb request = %d\n", res);
114       
115       /*
116         Generate response message if flag is set
117       */
118       
119       if(! report_mode_only){
120         // generate sgnb addition response message (ack or reject)
121         // if rejecting , we use cause = Misc and sub-cause  = om_intervention
122         mdclog_write(MDCLOG_DEBUG, "Generating X2AP response ..\n");
123         sgnb_data.cause = X2N_Cause_PR_misc;
124         sgnb_data.cause_desc = X2N_CauseMisc_om_intervention;
125         try{
126           res = sgnb_resp.encode_sgnb_addition_response(buffer, buf_size, sgnb_data, res);
127           if (! res){
128             mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: could not encode SgNB Addition Response PDU. Reason = %s\n", __FILE__, __LINE__, sgnb_resp.get_error().c_str());
129           }
130         }
131         catch(std::exception &e){
132           mdclog_write(MDCLOG_ERR, "Error:: %s, %d : Caught exception %s\n", __FILE__, __LINE__, e.what());
133         }
134         
135       }
136       else{
137         res = true;
138       }
139     }
140   }
141
142   ASN_STRUCT_FREE(asn_DEF_X2N_X2AP_PDU, x2ap_recv);
143   return res;
144   
145 }
146
147 bool protector::configure(bool enforce, int windowSize_, int threshold_, double blockRate_)
148 {
149   std::lock_guard<std::mutex> lck(*(m_access.get()));
150   
151
152   
153   m_windowSize=windowSize_;
154   bool res = m_window_ref.get()->resize_window(m_windowSize);
155   if (!res){
156     return false;
157   }
158
159   m_enforce = enforce;
160   m_threshold=threshold_;
161   m_blockRate=blockRate_;
162
163   mdclog_write(MDCLOG_INFO, "Policy : Enforce mode set to %d\n", m_enforce);
164   mdclog_write(MDCLOG_INFO, "Policy:  Trigger threshold set to %d\n", m_threshold);
165   mdclog_write(MDCLOG_INFO, "Policy : Blocking rate set to %f\n", m_blockRate);
166   mdclog_write(MDCLOG_INFO, "Policy : Window Size set to %d\n", m_windowSize);
167   return true;
168 }
169
170 unsigned long int protector::get_requests(void) const {
171   return m_req;
172 }
173
174 unsigned long int protector::get_rejects(void) const {
175   return m_rej;
176 }
177
178 void protector::clear()
179 {
180   std::lock_guard<std::mutex> lck(*(m_access.get()));
181   m_req = 0;
182   m_rej = 0;
183   m_window_ref.get()->clear();
184 }
185
186
187 bool protector::selectiveBlock() 
188 {
189   unsigned int num = (rand() % 100) + 1;    
190   if (num > m_blockRate)  //not blocking
191     return true;
192   else                    //blocking
193     return false;
194 }
195