Commit c947e23b authored by Lukas Rotheneder's avatar Lukas Rotheneder

feat(upf): draft framed routing for ebpf

parent cbac0e14
...@@ -306,7 +306,7 @@ void SessionManager::createSessionDirection( ...@@ -306,7 +306,7 @@ void SessionManager::createSessionDirection(
if (!pdrs.empty()) { if (!pdrs.empty()) {
auto pdrHighPrecedence = pdrs.front(); auto pdrHighPrecedence = pdrs.front();
logger.debug( logger.debug(
"The $s PDR %d has the Highest Precedence", direction, "The %s PDR %u has the Highest Precedence", direction,
pdrHighPrecedence->pdr_id.rule_id); pdrHighPrecedence->pdr_id.rule_id);
if (direction == "Uplink") { if (direction == "Uplink") {
createBPFSessionUL(pSession_establishment, pdrHighPrecedence); createBPFSessionUL(pSession_establishment, pdrHighPrecedence);
...@@ -398,6 +398,8 @@ void SessionManager::processPDRDetails( ...@@ -398,6 +398,8 @@ void SessionManager::processPDRDetails(
std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer; std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer;
logger.debug(
"upf_cfg.enable_fr: %s, %s PDR", upf_cfg.enable_fr ? "true" : "false", direction);
if (upf_cfg.enable_fr && direction == "Downlink") { //TODO check if (upf_cfg.enable_fr && direction == "Downlink") { //TODO check
if (ueIpAddress.v4){ if (ueIpAddress.v4){
std::vector<pfcp::framed_route_t> framedRoutes; std::vector<pfcp::framed_route_t> framedRoutes;
...@@ -467,7 +469,7 @@ void SessionManager::updateBPFSession( ...@@ -467,7 +469,7 @@ void SessionManager::updateBPFSession(
auto pdrHighPrecedenceDl = pSession->pdrs_downlink[0]; auto pdrHighPrecedenceDl = pSession->pdrs_downlink[0];
Logger::upf_app().debug( Logger::upf_app().debug(
"The Downlink PDR %d has the Highest Precedence", "The Downlink PDR %u has the Highest Precedence",
pdrHighPrecedenceDl->pdr_id.rule_id); pdrHighPrecedenceDl->pdr_id.rule_id);
Logger::upf_app().debug( Logger::upf_app().debug(
...@@ -484,7 +486,7 @@ void SessionManager::updateBPFSession( ...@@ -484,7 +486,7 @@ void SessionManager::updateBPFSession(
auto pdrHighPrecedenceUl = pSession->pdrs_uplink[0]; auto pdrHighPrecedenceUl = pSession->pdrs_uplink[0];
Logger::upf_app().debug( Logger::upf_app().debug(
"The Uplink PDR %d has the Highest Precedence", "The Uplink PDR %u has the Highest Precedence",
pdrHighPrecedenceUl->pdr_id.rule_id); pdrHighPrecedenceUl->pdr_id.rule_id);
Logger::upf_app().debug( Logger::upf_app().debug(
...@@ -587,6 +589,22 @@ void SessionManager::updateBPFSessionDL( ...@@ -587,6 +589,22 @@ void SessionManager::updateBPFSessionDL(
// pSession->qerIDsPerPDR.qers; // pSession->qerIDsPerPDR.qers;
// std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer = pSession->qers; // std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer = pSession->qers;
auto& logger = Logger::upf_app();
logger.debug(
"upf_cfg.enable_fr: %s, Downlink PDR", upf_cfg.enable_fr ? "true" : "false");
if (upf_cfg.enable_fr) {
if (ueIpAddress.v4){
std::vector<pfcp::framed_route_t> framedRoutes;
if(pdi.get(framedRoutes)) {
SessionProgramManager::getInstance().addFramedRoutes(ueIpAddress.ipv4_address.s_addr, framedRoutes);
}
} else {
Logger::upf_app().warn(
"Framed Route is not yet supported for Ipv6");
}
}
if (teid_ul) { if (teid_ul) {
SessionProgramManager::getInstance().createPipeline( SessionProgramManager::getInstance().createPipeline(
seidul, fteid.teid, INTERFACE_VALUE_CORE, seidul, fteid.teid, INTERFACE_VALUE_CORE,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <pfcp_session_lookup_xdp_user.h> #include <pfcp_session_lookup_xdp_user.h>
#include <UserPlaneComponent.h> #include <UserPlaneComponent.h>
#include <net/if.h> // if_nametoindex #include <net/if.h> // if_nametoindex
#include <framed_routing_bpf.h>
#include <observer/OnStateChangeSessionProgramObserver.h> #include <observer/OnStateChangeSessionProgramObserver.h>
// #include <pfcp/pfcp_far.h> // #include <pfcp/pfcp_far.h>
...@@ -296,17 +297,19 @@ void SessionProgramManager::addFramedRoutes(uint32_t ueIpAddress, std::vector<pf ...@@ -296,17 +297,19 @@ void SessionProgramManager::addFramedRoutes(uint32_t ueIpAddress, std::vector<pf
uint32_t cidr = 0; uint32_t cidr = 0;
const std::string ip_substring = const std::string ip_substring =
ipsubnetmask.substr(0, ipsubnetmask.find(subnet_delimeter)); ipsubnetmask.substr(0, ipsubnetmask.find(subnet_delimeter));
ip = FramedRouting::framedIPToUeIP(ip_substring); ip = fr::FramedRouting::framedIPToUeIP(ip_substring);
std::reverse(ipsubnetmask.begin(), ipsubnetmask.end()); std::reverse(ipsubnetmask.begin(), ipsubnetmask.end());
std::string subnet_substring = std::string subnet_substring =
ipsubnetmask.substr(0, ipsubnetmask.rfind(subnet_delimeter)); ipsubnetmask.substr(0, ipsubnetmask.rfind(subnet_delimeter));
cidr = FramedRouting::frameSubnetToUInt(subnet_substring); cidr = fr::FramedRouting::frameSubnetToUInt(subnet_substring);
Logger::upf_app().debug("Framed Route Subnet: %s -> IP %u, cidr %u", framedRoute.framed_route, ip, cidr);
auto key = framed_routing_key_for_ip_cidr(ip, cidr); auto key = framed_routing_key_for_ip_cidr(ip, cidr);
//auto routing_info = createLocalRoutingInformation(ipCidr); //auto routing_info = createLocalRoutingInformation(ipCidr);
//auto snat_info = createLocalSnatInformation(ipCidr); //auto snat_info = createLocalSnatInformation(ipCidr);
pPFCP_Session_LookupProgram->updateFramedRouteMappingMap(ueIpAddress, key); pPFCP_Session_LookupProgram->updateFramedRouteMappingMap(ueIpAddress, key);
Logger::upf_app().debug("Framed Routing map is updated!");
//localRouting->add_route(routing_info); //localRouting->add_route(routing_info);
//localRouting->add_source_snat(snat_info); //localRouting->add_source_snat(snat_info);
} }
......
...@@ -173,33 +173,9 @@ struct { ...@@ -173,33 +173,9 @@ struct {
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
/* Framed Routing */ /* Framed Routing */
struct FramedRoutingKeyBPF {
uint32_t networkAddress;
uint32_t subnet;
};
static __always_inline __u32 hash_framed_routing_key(struct FramedRoutingKeyBPF *key) {
__u32 hash = 17;
hash = hash * 31 + key->networkAddress;
hash = hash ^ key->subnet;
return hash;
}
static __always_inline struct FramedRoutingKeyBPF framed_routing_key_for_ip_cidr(__u32 ip, __u32 cidr) {
const __u32 ipv4Size = 32;
// Calculate the subnet address
__u32 subnet_mask = 0xffffffff << (ipv4Size - cidr);
// Calculate the network address
__u32 network_address = subnet_mask & ip;
struct FramedRoutingKeyBPF key = {network_address,subnet_mask};
return key;
}
struct { struct {
__uint(type, BPF_MAP_TYPE_HASH); __uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH); __uint(max_entries, MAX_UEs);
__type(key, u32); // hash_framed_routing_key __type(key, u32); // hash_framed_routing_key
__type(value, u32); // ue_ip __type(value, u32); // ue_ip
} m_framed_route_mapping SEC(".maps"); } m_framed_route_mapping SEC(".maps");
......
#ifndef OPENAIRINTERFACE_FRAMED_ROUTING_BPF_H
#define OPENAIRINTERFACE_FRAMED_ROUTING_BPF_H
#include <types.h>
#include <stdint.h>
struct FramedRoutingKeyBPF {
uint32_t networkAddress;
uint32_t subnet;
};
static __always_inline uint32_t hash_framed_routing_key(struct FramedRoutingKeyBPF *key) {
uint32_t hash = 17;
hash = hash * 31 + key->networkAddress;
hash = hash ^ key->subnet;
return hash;
}
static __always_inline struct FramedRoutingKeyBPF framed_routing_key_for_ip_cidr(uint32_t ip, uint32_t cidr) {
const uint32_t ipv4Size = 32;
// Calculate the subnet address
uint32_t subnet_mask = 0xffffffff << (ipv4Size - cidr);
// Calculate the network address
uint32_t network_address = subnet_mask & ip;
struct FramedRoutingKeyBPF key = {network_address,subnet_mask};
return key;
}
#endif //OPENAIRINTERFACE_FRAMED_ROUTING_BPF_H
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <utils/logger.h> #include <utils/logger.h>
#include <utils/utils.h> #include <utils/utils.h>
#include <next_prog_rule_key.h> #include <next_prog_rule_key.h>
#include <framed_routing_bpf.h>
#ifdef KERNEL_SPACE #ifdef KERNEL_SPACE
#include <linux/in.h> #include <linux/in.h>
...@@ -65,25 +66,27 @@ static __always_inline u32 tail_call_next_prog( ...@@ -65,25 +66,27 @@ static __always_inline u32 tail_call_next_prog(
static __always_inline u32 static __always_inline u32
handle_downlink_traffic(struct xdp_md* ctx, u32 ue_ip_address) { handle_downlink_traffic(struct xdp_md* ctx, u32 ue_ip_address) {
u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &ue_ip_address); u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &ue_ip_address);
bpf_debug("Handle downlink traffic for UE IP: 0x%x, as u32: %u", ue_ip_address, ue_ip_address);
if (teid_dl) { if (teid_dl) {
bpf_debug( bpf_debug(
"TEID downlink: 0x%x was found for UE IP: 0x%x", ue_ip_address, "TEID downlink: 0x%x was found for UE IP: 0x%x", *teid_dl,
*teid_dl); ue_ip_address);
tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, ue_ip_address); tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, ue_ip_address);
} else { } else {
uint32_t big_endian_ue_ip = __builtin_bswap32(ue_ip_address);
bpf_debug("No TEID found, try to find FramedRoute entry for big endian address %u", big_endian_ue_ip);
#pragma clang loop unroll(full) #pragma clang loop unroll(full)
for (int i = 32; i > 0; i--) { for (uint32_t i = 32; i > 0; i--) {
struct FramedRoutingKeyBPF key = framed_routing_key_for_ip_cidr(ue_ip_address, i); struct FramedRoutingKeyBPF key = framed_routing_key_for_ip_cidr(big_endian_ue_ip, i);
uint32_t fr_key = hash_framed_routing_key(&key);
u32 fr_key = hash_framed_routing_key(&key); bpf_debug("Check framed route table with key %u (for cidr %u)", fr_key, i);
u32* fr_ue_ip = bpf_map_lookup_elem(&m_framed_route_mapping, &fr_key); uint32_t* fr_ue_ip = bpf_map_lookup_elem(&m_framed_route_mapping, &fr_key);
if(fr_ue_ip) { if(fr_ue_ip) {
bpf_debug( bpf_debug(
"Framed Route detected for IP: 0x%x. UE IP: 0x%x", fr_ue_ip, ue_ip_address); "Framed Route detected for IP: 0x%x. UE IP: 0x%x", fr_ue_ip, big_endian_ue_ip);
u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &fr_ue_ip); u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, fr_ue_ip);
if (teid_dl) { if (teid_dl) {
bpf_debug("TEID downlink: 0x%x was found for Framed Route IP: 0x%x", *teid_dl, ue_ip_address); bpf_debug("TEID downlink: 0x%x was found for Framed Route IP: 0x%x", *teid_dl, big_endian_ue_ip);
tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, *fr_ue_ip); tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, *fr_ue_ip);
} }
} }
...@@ -169,11 +172,8 @@ static __always_inline u32 ipv4_handle(struct xdp_md* ctx, struct iphdr* iph) { ...@@ -169,11 +172,8 @@ static __always_inline u32 ipv4_handle(struct xdp_md* ctx, struct iphdr* iph) {
u32 ip_dest = iph->daddr; u32 ip_dest = iph->daddr;
bpf_debug("UE IP: 0x%x", ip_dest); bpf_debug("UE IP: 0x%x", ip_dest);
if (ip_dest == 0x0301010c) {
ip_dest = ip_dest - 0x01000000;
bpf_debug("New UE IP: 0x%x", ip_dest);
}
u8 protocol = iph->protocol; u8 protocol = iph->protocol;
bpf_debug("Protocol: 0x%x", protocol);
switch (protocol) { switch (protocol) {
case IPPROTO_UDP: { case IPPROTO_UDP: {
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <wrappers/BPFMaps.h> #include <wrappers/BPFMaps.h>
#include "interfaces.h" #include "interfaces.h"
#include "logger.hpp" #include "logger.hpp"
#include <pfcp_session_lookup_maps.h>
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
int is_little_endian2() { int is_little_endian2() {
...@@ -112,8 +111,10 @@ std::shared_ptr<BPFMap> PFCP_Session_LookupProgram::getFramedRouteMappingMap() { ...@@ -112,8 +111,10 @@ std::shared_ptr<BPFMap> PFCP_Session_LookupProgram::getFramedRouteMappingMap() {
} }
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
void PFCP_Session_LookupProgram::updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKey key) { void PFCP_Session_LookupProgram::updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKeyBPF key) {
__u32 hash_key = hash_framed_routing_key(&key); uint32_t hash_key = hash_framed_routing_key(&key);
Logger::upf_app().debug(
"update FramedRoutingMappingMap with key: %u, value: %u", hash_key, ue_ip);
mpFramedRouteMappingMap->update(hash_key, ue_ip, BPF_ANY); mpFramedRouteMappingMap->update(hash_key, ue_ip, BPF_ANY);
} }
...@@ -137,7 +138,7 @@ void PFCP_Session_LookupProgram::initializeMaps() { ...@@ -137,7 +138,7 @@ void PFCP_Session_LookupProgram::initializeMaps() {
mpSessionMappingMap = mpSessionMappingMap =
std::make_shared<BPFMap>(mpMaps->getMap("m_session_mapping")); std::make_shared<BPFMap>(mpMaps->getMap("m_session_mapping"));
mpFramedRouteMappingMap = mpFramedRouteMappingMap =
std::make_shared<BPFMap>(mpMaps->getMap("m_ueip_session")); std::make_shared<BPFMap>(mpMaps->getMap("m_framed_route_mapping"));
} }
/*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include <mutex> #include <mutex>
#include <signal.h> // signals #include <signal.h> // signals
#include <pfcp_session_lookup_xdp_kernel_skel.h> #include <pfcp_session_lookup_xdp_kernel_skel.h>
#include "pfcp_session_lookup_maps.h"
#include <wrappers/BPFMap.hpp> #include <wrappers/BPFMap.hpp>
#include <framed_routing_bpf.h>
// #include "qfi_flow_mapping_table.h" // #include "qfi_flow_mapping_table.h"
class BPFMaps; class BPFMaps;
...@@ -144,7 +144,7 @@ class PFCP_Session_LookupProgram { ...@@ -144,7 +144,7 @@ class PFCP_Session_LookupProgram {
std::shared_ptr<BPFMap> getFramedRouteMappingMap(); std::shared_ptr<BPFMap> getFramedRouteMappingMap();
void updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKey key); void updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKeyBPF key);
void removeFramedRoute(uint32_t key); void removeFramedRoute(uint32_t key);
......
...@@ -628,7 +628,7 @@ void pfcp_switch::add_pfcp_dl_pdr_by_ue_ip( ...@@ -628,7 +628,7 @@ void pfcp_switch::add_pfcp_dl_pdr_by_ue_ip(
uint32_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>> uint32_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>>
entry(ue_ip, pdrs); entry(ue_ip, pdrs);
ue_ipv4_hbo2pfcp_pdr.insert(entry); ue_ipv4_hbo2pfcp_pdr.insert(entry);
if (upf_cfg.enable_fr && pdr->pdi.second.framed_route.first) { if (!upf_cfg.enable_bpf_datapath && upf_cfg.enable_fr && pdr->pdi.second.framed_route.first) {
Logger::pfcp_switch().info("fr_ue_ip %4x ", ue_ip); Logger::pfcp_switch().info("fr_ue_ip %4x ", ue_ip);
Logger::pfcp_switch().info( Logger::pfcp_switch().info(
"framed routing ip: " + "framed routing ip: " +
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __BPFMAP_H__ #define __BPFMAP_H__
#include <bpf/bpf.h> #include <bpf/bpf.h>
#include <cerrno>
#include <bpf/libbpf.h> #include <bpf/libbpf.h>
#include "logger.hpp" #include "logger.hpp"
...@@ -116,7 +117,12 @@ int BPFMap::update(KeyType& key, ValueType& value, int flags) { ...@@ -116,7 +117,12 @@ int BPFMap::update(KeyType& key, ValueType& value, int flags) {
if (updateReturn != 0) { if (updateReturn != 0) {
// FIXME: Maybe Key is not support by fmt. // FIXME: Maybe Key is not support by fmt.
Logger::upf_app().error("The key cannot be updated in map"); Logger::upf_app().error(
"The key cannot be updated in map: %s (errno: %d, %s)",
mName.c_str(),
errno,
strerror(errno)
);
throw std::runtime_error("The BPF map cannot be updated"); throw std::runtime_error("The BPF map cannot be updated");
} else { } else {
Logger::upf_app().debug("The key is updated in the map: %s", mName.c_str()); Logger::upf_app().debug("The key is updated in the map: %s", mName.c_str());
......
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