Commit a84b728b authored by yangjian's avatar yangjian

add amf_agent function

parent c24ea6e0
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
AMF =
{
INSTANCE_ID = 10; # 0 is the default
PID_DIRECTORY = "/var/run"; # /var/run is the default
AMF_NAME = "OAI-AMF";
RELATIVE_CAPACITY = 50;
# Display statistics about whole system (in seconds)
STATISTICS_TIMER_INTERVAL = 20; # YOUR CONFIG HERE
CORE_CONFIGURATION:
{
EMERGENCY_SUPPORT = "false";
};
GUAMI:
{
MCC = "460"; MNC = "11"; RegionID = "128"; AMFSetID = "4"; AMFPointer = "1" # YOUR GUAMI CONFIG HERE
}
SERVED_GUAMI_LIST = (
{MCC = "460"; MNC = "11"; RegionID = "128"; AMFSetID = "4"; AMFPointer = "1"} #48bits <MCC><MNC><RegionID><AMFSetID><AMFPointer>
);
PLMN_SUPPORT_LIST = (
{
MCC = "460"; MNC = "11"; TAC = 100; # YOUR PLMN CONFIG HERE
SLICE_SUPPORT_LIST = (
{SST = "1"; SD = "none"} # YOUR NSSAI CONFIG HERE
)
}
);
INTERFACES:
{
# AMF binded interface for N1/N2 interface (NGAP)
NGAP_AMF:
{
INTERFACE_NAME = "ens32"; # YOUR NETWORK CONFIG HERE
IPV4_ADDRESS = "read";
PORT = 38412; # YOUR NETWORK CONFIG HERE
PPID = 60; # YOUR NETWORK CONFIG HERE
};
# AMF binded interface for Nausf interface
NAUSF:
{
INTERFACE_NAME = "ens32"; # YOUR NETWORK CONFIG HERE
IPV4_ADDRESS = "192.168.2.35/24";
PORT = 8383; # YOUR NETWORK CONFIG HERE
};
# AMF binded interface for N11
N11:
{
INTERFACE_NAME = "ens32"; # YOUR NETWORK CONFIG HERE
IPV4_ADDRESS = "read";
PORT = 8282; # YOUR NETWORK CONFIG HERE
SMF_INSTANCES_POOL = (
{SMF_INSTANCE_ID = 1; IPV4_ADDRESS = "192.168.2.35"; PORT = "8889"; VERSION = "v1"; SELECTED = "true"}, # YOUR SMF CONFIG HERE
{SMF_INSTANCE_ID = 2; IPV4_ADDRESS = "10.103.238.21"; PORT = "8181"; VERSION = "v1"; SELECTED = "false"} # YOUR SMF CONFIG HERE
);
};
# SBI-AMF_AGENT interface
AMF_AGENT: { IPV4_ADDRESS = "192.168.2.35"; PORT = 10001; };
};
AUTHENTICATION:
{
## MySQL mandatory options
MYSQL_server = "192.168.2.35"; # MySQL Server address
MYSQL_user = "yunshou"; # Database server login
MYSQL_pass = "123456"; # Database server password
MYSQL_db = "OAI_DB"; # Your database name
## OP
OPERATOR_key = "1006020f0a478bf6b699f15c062e42b3"; # OP key matching your database
RANDOM = "true";
};
NAS:
{
ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "NIA1" , "NIA0" , "NIA2" ];
ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "NEA0" , "NEA1" , "NEA2" ];
};
};
MODULES =
{
NGAP_MESSAGE = (
{MSG_NAME = "NGSetupRequest"; ProcedureCode = 21; TypeOfMessage = "initialMessage"}
);
};
......@@ -41,6 +41,9 @@
#include "amf_statistics.hpp"
#include "ngap_app.hpp"
#include <nlohmann/json.hpp>
#include <curl/curl.h>
using namespace ngap;
using namespace nas;
using namespace amf_application;
......@@ -125,6 +128,13 @@ void amf_app_task(void*) {
amf_app_inst->handle_itti_message(ref(*m));
} break;
case PUSH_TO_AMF_AGENT: {
Logger::amf_app().debug("Received itti_push_to_amf_agent");
itti_push_to_amf_agent* m =
dynamic_cast<itti_push_to_amf_agent*>(msg);
amf_app_inst->handle_itti_message(ref(*m));
} break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) {
......@@ -222,6 +232,152 @@ void amf_app::handle_itti_message(
}
//------------------------------------------------------------------------------
#define CURL_TIMEOUT_MS 300L
std::size_t callback_amf_agent(const char *in, std::size_t size, std::size_t num,
std::string *out) {
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
}
void amf_app::curl_http_client(std::string remoteUri, std::string Method,
std::string msgBody, std::string &Response) {
Logger::amf_n1().info("Send HTTP message with body %s", msgBody.c_str());
uint32_t str_len = msgBody.length();
char *body_data = (char *)malloc(str_len + 1);
memset(body_data, 0, str_len + 1);
memcpy((void *)body_data, (void *)msgBody.c_str(), str_len);
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (curl) {
CURLcode res = {};
struct curl_slist *headers = nullptr;
if (!Method.compare("POST") || !Method.compare("PATCH") ||
!Method.compare("PUT")) {
std::string content_type = "Content-Type: application/json";
headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
}
curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str());
if (!Method.compare("POST"))
curl_easy_setopt(curl, CURLOPT_HTTPPOST, 1);
else if (!Method.compare("PATCH"))
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
else if (!Method.compare("PUT")) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
} else
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
// curl_easy_setopt(curl, CURLOPT_INTERFACE, amf_cfg.nausf.if_name.c_str());
curl_easy_setopt(curl, CURLOPT_INTERFACE, amf_cfg.n11.if_name.c_str());
// Response information.
long httpCode = {0};
std::unique_ptr<std::string> httpData(new std::string());
std::unique_ptr<std::string> httpHeaderData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback_amf_agent);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_HEADERDATA, httpHeaderData.get());
if (!Method.compare("POST") || !Method.compare("PATCH") ||
!Method.compare("PUT")) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msgBody.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_data);
}
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
// get the response
std::string response = *httpData.get();
std::string json_data_response = "";
std::string resMsg = "";
bool is_response_ok = true;
Logger::amf_n1().info("Get response with httpcode (%d)", httpCode);
if (httpCode == 0) {
Logger::amf_n1().info("Cannot get response when calling %s",
remoteUri.c_str());
// free curl before returning
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return;
}
nlohmann::json response_data = {};
if (httpCode != 200 && httpCode != 201 && httpCode != 204) {
is_response_ok = false;
if (response.size() < 1) {
Logger::amf_n1().info("There's no content in the response");
// TODO: send context response error
return;
}
Logger::amf_n1().info("Wrong response code");
return;
}
else {
Response = *httpData.get();
}
if (!is_response_ok) {
try {
response_data = nlohmann::json::parse(json_data_response);
} catch (nlohmann::json::exception &e) {
Logger::amf_n1().info("Could not get Json content from the response");
// Set the default Cause
response_data["error"]["cause"] = "504 Gateway Timeout";
}
Logger::amf_n1().info("Get response with jsonData: %s",
json_data_response.c_str());
std::string cause = response_data["error"]["cause"];
Logger::amf_n1().info("Call Network Function services failure");
Logger::amf_n1().info("Cause value: %s", cause.c_str());
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
if (body_data) {
free(body_data);
body_data = NULL;
}
fflush(stdout);
}
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_push_to_amf_agent& itti_msg)
{
nlohmann::json amf_agent_data;
amf_agent_data["supi"] = itti_msg.supi;
amf_agent_data["accessType"] = itti_msg.accesstype;
amf_agent_data["rmState"] = itti_msg.rmState;
amf_agent_data["cmState"] = itti_msg.cmstate;
amf_agent_data["ranUeNgapId"] = itti_msg.ran_ue_ngap_id;
amf_agent_data["amfUeNgapId"] = itti_msg.amf_ue_ngap_id;
std::string remoteUri = amf_cfg.amf_agent_addr4 + ":" + std::to_string(amf_cfg.amf_agent_port) + "/namf-event-exposure/bridge";
std::string Method = "POST";
std::string msgBody = amf_agent_data.dump();
std::string Response;
curl_http_client(remoteUri, Method, msgBody, Response);
}
//------------------------------------------------------------------------------
......
......@@ -57,6 +57,10 @@ class amf_app {
void handle_itti_message(itti_n1n2_message_transfer_request& itti_msg);
void handle_itti_message(itti_test_signalling_paging& itti_msg);
void handle_itti_message(itti_test_signalling_network_initiated_deregistration& itti_msg);
void handle_itti_message(itti_push_to_amf_agent& itti_msg);
void curl_http_client(std::string remoteUri, std::string Method, std::string msgBody, std::string &Response);
// context management
std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx;
mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx;
......
......@@ -210,6 +210,10 @@ int amf_config::load(const std::string& config_file) {
smf_inst.selected = false;
smf_pool.push_back(smf_inst);
}
const Setting& amf_agent_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_AMF_AGENT];
amf_agent_cfg.lookupValue(AMF_CONFIG_STRING_INTERFACE_IPV4_ADDRESS_AMF_AGENT,amf_agent_addr4);
amf_agent_cfg.lookupValue(AMF_CONFIG_STRING_INTERFACE_PORT_AMF_AGENT,amf_agent_port);
} catch (const SettingNotFoundException& nfex) {
Logger::amf_app().error(
"%s : %s, using defaults", nfex.what(), nfex.getPath());
......
......@@ -52,6 +52,12 @@
#define AMF_CONFIG_STRING_PORT "PORT"
#define AMF_CONFIG_STRING_PPID "PPID"
#define AMF_CONFIG_STRING_INTERFACE_AMF_AGENT "AMF_AGENT"
#define AMF_CONFIG_STRING_INTERFACE_PORT_AMF_AGENT "PORT"
#define AMF_CONFIG_STRING_INTERFACE_IPV4_ADDRESS_AMF_AGENT "IPV4_ADDRESS"
#define AMF_CONFIG_STRING_INTERFACE_N11 "N11"
#define AMF_CONFIG_STRING_SMF_INSTANCES_POOL "SMF_INSTANCES_POOL"
#define AMF_CONFIG_STRING_SMF_INSTANCE_ID "SMF_INSTANCE_ID"
......@@ -172,6 +178,8 @@ class amf_config {
interface_cfg_t n2;
interface_cfg_t n11;
interface_cfg_t nausf;
std::string amf_agent_addr4;
unsigned int amf_agent_port;
itti_cfg_t itti;
unsigned int statistics_interval;
std::string AMF_Name;
......
......@@ -358,6 +358,8 @@ void amf_n1::nas_signalling_establishment_request_handle(
nc.get()->ran_ue_ngap_id = ran_ue_ngap_id;
nc.get()->serving_network = snn;
// stacs.UE_connected += 1;
} else {
// Logger::amf_n1().debug("existing nas_context with amf_ue_ngap_id(0x%x)
// --> Update",amf_ue_ngap_id); nc =
......@@ -373,12 +375,70 @@ void amf_n1::nas_signalling_establishment_request_handle(
"Received registration request message, handling...");
registration_request_handle(true, nc, ran_ue_ngap_id, amf_ue_ngap_id, snn,
plain_msg);
//--------------------------- push to amf agent ---------------------------
itti_push_to_amf_agent *itti_msg =
new itti_push_to_amf_agent(TASK_AMF_N1, TASK_AMF_APP);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->supi = "imsi-" + nc.get()->imsi;
itti_msg->accesstype = "3GPP_ACCESS";
itti_msg->cmstate = "CONNECTED";
if(nc.get()->_5gmm_state == _5GMM_REGISTERED)
{
itti_msg->rmState = "REGISTERED";
}
else
{
itti_msg->rmState = "DEREGISTERED";
}
std::shared_ptr<itti_push_to_amf_agent> i =
std::shared_ptr<itti_push_to_amf_agent>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_APP",
i->get_msg_name());
}
//------------------------------------------------------------------------
} break;
case SERVICE_REQUEST: {
Logger::amf_n1().debug("Received service request message, handling...");
if(nc != nullptr)
nc.get()->security_ctx->ul_count.seq_num = ulCount;
service_request_handle(true, nc, ran_ue_ngap_id, amf_ue_ngap_id, plain_msg);
//--------------------------- push to amf agent ---------------------------
itti_push_to_amf_agent *itti_msg =
new itti_push_to_amf_agent(TASK_AMF_N1, TASK_AMF_APP);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->supi = "imsi-" + nc.get()->imsi;
itti_msg->accesstype = "3GPP_ACCESS";
itti_msg->cmstate = "CONNECTED";
if(nc.get()->_5gmm_state == _5GMM_REGISTERED)
{
itti_msg->rmState = "REGISTERED";
}
else
{
itti_msg->rmState = "DEREGISTERED";
}
std::shared_ptr<itti_push_to_amf_agent> i =
std::shared_ptr<itti_push_to_amf_agent>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_APP",
i->get_msg_name());
}
//------------------------------------------------------------------------
} break;
case UE_INIT_DEREGISTER: {
Logger::amf_n1().debug(
......@@ -386,7 +446,38 @@ void amf_n1::nas_signalling_establishment_request_handle(
"...");
// ue_initiate_de_registration_handle(ran_ue_ngap_id, amf_ue_ngap_id,
// plain_msg);
//--------------------------- push to amf agent ---------------------------
itti_push_to_amf_agent *itti_msg =
new itti_push_to_amf_agent(TASK_AMF_N1, TASK_AMF_APP);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->supi = "imsi-" + nc.get()->imsi;
itti_msg->accesstype = "3GPP_ACCESS";
itti_msg->cmstate = "CONNECTED";
if(nc.get()->_5gmm_state == _5GMM_REGISTERED)
{
itti_msg->rmState = "REGISTERED";
}
else
{
itti_msg->rmState = "DEREGISTERED";
}
std::shared_ptr<itti_push_to_amf_agent> i =
std::shared_ptr<itti_push_to_amf_agent>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_APP",
i->get_msg_name());
}
//------------------------------------------------------------------------
} break;
default:
Logger::amf_n1().error("No handler for NAS message 0x%x", message_type);
}
......@@ -1481,7 +1572,7 @@ bool amf_n1::_5g_aka_confirmation_from_ausf(std::shared_ptr<nas_context> &nc,
kseaf_hex = format_string_as_hex(confirmationdataresponse.getKseaf());
else
return false;
memcpy(nc.get()->_5g_av[0].kseaf, kseaf_hex, 32);
print_buffer("amf_n1", "5G AV: kseaf", nc.get()->_5g_av[0].kseaf, 32);
free_wrapper((void **)&kseaf_hex);
......
......@@ -85,6 +85,7 @@ typedef enum {
TEST_SIGNALLING_PAGING,
TEST_SIGNALLING_NETWORK_INITIATED_DEREGISTRAATION,
PAGING,
PUSH_TO_AMF_AGENT,
TIME_OUT,
HEALTH_PING,
TERMINATE,
......
......@@ -82,6 +82,23 @@ class itti_test_signalling_network_initiated_deregistration : public itti_msg_am
long amf_ue_ngap_id;
};
class itti_push_to_amf_agent : public itti_msg_amf_app {
public:
itti_push_to_amf_agent(const task_id_t origin, const task_id_t destination)
: itti_msg_amf_app(PUSH_TO_AMF_AGENT, origin, destination) {}
itti_push_to_amf_agent(const itti_push_to_amf_agent& i) : itti_msg_amf_app(i) {}
public:
uint32_t ran_ue_ngap_id;
long amf_ue_ngap_id;
std::string supi;
std::string cmstate;
std::string rmState;
std::string accesstype;
};
#endif
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