Skip to content

Commit

Permalink
Install redirection rule with info in CCA
Browse files Browse the repository at this point in the history
Summary:
**Context**
Previously, session manager did not take action when the `FinalUnitAction` was `REDIRECT` although the related information `RedirectServer` was passed from FeG. In this diff, session manager stores the information and pass it to `LocalEnforcer` to install corresponding redirect rule.

**Implementation**
1. Store `RedirectServer` in the `SessionCredit` object when receiving charging credits (Gy)
2. Pass `RedirectServer` up to `LocalEnforcer` through the `ServiceAction` object when `LocalEnforcer` is checking if updates are required (quota exhaustion). Some cleaning up and refactoring were done since we never pass so many parameters from `SessionCredit` to LocalEnforcer before.
3. In `LocalEnforcer`, retrieve `RedirectServer` and other information, and install redirect rule through pipelined client.

**What is affected**
Existing functionality should not be affected.
OCS initiated redirection should work now.

Reviewed By: emakeev

Differential Revision: D17086278

fbshipit-source-id: 86b311064dc32602e9457622063ed9ae6b3a3e1e
  • Loading branch information
fishlinghu authored and facebook-github-bot committed Sep 4, 2019
1 parent 51c4921 commit 19614ca
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 97 deletions.
114 changes: 89 additions & 25 deletions lte/gateway/c/session_manager/CreditPool.cpp
Expand Up @@ -66,17 +66,46 @@ static CreditUsage::UpdateType convert_update_type_to_proto(
return CreditUsage::QUOTA_EXHAUSTED;
}

template<typename KeyType>
static void populate_output_actions(
std::string imsi,
std::string ip_addr,
KeyType key,
SessionRules *session_rules,
std::unique_ptr<ServiceAction> &action,
std::vector<std::unique_ptr<ServiceAction>> *actions_out)
{
action->set_imsi(imsi);
action->set_ip_addr(ip_addr);
session_rules->add_rules_to_action(*action, key);
actions_out->push_back(std::move(action));
}

void ChargingCreditPool::get_updates(
std::string imsi,
std::string ip_addr,
SessionRules *session_rules,
std::vector<CreditUsage> *updates_out,
std::vector<ActionPair<uint32_t>> *actions_out)
std::vector<std::unique_ptr<ServiceAction>> *actions_out)
{
for (auto &credit_pair : credit_map_) {
auto &credit = *(credit_pair.second);
auto action_type = credit.get_action();
if (action_type != CONTINUE_SERVICE) {
MLOG(MDEBUG) << "Subscriber " << imsi_ << " rating group "
<< credit_pair.first << " action type " << action_type;
actions_out->emplace_back(credit_pair.first, action_type);
auto action = std::make_unique<ServiceAction>(action_type);
if (action_type == REDIRECT) {
action->set_rating_group(credit_pair.first);
action->set_redirect_server(credit.get_redirect_server());
}
populate_output_actions(
imsi,
ip_addr,
credit_pair.first,
session_rules,
action,
actions_out);
} else {
auto update_type = credit.get_update_type();
if (update_type != CREDIT_NO_UPDATE) {
Expand Down Expand Up @@ -110,19 +139,37 @@ static uint64_t get_granted_units(const CreditUnit &unit, uint64_t default_val)
return unit.is_valid() ? unit.volume() : default_val;
}

static void receive_credit_with_default(
static SessionCredit::FinalActionInfo get_final_action_info(
const ChargingCredit &credit)
{
SessionCredit::FinalActionInfo final_action_info;
if (credit.is_final()) {
final_action_info.final_action = credit.final_action();
if (credit.final_action() == ChargingCredit_FinalAction_REDIRECT) {
final_action_info.redirect_server = credit.redirect_server();
}
}

return final_action_info;
}

static void receive_charging_credit_with_default(
SessionCredit &credit,
const GrantedUnits &gsu,
uint64_t default_volume,
uint32_t validity_time,
bool is_final,
ChargingCredit_FinalAction final_action)
const ChargingCredit &charging_credit)
{
uint64_t total = get_granted_units(gsu.total(), default_volume);
uint64_t tx = get_granted_units(gsu.tx(), default_volume);
uint64_t rx = get_granted_units(gsu.rx(), default_volume);

credit.receive_credit(total, tx, rx, validity_time, is_final, final_action);
credit.receive_credit(
total,
tx,
rx,
charging_credit.validity_time(),
charging_credit.is_final(),
get_final_action_info(charging_credit));
}

bool ChargingCreditPool::init_new_credit(const CreditUpdateResponse &update)
Expand All @@ -141,13 +188,11 @@ bool ChargingCreditPool::init_new_credit(const CreditUpdateResponse &update)
*/
uint64_t default_volume = 0;
auto credit = std::make_unique<SessionCredit>();
receive_credit_with_default(
receive_charging_credit_with_default(
*credit,
update.credit().granted_units(),
default_volume,
update.credit().validity_time(),
update.credit().is_final(),
update.credit().final_action());
update.credit());
credit_map_[update.charging_key()] = std::move(credit);
return true;
}
Expand All @@ -172,13 +217,11 @@ bool ChargingCreditPool::receive_credit(const CreditUpdateResponse &update)
<< "for subscriber " << imsi_ << " rating group "
<< update.charging_key();
uint64_t default_volume = 0; // default to not increasing credit
receive_credit_with_default(
receive_charging_credit_with_default(
*(it->second),
gsu,
default_volume,
update.credit().validity_time(),
update.credit().is_final(),
update.credit().final_action());
update.credit());
return true;
}

Expand Down Expand Up @@ -229,6 +272,21 @@ UsageMonitoringCreditPool::UsageMonitoringCreditPool(const std::string &imsi):
{
}

static void receive_monitoring_credit_with_default(
SessionCredit &credit,
const GrantedUnits &gsu,
uint64_t default_volume)
{
uint64_t total = get_granted_units(gsu.total(), default_volume);
uint64_t tx = get_granted_units(gsu.tx(), default_volume);
uint64_t rx = get_granted_units(gsu.rx(), default_volume);

SessionCredit::FinalActionInfo final_action_info;

credit.receive_credit(
total, tx, rx, 0, false, final_action_info);
}

bool UsageMonitoringCreditPool::add_used_credit(
const std::string &key,
uint64_t used_tx,
Expand Down Expand Up @@ -268,14 +326,24 @@ static UsageMonitorUpdate get_monitor_update_from_struct(
}

void UsageMonitoringCreditPool::get_updates(
std::string imsi,
std::string ip_addr,
SessionRules *session_rules,
std::vector<UsageMonitorUpdate> *updates_out,
std::vector<ActionPair<std::string>> *actions_out)
std::vector<std::unique_ptr<ServiceAction>> *actions_out)
{
for (auto &monitor_pair : monitor_map_) {
auto &credit = monitor_pair.second->credit;
auto action_type = credit.get_action();
if (action_type != CONTINUE_SERVICE) {
actions_out->emplace_back(monitor_pair.first, action_type);
auto action = std::make_unique<ServiceAction>(action_type);
populate_output_actions(
imsi,
ip_addr,
monitor_pair.first,
session_rules,
action,
actions_out);
}
auto update_type = credit.get_update_type();
if (update_type != CREDIT_NO_UPDATE) {
Expand Down Expand Up @@ -339,9 +407,8 @@ bool UsageMonitoringCreditPool::init_new_credit(
// validity time and final units not used for monitors
// unless defined, volume is defined as the maximum possible value
uint64_t default_volume = std::numeric_limits<uint64_t>::max();
receive_credit_with_default(
monitor->credit, update.credit().granted_units(), default_volume, 0, false,
ChargingCredit_FinalAction_TERMINATE);
receive_monitoring_credit_with_default(
monitor->credit, update.credit().granted_units(), default_volume);
monitor_map_[update.credit().monitoring_key()] = std::move(monitor);
return true;
}
Expand All @@ -368,13 +435,10 @@ bool UsageMonitoringCreditPool::receive_credit(
<< "for subscriber " << imsi_ << " monitoring key "
<< update.credit().monitoring_key();
uint64_t default_volume = 0;
receive_credit_with_default(
receive_monitoring_credit_with_default(
it->second->credit,
update.credit().granted_units(),
default_volume,
0,
false,
ChargingCredit_FinalAction_TERMINATE);
default_volume);
if (update.credit().action() == UsageMonitoringCredit::DISABLE) {
monitor_map_.erase(update.credit().monitoring_key());
}
Expand Down
26 changes: 12 additions & 14 deletions lte/gateway/c/session_manager/CreditPool.h
Expand Up @@ -14,17 +14,6 @@

namespace magma {

template<typename KeyType>
struct ActionPair {
KeyType key;
ServiceActionType action;
ActionPair(const KeyType &key_in, ServiceActionType action_in):
key(key_in),
action(action_in)
{
}
};

/**
* CreditPool is an interface that defines a group of credits to track. It is
* keyed by some type and requires some update response type to receive credit.
Expand All @@ -51,8 +40,11 @@ class CreditPool {
* get_updates gets any usage updates required by the credits in the pool
*/
virtual void get_updates(
std::string imsi,
std::string ip_addr,
SessionRules *session_rules,
std::vector<UpdateRequestType> *updates_out,
std::vector<ActionPair<KeyType>> *actions_out) = 0;
std::vector<std::unique_ptr<ServiceAction>> *actions_out) = 0;

/**
* get_termination_updates gets updates from all credits in the pool at the
Expand Down Expand Up @@ -88,8 +80,11 @@ class ChargingCreditPool :
bool reset_reporting_credit(const uint32_t &key) override;

void get_updates(
std::string imsi,
std::string ip_addr,
SessionRules *session_rules,
std::vector<CreditUsage> *updates_out,
std::vector<ActionPair<uint32_t>> *actions_out) override;
std::vector<std::unique_ptr<ServiceAction>> *actions_out) override;

bool get_termination_updates(
SessionTerminateRequest *termination_out) override;
Expand Down Expand Up @@ -131,8 +126,11 @@ class UsageMonitoringCreditPool :
bool reset_reporting_credit(const std::string &key) override;

void get_updates(
std::string imsi,
std::string ip_addr,
SessionRules *session_rules,
std::vector<UsageMonitorUpdate> *updates_out,
std::vector<ActionPair<std::string>> *actions_out) override;
std::vector<std::unique_ptr<ServiceAction>> *actions_out) override;

bool get_termination_updates(
SessionTerminateRequest *termination_out) override;
Expand Down
58 changes: 55 additions & 3 deletions lte/gateway/c/session_manager/LocalEnforcer.cpp
Expand Up @@ -36,6 +36,8 @@ std::chrono::milliseconds time_difference_from_now(

namespace magma {

uint32_t LocalEnforcer::REDIRECT_FLOW_PRIORITY = 2000;

using google::protobuf::RepeatedPtrField;
using google::protobuf::util::TimeUtil;

Expand Down Expand Up @@ -141,9 +143,10 @@ void LocalEnforcer::execute_actions(
action_p->get_ip_addr(),
action_p->get_rule_ids(),
action_p->get_rule_definitions());
} else if (action_p->get_type() == REDIRECT ||
action_p->get_type() == RESTRICT_ACCESS) {
MLOG(MDEBUG) << "Unsupported action type: " << action_p->get_type()
} else if (action_p->get_type() == REDIRECT) {
install_redirect_flow(action_p);
} else if (action_p->get_type() == RESTRICT_ACCESS) {
MLOG(MDEBUG) << "RESTRICT_ACCESS mode is unsupported"
<< ", will just terminate the service.";
terminate_service(
action_p->get_imsi(),
Expand Down Expand Up @@ -172,6 +175,55 @@ void LocalEnforcer::terminate_service(
}
}

// TODO: make session_manager.proto and policydb.proto to use common field
static RedirectInformation_AddressType address_type_converter(
RedirectServer_RedirectAddressType address_type)
{
switch(address_type) {
case RedirectServer_RedirectAddressType_IPV4:
return RedirectInformation_AddressType_IPv4;
case RedirectServer_RedirectAddressType_IPV6:
return RedirectInformation_AddressType_IPv6;
case RedirectServer_RedirectAddressType_URL:
return RedirectInformation_AddressType_URL;
case RedirectServer_RedirectAddressType_SIP_URI:
return RedirectInformation_AddressType_SIP_URI;
}
}

static PolicyRule create_redirect_rule(
const std::unique_ptr<ServiceAction> &action)
{
PolicyRule redirect_rule;
redirect_rule.set_id("redirect");
redirect_rule.set_priority(LocalEnforcer::REDIRECT_FLOW_PRIORITY);
redirect_rule.set_rating_group(action->get_rating_group());

RedirectInformation* redirect_info = redirect_rule.mutable_redirect();
redirect_info->set_support(RedirectInformation_Support_ENABLED);

auto redirect_server = action->get_redirect_server();
redirect_info->set_address_type(
address_type_converter(redirect_server.redirect_address_type()));
redirect_info->set_server_address(
redirect_server.redirect_server_address());

return redirect_rule;
}

void LocalEnforcer::install_redirect_flow(
const std::unique_ptr<ServiceAction> &action)
{
std::vector<std::string> static_rules;
std::vector<PolicyRule> dynamic_rules {create_redirect_rule(action)};

pipelined_client_->activate_flows_for_rules(
action->get_imsi(),
action->get_ip_addr(),
static_rules,
dynamic_rules);
}

UpdateSessionRequest LocalEnforcer::collect_updates()
{
UpdateSessionRequest request;
Expand Down
7 changes: 7 additions & 0 deletions lte/gateway/c/session_manager/LocalEnforcer.h
Expand Up @@ -130,6 +130,8 @@ class LocalEnforcer {
bool is_session_duplicate(
const std::string &imsi, const magma::SessionState::Config &config);

static uint32_t REDIRECT_FLOW_PRIORITY;

private:
struct RulesToProcess {
std::vector<std::string> static_rules;
Expand Down Expand Up @@ -247,6 +249,11 @@ class LocalEnforcer {
const std::string &imsi,
const std::vector<std::string> &rule_ids,
const std::vector<PolicyRule> &dynamic_rules);

/**
* Install flow for redirection through pipelined
*/
void install_redirect_flow(const std::unique_ptr<ServiceAction> &action);
};

} // namespace magma

0 comments on commit 19614ca

Please sign in to comment.