6412fd4488eb569e6888b805b063a0ae85f00a2a
[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_):  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 }
35
36
37 bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned char * buffer, size_t *buf_size )
38 {
39   
40   bool res = true;
41   
42   std::lock_guard<std::mutex> lck(*(m_access.get()));
43
44   X2AP_PDU_t * x2ap_recv = 0;
45
46   // /* Decode */
47   asn_dec_rval_t dec_res = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_X2AP_PDU, (void **)&x2ap_recv, msg_ref, msg_size);
48
49   /* Is this an SgNB Addition request ? */
50   if (dec_res.code == RC_OK){
51     if (x2ap_recv->present == X2AP_PDU_PR_initiatingMessage){
52       if (x2ap_recv->choice.initiatingMessage->procedureCode ==  ProcedureCode_id_sgNBAdditionPreparation ){
53         if (x2ap_recv->choice.initiatingMessage->value.present ==  X2InitiatingMessage__value_PR_SgNBAdditionRequest){
54           mdclog_write(MDCLOG_INFO, "Processing X2AP SgNB Addition Request message\n");
55           res = true;
56         }
57         else{
58           mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: X2AP Message (%d) not an SgNB Addition Request\n", __FILE__, __LINE__, x2ap_recv->choice.initiatingMessage->value.present);
59           res = false;
60         }
61       }
62       else{
63         mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: X2AP procedure code  %d does not match required %d\n", __FILE__, __LINE__, x2ap_recv->choice.initiatingMessage->procedureCode, ProcedureCode_id_sgNBAdditionPreparation);
64         res = false;
65       }
66     }
67     else{
68       mdclog_write(MDCLOG_ERR, "Error :: %s, %d:: Not an X2AP initiating message. X2AP Message type %d\n", __FILE__, __LINE__, x2ap_recv->present);
69       res = false;
70     }
71   }
72   else{
73     mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: Could not decode X2AP PDU of size %lu bytes \n", __FILE__, __LINE__, msg_size);
74     res = false;
75   }
76
77   if (res){
78     
79     //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
80     //xer_fprint(stdout,  &asn_DEF_X2AP_PDU, x2ap_recv);
81     //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl;
82
83     res = sgnb_req.get_fields(x2ap_recv->choice.initiatingMessage, sgnb_data);
84     if (!res){
85       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());
86     }
87     
88     if (res){
89       // Admission control
90       
91       m_req ++;
92       // update sliding window
93       m_window_ref.get()->update_window(1);
94       if (m_window_ref.get()->net_events  > m_threshold && m_enforce){
95         res = selectiveBlock();
96       }
97       else{
98         res = true;
99       }
100
101       if (!res){
102           m_rej ++;
103       }
104
105       /*
106         Generate response message 
107         Do we need to do this ? 
108         What if indication is report type ?
109         plugin is agnostic to subscription for now, so yes, we always generate
110         an appropriate response
111       */
112       
113       // generate sgnb addition response message (ack or reject)
114       // if rejecting , we use cause = Misc and sub-cause  = om_intervention
115       sgnb_data.cause = Cause_PR_misc;
116       sgnb_data.cause_desc = CauseMisc_om_intervention;
117       res = sgnb_resp.encode_sgnb_addition_response(buffer, buf_size, sgnb_data, res);
118       if (! res){
119         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());
120       }
121     }
122   }
123
124   ASN_STRUCT_FREE(asn_DEF_X2AP_PDU, x2ap_recv);
125   return res;
126   
127 }
128
129 bool protector::configure(bool enforce, int windowSize_, int threshold_, double blockRate_)
130 {
131   std::lock_guard<std::mutex> lck(*(m_access.get()));
132   
133
134   
135   m_windowSize=windowSize_;
136   bool res = m_window_ref.get()->resize_window(m_windowSize);
137   if (!res){
138     return false;
139   }
140
141   m_enforce = enforce;
142   m_threshold=threshold_;
143   m_blockRate=blockRate_;
144
145   mdclog_write(MDCLOG_INFO, "Policy : Enforce mode set to %d\n", m_enforce);
146   mdclog_write(MDCLOG_INFO, "Policy:  Trigger threshold set to %d\n", m_threshold);
147   mdclog_write(MDCLOG_INFO, "Policy : Blocking rate set to %f\n", m_blockRate);
148   mdclog_write(MDCLOG_INFO, "Policy : Window Size set to %d\n", m_windowSize);
149   return true;
150 }
151
152 unsigned long int protector::get_requests(void) const {
153   return m_req;
154 }
155
156 unsigned long int protector::get_rejects(void) const {
157   return m_rej;
158 }
159
160 void protector::clear()
161 {
162   std::lock_guard<std::mutex> lck(*(m_access.get()));
163   m_req = 0;
164   m_rej = 0;
165   m_window_ref.get()->clear();
166 }
167
168
169 bool protector::selectiveBlock() 
170 {
171   unsigned int num = (rand() % 100) + 1;    
172   if (num > m_blockRate)  //not blocking
173     return true;
174   else                    //blocking
175     return false;
176 }
177