Skip to content
Snippets Groups Projects
Commit a6bdab2d authored by Stefan Spettel's avatar Stefan Spettel
Browse files

feat(pcf): Integrate new entrypoint and jinja2 template and change configuration as discussed

parent 08842a20
No related branches found
No related tags found
1 merge request!18Created generic configuration framework to be used by all NFs
Pipeline #34769 passed
......@@ -22,42 +22,38 @@
##### Base configuration #####
# Name of the component, used towards NRF. Valid values: any string, DEFAULT="PCF"
name: "PCF"
name: "{{ env["PCF_NAME"] }}"
# Directories where policy configuration is stored, absolute path
pcc_rules_directory: "/openair-pcf/policies/pcc_rules"
traffic_rules_directory: "/openair-pcf/policies/traffic_rules"
policy_decisions_directory: "/openair-pcf/policies/policy_decisions"
pcc_rules_directory: "{{ env["PCC_RULES_DIR"] }}"
traffic_rules_directory: "{{ env["TRAFFIC_RULES_DIR"] }}"
policy_decisions_directory: "{{ env["POLICY_DECISIONS_DIR"] }}"
##### Options to enable/disable #####
# If "on": Register to NRF, DEFAULT= off
register_nrf: on
# If "on": Send only HTTP/2 requests, DEFAULT=off
use_http2: off
register_nrf: {{ env["REGISTER_NRF"] if "REGISTER_NRF" in env.keys() else 'no' }}
# If "2": Send only HTTP/2 requests, DEFAULT=1 (HTTP1)
client_http_version: {{ env["CLIENT_HTTP_VERSION"] if "CLIENT_HTTP_VERSION" in env.keys() else '1' }}
##### Local interface #####
# Local SBI interface
## name: Name of the NIC to read the IP address from
## Port: unsigned int between 0-65,535
## port_http: unsigned int between 1-65535 for HTTP1 port
## port_http2: unsigned int between 1-65535 for HTTP2 port
## http_version: Allowed values: "1", "2"
## api_version: Allowed values: "v1", "v2", used to create the 3GPP API version for the SBI URL
local_sbi_interface:
name: "eth0"
port: 80
http_version: 1
api_version: "v1"
# Local HTTP2 SBI interface, optional. When configured, HTTP2 server is used
local_sbi_interface_http2:
name: "eth0"
port: 8080
http_version: 2
api_version: "v1"
name: "{{ env["SBI_IF_NAME"] }}"
port_http: {{ env["SBI_PORT_HTTP1"] if "SBI_PORT_HTTP1" in env.keys() else '80' }}
port_http2: {{ env["SBI_PORT_HTTP2"] if "SBI_PORT_HTTP2" in env.keys() else '8080' }}
http_version: {{ env["SBI_HTTP_VERSION"] if "SBI_HTTP_VERSION" in env.keys() else '1' }}
api_version: "{{ env["SBI_API_VERSION"] if "SBI_API_VERSION"in env.keys() else 'v2' }}"
##### Next hop interfaces #####
# Next hop SBI interfaces
## url: has to follow this scheme: http://<name>:<port>
## host: IPv4 address or hostname
## api_version: Allowed values: "v1", "v2", used to create the 3GPP API version for the SBI URL
nrf:
url: "http://oai-nrf:80"
api_version: "v1"
host: "{{ env["NRF_HOST"] if "NRF_HOST"in env.keys() else 'oai-nrf' }}"
port: {{ env["NRF_PORT"] if "NRF_PORT" in env.keys() else '80' }}
api_version: "{{ env["NRF_API_VERSION"] if "NRF_API_VERSION" in env.keys() else 'v1' }}"
......@@ -25,7 +25,7 @@ import socket
import os
import sys
CONFIG_FILE = str(os.getenv('CONFIG_FILE','/openair-pcf/etc/pcf.conf'))
CONFIG_FILE = str(os.getenv('CONFIG_FILE','/openair-pcf/etc/conf.yaml'))
MOUNT_CONFIG = str(os.getenv('MOUNT_CONFIG','no')).lower()
def resolve(hostname):
......
......@@ -90,6 +90,7 @@ std::string config::to_string() const {
local_iface_out.append(val);
break;
case config_type_e::string:
case config_type_e::uint8:
base_conf_out.append(val);
break;
case config_type_e::option:
......@@ -155,6 +156,15 @@ const local_sbi_interface& config::get_local_sbi_interface(
return get<local_sbi_interface>(name);
}
uint8_t config::get_uint8_conf_val(const std::string& name) const {
return get_uint8_conf(name).get_value();
}
const uint8_config_value& config::get_uint8_conf(
const std::string& name) const {
return get<uint8_config_value>(name);
}
template<typename T>
const T& config::get(const std::string& name) const {
static_assert(
......
......@@ -123,6 +123,24 @@ class config_iface {
[[nodiscard]] virtual const local_interface& get_local_interface(
const std::string& name) const = 0;
/**
* Gets a uint8 configuration value
* @throws std::invalid_argument when name does not exist in configuration
* @param name of the configuration
* @return value
*/
[[nodiscard]] virtual uint8_t get_uint8_conf_val(
const std::string& name) const = 0;
/**
* Gets a uint8 configuration
* @throws std::invalid_argument when name does not exist in configuration
* @param name of the configuration
* @return value
*/
[[nodiscard]] virtual const uint8_config_value& get_uint8_conf(
const std::string& name) const = 0;
/**
* Displays the to_string method to the config logger
*/
......@@ -174,6 +192,12 @@ class config : public config_iface {
[[nodiscard]] const local_sbi_interface& get_local_sbi_interface(
const std::string& name) const override;
[[nodiscard]] uint8_t get_uint8_conf_val(
const std::string& name) const override;
[[nodiscard]] const uint8_config_value& get_uint8_conf(
const std::string& name) const override;
void display() const override;
private:
......
......@@ -73,7 +73,11 @@ bool sbi_interface::validate() {
sbi_interface::sbi_interface(YAML::Node const& node) {
m_api_version = node["api_version"].as<std::string>();
m_url = node["url"].as<std::string>();
// this is easily adaptable to HTTPS, just add a flag, and we change the URL
m_url.append("http://")
.append(node["host"].as<std::string>())
.append(":")
.append(node["port"].as<std::string>());
}
std::string sbi_interface::to_string(const std::string& indent) const {
......@@ -181,15 +185,11 @@ uint16_t local_interface::get_port() const {
}
local_sbi_interface::local_sbi_interface(YAML::Node const& node) {
auto iface = local_interface{node};
m_port = iface.m_port;
m_if_name = iface.m_if_name;
m_api_version = node["api_version"].as<std::string>();
auto http_version = node["http_version"].as<std::string>();
if (http_version == "2") {
m_use_http2 = true;
}
m_if_name = node["name"].as<std::string>();
m_port = node["port_http"].as<uint16_t>();
m_port_http2 = node["port_http2"].as<uint16_t>();
m_api_version = node["api_version"].as<std::string>();
m_http_version = node["http_version"].as<uint8_t>();
}
bool local_sbi_interface::validate() {
......@@ -197,6 +197,13 @@ bool local_sbi_interface::validate() {
if (!sbi_validate) {
return false;
}
if (m_http_version < 1 || m_http_version > 2) {
logger::logger_registry::get_logger(LOGGER_NAME)
.error("Wrong HTTP version: %u. Should be 1 or 2", m_http_version);
return false;
}
return local_interface::validate();
}
......@@ -211,11 +218,9 @@ std::string local_sbi_interface::to_string(const std::string& indent) const {
BASE_FORMATTER, INNER_LIST_ELEM, "API Version", inner_width,
m_api_version));
std::string http_version = m_use_http2 ? "2" : "1";
out.append(indent).append(fmt::format(
BASE_FORMATTER, INNER_LIST_ELEM, "HTTP Version", inner_width,
http_version));
m_http_version));
return out;
}
......@@ -224,8 +229,12 @@ const std::string& local_sbi_interface::get_api_version() const {
return m_api_version;
}
bool local_sbi_interface::use_http2() const {
return m_use_http2;
uint8_t local_sbi_interface::http_version() const {
return m_http_version;
}
uint16_t local_sbi_interface::get_port_http2() const {
return m_port_http2;
}
bool network_interface::validate_sbi_api_version(const std::string& v) {
......@@ -283,6 +292,48 @@ bool option_config_value::get_value() const {
return m_value;
}
uint8_config_value factory::get_uint8_config(uint8_t val) {
uint8_config_value v;
v.m_value = val;
return v;
}
uint8_config_value::uint8_config_value(const YAML::Node& node) {
m_value = node.as<uint8_t>();
}
std::string uint8_config_value::to_string(const std::string&) const {
return std::to_string(m_value);
}
bool uint8_config_value::validate() {
if (m_value < m_min_value || m_value > m_max_value) {
logger::logger_registry::get_logger(LOGGER_NAME)
.error(
"Value should be in [%u, %u], but it is: %u", m_min_value,
m_max_value, m_value);
return false;
}
m_set = true;
return true;
}
config_type_e uint8_config_value::get_config_type() const {
return config_type_e::uint8;
}
uint8_t uint8_config_value::get_value() const {
return m_value;
}
void uint8_config_value::set_validation_min_value(uint8_t val) {
m_min_value = val;
}
void uint8_config_value::set_validation_max_value(uint8_t val) {
m_max_value = val;
}
option_config_value factory::get_option_config(bool val) {
option_config_value v;
v.m_value = val;
......
......@@ -42,7 +42,7 @@ const std::vector<std::string> allowed_api_versions{"v1", "v2"};
const std::string URL_REGEX = "http://.*:[0-9]*";
// Only used for pretty-printing
enum class config_type_e { string, option, sbi, local, invalid };
enum class config_type_e { string, option, sbi, local, invalid, uint8 };
class config_type {
friend class yaml_file_iface;
......@@ -126,6 +126,27 @@ class option_config_value : public config_type {
[[nodiscard]] bool get_value() const;
};
class uint8_config_value : public config_type {
friend class factory;
private:
uint8_t m_value = 0;
uint8_t m_min_value = 0;
uint8_t m_max_value = UINT8_MAX;
public:
explicit uint8_config_value(YAML::Node const&);
uint8_config_value() = default;
[[nodiscard]] std::string to_string(const std::string& indent) const override;
[[nodiscard]] bool validate() override;
[[nodiscard]] config_type_e get_config_type() const override;
[[nodiscard]] uint8_t get_value() const;
void set_validation_min_value(uint8_t val);
void set_validation_max_value(uint8_t val);
};
class network_interface : public config_type {
public:
static bool validate_sbi_api_version(const std::string& v);
......@@ -175,8 +196,9 @@ class local_interface : public network_interface {
class local_sbi_interface : public local_interface {
private:
std::string m_api_version;
bool m_use_http2 = false;
std::string m_api_version{};
uint8_t m_http_version = 1;
uint16_t m_port_http2{};
public:
explicit local_sbi_interface(YAML::Node const&);
......@@ -186,7 +208,8 @@ class local_sbi_interface : public local_interface {
[[nodiscard]] std::string to_string(const std::string& indent) const override;
[[nodiscard]] const std::string& get_api_version() const;
[[nodiscard]] bool use_http2() const;
[[nodiscard]] uint8_t http_version() const;
[[nodiscard]] uint16_t get_port_http2() const;
};
class factory {
......@@ -194,6 +217,8 @@ class factory {
static option_config_value get_option_config(bool val);
static string_config_value get_string_config(const std::string& val);
static uint8_config_value get_uint8_config(uint8_t val);
};
} // namespace oai::config
......@@ -40,7 +40,10 @@ void oai::config::yaml_file::read_from_file(
bool success;
auto key = elem.first.as<std::string>();
if (elem.second.IsScalar()) {
success = convert_type<option_config_value>(key, elem.second, config);
success = convert_type<uint8_config_value>(key, elem.second, config);
if (!success) {
success = convert_type<option_config_value>(key, elem.second, config);
}
if (!success) {
success = convert_type<string_config_value>(key, elem.second, config);
}
......
......@@ -114,10 +114,10 @@ int main(int argc, char** argv) {
pcf_api_server_1->init(2);
std::thread pcf_http1_manager(&PCFApiServer::start, pcf_api_server_1.get());
if (pcf_cfg->sbi_http2.is_set()) {
if (pcf_cfg->sbi.http_version() == 2) {
// PCF NGHTTP API server (HTTP2)
pcf_api_server_2 = std::make_unique<pcf_http2_server>(
v4_address, pcf_cfg->sbi_http2.get_port(), pcf_app_inst);
v4_address, pcf_cfg->sbi.get_port_http2(), pcf_app_inst);
std::thread pcf_http2_manager(
&pcf_http2_server::start, pcf_api_server_2.get());
pcf_http2_manager.join();
......
......@@ -109,7 +109,7 @@ http_status_code_e pcf_client::do_request(
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
curl_easy_setopt(curl, CURLOPT_INTERFACE, pcf_cfg->sbi.get_if_name().c_str());
if (pcf_cfg->pcf_features.use_http2) {
if (pcf_cfg->pcf_features.client_http_version == 2) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// we use a self-signed test server, skip verification during debugging
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
......
......@@ -34,16 +34,17 @@ using namespace oai::config;
bool oai::pcf::config::pcf_config::init() {
// Default configuration
std::unique_ptr<config_type> use_http2 =
std::make_unique<option_config_value>(
factory::get_option_config(USE_HTTP2_DEFAULT_VALUE));
std::unique_ptr<config_type> client_http_version =
std::make_unique<uint8_config_value>(
factory::get_uint8_config(CLIENT_HTTP2_VERSION_DEFAULT_VALUE));
std::unique_ptr<config_type> register_nrf =
std::make_unique<option_config_value>(
factory::get_option_config(REGISTER_NRF_DEFAULT_VALUE));
std::unique_ptr<config_type> pcf_name = std::make_unique<string_config_value>(
factory::get_string_config(NAME_DEFAULT_VALUE));
m_cfg->set_configuration(PCF_CONFIG_STRING_USE_HTTP2, std::move(use_http2));
m_cfg->set_configuration(
PCF_CONFIG_STRING_CLIENT_HTTP_VERSION, std::move(client_http_version));
m_cfg->set_configuration(
PCF_CONFIG_STRING_REGISTER_NRF, std::move(register_nrf));
m_cfg->set_configuration(PCF_CONFIG_STRING_NAME, std::move(pcf_name));
......@@ -64,6 +65,7 @@ bool oai::pcf::config::pcf_config::init() {
if (m_cfg->get_support_feature(PCF_CONFIG_STRING_REGISTER_NRF)) {
m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_NRF);
}
set_validation_constraints();
bool validated = m_cfg->validate();
if (!validated) {
......@@ -77,11 +79,6 @@ bool oai::pcf::config::pcf_config::init() {
void oai::pcf::config::pcf_config::set_direct_variables() {
sbi = m_cfg->get_local_sbi_interface(PCF_CONFIG_STRING_SBI_IFACE);
try {
sbi_http2 =
m_cfg->get_local_sbi_interface(PCF_CONFIG_STRING_SBI_IFACE_HTTP2);
} catch (std::invalid_argument&) {
}
nrf_addr = m_cfg->get_sbi_interface(PCF_CONFIG_STRING_NRF);
pcc_rules_path = m_cfg->get_base_conf_val(PCF_CONFIG_STRING_PCC_RULES_DIR);
......@@ -92,10 +89,22 @@ void oai::pcf::config::pcf_config::set_direct_variables() {
pcf_features.register_nrf =
m_cfg->get_support_feature(PCF_CONFIG_STRING_REGISTER_NRF);
pcf_features.use_http2 =
m_cfg->get_support_feature(PCF_CONFIG_STRING_USE_HTTP2);
pcf_features.client_http_version =
m_cfg->get_uint8_conf_val(PCF_CONFIG_STRING_CLIENT_HTTP_VERSION);
}
void oai::pcf::config::pcf_config::display() {
m_cfg->display();
}
void oai::pcf::config::pcf_config::set_validation_constraints() {
std::unique_ptr<uint8_config_value> http_client_version_ptr =
std::make_unique<uint8_config_value>(
m_cfg->get_uint8_conf(PCF_CONFIG_STRING_CLIENT_HTTP_VERSION));
http_client_version_ptr->set_validation_max_value(2);
http_client_version_ptr->set_validation_min_value(1);
m_cfg->set_configuration(
PCF_CONFIG_STRING_CLIENT_HTTP_VERSION,
std::move(http_client_version_ptr));
}
......@@ -33,32 +33,29 @@
namespace oai::pcf::config {
const std::string NAME_DEFAULT_VALUE = "PCF";
const bool REGISTER_NRF_DEFAULT_VALUE = false;
const bool USE_HTTP2_DEFAULT_VALUE = false;
const std::string PCF_CONFIG_STRING_REGISTER_NRF = "register_nrf";
const std::string PCF_CONFIG_STRING_USE_HTTP2 = "use_http2";
const std::string PCF_CONFIG_STRING_NAME = "name";
const std::string PCF_CONFIG_STRING_PCC_RULES_DIR = "pcc_rules_directory";
const std::string NAME_DEFAULT_VALUE = "PCF";
const bool REGISTER_NRF_DEFAULT_VALUE = false;
const uint8_t CLIENT_HTTP2_VERSION_DEFAULT_VALUE = 1;
const std::string PCF_CONFIG_STRING_REGISTER_NRF = "register_nrf";
const std::string PCF_CONFIG_STRING_CLIENT_HTTP_VERSION = "client_http_version";
const std::string PCF_CONFIG_STRING_NAME = "name";
const std::string PCF_CONFIG_STRING_PCC_RULES_DIR = "pcc_rules_directory";
const std::string PCF_CONFIG_STRING_POLICY_DECISIONS_DIR =
"policy_decisions_directory";
const std::string PCF_CONFIG_STRING_TRAFFIC_RULES_DIR =
"traffic_rules_directory";
const std::string PCF_CONFIG_STRING_SBI_IFACE = "local_sbi_interface";
const std::string PCF_CONFIG_STRING_SBI_IFACE_HTTP2 =
"local_sbi_interface_http2";
const std::string PCF_CONFIG_STRING_NRF = "nrf";
const std::string PCF_CONFIG_STRING_NRF = "nrf";
struct support_features {
bool register_nrf;
bool use_http2;
uint8_t client_http_version;
};
class pcf_config {
public:
oai::config::local_sbi_interface sbi;
oai::config::local_sbi_interface sbi_http2;
std::string pcc_rules_path;
std::string policy_decisions_path;
std::string traffic_rules_path;
......@@ -90,5 +87,7 @@ class pcf_config {
std::string m_config_path;
void set_direct_variables();
void set_validation_constraints();
};
} // namespace oai::pcf::config
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment