Commit 0dba68d6 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'support-phone' into 'develop'

Support phone

See merge request oai/cn5g/oai-cn5g-smf!52
parents 678b126f 8b872ed6
......@@ -133,6 +133,7 @@ bool conv::plmnFromString(
p.mcc_digit3 = mcc[2] - '0';
else
return false;
// MNC
if (isdigit(mnc[0]))
p.mnc_digit1 = mnc[0] - '0';
......@@ -147,6 +148,8 @@ bool conv::plmnFromString(
p.mnc_digit3 = mnc[2] - '0';
else
return false;
} else {
p.mnc_digit3 = 0x0;
}
return true;
}
......
......@@ -23,6 +23,7 @@
#include <iostream>
#include "epc.h"
#include "conversions.h"
using namespace EPC;
......@@ -49,6 +50,29 @@ std::string Utility::home_network_gprs(const char* mnc, const char* mcc) {
return s;
}
std::string Utility::home_network_gprs(const plmn_t& plmn) {
// '.mnc(\d{3})\.mcc(\d{3})\.gprs'
std::string s;
uint16_t mcc = 0;
uint16_t mnc = 0;
uint16_t mnc_len = 0;
mcc = plmn.mcc_digit1 * 100 + plmn.mcc_digit2 * 10 + plmn.mcc_digit3;
mnc_len = (plmn.mnc_digit3 == 0x0 ? 2 : 3);
mnc = plmn.mnc_digit1 * 10 + plmn.mnc_digit2;
mnc = (mnc_len == 2 ? mnc : mnc * 10 + plmn.mnc_digit3);
s.append(".mnc");
if (mnc_len == 2) s.append("0");
s.append(std::to_string(mnc));
s.append(".mcc");
s.append(std::to_string(mcc));
s.append(".gprs");
return s;
}
std::string Utility::home_network_gprs(const unsigned char* plmnid) {
PARSE_PLMNID(plmnid);
return home_network_gprs(mnc, mcc);
......
......@@ -24,6 +24,7 @@
#include <sstream>
#include <list>
#include <vector>
#include "3gpp_23.003.h"
/*
MCC digit 1 - low order nibble octet 1
......@@ -82,6 +83,7 @@ class Utility {
static std::string home_network(const char* mnc, const char* mcc);
static std::string home_network(const unsigned char* plmnid);
static std::string home_network_gprs(const char* mnc, const char* mcc);
static std::string home_network_gprs(const plmn_t& plmn);
static std::string home_network_gprs(const unsigned char* plmnid);
static std::string tai_fqdn(
const char* lb, const char* hb, const char* mnc, const char* mcc);
......
......@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include "string.hpp"
#include "logger.hpp"
#include <stdarg.h>
#include <algorithm>
......@@ -94,13 +95,85 @@ void util::ipv4_to_bstring(struct in_addr ipv4_address, bstring str) {
bitstream_addr[2] = (uint8_t)(((ipv4_address.s_addr) & 0x00ff0000) >> 16);
bitstream_addr[3] = (uint8_t)(((ipv4_address.s_addr) & 0xff000000) >> 24);
// str = bfromcstralloc(4, "\0");
// str = bfromcstralloc(4, "\0");
str->slen = 4;
memcpy(str->data, bitstream_addr, sizeof(bitstream_addr));
}
void util::ipv6_to_bstring(struct in6_addr ipv6_address, bstring str) {
char str_addr6[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &ipv6_address, str_addr6, sizeof(str_addr6))) {
std::string ipv6_addr_str((char*) str_addr6, INET6_ADDRSTRLEN);
// Logger::smf_app().info(" Ipv6 address....: %s", ipv6_addr_str.c_str());
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
if (inet_pton(AF_INET6, util::trim(ipv6_addr_str).c_str(), buf_in6_addr) ==
1) {
str->slen = 16;
memcpy(str->data, buf_in6_addr, sizeof(buf_in6_addr));
}
}
}
void util::ipv4v6_to_pdu_address_information(
struct in_addr ipv4_address, struct in6_addr ipv6_address, bstring str) {
unsigned char bitstream_addr[12];
char str_addr6[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &ipv6_address, str_addr6, sizeof(str_addr6))) {
std::string ipv6_addr_str((char*) str_addr6, INET6_ADDRSTRLEN);
// Logger::smf_app().info(" Ipv6 address....: %s", ipv6_addr_str.c_str());
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
if (inet_pton(AF_INET6, util::trim(ipv6_addr_str).c_str(), buf_in6_addr) ==
1) {
for (int i = 0; i <= 7; i++)
bitstream_addr[i] = (uint8_t)(buf_in6_addr[i]);
}
}
bitstream_addr[8] = (uint8_t)((ipv4_address.s_addr) & 0x000000ff);
bitstream_addr[9] = (uint8_t)(((ipv4_address.s_addr) & 0x0000ff00) >> 8);
bitstream_addr[10] = (uint8_t)(((ipv4_address.s_addr) & 0x00ff0000) >> 16);
bitstream_addr[11] = (uint8_t)(((ipv4_address.s_addr) & 0xff000000) >> 24);
str->slen = 12;
memcpy(str->data, bitstream_addr, sizeof(bitstream_addr));
}
void util::string_to_bstring(const std::string& str, bstring bstr) {
// bstr = bfromcstralloc(str.length(), "\0");
// bstr = bfromcstralloc(str.length(), "\0");
bstr->slen = str.length();
memcpy((void*) bstr->data, (void*) str.c_str(), str.length());
}
bool util::string_to_dotted(const std::string& str, std::string& dotted) {
uint8_t offset = 0;
uint8_t* last_size;
uint8_t word_length = 0;
uint8_t value[str.length() + 1];
dotted = {};
last_size = &value[0];
while (str[offset]) {
// We replace the . by the length of the word
if (str[offset] == '.') {
*last_size = word_length;
word_length = 0;
last_size = &value[offset + 1];
} else {
word_length++;
value[offset + 1] = str[offset];
}
offset++;
}
*last_size = word_length;
dotted.assign((const char*) value, str.length() + 1);
return true;
};
void util::string_to_dnn(const std::string& str, bstring bstr) {
bstr->slen = str.length();
memcpy((void*) bstr->data, (void*) str.c_str(), str.length());
}
......@@ -47,6 +47,21 @@ std::string& trim(std::string& s);
void ipv4_to_bstring(struct in_addr ipv4_address, bstring str);
void ipv6_to_bstring(struct in6_addr ipv6_address, bstring str);
/*
* Create a PDU Address Information in form of a bstring (byte 0-7: IPv6 prefix,
* 8-11: Ipv4 Address)
* @param [struct in_addr] ipv4_address: IPv4 address
* @param [struct in6_addr ] ipv6_address: IPv6 address
* @param [bstring] str: store the PDU Address Information
* @return void
*/
void ipv4v6_to_pdu_address_information(
struct in_addr ipv4_address, struct in6_addr ipv6_address, bstring str);
void string_to_bstring(const std::string& str, bstring bstr);
bool string_to_dotted(const std::string& str, std::string& dotted);
void string_to_dnn(const std::string& str, bstring bstr);
} // namespace util
#endif
......@@ -44,6 +44,7 @@ int encode_snssai(SNSSAI snssai, uint8_t iei, uint8_t* buffer, uint32_t len) {
}
ielen = snssai.len;
ielen = 1;
*(buffer + encoded) = ielen;
encoded++;
......
......@@ -36,10 +36,10 @@ int encode__pdu_session_type(
buffer, _PDU_SESSION_TYPE_MINIMUM_LENGTH, len);
if (iei > 0) {
bitStream |= (iei & 0xf0);
bitStream |= (iei & 0xf0) ;
}
bitStream |= (_pdusessiontype.pdu_session_type_value & 0x07);
bitStream |= ((_pdusessiontype.pdu_session_type_value & 0x07) | 0x10);
ENCODE_U8(buffer + encoded, bitStream, encoded);
return encoded;
......
......@@ -215,6 +215,7 @@ int encode_pdu_session_establishment_accept(
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(
buffer, PDU_SESSION_ESTABLISHMENT_ACCEPT_MINIMUM_LENGTH, len);
if ((encoded_result = encode__pdu_session_type(
pdu_session_establishment_accept->_pdusessiontype, 0,
buffer + encoded, len - encoded)) < 0)
......
......@@ -30,6 +30,7 @@
#include "smf_app.hpp"
#include <boost/uuid/random_generator.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <cstdlib>
#include <iostream>
......@@ -81,6 +82,7 @@ void smf_app_task(void*);
int smf_app::apply_config(const smf_config& cfg) {
Logger::smf_app().info("Apply config...");
paa_t paa = {};
for (int ia = 0; ia < cfg.num_dnn; ia++) {
if (cfg.dnn[ia].pool_id_iv4 >= 0) {
int pool_id = cfg.dnn[ia].pool_id_iv4;
......@@ -90,13 +92,18 @@ int smf_app::apply_config(const smf_config& cfg) {
cfg.dnn[ia].dnn, pool_id, cfg.ue_pool_range_low[pool_id], range);
// TODO: check with dnn_label
Logger::smf_app().info("Applied config %s", cfg.dnn[ia].dnn.c_str());
paa.ipv4_address = cfg.ue_pool_range_low[pool_id];
}
if (cfg.dnn[ia].pool_id_iv6 >= 0) {
int pool_id = cfg.dnn[ia].pool_id_iv6;
paa_dynamic::get_instance().add_pool(
cfg.dnn[ia].dnn, pool_id, cfg.paa_pool6_prefix[pool_id],
cfg.paa_pool6_prefix_len[pool_id]);
paa.ipv6_address = cfg.paa_pool6_prefix[pool_id];
// TODO: check with dnn_label
Logger::smf_app().info(
"Applied config for IPv6 %s", cfg.dnn[ia].dnn.c_str());
}
}
......@@ -506,7 +513,7 @@ void smf_app::handle_itti_msg(std::shared_ptr<itti_n4_node_failure> snf) {
"Remove the associated PDU session (SUPI " SUPI_64_FMT
", PDU Sessin Id %d)",
supi64, it.second->pdu_session_id);
//TODO: remove the session
// TODO: remove the session
}
}
}
......@@ -729,6 +736,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
// Get necessary info from NAS
xgpp_conv::sm_context_request_from_nas(decoded_nas_msg, smreq->req);
pdu_session_type.pdu_session_type = smreq->req.get_pdu_session_type();
// TODO: Support IPv4 only for now
if (pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV6) {
cause_n1 = cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED;
......@@ -737,7 +745,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
(pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_UNSTRUCTURED)) {
cause_n1 = cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE;
}
if (pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4) {
if ((pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4) and
(pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4V6)) {
// PDU Session Establishment Reject
if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
smreq->req, n1_sm_message, cause_n1)) {
......@@ -947,7 +957,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
"Retrieve Session Management Subscription data from the UDM");
if (smf_sbi_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
// update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription);
sc.get()->insert_dnn_subscription(snssai, dnn, subscription);
} else {
// Cannot retrieve information from UDM, reject PDU session
// establishment
......@@ -982,11 +992,14 @@ void smf_app::handle_pdu_session_create_sm_context_request(
if (get_session_management_subscription_data(
supi64, dnn, snssai, subscription)) {
// update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription);
sc.get()->insert_dnn_subscription(snssai, dnn, subscription);
}
}
}
// store PLMN
sc.get()->set_plmn(smreq->req.get_plmn());
// Step 8. generate a SMF context Id and store the corresponding information
// in a map (SM_Context_ID, (supi, dnn, nssai, pdu_session_id))
scid_t scid = generate_smf_context_ref();
......@@ -1000,7 +1013,6 @@ void smf_app::handle_pdu_session_create_sm_context_request(
smreq->set_scid(scid);
// store scid in the context itself
sc.get()->set_scid(scid);
Logger::smf_app().debug("Generated a SMF Context ID " SCID_FMT " ", scid);
// Step 9. Let the context handle the message
......@@ -1639,21 +1651,20 @@ bool smf_app::get_session_management_subscription_data(
Logger::smf_app().debug(
"Default session type %s",
smf_cfg.session_management_subscription[i].session_type.c_str());
if (smf_cfg.session_management_subscription[i].session_type.compare(
"IPV4") == 0) {
std::string session_type =
smf_cfg.session_management_subscription[i].session_type;
if (boost::iequals(session_type, "IPv4")) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4;
} else if (
smf_cfg.session_management_subscription[i].session_type.compare(
"IPV6") == 0) {
} else if (boost::iequals(session_type, "IPv6")) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV6;
} else if (
smf_cfg.session_management_subscription[i].session_type.compare(
"IPV4V6") == 0) {
} else if (boost::iequals(session_type, "IPv4v6")) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4V6;
}
dnn_configuration->pdu_session_types.default_session_type =
pdu_session_type;
......
......@@ -186,6 +186,16 @@ class smf_app {
protocol_configuration_options_t& pco_resp,
const pco_protocol_or_container_id_t* const poc_id);
/*
* process_pco_dns_server_v6_request
* @param [protocol_configuration_options_t &] pco_resp
* @param [pco_protocol_or_container_id_t *const] proc_id
* @return
*/
int process_pco_dns_server_v6_request(
protocol_configuration_options_t& pco_resp,
const pco_protocol_or_container_id_t* const poc_id);
/*
* process_pco_link_mtu_request
* @param [protocol_configuration_options_t &] pco_resp
......
......@@ -437,19 +437,19 @@ int smf_config::load(const string& config_file) {
if (boost::iequals(astring, "IPv4")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_IPV4;
} else if (boost::iequals(astring, "IPv6") == 0) {
} else if (boost::iequals(astring, "IPv6")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_IPV6;
} else if (boost::iequals(astring, "IPv4IPv6") == 0) {
} else if (boost::iequals(astring, "IPv4v6")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_IPV4V6;
} else if (boost::iequals(astring, "Unstructured") == 0) {
} else if (boost::iequals(astring, "Unstructured")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_UNSTRUCTURED;
} else if (boost::iequals(astring, "Ethernet") == 0) {
} else if (boost::iequals(astring, "Ethernet")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_ETHERNET;
} else if (boost::iequals(astring, "Reserved") == 0) {
} else if (boost::iequals(astring, "Reserved")) {
dnn[dnn_idx].pdu_session_type.pdu_session_type =
PDU_SESSION_TYPE_E_RESERVED;
} else {
......@@ -873,8 +873,14 @@ void smf_config::display() {
dnn[i].pool_id_iv4, range_low.c_str(), range_high.c_str());
}
if (dnn[i].pool_id_iv6 >= 0) {
if (inet_ntop(
AF_INET6, &paa_pool6_prefix[dnn[i].pool_id_iv6], str_addr6,
sizeof(str_addr6))) {
Logger::smf_app().info(
" " SMF_CONFIG_STRING_IPV6_POOL ": %d", dnn[i].pool_id_iv6);
" " SMF_CONFIG_STRING_IPV6_POOL ": %d (%s / %d)",
dnn[i].pool_id_iv6, str_addr6,
paa_pool6_prefix_len[dnn[i].pool_id_iv6]);
}
}
}
......
......@@ -1128,8 +1128,8 @@ void smf_context::get_session_ambr(
std::shared_ptr<dnn_configuration_t> sdc = {};
find_dnn_subscription(snssai, ss);
uint32_t bit_rate_dl = {1};
uint32_t bit_rate_ul = {1};
uint32_t bit_rate_dl = {110000000}; // TODO: to be updated
uint32_t bit_rate_ul = {110000000}; // TODO: to be updated
session_ambr.pDUSessionAggregateMaximumBitRateDL.size = 4;
session_ambr.pDUSessionAggregateMaximumBitRateDL.buf =
......@@ -1328,7 +1328,8 @@ void smf_context::handle_pdu_session_create_sm_context_request(
.ci_dns_server_ipv4_address_request = 0,
.ci_ip_address_allocation_via_nas_signalling = 0,
.ci_ipv4_address_allocation_via_dhcpv4 = 0,
.ci_ipv4_link_mtu_request = 0};
.ci_ipv4_link_mtu_request = 0,
.ci_dns_server_ipv6_address_request = 0};
smf_app_inst->process_pco_request(pco_req, pco_resp, pco_ids);
sm_context_resp_pending->res.set_epco(pco_resp);
......@@ -1338,8 +1339,55 @@ void smf_context::handle_pdu_session_create_sm_context_request(
bool set_paa = false;
paa_t paa = {};
Logger::smf_app().debug("UE Address Allocation");
switch (sp->pdu_session_type.pdu_session_type) {
case PDU_SESSION_TYPE_E_IPV4V6: {
Logger::smf_app().debug(
"PDU Session Type IPv4v6, select PDU Session Type IPv4");
bool paa_res = false;
// TODO: Verified if use default session type or requested session type
std::shared_ptr<session_management_subscription> ss = {};
std::shared_ptr<dnn_configuration_t> sdc = {};
find_dnn_subscription(snssai, ss);
if (nullptr != ss.get()) {
ss.get()->find_dnn_configuration(sd->dnn_in_use, sdc);
if (nullptr != sdc.get()) {
paa.pdu_session_type.pdu_session_type =
sdc.get()
->pdu_session_types.default_session_type.pdu_session_type;
}
}
// TODO: use requested PDU Session Type?
// paa.pdu_session_type.pdu_session_type = PDU_SESSION_TYPE_E_IPV4V6;
if ((not paa_res) || (not paa.is_ip_assigned())) {
bool success =
paa_dynamic::get_instance().get_free_paa(sd->dnn_in_use, paa);
if (success) {
set_paa = true;
} else {
// ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED;
set_paa = false;
request_accepted = false;
sm_context_resp->res.set_cause(static_cast<uint8_t>(
cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES));
}
// TODO: Static IP address allocation
} else if ((paa_res) && (paa.is_ip_assigned())) {
set_paa = true;
}
Logger::smf_app().info(
"PAA, Ipv4 Address: %s",
inet_ntoa(*((struct in_addr*) &paa.ipv4_address)));
char str_addr6[INET6_ADDRSTRLEN];
if (inet_ntop(
AF_INET6, &paa.ipv6_address, str_addr6, sizeof(str_addr6))) {
Logger::smf_app().info("PAA, IPv6 Address: %s", str_addr6);
}
}; break;
case PDU_SESSION_TYPE_E_IPV4: {
Logger::smf_app().debug("PDU Session Type IPv4");
if (!pco_ids.ci_ipv4_address_allocation_via_dhcpv4) {
// use SM NAS signalling
// static or dynamic address allocation
......@@ -1357,7 +1405,10 @@ void smf_context::handle_pdu_session_create_sm_context_request(
if (nullptr != sdc.get()) {
paa.pdu_session_type.pdu_session_type =
sdc.get()
->pdu_session_types.default_session_type.pdu_session_type;
->pdu_session_types.default_session_type
.pdu_session_type; // TODO: Verified if use default session
// type or requested session type
// TODO: static ip address
}
}
......@@ -1395,11 +1446,6 @@ void smf_context::handle_pdu_session_create_sm_context_request(
Logger::smf_app().debug("IPv6 has not been supported yet!");
} break;
case PDU_SESSION_TYPE_E_IPV4V6: {
// TODO:
Logger::smf_app().debug("IPv4/v6 has not been supported yet!");
} break;
default: {
Logger::smf_app().error(
"Unknown PDN type %d", sp->pdu_session_type.pdu_session_type);
......@@ -1535,7 +1581,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
if (sm_context_resp->res.get_cause() !=
static_cast<uint8_t>(cause_value_5gsm_e::CAUSE_255_REQUEST_ACCEPTED)) {
// clear pco, ambr
// TODO:
// free paa
paa_t free_paa = {};
free_paa = sm_context_resp->res.get_paa();
......@@ -1543,11 +1589,12 @@ void smf_context::handle_pdu_session_create_sm_context_request(
switch (sp->pdu_session_type.pdu_session_type) {
case PDU_SESSION_TYPE_E_IPV4:
case PDU_SESSION_TYPE_E_IPV4V6:
paa_dynamic::get_instance().release_paa(
sd->dnn_in_use, free_paa.ipv4_address);
break;
// paa_dynamic::get_instance().release_paa(
// sd->dnn_in_use, free_paa.ipv4_address);
// break;
case PDU_SESSION_TYPE_E_IPV6:
paa_dynamic::get_instance().release_paa(sd->dnn_in_use, free_paa);
break;
case PDU_SESSION_TYPE_E_UNSTRUCTURED:
case PDU_SESSION_TYPE_E_ETHERNET:
case PDU_SESSION_TYPE_E_RESERVED:
......@@ -2826,11 +2873,35 @@ void smf_context::insert_dnn_subscription(
const snssai_t& snssai,
std::shared_ptr<session_management_subscription>& ss) {
std::unique_lock<std::recursive_mutex> lock(m_context);
dnn_subscriptions[(uint8_t) snssai.sST] = ss;
Logger::smf_app().info(
"Inserted DNN Subscription, key: %d", (uint8_t) snssai.sST);
}
//------------------------------------------------------------------------------
void smf_context::insert_dnn_subscription(
const snssai_t& snssai, const std::string& dnn,
std::shared_ptr<session_management_subscription>& ss) {
std::unique_lock<std::recursive_mutex> lock(m_context);
if (dnn_subscriptions.count((uint8_t) snssai.sST) > 0) {
std::shared_ptr<session_management_subscription> old_ss =
dnn_subscriptions.at((uint8_t) snssai.sST);
std::shared_ptr<dnn_configuration_t> dnn_configuration = {};
ss.get()->find_dnn_configuration(dnn, dnn_configuration);
if (dnn_configuration != nullptr) {
old_ss.get()->insert_dnn_configuration(dnn, dnn_configuration);
}
} else {
dnn_subscriptions[(uint8_t) snssai.sST] = ss;
}
Logger::smf_app().info(
"Inserted DNN Subscription, key: %d, dnn %s", (uint8_t) snssai.sST,
dnn.c_str());
}
//------------------------------------------------------------------------------
bool smf_context::is_dnn_snssai_subscription_data(
const std::string& dnn, const snssai_t& snssai) {
......@@ -3187,6 +3258,16 @@ void smf_context::get_amf_addr(std::string& addr) const {
addr = amf_addr;
}
//------------------------------------------------------------------------------
void smf_context::set_plmn(const plmn_t& plmn) {
this->plmn = plmn;
}
//------------------------------------------------------------------------------
void smf_context::get_plmn(plmn_t& plmn) const {
plmn = this->plmn;
}
//------------------------------------------------------------------------------
bool dnn_context::find_pdu_session(
const uint32_t pdu_session_id,
......
......@@ -562,7 +562,8 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
pending_procedures(),
dnn_subscriptions(),
scid(0),
event_sub() {
event_sub(),
plmn() {
supi_prefix = {};
// Subscribe to sm context status change
sm_context_status_connection =
......@@ -853,6 +854,18 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
const snssai_t& snssai,
std::shared_ptr<session_management_subscription>& ss);
/*
* Insert a session management subscription into the SMF context
* @param [const snssai_t&] snssai
* @param [const dnn&] dnn
* @param [std::shared_ptr<session_management_subscription>&] ss: pointer to
* the subscription
* @return void
*/
void insert_dnn_subscription(
const snssai_t& snssai, const std::string& dnn,
std::shared_ptr<session_management_subscription>& ss);
/*
* Verify whether a subscription data exist with a given dnn and snssai
* @param [const std::string &] dnn: DNN
......@@ -1043,6 +1056,9 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
*/
void get_amf_addr(std::string& addr) const;
void set_plmn(const plmn_t& plmn);
void get_plmn(plmn_t& plmn) const;
private:
std::vector<std::shared_ptr<dnn_context>> dnns;
std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
......@@ -1052,6 +1068,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
supi_t supi;
std::string supi_prefix;
scid_t scid; // SM Context ID
plmn_t plmn;
// AMF IP addr
string amf_addr;
......
......@@ -362,6 +362,11 @@ void pdu_session_create_sm_context_request::get_plmn(plmn_t& p) const {
p = m_serving_network;
}
//-----------------------------------------------------------------------------
plmn_t pdu_session_create_sm_context_request::get_plmn() const {
return m_serving_network;
}
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_request::set_an_type(
const std::string& an_type) {
......
......@@ -269,6 +269,7 @@ class pdu_session_create_sm_context_request
void get_epco(protocol_configuration_options_t& p) const;
void set_plmn(const plmn_t p);
void get_plmn(plmn_t& p) const;
plmn_t get_plmn() const;
void set_an_type(const std::string& an_type);
void get_an_type(std::string& an_type) const;
void set_guami(const guami_5g_t& guami);
......
......@@ -36,6 +36,7 @@
#include "smf.h"
#include "smf_app.hpp"
#include "3gpp_conversions.hpp"
#include "epc.h"
extern "C" {
#include "dynamic_memory_check.h"
......@@ -102,11 +103,11 @@ bool smf_n1::create_n1_pdu_session_establishment_accept(
"PDU Session Type: %d", sm_msg->pdu_session_establishment_accept
._pdusessiontype.pdu_session_type_value);
sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value =
SSC_MODE_1; // TODO: get from sm_context_res
Logger::smf_n1().debug(
"SSC Mode: %d",
sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value);
// sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value =
// SSC_MODE_1; // TODO: get from sm_context_res
// Logger::smf_n1().debug(
// "SSC Mode: %d",
// sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value);
// authorized QoS rules of the PDU session: QOSRules (Section 6.2.5@3GPP
// TS 24.501) (Section 6.4.1.3@3GPP TS 24.501 V16.1.0) Make sure that the
......@@ -152,23 +153,47 @@ bool smf_n1::create_n1_pdu_session_establishment_accept(
return false;
}
sm_msg->pdu_session_establishment_accept.presence = 0x03df;
sm_msg->pdu_session_establishment_accept.presence = 0x038a;
if (static_cast<uint8_t>(sm_cause) > 0) {
sm_msg->pdu_session_establishment_accept.presence = 0x039b;
sm_msg->pdu_session_establishment_accept._5gsmcause =
static_cast<uint8_t>(sm_cause);
Logger::smf_n1().debug(
"5GSM Cause: %d", sm_msg->pdu_session_establishment_accept._5gsmcause);
}
// PDUAddress
paa_t paa = sm_context_res.get_paa();
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_address_information =
bfromcstralloc(4, "\0");
Logger::smf_n1().debug(
"PDU Session Type %s", paa.pdu_session_type.toString().c_str());
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_session_type_value =
static_cast<uint8_t>(paa.pdu_session_type.pdu_session_type);
if (paa.pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV4) {
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information = bfromcstralloc(4, "\0");
util::ipv4_to_bstring(
paa.ipv4_address, sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information);
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_session_type_value =
static_cast<uint8_t>(PDU_SESSION_TYPE_E_IPV4);
Logger::smf_n1().debug(
"UE Address %s", conv::toString(paa.ipv4_address).c_str());
"UE IPv4 Address %s", conv::toString(paa.ipv4_address).c_str());
} else if (
paa.pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV4V6) {
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information = bfromcstralloc(12, "\0");
util::ipv4v6_to_pdu_address_information(
paa.ipv4_address, paa.ipv6_address,
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information);
Logger::smf_n1().debug(
"UE IPv4 Address %s", conv::toString(paa.ipv4_address).c_str());
char str_addr6[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &paa.ipv6_address, str_addr6, sizeof(str_addr6))) {
Logger::smf_n1().debug("UE IPv6 Address: %s", str_addr6);
}
} else if (paa.pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV6) {
// TODO:
Logger::smf_n1().debug("IPv6 is not fully supported yet!");
}
// TODO: GPRSTimer
// sm_msg->pdu_session_establishment_accept.gprstimer.unit =
......@@ -228,11 +253,18 @@ bool smf_n1::create_n1_pdu_session_establishment_accept(
.extendedprotocolconfigurationoptions);
// DNN
plmn_t plmn = {};
sc.get()->get_plmn(plmn);
std::string gprs = EPC::Utility::home_network_gprs(plmn);
std::string full_dnn =
sm_context_res.get_dnn() + gprs; //".mnc011.mcc110.gprs";
std::string dotted;
util::string_to_dotted(full_dnn, dotted);
Logger::smf_n1().debug(
"Full DNN %s, dotted DNN %s", full_dnn.c_str(), dotted.c_str());
sm_msg->pdu_session_establishment_accept.dnn =
bfromcstralloc(sm_context_res.get_dnn().length(), "\0");
util::string_to_bstring(
sm_context_res.get_dnn(), sm_msg->pdu_session_establishment_accept.dnn);
Logger::smf_n1().debug("DNN %s", sm_context_res.get_dnn().c_str());
bfromcstralloc(dotted.length() + 1, "\0");
util::string_to_dnn(dotted, sm_msg->pdu_session_establishment_accept.dnn);
Logger::smf_n1().info("Encode PDU Session Establishment Accept");
// Encode NAS message
......
......@@ -33,6 +33,8 @@
#include <map>
#include "logger.hpp"
#include "string.hpp"
#include <boost/algorithm/string.hpp>
class ipv6_pool {
public:
......@@ -180,13 +182,15 @@ class paa_dynamic {
ipv4_pool pool(first, range);
ipv4_pools[uint32pool_id] = pool;
}
if (!dnns.count(dnn_label)) {
dnn_dynamic_pools adp = {};
if (dnns.count(dnn_label)) {
adp = dnns[dnn_label];
}
adp.add_ipv4_pool_id(uint32pool_id);
dnns[dnn_label] = adp;
}
}
}
void add_pool(
const std::string& dnn_label, const int pool_id,
......@@ -197,13 +201,15 @@ class paa_dynamic {
ipv6_pool pool(prefix, prefix_len);
ipv6_pools[uint32pool_id] = pool;
}
if (!dnns.count(dnn_label)) {
dnn_dynamic_pools adp = {};
if (dnns.count(dnn_label)) {
adp = dnns[dnn_label];
}
adp.add_ipv6_pool_id(uint32pool_id);
dnns[dnn_label] = adp;
}
}
}
bool get_free_paa(const std::string& dnn_label, paa_t& paa) {
if (dnns.count(dnn_label)) {
......@@ -225,10 +231,13 @@ class paa_dynamic {
paa.pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV4V6) {
bool success = false;
std::vector<uint32_t>::const_iterator it4 = {};
uint32_t ipv4_pool_id = 0;
for (it4 = dnn_pool.ipv4_pool_ids.begin();
it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) {
success = true;
ipv4_pool_id = *it4;
break;
}
}
if (success) {
......@@ -239,7 +248,7 @@ class paa_dynamic {
return true;
}
}
ipv4_pools[*it4].free_address(paa.ipv4_address);
ipv4_pools[ipv4_pool_id].free_address(paa.ipv4_address);
}
Logger::smf_app().warn(
"Could not get PAA PDU_SESSION_TYPE_E_IPV4V6 for DNN %s",
......@@ -290,6 +299,7 @@ class paa_dynamic {
return false;
} else if (
paa.pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV6) {
Logger::smf_app().debug("IPv6 is not fully supported yet!");
return true;
}
}
......
......@@ -35,6 +35,7 @@
#include "rfc_1877.h"
#include "smf_app.hpp"
#include "smf_config.hpp"
#include "string.hpp"
using namespace smf;
......@@ -283,6 +284,38 @@ int smf_app::process_pco_dns_server_request(
return pco_push_protocol_or_container_id(pco_resp, &poc_id_resp);
}
//------------------------------------------------------------------------------
int smf_app::process_pco_dns_server_v6_request(
protocol_configuration_options_t& pco_resp,
const pco_protocol_or_container_id_t* const poc_id) {
in6_addr ipcp_out_dns_prim_ipv6_addr = smf_cfg.default_dnsv6;
pco_protocol_or_container_id_t poc_id_resp = {0};
uint8_t dnsv6_array[16];
Logger::smf_app().debug(
"PCO: Protocol identifier IPCP option DNS Server v6 Request");
poc_id_resp.protocol_id = PCO_CONTAINER_IDENTIFIER_DNS_SERVER_IPV6_ADDRESS;
poc_id_resp.length_of_protocol_id_contents = 16;
char str_addr6[INET6_ADDRSTRLEN];
if (inet_ntop(
AF_INET6, &ipcp_out_dns_prim_ipv6_addr, str_addr6,
sizeof(str_addr6))) {
std::string ipv6_addr_str((char*) str_addr6, INET6_ADDRSTRLEN);
// Logger::smf_app().info(" Ipv6 address....: %s", ipv6_addr_str.c_str());
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
if (inet_pton(AF_INET6, util::trim(ipv6_addr_str).c_str(), buf_in6_addr) ==
1) {
for (int i = 0; i <= 15; i++) dnsv6_array[i] = (uint8_t)(buf_in6_addr[i]);
}
}
std::string tmp_s((const char*) &dnsv6_array[0], sizeof(dnsv6_array));
poc_id_resp.protocol_id_contents = tmp_s;
return pco_push_protocol_or_container_id(pco_resp, &poc_id_resp);
}
//------------------------------------------------------------------------------
int smf_app::process_pco_link_mtu_request(
protocol_configuration_options_t& pco_resp,
......@@ -335,7 +368,11 @@ int smf_app::process_pco_request(
pco_resp, &pco_req.protocol_or_container_ids[id]);
pco_ids.ci_dns_server_ipv4_address_request = true;
break;
case PCO_CONTAINER_IDENTIFIER_DNS_SERVER_IPV6_ADDRESS:
process_pco_dns_server_v6_request(
pco_resp, &pco_req.protocol_or_container_ids[id]);
pco_ids.ci_dns_server_ipv6_address_request = true;
break;
case PCO_CONTAINER_IDENTIFIER_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING:
Logger::smf_app().debug("PCO: Allocation via NAS signaling requested");
pco_ids.ci_ip_address_allocation_via_nas_signalling = true;
......
......@@ -47,6 +47,7 @@ typedef struct protocol_configuration_options_ids_s {
uint8_t ci_ip_address_allocation_via_nas_signalling : 1;
uint8_t ci_ipv4_address_allocation_via_dhcpv4 : 1;
uint8_t ci_ipv4_link_mtu_request : 1;
uint8_t ci_dns_server_ipv6_address_request : 1;
} protocol_configuration_options_ids_t;
#endif
......@@ -414,7 +414,7 @@ void session_create_sm_context_procedure::handle_itti_msg(
// TODO: Support IPv4 only for now
if (n11_triggered_pending->res.get_pdu_session_type() ==
PDU_SESSION_TYPE_E_IPV4V6) {
PDU_SESSION_TYPE_E_IPV6) {
n11_triggered_pending->res.set_pdu_session_type(PDU_SESSION_TYPE_E_IPV4);
cause_n1 =
cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment