Commit de11cb2a authored by Franck Messaoudi's avatar Franck Messaoudi

Update: Cleaning and refactoring program folder

parent cfb8d8bc
################################################################################
# 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
################################################################################
# OAI UPF EBPF MAP SIZES Configuration File
###
# This configuration file defines key parameters for optimizing memory allocation and tuning the User Plane Function (UPF). The values set in this file directly impact the size of eBPF maps used for packet processing.
# Configuration Parameters. Each parameter in this file controls a specific aspect of UPF behavior.
# 1. Network Interface Limits
# max_upf_interfaces (Default: 8)
# Specifies the maximum number of network interfaces that UPF can manage.
# Example: Physical/virtual interfaces for GTP-U traffic.
# max_upf_redirect_interfaces (Default: 4)
# Defines the maximum number of interfaces used for traffic redirection.
# Example: Used in PDRs for forwarding packets to specific egress interfaces.
max_upf_interfaces = 8
max_upf_redirect_interfaces = 4
# 2. Session and Rule Limits
# max_pdu_session (Default: 10,000)
# Determines the maximum number of concurrent PDU sessions that UPF can handle.
# Affects the memory allocation for session-related eBPF maps.
# max_pdrs_per_pdu_session (Default: 8)
# Defines the maximum number of Packet Detection Rules (PDRs) that can be applied per PDU session.
# PDRs dictate how packets are processed, forwarded, or dropped.
# max_qos_flows_per_pdu_session (Default: 8)
# Sets the maximum number of QoS flows that a single PDU session can manage.
# Impacts QoS-related eBPF maps (e.g., shaping, policing).
# max_sdf_filters_per_pdu_session (Default: 8)
# Specifies the maximum number of Service Data Flow (SDF) filters per session.
# SDF filters define how traffic is classified within a QoS flow.
max_pdu_session = 10000
max_pdrs_per_pdu_session = 8
max_qos_flows_per_pdu_session = 8
max_sdf_filters_per_pdu_session = 8
# 3. ARP Table Limit
# max_arp_entries (Default: 4)
# Limits the number of ARP table entries stored in eBPF maps.
# Used for resolving MAC addresses in the UPF forwarding path.
max_arp_entries = 1572
# Usage Instructions
# Modify Configuration Values
# Edit the file ebpf_maps.conf to adjust UPF parameters based on deployment needs.
# Example:
# max_pdu_session = 5000
# max_pdrs_per_pdu_session = 16
# Loading the Configuration in Code
# A configuration parser (e.g., ConfigLoader) should read this file and apply the values at runtime.
# Example (C++):
# ConfigLoader config;
# config.loadConfig("upf_config.conf");
# int max_pdu_sessions = config.getValue("max_pdu_session", 10000);
# Memory Optimization
# Ensure the values are optimized to avoid excessive memory usage.
# Example: Reducing max_pdu_session decreases memory footprint.
# Best Practices
# Monitor Resource Usage: Adjust values based on system memory and performance requirements.
# Tune PDU Session Limits: Increase max_pdu_session if handling high session loads.
# Optimize QoS Handling: Set appropriate values for max_qos_flows_per_pdu_session based on traffic characteristics.
...@@ -49,10 +49,11 @@ add_library(UPF_XDP STATIC ...@@ -49,10 +49,11 @@ add_library(UPF_XDP STATIC
SessionManager.cpp SessionManager.cpp
SessionPrograms.cpp SessionPrograms.cpp
programs/pfcp_session_lookup_xdp_user.cpp programs/pfcp_session_lookup_xdp_user.cpp
#programs/far_xdp_user.cpp
programs/BPFProgram.cpp programs/BPFProgram.cpp
wrappers/BPFMaps.cpp wrappers/BPFMaps.cpp
wrappers/BPFMap.cpp wrappers/BPFMap.cpp
programs/utils/bpf_utils.cpp
programs/utils/net_utils.cpp
) )
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../build/ext/libbpf/src) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../build/ext/libbpf/src)
...@@ -106,6 +107,8 @@ install( ...@@ -106,6 +107,8 @@ install(
programs/BPFProgram.cpp programs/BPFProgram.cpp
wrappers/BPFMaps.cpp wrappers/BPFMaps.cpp
wrappers/BPFMap.cpp wrappers/BPFMap.cpp
programs/utils/bpf_utils.cpp
programs/utils/net_utils.cpp
) )
target_link_libraries(UPF_TC target_link_libraries(UPF_TC
......
...@@ -732,7 +732,8 @@ void SessionProgramManager::modifyPipeline( ...@@ -732,7 +732,8 @@ void SessionProgramManager::modifyPipeline(
seid, value, BPF_ANY); seid, value, BPF_ANY);
logger.debug("Instantiate a new QERProgram"); logger.debug("Instantiate a new QERProgram");
std::shared_ptr<QERProgram> pQERProgram = std::make_shared<QERProgram>(); std::shared_ptr<QERProgram> pQERProgram =
std::make_shared<QERProgram>(upf_cfg);
pQERProgram->setup(seid, session->qers_downlink, session->pdrs_downlink); pQERProgram->setup(seid, session->qers_downlink, session->pdrs_downlink);
} }
......
...@@ -7,12 +7,11 @@ ...@@ -7,12 +7,11 @@
#include "sdf_filter.h" #include "sdf_filter.h"
#include "qos_flow.h" #include "qos_flow.h"
#define MAX_INTERFACES 10 const volatile int max_egress_interfaces SEC(".rodata");
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
struct { struct {
__uint(type, BPF_MAP_TYPE_DEVMAP); __uint(type, BPF_MAP_TYPE_DEVMAP);
__uint(max_entries, MAX_INTERFACES); __uint(max_entries, 1);
__type(key, u32); // u8? __type(key, u32); // u8?
__type(value, u32); __type(value, u32);
} m_egress_ifindex SEC(".maps"); } m_egress_ifindex SEC(".maps");
......
...@@ -4,29 +4,6 @@ ...@@ -4,29 +4,6 @@
#include <types.h> #include <types.h>
// /* Use uint8_t*/
// struct s_gate {
// uint8_t ul_gate;
// uint8_t dl_gate;
// };
// struct s_mbr {
// uint64_t ul_mbr;
// uint64_t dl_mbr;
// };
// struct s_gbr {
// uint64_t ul_gbr;
// uint64_t dl_gbr;
// };
// struct s_fiveQosFlow {
// struct s_gate gate;
// struct s_mbr mbr;
// struct s_gbr gbr;
// uint64_t qfi;
// };
struct s_fiveQosFlow { struct s_fiveQosFlow {
uint8_t gate; uint8_t gate;
uint64_t mbr; uint64_t mbr;
......
#ifndef CONFIG_MANAGER_HPP
#define CONFIG_MANAGER_HPP
#include <sys/types.h>
class ConfigManager {
public:
// Returns the singleton instance
static ConfigManager& getInstance();
// Initializes the configuration
void initialize(bool enableBpfDatapath, bool enableQos);
// Checks if BPF datapath is enabled
bool isBpfDatapathEnabled() const;
// Checks if QoS is enabled
bool isQosEnabled() const;
private:
// Private constructor to prevent instantiation
ConfigManager() = default;
// Deleted copy constructor and assignment operator
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
// Configuration variables
bool enable_bpf_datapath = false;
bool enable_qos = false;
u_int16_t max_upf_interfaces = 8;
u_int16_t max_upf_redirect_interfaces = 4;
u_int16_t max_pdu_session = 10000;
u_int16_t max_pdrs_per_pdu_session = 8;
u_int16_t max_qos_flows_per_pdu_session = 8;
u_int16_t max_sdf_filters_per_pdu_session = 8;
u_int16_t max_arp_entries = 1572;
};
#endif // CONFIG_MANAGER_HPP
\ No newline at end of file
...@@ -9,10 +9,20 @@ ...@@ -9,10 +9,20 @@
#include "interfaces.h" #include "interfaces.h"
#include "logger.hpp" #include "logger.hpp"
#include "upf_config.hpp" #include "upf_config.hpp"
#include "utils/net_utils.hpp"
#include "utils/bpf_utils.hpp"
using namespace oai::config; using namespace oai::config;
extern upf_config upf_cfg; extern upf_config upf_cfg;
const std::string UDP_INTERFACE =
UserPlaneComponent::getInstance().getUDPInterface();
const std::string GTP_INTERFACE =
UserPlaneComponent::getInstance().getGTPInterface();
using namespace oai::utils::net;
using namespace oai::utils::bpf;
class XDPSection { class XDPSection {
public: public:
static constexpr const char* Uplink = "xdp_handle_uplink"; static constexpr const char* Uplink = "xdp_handle_uplink";
...@@ -21,121 +31,68 @@ class XDPSection { ...@@ -21,121 +31,68 @@ class XDPSection {
}; };
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
int is_little_endian2() { void PFCP_Session_LookupProgram::configurePfcpSessionLookupMaps(
u32 value = 1;
u8* byte = (u8*) &value;
return (*byte == 1);
}
/*---------------------------------------------------------------------------------------------------------------*/
// PFCP_Session_LookupProgram::PFCP_Session_LookupProgram(
// const std::string& gtpInterface, const std::string& udpInterface,
// const upf_config& upf_cfg)
// : mGTPInterface(gtpInterface), mUDPInterface(udpInterface) {
// struct pfcp_session_lookup_xdp_kernel_c* skel = nullptr;
// int ret = -1;
// Logger::upf_app().info("Initializing PFCP Session Lookup BPF program...");
// // create the open function (callable)
// auto open_fn = [&upf_cfg, this]() -> pfcp_session_lookup_xdp_kernel_c* {
// struct pfcp_session_lookup_xdp_kernel_c* skel =
// pfcp_session_lookup_xdp_kernel_c__open();
// if (!skel) {
// Logger::upf_app().error("Failed to open BPF skeleton");
// return nullptr;
// }
// // configure maps / rodata here (same pattern as kernel perf)
// uint32_t max_rules_match_pdr =
// upf_cfg.max_pdrs_per_pdu_session * upf_cfg.max_pdu_session;
// bpf_map__set_max_entries(
// skel->maps.m_upf_interfaces, upf_cfg.max_upf_interfaces);
// bpf_map__set_max_entries(
// skel->maps.m_redirect_interfaces,
// upf_cfg.max_upf_redirect_interfaces);
// bpf_map__set_max_entries(
// skel->maps.m_session_mapping, upf_cfg.max_pdu_session);
// bpf_map__set_max_entries(
// skel->maps.m_session_pdrs, upf_cfg.max_pdrs_per_pdu_session);
// bpf_map__set_max_entries(
// skel->maps.m_sdf_filter, upf_cfg.max_sdf_filters_per_pdu_session);
// bpf_map__set_max_entries(skel->maps.m_arp_table,
// upf_cfg.max_arp_entries);
// bpf_map__set_max_entries(skel->maps.m_rules_match_pdr,
// max_rules_match_pdr);
// redirect interfaces and arp tables sould be less or
// equal than max upf interfaces(
// even incuding n4 since URR is also using this interface to
// forward
// traffic to SMF)
// /*---------------------------------------------------------------------------------------------------------------*/
// struct {
// __uint(type, BPF_MAP_TYPE_DEVMAP);
// __uint(max_entries, MAX_INTERFACES);
// __type(key, u32); // id
// __type(value, u32); // tx port
// } m_redirect_interfaces SEC(".maps");
// /*---------------------------------------------------------------------------------------------------------------*/
// struct {
// __uint(type, BPF_MAP_TYPE_HASH);
// __uint(max_entries, ARP_ENTRIES_MAX_SIZE);
// __type(key, u32); // IPv4 address
// __type(value, struct s_arp_mapping); // <IP Address, MAC address>
// } m_arp_table SEC(".maps");
// // optionally set rodata fields:
// if (skel->rodata) {
// skel->rodata->max_upf_interfaces = upf_cfg.max_upf_interfaces;
// skel->rodata->max_upf_redirect_interfaces =
// upf_cfg.max_upf_redirect_interfaces;
// skel->rodata->max_pdu_session = upf_cfg.max_pdu_session;
// skel->rodata->max_pdrs_per_pdu_session =
// upf_cfg.max_pdrs_per_pdu_session;
// skel->rodata->max_sdf_filters_per_pdu_session =
// upf_cfg.max_sdf_filters_per_pdu_session;
// skel->rodata->max_arp_entries = upf_cfg.max_arp_entries;
// }
// return skel;
// };
// // now create the lifecycle object with a callable open_fn (not a raw skel)
// mpLifeCycle = std::make_shared<PFCP_Session_LookupProgramLifeCycle>(
// open_fn,
// /* load */ pfcp_session_lookup_xdp_kernel_c__load,
// /* attach */ pfcp_session_lookup_xdp_kernel_c__attach,
// /* destroy*/ pfcp_session_lookup_xdp_kernel_c__destroy);
// }
/*---------------------------------------------------------------------------------------------------------------*/
void PFCP_Session_LookupProgram::configure_bpf_maps_and_rodata(
struct pfcp_session_lookup_xdp_kernel_c* skel, const upf_config& upf_cfg) { struct pfcp_session_lookup_xdp_kernel_c* skel, const upf_config& upf_cfg) {
if (!skel) { if (!skel) {
Logger::upf_app().error("Null skeleton in configure_bpf_maps_and_rodata"); Logger::upf_app().error("Null skeleton in configurePfcpSessionLookupMaps");
return; return;
} }
int num_ifaces = count_available_interfaces();
if (upf_cfg.max_upf_interfaces > num_ifaces) {
Logger::upf_app().warn(
"Configured max_upf_interfaces (%u) exceeds available system "
"interfaces (%d). "
"Clamping to %d.",
upf_cfg.max_upf_interfaces, num_ifaces, num_ifaces);
}
if (upf_cfg.max_upf_redirect_interfaces > upf_cfg.max_upf_interfaces) {
Logger::upf_app().error(
"Invalid config: max_upf_redirect_interfaces (%u) cannot exceed "
"max_upf_interfaces (%u).",
upf_cfg.max_upf_redirect_interfaces, upf_cfg.max_upf_interfaces);
throw std::runtime_error(
"Invalid UPF configuration (redirect > interfaces)");
}
if (upf_cfg.max_upf_redirect_interfaces > upf_cfg.max_arp_entries) {
Logger::upf_app().warn(
"max_upf_redirect_interfaces (%u) > max_arp_entries (%u): "
"redirects may not all resolve via ARP.",
upf_cfg.max_upf_redirect_interfaces, upf_cfg.max_arp_entries);
}
// Compute derived limits // Compute derived limits
uint32_t max_rules_match_pdr = uint32_t max_rules_match_pdr =
upf_cfg.max_pdrs_per_pdu_session * upf_cfg.max_pdu_session; upf_cfg.max_pdrs_per_pdu_session * upf_cfg.max_pdu_session;
// Configure BPF map sizes bool ok = true;
bpf_map__set_max_entries( ok &= configure_map_max_entries(
skel->maps.m_upf_interfaces, upf_cfg.max_upf_interfaces); skel->maps.m_upf_interfaces, "m_upf_interfaces",
bpf_map__set_max_entries( upf_cfg.max_upf_interfaces);
skel->maps.m_redirect_interfaces, upf_cfg.max_upf_redirect_interfaces); ok &= configure_map_max_entries(
bpf_map__set_max_entries( skel->maps.m_redirect_interfaces, "m_redirect_interfaces",
skel->maps.m_session_mapping, upf_cfg.max_pdu_session); upf_cfg.max_upf_redirect_interfaces);
bpf_map__set_max_entries( ok &= configure_map_max_entries(
skel->maps.m_session_pdrs, upf_cfg.max_pdrs_per_pdu_session); skel->maps.m_session_mapping, "m_session_mapping",
bpf_map__set_max_entries( upf_cfg.max_pdu_session);
skel->maps.m_sdf_filter, upf_cfg.max_sdf_filters_per_pdu_session); ok &= configure_map_max_entries(
bpf_map__set_max_entries(skel->maps.m_arp_table, upf_cfg.max_arp_entries); skel->maps.m_session_pdrs, "m_session_pdrs",
bpf_map__set_max_entries(skel->maps.m_rules_match_pdr, max_rules_match_pdr); upf_cfg.max_pdrs_per_pdu_session);
ok &= configure_map_max_entries(
skel->maps.m_sdf_filter, "m_sdf_filter",
upf_cfg.max_sdf_filters_per_pdu_session);
ok &= configure_map_max_entries(
skel->maps.m_arp_table, "m_arp_table", upf_cfg.max_arp_entries);
ok &= configure_map_max_entries(
skel->maps.m_rules_match_pdr, "m_rules_match_pdr", max_rules_match_pdr);
if (!ok) {
Logger::upf_app().error(
"One or more BPF map configurations failed for PFCP Session Lookup "
"program.");
throw std::runtime_error("PFCP Session Lookup map configuration failed");
}
// Configure .rodata constants (if available) // Configure .rodata constants (if available)
if (skel->rodata) { if (skel->rodata) {
...@@ -170,7 +127,7 @@ PFCP_Session_LookupProgram::PFCP_Session_LookupProgram( ...@@ -170,7 +127,7 @@ PFCP_Session_LookupProgram::PFCP_Session_LookupProgram(
} }
// Configure maps and rodata // Configure maps and rodata
this->configure_bpf_maps_and_rodata(skel, upf_cfg); this->configurePfcpSessionLookupMaps(skel, upf_cfg);
return skel; return skel;
}; };
...@@ -231,11 +188,9 @@ void PFCP_Session_LookupProgram::setup(bool isQosEnabled) { ...@@ -231,11 +188,9 @@ void PFCP_Session_LookupProgram::setup(bool isQosEnabled) {
mpLifeCycle->attach(); mpLifeCycle->attach();
Logger::upf_app().debug("Configure redirect interface"); Logger::upf_app().debug("Configure redirect interface");
auto udpInterface = UserPlaneComponent::getInstance().getUDPInterface();
auto gtpInterface = UserPlaneComponent::getInstance().getGTPInterface();
uint32_t udpInterfaceIndex = if_nametoindex(udpInterface.c_str()); uint32_t udpInterfaceIndex = if_nametoindex(UDP_INTERFACE.c_str());
uint32_t gtpInterfaceIndex = if_nametoindex(gtpInterface.c_str()); uint32_t gtpInterfaceIndex = if_nametoindex(UDP_INTERFACE.c_str());
uint32_t uplinkId = static_cast<uint32_t>(FlowDirection::UPLINK); uint32_t uplinkId = static_cast<uint32_t>(FlowDirection::UPLINK);
uint32_t downlinkId = static_cast<uint32_t>(FlowDirection::DOWNLINK); uint32_t downlinkId = static_cast<uint32_t>(FlowDirection::DOWNLINK);
......
...@@ -56,7 +56,7 @@ class PFCP_Session_LookupProgram { ...@@ -56,7 +56,7 @@ class PFCP_Session_LookupProgram {
private: private:
void initializeMaps(); void initializeMaps();
void configure_bpf_maps_and_rodata( void configurePfcpSessionLookupMaps(
struct pfcp_session_lookup_xdp_kernel_c* skel, const upf_config& upf_cfg); struct pfcp_session_lookup_xdp_kernel_c* skel, const upf_config& upf_cfg);
pfcp_session_lookup_xdp_kernel_c* spSkeleton; pfcp_session_lookup_xdp_kernel_c* spSkeleton;
std::shared_ptr<PFCP_Session_LookupProgramLifeCycle> mpLifeCycle; std::shared_ptr<PFCP_Session_LookupProgramLifeCycle> mpLifeCycle;
......
This diff is collapsed.
...@@ -16,6 +16,12 @@ ...@@ -16,6 +16,12 @@
// #include <netlink/route/qdisc.h> // #include <netlink/route/qdisc.h>
#include <qos_flow.h> #include <qos_flow.h>
#include <pfcp_session.hpp> #include <pfcp_session.hpp>
#include "upf_config.hpp"
using namespace oai::config;
extern upf_config upf_cfg;
class BPFMaps; class BPFMaps;
class BPFMap; class BPFMap;
class SessionManager; class SessionManager;
...@@ -23,144 +29,59 @@ class SessionManager; ...@@ -23,144 +29,59 @@ class SessionManager;
using QERProgramLifeCycle = ProgramLifeCycle<qer_tc_kernel_c>; using QERProgramLifeCycle = ProgramLifeCycle<qer_tc_kernel_c>;
/**
* @brief Singleton class to abstract the UPF bpf tc program.
*/
class QERProgram : public BPFProgram { class QERProgram : public BPFProgram {
public: public:
/*---------------------------------------------------------------------------------------------------------------*/ explicit QERProgram(const upf_config& upf_cfg);
/**
* @brief Construct a new QERProgram object.
*
*/
explicit QERProgram();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Destroy the QERProgram object
*/
virtual ~QERProgram(); virtual ~QERProgram();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Setup the tc BPF program when QoS Feature is disabled
*
*/
void setup(); void setup();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Setup tc BPF program when QoS Feature is enabled
*
* @param const std::string&
* @param const std::string&
* @param const char*
* @param std::vector<struct s_fiveQosFlow*>
* @param uint64_t
* @param struct gtpUTunnel*
*/
void setup( void setup(
uint64_t seid, std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer, uint64_t seid, std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>> pdrs); std::vector<std::shared_ptr<pfcp::pfcp_pdr>> pdrs);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the BPFMaps object.
*
* @return std::shared_ptr<BPFMaps> The reference of the BPFMaps.
*/
std::shared_ptr<BPFMaps> getMaps(); std::shared_ptr<BPFMaps> getMaps();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Tear downs the BPF program.
*
*/
void tearDown(); void tearDown();
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<BPFMap> getEgressIfindexMap() const; std::shared_ptr<BPFMap> getEgressIfindexMap() const;
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the n3 GTP-U Tunnel Map object.
*
* @return std::shared_ptr<BPFMap> The seid value of the PDU session
* associated with the n3 GTP-U Tunnel.
*/
std::shared_ptr<BPFMap> geGtpUTunnelMap() const; std::shared_ptr<BPFMap> geGtpUTunnelMap() const;
std::shared_ptr<BPFMap> getSdfFilterMap() const; std::shared_ptr<BPFMap> getSdfFilterMap() const;
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<BPFMap> get5GQoSFlowParamsMap() const; std::shared_ptr<BPFMap> get5GQoSFlowParamsMap() const;
/*---------------------------------------------------------------------------------------------------------------*/
// std::shared_ptr<BPFMap> getQoSFlowMap() const;
// std::shared_ptr<BPFMap> getDefaultQfiMap() const;
/*---------------------------------------------------------------------------------------------------------------*/
// struct qer_tc_kernel_c* get_bpf_skel_object();
// int teardown_hook(int ifindex);
// int tc_detach_egress(int ifindex);
// int tc_attach_egress(
// int ifindex, struct qer_tc_kernel_c* obj, const char* section_name);
// int tc_attach_ingress(
// int ifindex, struct qer_tc_kernel_c* obj, const char* section_name);
// int add_clsact_qdisc(int ifindex, enum bpf_tc_attach_point attach_point);
bool no_htb_root_qdisc(const std::string interface); bool no_htb_root_qdisc(const std::string interface);
bool no_htb_default_class(const std::string interface); bool no_htb_default_class(const std::string interface);
bool no_tc_filter_bpf(const std::string interface); bool no_tc_filter_bpf(const std::string interface);
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<pfcp::pfcp_qer> retrive_default_qer_with_default_qfi( std::shared_ptr<pfcp::pfcp_qer> retrive_default_qer_with_default_qfi(
std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer); std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer);
void setDefaultClassHandle(uint32_t handle) {
m_default_class_handle = handle;
}
uint32_t getDefaultClassHandle() const { return m_default_class_handle; }
void setDefaultClassRate(uint32_t rate) { m_default_class_rate = rate; }
uint32_t getDefaultClassRate() const { return m_default_class_rate; }
void setDefaultClassCeil(uint32_t ceil) { m_default_class_ceil = ceil; }
uint32_t getDefaultClassCeil() const { return m_default_class_ceil; }
void setR2qRoot(uint32_t r2q) { m_r2q_root = r2q; }
uint32_t getR2qRoot() const { return m_r2q_root; }
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
private: private:
/** uint32_t m_default_class_handle;
* @brief Initialize BPF wrappers maps. uint32_t m_default_class_rate; // kbps
* uint32_t m_default_class_ceil; // kbps
*/ uint32_t m_r2q_root; // qdisc r2q
void initializeMaps(); void initializeMaps();
void configureQerMaps(
struct qer_tc_kernel_c* skel, const upf_config& upf_cfg);
void build_pdr_map(const std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs); void build_pdr_map(const std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs);
std::shared_ptr<pfcp::pfcp_pdr> get_pdr_by_qer_id(uint32_t qer_id) const; std::shared_ptr<pfcp::pfcp_pdr> get_pdr_by_qer_id(uint32_t qer_id) const;
std::unordered_map<uint32_t, std::shared_ptr<pfcp::pfcp_pdr>> pdr_map; std::unordered_map<uint32_t, std::shared_ptr<pfcp::pfcp_pdr>> pdr_map;
// void storeQosFlow(std::shared_ptr<pfcp::pfcp_qer> pQer);
/*---------------------------------------------------------------------------------------------------------------*/
// The reference of the bpf maps.
std::shared_ptr<BPFMaps> mpMaps; std::shared_ptr<BPFMaps> mpMaps;
/*---------------------------------------------------------------------------------------------------------------*/
// The skeleton of the UPF program generated by bpftool.
// ProgramLifeCycle is the owner of the pointer.
qer_tc_kernel_c* spSkeleton; qer_tc_kernel_c* spSkeleton;
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<BPFMap> mpEgressIfindexMap; std::shared_ptr<BPFMap> mpEgressIfindexMap;
/*---------------------------------------------------------------------------------------------------------------*/
// The BPF lifecycle program.
std::shared_ptr<QERProgramLifeCycle> mpLifeCycle; std::shared_ptr<QERProgramLifeCycle> mpLifeCycle;
/*---------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------------------------*/
// The 5G QoS Flow Parameters map.
std::shared_ptr<BPFMap> mp5GQoSFlowParamsMap; std::shared_ptr<BPFMap> mp5GQoSFlowParamsMap;
/*---------------------------------------------------------------------------------------------------------------*/
// The 5G QoS Flow.
// std::shared_ptr<BPFMap> mpQoSFlowMap;
// std::shared_ptr<BPFMap> mpDefaultQfiMap;
/*---------------------------------------------------------------------------------------------------------------*/
std::vector<struct s_fiveQosFlow> qosFlowsQfis; std::vector<struct s_fiveQosFlow> qosFlowsQfis;
}; };
......
// bpf_utils.cpp
#include "bpf_utils.hpp"
#include "logger.hpp"
namespace oai::utils::bpf {
bool configure_map_max_entries(
struct bpf_map* map, const std::string& map_name, uint32_t max_entries) {
if (!map) {
Logger::upf_app().error(
"Cannot configure BPF map %s: null pointer", map_name);
return false;
}
if (max_entries == 0) {
Logger::upf_app().warn(
"Map %s has zero max_entries — skipping configuration", map_name);
return false;
}
int ret = bpf_map__set_max_entries(map, max_entries);
if (ret < 0) {
Logger::upf_app().error(
"Failed to set max_entries=%d for map %s: %d", max_entries, map_name,
strerror(-ret));
return false;
}
Logger::upf_app().debug(
"Configured map %s with max_entries=%d", map_name, max_entries);
return true;
}
} // namespace oai::utils::bpf
// bpf_utils.hpp
#pragma once
#include <bpf/libbpf.h>
#include <string>
#include <cstdint>
namespace oai::utils::bpf {
/**
* @brief Safely set the maximum entries of a BPF map.
*
* @param map Pointer to the libbpf map handle.
* @param map_name Human-readable name for logging.
* @param max_entries Desired maximum number of entries.
* @return true on success, false otherwise.
*/
bool configure_map_max_entries(
struct bpf_map* map, const std::string& map_name, uint32_t max_entries);
} // namespace oai::utils::bpf
#include "net_utils.hpp"
#include <ifaddrs.h>
#include <net/if.h>
#include "logger.hpp"
#include "helpers/GetNicInformation.hpp"
namespace oai::utils::net {
//---------------------------------------------------------------------------------------------------------------
int count_available_interfaces() {
int num_ifaces = 0;
struct ifaddrs* ifaddr = nullptr;
if (getifaddrs(&ifaddr) == 0) {
for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) ++num_ifaces;
}
freeifaddrs(ifaddr);
} else {
Logger::upf_app().warn("Unable to enumerate network interfaces");
}
return num_ifaces;
}
//---------------------------------------------------------------------------------------------------------------
bool interface_exists(const std::string& ifname) {
return if_nametoindex(ifname.c_str()) != 0;
}
//---------------------------------------------------------------------------------------------------------------
int get_interface_index(const std::string& ifname) {
return static_cast<int>(if_nametoindex(ifname.c_str()));
}
} // namespace oai::utils::net
#pragma once
#include <string>
namespace oai::utils::net {
int count_available_interfaces();
bool interface_exists(const std::string& ifname);
int get_interface_index(const std::string& ifname);
} // namespace oai::utils::net
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