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(
if (!pdrs.empty()) {
auto pdrHighPrecedence = pdrs.front();
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);
if (direction == "Uplink") {
createBPFSessionUL(pSession_establishment, pdrHighPrecedence);
......@@ -398,6 +398,8 @@ void SessionManager::processPDRDetails(
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 (ueIpAddress.v4){
std::vector<pfcp::framed_route_t> framedRoutes;
......@@ -467,7 +469,7 @@ void SessionManager::updateBPFSession(
auto pdrHighPrecedenceDl = pSession->pdrs_downlink[0];
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);
Logger::upf_app().debug(
......@@ -484,7 +486,7 @@ void SessionManager::updateBPFSession(
auto pdrHighPrecedenceUl = pSession->pdrs_uplink[0];
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);
Logger::upf_app().debug(
......@@ -587,6 +589,22 @@ void SessionManager::updateBPFSessionDL(
// pSession->qerIDsPerPDR.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) {
SessionProgramManager::getInstance().createPipeline(
seidul, fteid.teid, INTERFACE_VALUE_CORE,
......
......@@ -6,6 +6,7 @@
#include <pfcp_session_lookup_xdp_user.h>
#include <UserPlaneComponent.h>
#include <net/if.h> // if_nametoindex
#include <framed_routing_bpf.h>
#include <observer/OnStateChangeSessionProgramObserver.h>
// #include <pfcp/pfcp_far.h>
......@@ -296,17 +297,19 @@ void SessionProgramManager::addFramedRoutes(uint32_t ueIpAddress, std::vector<pf
uint32_t cidr = 0;
const std::string ip_substring =
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::string subnet_substring =
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 routing_info = createLocalRoutingInformation(ipCidr);
//auto snat_info = createLocalSnatInformation(ipCidr);
pPFCP_Session_LookupProgram->updateFramedRouteMappingMap(ueIpAddress, key);
Logger::upf_app().debug("Framed Routing map is updated!");
//localRouting->add_route(routing_info);
//localRouting->add_source_snat(snat_info);
}
......
......@@ -173,33 +173,9 @@ struct {
/*---------------------------------------------------------------------------------------------------------------*/
/* 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 {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH);
__uint(max_entries, MAX_UEs);
__type(key, u32); // hash_framed_routing_key
__type(value, u32); // ue_ip
} 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 @@
#include <utils/logger.h>
#include <utils/utils.h>
#include <next_prog_rule_key.h>
#include <framed_routing_bpf.h>
#ifdef KERNEL_SPACE
#include <linux/in.h>
......@@ -65,25 +66,27 @@ static __always_inline u32 tail_call_next_prog(
static __always_inline u32
handle_downlink_traffic(struct xdp_md* ctx, u32 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) {
bpf_debug(
"TEID downlink: 0x%x was found for UE IP: 0x%x", ue_ip_address,
*teid_dl);
"TEID downlink: 0x%x was found for UE IP: 0x%x", *teid_dl,
ue_ip_address);
tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, ue_ip_address);
} 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)
for (int i = 32; i > 0; i--) {
struct FramedRoutingKeyBPF key = framed_routing_key_for_ip_cidr(ue_ip_address, i);
u32 fr_key = hash_framed_routing_key(&key);
u32* fr_ue_ip = bpf_map_lookup_elem(&m_framed_route_mapping, &fr_key);
for (uint32_t i = 32; i > 0; i--) {
struct FramedRoutingKeyBPF key = framed_routing_key_for_ip_cidr(big_endian_ue_ip, i);
uint32_t fr_key = hash_framed_routing_key(&key);
bpf_debug("Check framed route table with key %u (for cidr %u)", fr_key, i);
uint32_t* fr_ue_ip = bpf_map_lookup_elem(&m_framed_route_mapping, &fr_key);
if(fr_ue_ip) {
bpf_debug(
"Framed Route detected for IP: 0x%x. UE IP: 0x%x", fr_ue_ip, ue_ip_address);
u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &fr_ue_ip);
"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);
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);
}
}
......@@ -169,11 +172,8 @@ static __always_inline u32 ipv4_handle(struct xdp_md* ctx, struct iphdr* iph) {
u32 ip_dest = iph->daddr;
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;
bpf_debug("Protocol: 0x%x", protocol);
switch (protocol) {
case IPPROTO_UDP: {
......
......@@ -8,7 +8,6 @@
#include <wrappers/BPFMaps.h>
#include "interfaces.h"
#include "logger.hpp"
#include <pfcp_session_lookup_maps.h>
/*---------------------------------------------------------------------------------------------------------------*/
int is_little_endian2() {
......@@ -112,8 +111,10 @@ std::shared_ptr<BPFMap> PFCP_Session_LookupProgram::getFramedRouteMappingMap() {
}
/*---------------------------------------------------------------------------------------------------------------*/
void PFCP_Session_LookupProgram::updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKey key) {
__u32 hash_key = hash_framed_routing_key(&key);
void PFCP_Session_LookupProgram::updateFramedRouteMappingMap(uint32_t ue_ip, FramedRoutingKeyBPF 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);
}
......@@ -137,7 +138,7 @@ void PFCP_Session_LookupProgram::initializeMaps() {
mpSessionMappingMap =
std::make_shared<BPFMap>(mpMaps->getMap("m_session_mapping"));
mpFramedRouteMappingMap =
std::make_shared<BPFMap>(mpMaps->getMap("m_ueip_session"));
std::make_shared<BPFMap>(mpMaps->getMap("m_framed_route_mapping"));
}
/*---------------------------------------------------------------------------------------------------------------*/
......@@ -8,8 +8,8 @@
#include <mutex>
#include <signal.h> // signals
#include <pfcp_session_lookup_xdp_kernel_skel.h>
#include "pfcp_session_lookup_maps.h"
#include <wrappers/BPFMap.hpp>
#include <framed_routing_bpf.h>
// #include "qfi_flow_mapping_table.h"
class BPFMaps;
......@@ -144,7 +144,7 @@ class PFCP_Session_LookupProgram {
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);
......
......@@ -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>>>>
entry(ue_ip, pdrs);
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(
"framed routing ip: " +
......
......@@ -2,6 +2,7 @@
#define __BPFMAP_H__
#include <bpf/bpf.h>
#include <cerrno>
#include <bpf/libbpf.h>
#include "logger.hpp"
......@@ -116,7 +117,12 @@ int BPFMap::update(KeyType& key, ValueType& value, int flags) {
if (updateReturn != 0) {
// 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");
} else {
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