Commit 4cbe461a authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

Remove local test

parent f47a5519
......@@ -2,5 +2,5 @@
## v1.0.0 -- September 2020 ##
* Initial release
* Initial release, SMF can handle basic PDU session-related procedures e.g., session establishment request, session modification and session release.
......@@ -74,6 +74,5 @@ openair-cn5g-smf
├── oai_smf: SMF main directory, contains the "main" CMakeLists.txt file.
├── pfcp: Generic PFCP stack implementation.
├── smf_app: SMF network functions procedures and contexts.
├── test: Minimal implementation for AMF, UDM network functions for testing purpose.
└── udp : UDP server implementation.
</pre>
......@@ -12,8 +12,8 @@ SMF_CONF[@INSTANCE@]=$INSTANCE
SMF_CONF[@PREFIX@]=$PREFIX
SMF_CONF[@PID_DIRECTORY@]='/var/run'
SMF_CONF[@SMF_INTERFACE_NAME_FOR_N4@]='wlo1'
SMF_CONF[@SMF_INTERFACE_NAME_FOR_SBI@]='wlo1'
SMF_CONF[@SMF_INTERFACE_NAME_FOR_N4@]='enx0050b6f4b8f0'
SMF_CONF[@SMF_INTERFACE_NAME_FOR_SBI@]='enx0050b6f4b8f0'
SMF_CONF[@SMF_INTERFACE_PORT_FOR_SBI@]='80'
SMF_CONF[@SMF_INTERFACE_HTTP2_PORT_FOR_SBI@]='9090'
......@@ -27,7 +27,7 @@ SMF_CONF[@AMF_IPV4_ADDRESS@]='192.168.122.183'
SMF_CONF[@AMF_PORT@]='80'
SMF_CONF[@AMF_API_VERSION@]='v1'
SMF_CONF[@UPF_IPV4_ADDRESS@]='192.168.122.151'
SMF_CONF[@UPF_IPV4_ADDRESS@]='192.168.12.245'
SMF_CONF[@NRF_IPV4_ADDRESS@]='192.168.1.23'
SMF_CONF[@NRF_PORT@]='8080'
......
......@@ -118,7 +118,7 @@ SMF =
{ NSSAI_SST = 222, NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"},
{ NSSAI_SST = 111; NSSAI_SD = "321", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
{ NSSAI_SST = 111; NSSAI_SD = "124", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "10Mbps", SESSION_AMBR_DL = "11Mbps"}
);
......
cmake_minimum_required (VERSION 3.2)
project(amf-server)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" )
include_directories(model)
include_directories(api)
include_directories(impl)
file(GLOB SRCS
${CMAKE_CURRENT_SOURCE_DIR}/api/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/impl/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/model/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
add_executable(${PROJECT_NAME} ${SRCS} )
#add_dependencies(${PROJECT_NAME} PISTACHE NLOHMANN)
target_link_libraries(${PROJECT_NAME} pistache pthread)
# REST API Server for Namf_Communication
## Overview
This API Server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
It uses the [Pistache](https://github.com/oktal/pistache) Framework.
## Files organization
The Pistache C++ REST server generator creates three folders:
- `api`: This folder contains the handlers for each method specified in the OpenAPI definition. Every handler extracts
the path and body parameters (if any) from the requests and tries to parse and possibly validate them.
Once this step is completed, the main API class calls the corresponding abstract method that should be implemented
by the developer (a basic implementation is provided under the `impl` folder)
- `impl`: As written above, the implementation folder contains, for each API, the corresponding implementation class,
which extends the main API class and implements the abstract methods.
Every method receives the path and body parameters as constant reference variables and a reference to the response
object, that should be filled with the right response and sent at the end of the method with the command:
response.send(returnCode, responseBody, [mimeType])
- `model`: This folder contains the corresponding class for every object schema found in the OpenAPI specification.
The main folder contains also a file with a main that can be used to start the server.
Of course, is you should customize this file based on your needs
## Installation
First of all, you need to download and install the libraries listed [here](#libraries-required).
Once the libraries are installed, in order to compile and run the server please follow the steps below:
```bash
mkdir build
cd build
cmake ..
make
```
Once compiled run the server:
```bash
cd build
./api-server
```
## Libraries required
- [pistache](http://pistache.io/quickstart)
- [JSON for Modern C++](https://github.com/nlohmann/json/#integration): Please download the `json.hpp` file and
put it under the model/nlohmann folder
## Namespaces
oai.amf.api
oai.amf.model
/**
* Namf_Communication
* AMF Communication Service © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "pistache/endpoint.h"
#include "pistache/http.h"
#include "pistache/router.h"
#ifdef __linux__
#include <vector>
#include <signal.h>
#include <unistd.h>
#endif
#include "IndividualSubscriptionDocumentApiImpl.h"
#include "IndividualUeContextDocumentApiImpl.h"
#include "N1N2IndividualSubscriptionDocumentApiImpl.h"
#include "N1N2MessageCollectionDocumentApiImpl.h"
#include "N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl.h"
#include "NonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl.h"
#include "NonUEN2MessagesCollectionDocumentApiImpl.h"
#include "NonUEN2MessagesSubscriptionsCollectionDocumentApiImpl.h"
#include "SubscriptionsCollectionDocumentApiImpl.h"
#define PISTACHE_SERVER_THREADS 2
#define PISTACHE_SERVER_MAX_PAYLOAD 32768
static Pistache::Http::Endpoint *httpEndpoint;
#ifdef __linux__
static void sigHandler(int sig){
switch(sig){
case SIGINT:
case SIGQUIT:
case SIGTERM:
case SIGHUP:
default:
httpEndpoint->shutdown();
break;
}
exit(0);
}
static void setUpUnixSignals(std::vector<int> quitSignals) {
sigset_t blocking_mask;
sigemptyset(&blocking_mask);
for (auto sig : quitSignals)
sigaddset(&blocking_mask, sig);
struct sigaction sa;
sa.sa_handler = sigHandler;
sa.sa_mask = blocking_mask;
sa.sa_flags = 0;
for (auto sig : quitSignals)
sigaction(sig, &sa, nullptr);
}
#endif
using namespace oai::amf::api;
int main(int argc, char* argv[]) {
#ifdef __linux__
std::vector<int> sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
setUpUnixSignals(sigs);
#endif
std::string amf_ip_address;
if ((argc != 1) && (argc != 3)) {
std::cout << "Error: Usage is " <<std::endl;
std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl;
return -1;
}
if (argc == 1) {
amf_ip_address.append(std::string("192.168.28.3"));
} else {
int opt = 0;
while ((opt = getopt(argc, argv, "i:")) != -1) {
switch(opt) {
case 'i':
amf_ip_address.append(optarg);
break;
default:
std::cout << "Error: Usage is " <<std::endl;
std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl;
return -1;
break;
}
}
}
Pistache::Address addr(amf_ip_address, Pistache::Port(80));
httpEndpoint = new Pistache::Http::Endpoint((addr));
auto router = std::make_shared<Pistache::Rest::Router>();
auto opts = Pistache::Http::Endpoint::options()
.threads(PISTACHE_SERVER_THREADS);
opts.flags(Pistache::Tcp::Options::ReuseAddr);
opts.maxPayload(PISTACHE_SERVER_MAX_PAYLOAD);
httpEndpoint->init(opts);
IndividualSubscriptionDocumentApiImpl IndividualSubscriptionDocumentApiserver(router);
IndividualSubscriptionDocumentApiserver.init();
IndividualUeContextDocumentApiImpl IndividualUeContextDocumentApiserver(router);
IndividualUeContextDocumentApiserver.init();
N1N2IndividualSubscriptionDocumentApiImpl N1N2IndividualSubscriptionDocumentApiserver(router);
N1N2IndividualSubscriptionDocumentApiserver.init();
N1N2MessageCollectionDocumentApiImpl N1N2MessageCollectionDocumentApiserver(router);
N1N2MessageCollectionDocumentApiserver.init();
N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiImpl N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiserver(router);
N1N2SubscriptionsCollectionForIndividualUEContextsDocumentApiserver.init();
NonUEN2MessageNotificationIndividualSubscriptionDocumentApiImpl NonUEN2MessageNotificationIndividualSubscriptionDocumentApiserver(router);
NonUEN2MessageNotificationIndividualSubscriptionDocumentApiserver.init();
NonUEN2MessagesCollectionDocumentApiImpl NonUEN2MessagesCollectionDocumentApiserver(router);
NonUEN2MessagesCollectionDocumentApiserver.init();
NonUEN2MessagesSubscriptionsCollectionDocumentApiImpl NonUEN2MessagesSubscriptionsCollectionDocumentApiserver(router);
NonUEN2MessagesSubscriptionsCollectionDocumentApiserver.init();
SubscriptionsCollectionDocumentApiImpl SubscriptionsCollectionDocumentApiserver(router);
SubscriptionsCollectionDocumentApiserver.init();
std::cout << "AMF server is listening on address: " << amf_ip_address.c_str() << std::endl;
httpEndpoint->setHandler(router->handler());
httpEndpoint->serve();
httpEndpoint->shutdown();
}
/**
* Namf_Communication
* AMF Communication Service © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "IndividualSubscriptionDocumentApi.h"
#include "Helpers.h"
namespace oai {
namespace amf {
namespace api {
using namespace org::openapitools::server::helpers;
using namespace oai::amf::model;
IndividualSubscriptionDocumentApi::IndividualSubscriptionDocumentApi(std::shared_ptr<Pistache::Rest::Router> rtr) {
router = rtr;
}
void IndividualSubscriptionDocumentApi::init() {
setupRoutes();
}
void IndividualSubscriptionDocumentApi::setupRoutes() {
using namespace Pistache::Rest;
Routes::Put(*router, base + "/subscriptions/:subscriptionId", Routes::bind(&IndividualSubscriptionDocumentApi::a_mf_status_change_subscribe_modfy_handler, this));
Routes::Delete(*router, base + "/subscriptions/:subscriptionId", Routes::bind(&IndividualSubscriptionDocumentApi::a_mf_status_change_un_subscribe_handler, this));
// Default handler, called when a route is not found
router->addCustomHandler(Routes::bind(&IndividualSubscriptionDocumentApi::individual_subscription_document_api_default_handler, this));
}
void IndividualSubscriptionDocumentApi::a_mf_status_change_subscribe_modfy_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto subscriptionId = request.param(":subscriptionId").as<std::string>();
// Getting the body param
SubscriptionData subscriptionData;
try {
nlohmann::json::parse(request.body()).get_to(subscriptionData);
this->a_mf_status_change_subscribe_modfy(subscriptionId, subscriptionData, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualSubscriptionDocumentApi::a_mf_status_change_un_subscribe_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto subscriptionId = request.param(":subscriptionId").as<std::string>();
try {
this->a_mf_status_change_un_subscribe(subscriptionId, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualSubscriptionDocumentApi::individual_subscription_document_api_default_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
}
}
}
}
/**
* Namf_Communication
* AMF Communication Service © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* IndividualSubscriptionDocumentApi.h
*
*
*/
#ifndef IndividualSubscriptionDocumentApi_H_
#define IndividualSubscriptionDocumentApi_H_
#include <pistache/http.h>
#include <pistache/router.h>
#include <pistache/http_headers.h>
#include <pistache/optional.h>
#include "ProblemDetails.h"
#include "SubscriptionData.h"
#include <string>
namespace oai {
namespace amf {
namespace api {
using namespace oai::amf::model;
class IndividualSubscriptionDocumentApi {
public:
IndividualSubscriptionDocumentApi(std::shared_ptr<Pistache::Rest::Router>);
virtual ~IndividualSubscriptionDocumentApi() {}
void init();
const std::string base = "/namf-comm/v1";
private:
void setupRoutes();
void a_mf_status_change_subscribe_modfy_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void a_mf_status_change_un_subscribe_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
void individual_subscription_document_api_default_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response);
std::shared_ptr<Pistache::Rest::Router> router;
/// <summary>
/// Namf_Communication AMF Status Change Subscribe Modify service Operation
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="subscriptionId">AMF Status Change Subscription Identifier</param>
/// <param name="subscriptionData"></param>
virtual void a_mf_status_change_subscribe_modfy(const std::string &subscriptionId, const SubscriptionData &subscriptionData, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Namf_Communication AMF Status Change UnSubscribe service Operation
/// </summary>
/// <remarks>
///
/// </remarks>
/// <param name="subscriptionId">AMF Status Change Subscription Identifier</param>
virtual void a_mf_status_change_un_subscribe(const std::string &subscriptionId, Pistache::Http::ResponseWriter &response) = 0;
};
}
}
}
#endif /* IndividualSubscriptionDocumentApi_H_ */
/**
* Namf_Communication
* AMF Communication Service © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "IndividualUeContextDocumentApi.h"
#include "Helpers.h"
namespace oai {
namespace amf {
namespace api {
using namespace org::openapitools::server::helpers;
using namespace oai::amf::model;
IndividualUeContextDocumentApi::IndividualUeContextDocumentApi(std::shared_ptr<Pistache::Rest::Router> rtr) {
router = rtr;
}
void IndividualUeContextDocumentApi::init() {
setupRoutes();
}
void IndividualUeContextDocumentApi::setupRoutes() {
using namespace Pistache::Rest;
Routes::Put(*router, base + "/ue-contexts/:ueContextId", Routes::bind(&IndividualUeContextDocumentApi::create_ue_context_handler, this));
Routes::Post(*router, base + "/ue-contexts/:ueContextId/assign-ebi", Routes::bind(&IndividualUeContextDocumentApi::e_bi_assignment_handler, this));
Routes::Post(*router, base + "/ue-contexts/:ueContextId/transfer-update", Routes::bind(&IndividualUeContextDocumentApi::registration_status_update_handler, this));
Routes::Post(*router, base + "/ue-contexts/:ueContextId/release", Routes::bind(&IndividualUeContextDocumentApi::release_ue_context_handler, this));
Routes::Post(*router, base + "/ue-contexts/:ueContextId/transfer", Routes::bind(&IndividualUeContextDocumentApi::u_e_context_transfer_handler, this));
// Default handler, called when a route is not found
router->addCustomHandler(Routes::bind(&IndividualUeContextDocumentApi::individual_ue_context_document_api_default_handler, this));
}
void IndividualUeContextDocumentApi::create_ue_context_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto ueContextId = request.param(":ueContextId").as<std::string>();
// Getting the body param
Inline_object inlineObject;
try {
nlohmann::json::parse(request.body()).get_to(inlineObject);
this->create_ue_context(ueContextId, inlineObject, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualUeContextDocumentApi::e_bi_assignment_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto ueContextId = request.param(":ueContextId").as<std::string>();
// Getting the body param
AssignEbiData assignEbiData;
try {
nlohmann::json::parse(request.body()).get_to(assignEbiData);
this->e_bi_assignment(ueContextId, assignEbiData, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualUeContextDocumentApi::registration_status_update_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto ueContextId = request.param(":ueContextId").as<std::string>();
// Getting the body param
UeRegStatusUpdateReqData ueRegStatusUpdateReqData;
try {
nlohmann::json::parse(request.body()).get_to(ueRegStatusUpdateReqData);
this->registration_status_update(ueContextId, ueRegStatusUpdateReqData, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualUeContextDocumentApi::release_ue_context_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto ueContextId = request.param(":ueContextId").as<std::string>();
// Getting the body param
UEContextRelease uEContextRelease;
try {
nlohmann::json::parse(request.body()).get_to(uEContextRelease);
this->release_ue_context(ueContextId, uEContextRelease, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualUeContextDocumentApi::u_e_context_transfer_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the path params
auto ueContextId = request.param(":ueContextId").as<std::string>();
// Getting the body param
UeContextTransferReqData ueContextTransferReqData;
try {
nlohmann::json::parse(request.body()).get_to(ueContextTransferReqData);
this->u_e_context_transfer(ueContextId, ueContextTransferReqData, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void IndividualUeContextDocumentApi::individual_ue_context_document_api_default_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
}
}
}
}
/**
* Namf_Communication
* AMF Communication Service © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/