X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fprotector-plugin%2FNetworkProtector.cc;h=bdd6016f6a0ee550d536612845f60346dbdfdb62;hb=refs%2Fchanges%2F01%2F2001%2F2;hp=6412fd4488eb569e6888b805b063a0ae85f00a2a;hpb=b9d7e9c232a4371ddfed51c58e5a57f87b057229;p=ric-app%2Fadmin.git diff --git a/src/protector-plugin/NetworkProtector.cc b/src/protector-plugin/NetworkProtector.cc index 6412fd4..bdd6016 100644 --- a/src/protector-plugin/NetworkProtector.cc +++ b/src/protector-plugin/NetworkProtector.cc @@ -26,32 +26,47 @@ #include // For srand() and rand() -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) -{ - m_counter = 0; - m_window_ref = std::make_unique(m_windowSize); +protector::protector( bool report){ m_access = std::make_unique(); + report_mode_only = report; + + // there is always a default policy with id 0 (never gets deleted, can only be re-configured) + // default values from policy constructor will be used. + policy_list.insert(std::pair(0, protector_policy())); + } +// constructor that over-rides default values for policy 0 +protector::protector( bool enforce, int window_size, int threshold, double blocking_rate, bool report){ + m_access = std::make_unique(); + report_mode_only = report; -bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned char * buffer, size_t *buf_size ) -{ + // there is always a default policy with id 0 (never gets deleted, can only be re-configured) + policy_list.insert(std::pair(0, protector_policy(enforce, window_size, threshold, blocking_rate))); + +} + + +bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned char * buffer, size_t *buf_size ){ bool res = true; + protector_policy * policy_ref; std::lock_guard lck(*(m_access.get())); - - X2AP_PDU_t * x2ap_recv = 0; - + + X2N_X2AP_PDU_t * x2ap_recv = 0; + asn_dec_rval_t dec_res; + // /* Decode */ - asn_dec_rval_t dec_res = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_X2AP_PDU, (void **)&x2ap_recv, msg_ref, msg_size); - - /* Is this an SgNB Addition request ? */ + dec_res = asn_decode(0,ATS_ALIGNED_BASIC_PER, &asn_DEF_X2N_X2AP_PDU, (void **)&x2ap_recv, msg_ref, msg_size); + if (dec_res.code == RC_OK){ - if (x2ap_recv->present == X2AP_PDU_PR_initiatingMessage){ - if (x2ap_recv->choice.initiatingMessage->procedureCode == ProcedureCode_id_sgNBAdditionPreparation ){ - if (x2ap_recv->choice.initiatingMessage->value.present == X2InitiatingMessage__value_PR_SgNBAdditionRequest){ - mdclog_write(MDCLOG_INFO, "Processing X2AP SgNB Addition Request message\n"); + /* Is this an SgNB Addition request ? */ + mdclog_write(MDCLOG_DEBUG, "Decoded X2AP PDU successfully. Processing X2 message fields to ascertain type etc ...\n"); + if (x2ap_recv->present == X2N_X2AP_PDU_PR_initiatingMessage){ + if (x2ap_recv->choice.initiatingMessage->procedureCode == X2N_ProcedureCode_id_sgNBAdditionPreparation ){ + if (x2ap_recv->choice.initiatingMessage->value.present == X2N_InitiatingMessage__value_PR_SgNBAdditionRequest){ + mdclog_write(MDCLOG_DEBUG, "Processing X2AP SgNB Addition Request message\n"); res = true; } else{ @@ -60,7 +75,7 @@ bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned cha } } else{ - 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); + 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); res = false; } } @@ -70,12 +85,14 @@ bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned cha } } else{ - mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: Could not decode X2AP PDU of size %lu bytes \n", __FILE__, __LINE__, msg_size); + mdclog_write(MDCLOG_ERR, "Error :: %s, %d :: Could not decode X2AP PDU of size %lu bytes\n", __FILE__, __LINE__, msg_size); res = false; } - + if (res){ + mdclog_write(MDCLOG_DEBUG, "Extracting SgNB Addition Request fields..."); + //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl; //xer_fprint(stdout, &asn_DEF_X2AP_PDU, x2ap_recv); //std::cout <<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << std::endl; @@ -86,90 +103,299 @@ bool protector::operator()(unsigned char *msg_ref, size_t msg_size, unsigned cha } if (res){ - // Admission control + mdclog_write(MDCLOG_DEBUG, "Decoded and extracted X2AP PDU data. Number of erabs = %lu\n", sgnb_data.get_list()->size()); + mdclog_write(MDCLOG_DEBUG, "Applying admission control logic ..."); + + // Find if policy associated with this subscription id + auto it_policy = policy_list.find(sgnb_data.subscriber_profile_id); - m_req ++; - // update sliding window - m_window_ref.get()->update_window(1); - if (m_window_ref.get()->net_events > m_threshold && m_enforce){ - res = selectiveBlock(); + if (it_policy == policy_list.end()){ + // apply default policy + policy_ref = & policy_list[0]; + } + else{ + policy_ref = & (it_policy->second); + } + + net_requests ++; + policy_ref->_req++; + policy_ref->_window_ref.get()->update_window(1); + + // apply blocking probability if m_enforce + if ( policy_ref->_enforce && policy_ref->_window_ref.get()->net_events > policy_ref->_threshold){ + res = selectiveBlock(policy_ref->_block_rate); } else{ res = true; } if (!res){ - m_rej ++; + policy_ref->_rej ++; + net_rejects ++; } - + + mdclog_write(MDCLOG_DEBUG, "Plugin decision for sgnb request = %d\n", res); + /* - Generate response message - Do we need to do this ? - What if indication is report type ? - plugin is agnostic to subscription for now, so yes, we always generate - an appropriate response + Generate response message if flag is set */ - // generate sgnb addition response message (ack or reject) - // if rejecting , we use cause = Misc and sub-cause = om_intervention - sgnb_data.cause = Cause_PR_misc; - sgnb_data.cause_desc = CauseMisc_om_intervention; - res = sgnb_resp.encode_sgnb_addition_response(buffer, buf_size, sgnb_data, res); - if (! res){ - 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()); + if(! report_mode_only){ + // generate sgnb addition response message (ack or reject) + // if rejecting , we use cause = Misc and sub-cause = om_intervention + mdclog_write(MDCLOG_DEBUG, "Generating X2AP response ..\n"); + sgnb_data.cause = X2N_Cause_PR_misc; + sgnb_data.cause_desc = X2N_CauseMisc_om_intervention; + try{ + res = sgnb_resp.encode_sgnb_addition_response(buffer, buf_size, sgnb_data, res); + if (! res){ + 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()); + } + } + catch(std::exception &e){ + mdclog_write(MDCLOG_ERR, "Error:: %s, %d : Caught exception %s\n", __FILE__, __LINE__, e.what()); + } + + } + else{ + res = true; } } } - - ASN_STRUCT_FREE(asn_DEF_X2AP_PDU, x2ap_recv); + + + ASN_STRUCT_FREE(asn_DEF_X2N_X2AP_PDU, x2ap_recv); return res; } - -bool protector::configure(bool enforce, int windowSize_, int threshold_, double blockRate_) -{ + +// configure an existing policy +bool protector::configure(bool enforce, int windowSize_, int threshold_, double blockRate_, int id){ std::lock_guard lck(*(m_access.get())); + std::stringstream ss; + // basic validation of input + if(windowSize_ <= 0){ + ss << "Illegal value for window size = " << windowSize_ << " when configuring policy " << std::endl; + error_string = ss.str(); + return false; + } + if(threshold_ < 0){ + ss << "Illegal value for trigger threshold = " << threshold_ << " when configuring policy " << std::endl; + error_string = ss.str(); + return false; + } + + if(blockRate_ < 0 || blockRate_ > 100){ + ss << "Illegal value for blocking rate = " << blockRate_ << " when configuring policy " << std::endl; + error_string = ss.str(); + return false; + } + if (id < 0){ + ss << "Illegal value for class id = " << id << " when configuring policy " << std::endl; + error_string = ss.str(); + return false; + } + + // find policy + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + mdclog_write(MDCLOG_ERR, "Error : %s, %d : No policy with id %d found for configuration\n", __FILE__, __LINE__, id); + return false; + } - m_windowSize=windowSize_; - bool res = m_window_ref.get()->resize_window(m_windowSize); + bool res = policy_it->second._window_ref.get()->resize_window(windowSize_); if (!res){ + error_string = policy_it->second._window_ref.get()->get_error(); + return false; + } + policy_it->second._window_size = windowSize_; + + // enforce is set globally + policy_it->second._enforce = enforce; + + policy_it->second._threshold=threshold_; + policy_it->second._block_rate=blockRate_; + mdclog_write(MDCLOG_DEBUG, "Configured policy with id %d with enforce=%d, window size = %d, threshold = %d, blocking rate = %f\n", id, policy_it->second._enforce, policy_it->second._window_size, policy_it->second._threshold, policy_it->second._block_rate); + + return true; +} + +// add a policy +bool protector::add_policy(bool enforce, int windowSize_, int threshold_, double blockRate_, int id){ + std::lock_guard lck(*(m_access.get())); + std::stringstream ss; + + + // find policy + auto policy_it = policy_list.find(id); + if (policy_it != policy_list.end()){ + ss <<"Error : " << __FILE__ << "," << __LINE__ << ": " << "Policy with id " << id << " already exists. Cannot be added" << std::endl; + error_string = ss.str(); + mdclog_write(MDCLOG_ERR, "%s\n", error_string.c_str()); + return false; + } + + // basic validation of input + if(windowSize_ <= 0){ + ss << "Illegal value for window size = " << windowSize_ << " when adding policy " << std::endl; + error_string = ss.str(); + return false; + } + if(threshold_ < 0){ + ss << "Illegal value for trigger threshold = " << threshold_ << " when adding policy " << std::endl; + error_string = ss.str(); return false; } - m_enforce = enforce; - m_threshold=threshold_; - m_blockRate=blockRate_; + if(blockRate_ < 0 || blockRate_ > 100){ + ss << "Illegal value for blocking rate = " << blockRate_ << " when adding policy " << std::endl; + error_string = ss.str(); + return false; + } + if (id < 0){ + ss << "Illegal value for class id = " << id << " when adding policy " << std::endl; + error_string = ss.str(); + return false; + } + + + // create the policy + try{ + policy_list.insert(std::pair (id, protector_policy(enforce, windowSize_, threshold_, blockRate_))); + } + catch(std::exception &e){ + ss <<"Error : " << __FILE__ << "," << __LINE__ << ": " << "Error creating policy. Reason = " << e.what() << std::endl; + error_string = ss.str(); + mdclog_write(MDCLOG_ERR, "%s\n", error_string.c_str()); + return false; + } + + mdclog_write(MDCLOG_DEBUG, "Added new policy with id %d with enforce=%d, window size = %d, threshold = %d, blocking rate = %f\n", id, enforce, windowSize_, threshold_, blockRate_); - mdclog_write(MDCLOG_INFO, "Policy : Enforce mode set to %d\n", m_enforce); - mdclog_write(MDCLOG_INFO, "Policy: Trigger threshold set to %d\n", m_threshold); - mdclog_write(MDCLOG_INFO, "Policy : Blocking rate set to %f\n", m_blockRate); - mdclog_write(MDCLOG_INFO, "Policy : Window Size set to %d\n", m_windowSize); return true; } -unsigned long int protector::get_requests(void) const { - return m_req; +// delete a policy +bool protector::delete_policy(int id){ + std::lock_guard lck(*(m_access.get())); + std::stringstream ss; + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + ss <<"Error : " << __FILE__ << "," << __LINE__ << ": " << " No policy with id = " << id << " found" << std::endl; + error_string = ss.str(); + mdclog_write(MDCLOG_ERR, "%s\n", error_string.c_str()); + return false; + } + + policy_list.erase(policy_it); + mdclog_write(MDCLOG_DEBUG, "Deleted policy %d\n", id); + return true; } -unsigned long int protector::get_rejects(void) const { - return m_rej; + +// query a policy : responsibility of caller to ensure +// vector is empty +// returns parameters of policy in the vector +bool protector::query_policy(int id, std::vector & info){ + + std::lock_guard lck(*(m_access.get())); + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + return false; + } + + info.push_back(policy_it->second._enforce); + info.push_back(policy_it->second._window_size); + info.push_back(policy_it->second._threshold); + info.push_back(policy_it->second._block_rate); + return true; } +// returns requests that fall under a policy +// if id is -1, returns total requests +// if non-existent policy, returns -1 +// counters are cumulative +long int protector::get_requests(int id) const { + if (id == -1){ + return net_requests; + } + + std::lock_guard lck(*(m_access.get())); + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + return -1; + } + else{ + return policy_it->second._req; + } + +} + +// returns requests that fall under a policy +// if id is -1 , returns total rejects +// if non-existent policy, returns -1 +// counters are cumulative +long int protector::get_rejects(int id) const { + + if (id == -1){ + return net_rejects; + } + + std::lock_guard lck(*(m_access.get())); + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + return -1; + } + else{ + return policy_it->second._rej; + } + +} + +// returns list of active policies in +// supplied vector (policy is indexed by subscriber profile id) +void protector::get_active_policies(std::vector & active){ + std::lock_guard lck(*(m_access.get())); + for (const auto &e : policy_list){ + active.push_back(e.first); + } +} + +// returns true if policy active else false +bool protector::is_active(int id){ + auto policy_it = policy_list.find(id); + if (policy_it == policy_list.end()){ + return false; + } + else{ + return true; + } +} + +// clears counters for all policies void protector::clear() { + std::lock_guard lck(*(m_access.get())); - m_req = 0; - m_rej = 0; - m_window_ref.get()->clear(); + + for(auto &e : policy_list){ + e.second._window_ref.get()->clear(); + e.second._counter = 0; + e.second._req = 0; + e.second._rej = 0; + } + + net_requests = 0; + net_rejects = 0; } -bool protector::selectiveBlock() +bool protector::selectiveBlock(double block_rate) { unsigned int num = (rand() % 100) + 1; - if (num > m_blockRate) //not blocking + if (num > block_rate) //not blocking return true; else //blocking return false;