Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
oai-upf-6g
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenXG
oai-upf-6g
Commits
3313d4e2
Commit
3313d4e2
authored
Dec 06, 2024
by
Franck Messaoudi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update: update code to manage separately the tc bpf program
parent
694fc287
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
434 additions
and
280 deletions
+434
-280
src/oai_upf/main.cpp
src/oai_upf/main.cpp
+3
-4
src/upf_app/SessionManager.cpp
src/upf_app/SessionManager.cpp
+47
-31
src/upf_app/SessionProgramManager.cpp
src/upf_app/SessionProgramManager.cpp
+45
-36
src/upf_app/SessionProgramManager.h
src/upf_app/SessionProgramManager.h
+0
-6
src/upf_app/SessionPrograms.h
src/upf_app/SessionPrograms.h
+2
-2
src/upf_app/UserPlaneComponent.cpp
src/upf_app/UserPlaneComponent.cpp
+8
-2
src/upf_app/bpf/protocols/udp.h
src/upf_app/bpf/protocols/udp.h
+6
-5
src/upf_app/bpf/rules/far/far_maps.h
src/upf_app/bpf/rules/far/far_maps.h
+6
-6
src/upf_app/bpf/rules/pdr/pfcp_session_lookup_xdp_kernel.c
src/upf_app/bpf/rules/pdr/pfcp_session_lookup_xdp_kernel.c
+83
-36
src/upf_app/bpf/rules/qer/qer_tc_kernel.c
src/upf_app/bpf/rules/qer/qer_tc_kernel.c
+2
-1
src/upf_app/bpf/rules/qer/qos_flow.h
src/upf_app/bpf/rules/qer/qos_flow.h
+27
-17
src/upf_app/helpers/ConfigManager.cpp
src/upf_app/helpers/ConfigManager.cpp
+0
-0
src/upf_app/helpers/ConfigManager.hpp
src/upf_app/helpers/ConfigManager.hpp
+31
-0
src/upf_app/programs/pfcp_session_lookup_xdp_user.cpp
src/upf_app/programs/pfcp_session_lookup_xdp_user.cpp
+23
-6
src/upf_app/programs/pfcp_session_lookup_xdp_user.h
src/upf_app/programs/pfcp_session_lookup_xdp_user.h
+1
-1
src/upf_app/programs/qer_tc_user.cpp
src/upf_app/programs/qer_tc_user.cpp
+109
-93
src/upf_app/programs/qer_tc_user.h
src/upf_app/programs/qer_tc_user.h
+4
-0
src/upf_app/simpleswitch/pfcp_switch.cpp
src/upf_app/simpleswitch/pfcp_switch.cpp
+37
-34
No files found.
src/oai_upf/main.cpp
View file @
3313d4e2
...
...
@@ -115,9 +115,6 @@ void my_app_signal_handler(int s) {
//------------------------------------------------------------------------------
void
setup_bpf
()
{
// std::shared_ptr<RulesUtilities> mpRulesFactory;
// mpRulesFactory = std::make_shared<RulesUtilitiesImpl>();
std
::
string
sGTPInterface
=
N3_IF_NAME
;
std
::
string
sUDPInterface
=
N6_IF_NAME
;
Logger
::
upf_app
().
info
(
"GTP interface: %s"
,
sGTPInterface
.
c_str
());
...
...
@@ -134,6 +131,8 @@ int main(int argc, char** argv) {
return
1
;
}
const
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
// Logger
// Config
std
::
string
conf_file_name
=
Options
::
getlibconfigConfig
();
...
...
@@ -208,7 +207,7 @@ int main(int argc, char** argv) {
fflush
(
fp
);
fclose
(
fp
);
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
setup_bpf
();
}
// once all udp servers initialized
...
...
src/upf_app/SessionManager.cpp
View file @
3313d4e2
...
...
@@ -144,7 +144,8 @@ void SessionManager::processPDRs(
const
bool
is_qos_enabled
=
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
;
// Helper function to find QER by ID
auto
find_qer_by_id
=
[
&
](
uint64_t
qer_id
)
->
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>
{
auto
find_qer_by_id
=
[
&
](
uint64_t
qer_id
)
->
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>
{
for
(
auto
&
qer
:
pSession_establishment
->
qers
)
{
if
(
qer
->
qer_id
.
second
.
qer_id
==
qer_id
)
{
return
qer
;
...
...
@@ -235,24 +236,24 @@ void SessionManager::prepareEbpfSession(
pfcp
::
pdi
pdi
;
pfcp
::
source_interface_t
sourceInterface
;
if
(
!
(
pdrHighPrecedence
->
get
(
pdi
)
&&
pdi
.
get
(
sourceInterface
))){
if
(
!
(
pdrHighPrecedence
->
get
(
pdi
)
&&
pdi
.
get
(
sourceInterface
)))
{
throw
std
::
runtime_error
(
"Missing Mandatory IE (PDI or Source Interface) within PDR: "
+
std
::
to_string
(
pdrHighPrecedence
->
pdr_id
.
rule_id
));
"Missing Mandatory IE (PDI or Source Interface) within PDR: "
+
std
::
to_string
(
pdrHighPrecedence
->
pdr_id
.
rule_id
));
}
logger
.
debug
(
"The PDR %d has the Highest Precedence"
,
pdrHighPrecedence
->
pdr_id
.
rule_id
);
"The PDR %d has the Highest Precedence"
,
pdrHighPrecedence
->
pdr_id
.
rule_id
);
processPDRDetails
(
pSession_establishment
,
pdrHighPrecedence
);
}
processPDRDetails
(
pSession_establishment
,
pdrHighPrecedence
);
}
//---------------------------------------------------------------------------------------------------------------
void
SessionManager
::
processPDRDetails
(
std
::
shared_ptr
<
pfcp
::
pfcp_session
>
pSession
,
std
::
shared_ptr
<
pfcp
::
pfcp_pdr
>
pdrHighPrecedence
)
{
auto
&
logger
=
Logger
::
upf_app
();
auto
&
logger
=
Logger
::
upf_app
();
const
bool
is_qos_enabled
=
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
;
pfcp
::
pdi
pdi
;
...
...
@@ -271,38 +272,44 @@ void SessionManager::processPDRDetails(
int
interfaceValue
=
sourceInterface
.
interface_value
;
switch
(
interfaceValue
)
{
case
INTERFACE_VALUE_CORE
:{
case
INTERFACE_VALUE_CORE
:
{
direction
=
Direction
::
Uplink
;
logger
.
debug
(
"Create the eBPF Uplink Datapath for Session %lu"
,
pSession
->
get_up_seid
());
logger
.
debug
(
"Create the eBPF Uplink Datapath for Session %lu"
,
pSession
->
get_up_seid
());
break
;
}
case
INTERFACE_VALUE_ACCESS
:{
case
INTERFACE_VALUE_ACCESS
:
{
direction
=
Direction
::
Downlink
;
logger
.
debug
(
"Create the eBPF Downlink Datapath for Session %lu"
,
pSession
->
get_up_seid
());
logger
.
debug
(
"Create the eBPF Downlink Datapath for Session %lu"
,
pSession
->
get_up_seid
());
break
;
}
default:
{
default:
{
Logger
::
upf_app
().
warn
(
"Unknown interface value: %d"
,
interfaceValue
);
break
;
}
}
// Check for missing FTEID
// Check for missing FTEID
if
(
!
pdi
.
get
(
fteid
))
{
fteid
.
teid
=
-
1
;
logger
.
warn
(
"FTEID is missing for the current PDR. "
"Note: This IE should not be present if the Traffic Endpoint ID is present. "
"If the CHOOSE (CH) bit is set to 1, the UP function is expected to assign "
"Note: This IE should not be present if the Traffic Endpoint ID is "
"present. "
"If the CHOOSE (CH) bit is set to 1, the UP function is expected to "
"assign "
"a local F-TEID to the PDR."
);
if
(
fteid
.
ch
)
{
logger
.
debug
(
"CHOOSE (CH) bit is set in FTEID."
);
logger
.
debug
(
"CHOOSE (CH) bit is set in FTEID."
);
}
else
{
logger
.
debug
(
"CHOOSE (CH) bit is not set in FTEID."
);
logger
.
debug
(
"CHOOSE (CH) bit is not set in FTEID."
);
}
}
...
...
@@ -312,14 +319,15 @@ void SessionManager::processPDRDetails(
logger
.
warn
(
"UE IP Address is missing for the current PDR. "
"Note: This IE should not be present if the Traffic Endpoint ID is present."
);
"Note: This IE should not be present if the Traffic Endpoint ID is "
"present."
);
}
// Log PDI extraction details
logger
.
debug
(
"PDI successfully extracted from PDR ID: %d."
,
pdr_id
);
logger
.
debug
(
"Extracting FAR from the highest precedence PDR ID: %d."
,
pdr_id
);
std
::
shared_ptr
<
pfcp
::
pfcp_far
>
pFar
;
if
(
!
extractFar
(
pdrHighPrecedence
,
pSession
,
pFar
))
{
...
...
@@ -334,18 +342,26 @@ void SessionManager::processPDRDetails(
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
pQer
;
/*
* TODO: implement the QoS Enforcement on the uplink side
if (is_qos_enabled) {
pQer = (direction == Direction::Uplink) ? pSession->qers_uplink :
pSession
->
qers_downlink
;
SessionProgramManager
::
getInstance
().
createPipeline
(
std::vector<std::shared_ptr<pfcp::pfcp_qer>>{}
;
}
SessionProgramManager::getInstance().createPipeline(
pSession->get_up_seid(), fteid.teid, interfaceValue,
ueIpAddress
.
ipv4_address
.
s_addr
,
pFar
,
pQer
,
false
,
0
);
}
else
{
SessionProgramManager
::
getInstance
().
createPipeline
(
pSession
->
get_up_seid
(),
fteid
.
teid
,
interfaceValue
,
ueIpAddress
.
ipv4_address
.
s_addr
,
pFar
,
false
,
0
);
}
ueIpAddress.ipv4_address.s_addr, pFar, pQer, false, 0);
*/
if
(
is_qos_enabled
)
{
pQer
=
(
direction
==
Direction
::
Downlink
)
?
pSession
->
qers_downlink
:
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
{};
}
SessionProgramManager
::
getInstance
().
createPipeline
(
pSession
->
get_up_seid
(),
fteid
.
teid
,
interfaceValue
,
ueIpAddress
.
ipv4_address
.
s_addr
,
pFar
,
pQer
,
false
,
0
);
}
//---------------------------------------------------------------------------------------------------------------
...
...
src/upf_app/SessionProgramManager.cpp
View file @
3313d4e2
...
...
@@ -196,30 +196,30 @@ void SessionProgramManager::storeSessionMappingMap(
void
SessionProgramManager
::
updateARPTableForN6
(
std
::
shared_ptr
<
PFCP_Session_LookupProgram
>
pPFCP_Session_LookupProgram
,
uint32_t
dnIP
,
uint32_t
upfn6IP
)
{
try
{
std
::
string
remoteDN
=
"192.168.24.160"
;
uint32_t
remoteN6IPv4
=
inet_addr
(
remoteDN
.
c_str
());
// const char* remoteN6MAC = "0061BB000001";
uint8_t
remoteN6MAC
[
6
]
=
{
0x00
,
0x61
,
0xbb
,
0x00
,
0x00
,
0x01
};
Logger
::
upf_app
().
warn
(
"updateARPTableForN6 is modified with hard values to test with "
"Trex! I dont understand why the execution goes through the "
"exception!"
"Need to check and debug"
);
struct
s_arp_mapping
map_table
;
memset
(
&
map_table
,
0
,
sizeof
(
struct
s_arp_mapping
));
memcpy
(
map_table
.
mac_address
,
remoteN6MAC
,
6
);
map_table
.
ipv4_address
=
remoteN6IPv4
;
try
{
std
::
string
remoteDN
=
"192.168.24.160"
;
uint32_t
remoteN6IPv4
=
inet_addr
(
remoteDN
.
c_str
());
// const char* remoteN6MAC = "0061BB000001";
uint8_t
remoteN6MAC
[
6
]
=
{
0x00
,
0x61
,
0xbb
,
0x00
,
0x00
,
0x01
};
pPFCP_Session_LookupProgram
->
getArpTableMap
()
->
update
(
upfn6IP
,
map_table
,
BPF_ANY
);
}
catch
(
const
std
::
exception
&
ex
)
{
Logger
::
upf_app
().
error
(
"Error: The ARP table was not updated for N6 Next HOP"
);
}
}
Logger
::
upf_app
().
warn
(
"updateARPTableForN6 is modified with hard values to test with "
"Trex! I dont understand why the execution goes through the "
"exception!"
"Need to check and debug"
);
struct
s_arp_mapping
map_table
;
memset
(
&
map_table
,
0
,
sizeof
(
struct
s_arp_mapping
));
memcpy
(
map_table
.
mac_address
,
remoteN6MAC
,
6
);
map_table
.
ipv4_address
=
remoteN6IPv4
;
pPFCP_Session_LookupProgram
->
getArpTableMap
()
->
update
(
upfn6IP
,
map_table
,
BPF_ANY
);
}
catch
(
const
std
::
exception
&
ex
)
{
Logger
::
upf_app
().
error
(
"Error: The ARP table was not updated for N6 Next HOP"
);
}
}
/*
void SessionProgramManager::updateARPTableForN6(
...
...
@@ -272,8 +272,7 @@ void SessionProgramManager::updateARPTableForN3(
for
(
auto
it
=
pfcpPrograms
->
begin
();
it
!=
pfcpPrograms
->
end
();
++
it
)
{
// Access the members of the 'farprograms' struct
uint64_t
savedSeid
=
it
->
seid
;
std
::
shared_ptr
<
PFCP_Session_LookupProgram
>
pPFCP_Session_LookupProgram
=
std
::
shared_ptr
<
PFCP_Session_LookupProgram
>
pPFCP_Session_LookupProgram
=
it
->
pPFCP_Session_LookupProgram
;
if
(
savedSeid
==
seid
)
{
...
...
@@ -311,7 +310,8 @@ void SessionProgramManager::updateARPTableForN3(
// for (auto it = pfcpPrograms->begin(); it != pfcpPrograms->end(); ++it) {
// // Access the members of the 'farprograms' struct
// uint64_t savedSeid = it->seid;
// std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram =
// std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram
// =
// it->pPFCP_Session_LookupProgram;
// if (savedSeid == seid) {
...
...
@@ -366,15 +366,27 @@ void SessionProgramManager::createPipeline(
uint32_t
ueIpAddress
,
std
::
shared_ptr
<
pfcp
::
pfcp_far
>
pFar
,
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
pQer
,
bool
isModification
,
uint32_t
teid2
)
{
uint32_t
dnIP
=
upf_cfg
.
remote_n6
.
s_addr
;
uint32_t
upfn3IP
=
upf_cfg
.
n3
.
addr4
.
s_addr
;
uint32_t
upfn6IP
=
upf_cfg
.
n6
.
addr4
.
s_addr
;
uint32_t
far_id
=
pFar
->
far_id
.
far_id
;
uint32_t
dnIP
=
upf_cfg
.
remote_n6
.
s_addr
;
uint32_t
upfn3IP
=
upf_cfg
.
n3
.
addr4
.
s_addr
;
uint32_t
upfn6IP
=
upf_cfg
.
n6
.
addr4
.
s_addr
;
uint32_t
far_id
=
pFar
->
far_id
.
far_id
;
next_rule_prog_index_key
key
;
initializeNextRuleProgIndexKey
(
key
,
teid1
,
ueIpAddress
,
sourceInterface
);
bool
enforcing_qos
=
!
pQer
.
empty
();
const
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
const
bool
isQosEnabled
=
isBpfAccelerationEnabled
&&
upf_cfg
.
enable_qos
;
/*======================================================================================*/
if
(
isQosEnabled
&&
enforcing_qos
)
{
Logger
::
upf_app
().
debug
(
"Instantiate a new QERProgram "
);
std
::
shared_ptr
<
QERProgram
>
pQERProgram
=
std
::
make_shared
<
QERProgram
>
();
pQERProgram
->
setup
(
seid
,
pQer
);
}
/*======================================================================================*/
auto
pPFCP_Session_LookupProgram
=
UserPlaneComponent
::
getInstance
().
getPFCP_Session_LookupProgram
();
...
...
@@ -414,12 +426,9 @@ void SessionProgramManager::createPipeline(
void
SessionProgramManager
::
removePipeline
(
uint64_t
seid
)
{
Logger
::
upf_app
().
debug
(
"Remove FARProgram index from UPFProgram map"
);
auto
it
=
mSessionProgramsMap
.
find
(
seid
);
if
(
it
==
mSessionProgramsMap
.
end
())
{
Logger
::
upf_app
().
error
(
"Session %d Does Not Exist. It Cannot be Removed"
,
seid
);
// throw std::runtime_error("Session does Not Exist. It Cannot be
// Removed");
Logger
::
upf_app
().
error
(
"Session with SEID: %lu Does Not Exist"
,
seid
);
}
Logger
::
upf_app
().
debug
(
...
...
src/upf_app/SessionProgramManager.h
View file @
3313d4e2
...
...
@@ -14,7 +14,6 @@
class
BPFMap
;
class
OnStateChangeSessionProgramObserver
;
class
PFCP_Session_LookupProgram
;
// class PFCP_Session_PDR_LookupProgram;
class
SessionPrograms
;
class
FARProgram
;
...
...
@@ -112,11 +111,6 @@ class SessionProgramManager {
bool
isModification
=
false
,
uint32_t
teid2
=
0
);
/*---------------------------------------------------------------------------------------------------------------*/
void
createPipeline
(
uint64_t
seid
,
uint32_t
teid1
,
uint8_t
sourceInterface
,
uint32_t
ueIpAddress
,
std
::
shared_ptr
<
pfcp
::
pfcp_far
>
pFar
,
bool
isModification
=
false
,
uint32_t
teid2
=
0
);
/*---------------------------------------------------------------------------------------------------------------*/
void
initializeNextRuleProgIndexKey
(
next_rule_prog_index_key
&
key
,
uint32_t
teid
,
uint32_t
ueIpAddress
,
uint8_t
sourceInterface
);
...
...
src/upf_app/SessionPrograms.h
View file @
3313d4e2
...
...
@@ -7,8 +7,8 @@
#include <next_prog_rule_key.h>
/**
* @brief This class represents the
datapath path. It stores the program related
* to a PFCP session. For each session, there might be a QERProgram. The
* @brief This class represents the
Data-Path path. It stores the program
*
related
to a PFCP session. For each session, there might be a QERProgram. The
* FARProgram is mandatory.
*
*/
...
...
src/upf_app/UserPlaneComponent.cpp
View file @
3313d4e2
#include "UserPlaneComponent.h"
#include <SessionManager.h>
//#include <pfcp_session_pdr_lookup_xdp_user.h>
#include <SessionProgramManager.h>
#include <SignalHandler.h>
#include <pfcp_session_lookup_xdp_user.h>
#include "logger.hpp"
#include <helpers/GetNicInformation.hpp>
#include "upf_config.hpp"
using
namespace
oai
::
config
;
extern
upf_config
upf_cfg
;
//---------------------------------------------------------------------------------------------------------------
UserPlaneComponent
::
UserPlaneComponent
()
{
// Set new handlers for libbpf.
...
...
@@ -82,9 +85,12 @@ void UserPlaneComponent::setMembers(
//---------------------------------------------------------------------------------------------------------------
void
UserPlaneComponent
::
setup
(
const
std
::
string
&
gtpInterface
,
const
std
::
string
&
udpInterface
)
{
const
bool
isQosEnabled
=
upf_cfg
.
enable_qos
;
setMembers
(
gtpInterface
,
udpInterface
);
SignalHandler
::
getInstance
().
enable
();
mpPFCP_Session_LookupProgram
->
setup
();
mpPFCP_Session_LookupProgram
->
setup
(
isQosEnabled
);
// Pass maps to sessionManager.
mpSessionManager
=
std
::
make_shared
<
SessionManager
>
();
...
...
src/upf_app/bpf/protocols/udp.h
View file @
3313d4e2
...
...
@@ -6,17 +6,18 @@
#include <linux/bpf.h>
#include <linux/if_ether.h>
//#define UDP_CSUM_OFFSET (sizeof(struct ethhdr) + offsetof(struct udphdr, check))
//#define UDP_CSUM_OFFSET (sizeof(struct ethhdr) + offsetof(struct udphdr,
//check))
// static u32 udp_handle(
// struct xdp_md* ctx, struct udphdr* udph, u32 src_ip, u32 dest_ip);
// static u32 udp_handle(
// struct xdp_md* ctx, struct udphdr* udph, u32 dest_ip);
static
u32
udp_handle
(
struct
xdp_md
*
p_ctx
,
struct
udphdr
*
udph
,
u32
src_ip
,
u32
dest_ip
,
u8
dscp
);
//
static u32 udp_handle(
//
struct xdp_md* p_ctx, struct udphdr* udph, u32 src_ip, u32 dest_ip,
//
u8 dscp);
static
u32
handle_uplink_traffic
(
struct
xdp_md
*
p_ctx
,
struct
udphdr
*
udph
);
//
static u32 handle_uplink_traffic(struct xdp_md* p_ctx, struct udphdr* udph);
#endif // PROTOCOLS_UDP_H
src/upf_app/bpf/rules/far/far_maps.h
View file @
3313d4e2
...
...
@@ -37,12 +37,12 @@ struct {
}
m_arp_table
SEC
(
".maps"
);
/*---------------------------------------------------------------------------------------------------------------*/
struct
{
__uint
(
type
,
BPF_MAP_TYPE_HASH
);
__uint
(
max_entries
,
MAX_FAR_PROGRAMS
);
__type
(
key
,
u32
);
__type
(
value
,
u32
);
}
m_enforcing_qos
SEC
(
".maps"
);
//
struct {
//
__uint(type, BPF_MAP_TYPE_HASH);
//
__uint(max_entries, MAX_FAR_PROGRAMS);
//
__type(key, u32);
//
__type(value, u32);
//
} m_enforcing_qos SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
...
...
src/upf_app/bpf/rules/pdr/pfcp_session_lookup_xdp_kernel.c
View file @
3313d4e2
...
...
@@ -57,7 +57,6 @@ struct vlan_hdr {
static
u32
upf_n3_ip
=
0
;
static
u32
upf_n6_ip
=
0
;
static
u32
ue_ip
=
0
;
static
u8
next_hop_n3_mac_address
[
6
]
=
{
0
};
static
u8
next_hop_n6_mac_address
[
6
]
=
{
0
};
...
...
@@ -259,69 +258,69 @@ create_outer_header_gtpu_ipv4(struct xdp_md* ctx, pfcp_far_t_* p_far) {
/*---------------------------------------------------------------------------------------------------------------*/
SEC
(
"xdp"
)
int
xdp_handle_uplink
(
struct
xdp_md
*
ctx
)
{
bpf_debug
(
"================< PFCP PDR Sesction: Handle Uplink >================"
);
bpf_debug
(
"================< XDP: Handle Uplink >================"
);
void
*
data
=
(
void
*
)
(
long
)
ctx
->
data
;
void
*
data_end
=
(
void
*
)
(
long
)
ctx
->
data_end
;
struct
ethhdr
*
ethh
=
(
void
*
)
(
long
)
ctx
->
data
;
u16
eth_type
=
bpf_htons
(
ethh
->
h_proto
);
u64
offset
=
sizeof
(
*
ethh
);
if
((
void
*
)
(
ethh
+
1
)
>
(
void
*
)
(
long
)
ctx
->
data_end
)
{
bpf_debug
(
"Invalid Ethernet header"
);
bpf_debug
(
"
Error:
Invalid Ethernet header"
);
return
XDP_DROP
;
}
u16
eth_type
=
bpf_htons
(
ethh
->
h_proto
);
bpf_debug
(
"Debug: eth_type:0x%x"
,
eth_type
);
switch
(
eth_type
)
{
case
ETH_P_IP
:
{
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
((
void
*
)
ethh
+
offset
);
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
((
void
*
)
ethh
+
sizeof
(
*
ethh
)
);
if
((
void
*
)
(
iph
+
1
)
>
data_end
)
{
bpf_debug
(
"Invalid IPv4 Packet"
);
bpf_debug
(
"
Error:
Invalid IPv4 Packet"
);
return
XDP_DROP
;
}
struct
udphdr
*
udph
=
(
struct
udphdr
*
)
(
iph
+
1
);
if
((
void
*
)
(
udph
+
1
)
>
data_end
)
{
bpf_debug
(
"Invalid UDP packet"
);
bpf_debug
(
"
Error:
Invalid UDP packet"
);
return
XDP_DROP
;
}
if
(
bpf_htons
(
udph
->
dest
)
==
GTP_UDP_PORT
)
{
bpf_debug
(
"
This is a GTP t
raffic"
);
bpf_debug
(
"
Identified GTP T
raffic"
);
struct
gtpuhdr
*
gtpuh
=
(
struct
gtpuhdr
*
)
(
udph
+
1
);
// Check if the GTP header extends beyond the data end.
if
((
void
*
)
gtpuh
+
sizeof
(
*
gtpuh
)
>
data_end
)
{
bpf_debug
(
"
Invalid GTP
U packet"
);
bpf_debug
(
"
Error: Invalid GTP-
U packet"
);
return
XDP_DROP
;
}
if
(
gtpuh
->
message_type
!=
GTPU_G_PDU
)
{
bpf_debug
(
"Message type 0x%x is not GTPU GPDU(0x%x)
\n
"
,
gtpuh
->
message_type
,
GTPU_G_PDU
);
return
XDP_PASS
;
}
struct
ethhdr
*
ethh_new
=
data
+
GTP_ENCAPSULATED_SIZE
;
if
((
void
*
)
ethh_new
+
sizeof
(
*
ethh_new
)
>
data_end
)
{
bpf_debug
(
"
Invali
d Ethernet packet"
);
bpf_debug
(
"
Error: Invalid encapsulate
d Ethernet packet"
);
return
XDP_DROP
;
}
struct
iphdr
*
iph_inner
=
(
void
*
)
(
ethh_new
+
1
);
if
((
void
*
)
iph_inner
+
sizeof
(
*
iph_inner
)
>
data_end
)
{
bpf_debug
(
"Invalid Inner IP packet"
);
bpf_debug
(
"
Error:
Invalid Inner IP packet"
);
return
XDP_DROP
;
}
u32
src_ip_in
=
bpf_htonl
(
iph_inner
->
saddr
);
if
(
gtpuh
->
message_type
!=
GTPU_G_PDU
)
{
bpf_debug
(
"Message type 0x%x is not GTPU GPDU(0x%x)
\n
"
,
gtpuh
->
message_type
,
GTPU_G_PDU
);
return
XDP_PASS
;
}
struct
next_rule_prog_index_key
map_key
=
{
0
};
map_key
.
teid
=
gtpuh
->
teid
;
map_key
.
source_value
=
INTERFACE_VALUE_ACCESS
;
...
...
@@ -332,19 +331,17 @@ int xdp_handle_uplink(struct xdp_md* ctx) {
if
(
p_far
)
{
bpf_debug
(
"FAR ID = %d"
,
p_far
->
far_id
.
far_id
);
u8
dest_interface
=
p_far
->
forwarding_parameters
.
destination_interface
.
interface_value
;
// u8 dest_interface = p_far->forwarding_parameters.destination_interface.interface_value;
if
(
!
p_far
->
apply_action
.
forw
)
{
bpf_debug
(
"Forward Action Is NOT set"
);
return
XDP_PASS
;
}
bpf_debug
(
"GTP Header Removal
...
"
);
bpf_debug
(
"GTP Header Removal
in Progress
"
);
__builtin_memcpy
(
ethh_new
,
ethh
,
sizeof
(
*
ethh
));
// Retrieve the N6 Interface IP address:
e_reference_point
n6_key
=
N6_INTERFACE
;
if
(
!
cached_n6
)
{
...
...
@@ -378,6 +375,7 @@ int xdp_handle_uplink(struct xdp_md* ctx) {
sizeof
(
ethh_new
->
h_dest
));
// Adjust head to the right.
if
(
bpf_xdp_adjust_head
(
ctx
,
GTP_ENCAPSULATED_SIZE
))
{
bpf_debug
(
"Error: Adjusting packet head failed"
);
return
XDP_DROP
;
}
...
...
@@ -385,7 +383,7 @@ int xdp_handle_uplink(struct xdp_md* ctx) {
// ethh_new->h_dest[1], ethh_new->h_dest[2]); bpf_debug(" %x:%x:%x",
// ethh_new->h_dest[3], ethh_new->h_dest[4], ethh_new->h_dest[5]);
bpf_debug
(
"
The Packet is redirected for transmission to DN ...
"
);
bpf_debug
(
"
Redirecting Packet to DN
"
);
return
bpf_redirect_map
(
&
m_redirect_interfaces
,
UPLINK
,
0
);
...
...
@@ -396,7 +394,7 @@ int xdp_handle_uplink(struct xdp_md* ctx) {
}
}
default:
{
bpf_debug
(
"
Cannot parse L2: L3off:%llu proto:0x%x"
,
offset
,
eth_type
);
bpf_debug
(
"
Unsupported protocol: 0x%x"
,
eth_type
);
return
XDP_PASS
;
}
}
...
...
@@ -405,32 +403,32 @@ int xdp_handle_uplink(struct xdp_md* ctx) {
/*---------------------------------------------------------------------------------------------------------------*/
SEC
(
"xdp"
)
int
xdp_handle_downlink
(
struct
xdp_md
*
ctx
)
{
bpf_debug
(
"================< PFCP PDR Sesction: Handle Downlink >================"
);
bpf_debug
(
"================< XDP: Handle Downlink >================"
);
void
*
data_end
=
(
void
*
)
(
long
)
ctx
->
data_end
;
struct
ethhdr
*
ethh
=
(
void
*
)
(
long
)
ctx
->
data
;
u64
offset
=
sizeof
(
*
ethh
);
if
((
void
*
)
(
ethh
+
1
)
>
(
void
*
)
(
long
)
ctx
->
data_end
)
{
bpf_debug
(
"Invalid Ethernet header"
);
bpf_debug
(
"
Error:
Invalid Ethernet header"
);
return
XDP_DROP
;
}
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
((
void
*
)
ethh
+
offset
);
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
((
void
*
)
ethh
+
sizeof
(
*
ethh
)
);
if
((
void
*
)
(
iph
+
1
)
>
data_end
)
{
bpf_debug
(
"Invalid IPv4 Packet"
);
bpf_debug
(
"
Error:
Invalid IPv4 Packet"
);
return
XDP_DROP
;
}
u32
ip_dest
=
bpf_htonl
(
iph
->
daddr
);
struct
session_id
*
session
=
bpf_map_lookup_elem
(
&
m_session_mapping
,
&
ip_dest
);
// u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &ip_dest);
if
(
session
)
{
u32
teid_dl
=
session
->
teid_dl
;
bpf_debug
(
"TEID downlink: 0x%x was found for UE IP: 0x%x"
,
teid_dl
,
ip_dest
);
"TEID for downlink: 0x%x, UE IP: 0x%x"
,
teid_dl
,
ip_dest
);
struct
next_rule_prog_index_key
map_key
=
{
0
};
map_key
.
teid
=
teid_dl
;
map_key
.
source_value
=
INTERFACE_VALUE_CORE
;
...
...
@@ -446,6 +444,55 @@ int xdp_handle_downlink(struct xdp_md* ctx) {
}
}
bpf_debug
(
"Session not found for Downlink, tail call failed"
);
return
XDP_PASS
;
}
/*---------------------------------------------------------------------------------------------------------------*/
SEC
(
"xdp"
)
int
xdp_handle_shaping
(
struct
xdp_md
*
ctx
)
{
bpf_debug
(
"================< XDP: Handle Shaping >================"
);
void
*
data_end
=
(
void
*
)
(
long
)
ctx
->
data_end
;
struct
ethhdr
*
ethh
=
(
void
*
)
(
long
)
ctx
->
data
;
if
((
void
*
)
(
ethh
+
1
)
>
(
void
*
)
(
long
)
ctx
->
data_end
)
{
bpf_debug
(
"Error: Invalid Ethernet header"
);
return
XDP_DROP
;
}
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
((
void
*
)
ethh
+
sizeof
(
*
ethh
));
if
((
void
*
)
(
iph
+
1
)
>
data_end
)
{
bpf_debug
(
"Error: Invalid IPv4 Packet"
);
return
XDP_DROP
;
}
u32
ip_dest
=
bpf_htonl
(
iph
->
daddr
);
struct
session_id
*
session
=
bpf_map_lookup_elem
(
&
m_session_mapping
,
&
ip_dest
);
if
(
session
)
{
u32
teid_dl
=
session
->
teid_dl
;
bpf_debug
(
"TEID downlink: 0x%x was found for UE IP: 0x%x"
,
teid_dl
,
ip_dest
);
struct
next_rule_prog_index_key
map_key
=
{
0
};
map_key
.
teid
=
teid_dl
;
map_key
.
source_value
=
INTERFACE_VALUE_CORE
;
map_key
.
ipv4_address
=
ip_dest
;
pfcp_far_t_
*
p_far
=
bpf_map_lookup_elem
(
&
m_next_rule_prog_index
,
&
map_key
);
if
(
p_far
)
{
bpf_debug
(
"FAR ID = %d"
,
p_far
->
far_id
.
far_id
);
create_outer_header_gtpu_ipv4
(
ctx
,
p_far
);
bpf_debug
(
"The packet is passed to tc layer"
);
return
XDP_PASS
;
}
}
bpf_debug
(
"BPF tail call was not executed!"
);
return
XDP_PASS
;
...
...
src/upf_app/bpf/rules/qer/qer_tc_kernel.c
View file @
3313d4e2
...
...
@@ -226,7 +226,7 @@ sdf_filter(struct __sk_buff* skb, struct ethhdr* ethh) {
SEC
(
"tc/egress"
)
int
tc_filter_traffic
(
struct
__sk_buff
*
skb
)
{
bpf_debug
(
"==========<
QER Rules
>==========
\n
"
);
bpf_debug
(
"==========<
tc/egress: Filter Traffic
>==========
\n
"
);
// void *data = (void *)(long)skb->data;
// void *data_meta = (void *)(long)skb->data_meta;
...
...
@@ -265,6 +265,7 @@ int tc_filter_traffic(struct __sk_buff* skb) {
SEC
(
"tc/ingress"
)
int
tc_redirect_traffic
(
struct
__sk_buff
*
skb
)
{
bpf_debug
(
"==========< tc/ingress: Redirect Traffic >==========
\n
"
);
int
key
=
DOWNLINK
,
*
ifindex
;
// return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
...
...
src/upf_app/bpf/rules/qer/qos_flow.h
View file @
3313d4e2
...
...
@@ -4,27 +4,37 @@
#include <types.h>
/* Use uint8_t*/
struct
s_gate
{
uint8_t
ul_gate
;
uint8_t
dl_gate
;
};
/
/ /
* 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_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_gbr
{
uint64_t
ul_gbr
;
uint64_t
dl_gbr
;
};
struct
s_fiveQosFlow
{
struct
s_gate
gate
;
struct
s_mbr
mbr
;
struct
s_gbr
gbr
;
uint
64
_t
qfi
;
uint8_t
gate
;
uint64_t
mbr
;
uint64_t
gbr
;
uint
8
_t
qfi
;
};
#endif //__QOS_FLOW_H__
\ No newline at end of file
src/upf_app/helpers/ConfigManager.cpp
0 → 100644
View file @
3313d4e2
src/upf_app/helpers/ConfigManager.hpp
0 → 100644
View file @
3313d4e2
#ifndef CONFIG_MANAGER_HPP
#define CONFIG_MANAGER_HPP
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
;
};
#endif // CONFIG_MANAGER_HPP
\ No newline at end of file
src/upf_app/programs/pfcp_session_lookup_xdp_user.cpp
View file @
3313d4e2
...
...
@@ -12,6 +12,14 @@
using
namespace
oai
::
config
;
extern
upf_config
upf_cfg
;
class
XDPSection
{
public:
static
constexpr
const
char
*
Uplink
=
"xdp_handle_uplink"
;
static
constexpr
const
char
*
Downlink
=
"xdp_handle_downlink"
;
static
constexpr
const
char
*
Shaping
=
"xdp_handle_shaping"
;
};
/*---------------------------------------------------------------------------------------------------------------*/
int
is_little_endian2
()
{
u32
value
=
1
;
...
...
@@ -73,7 +81,7 @@ void PFCP_Session_LookupProgram::create_upf_interface_map_entry(
PFCP_Session_LookupProgram
::~
PFCP_Session_LookupProgram
()
{}
/*---------------------------------------------------------------------------------------------------------------*/
void
PFCP_Session_LookupProgram
::
setup
()
{
void
PFCP_Session_LookupProgram
::
setup
(
bool
isQosEnabled
)
{
spSkeleton
=
mpLifeCycle
->
open
();
initializeMaps
();
mpLifeCycle
->
load
();
...
...
@@ -91,7 +99,7 @@ void PFCP_Session_LookupProgram::setup() {
mpEgressInterfaceMap
->
update
(
uplinkId
,
udpInterfaceIndex
,
BPF_ANY
);
mpEgressInterfaceMap
->
update
(
downlinkId
,
gtpInterfaceIndex
,
BPF_ANY
);
Logger
::
upf_app
().
debug
(
"Adding Reference Points to m_upf_interface Map
:
"
);
Logger
::
upf_app
().
debug
(
"Adding Reference Points to m_upf_interface Map"
);
create_upf_interface_map_entry
(
N3_INTERFACE
);
create_upf_interface_map_entry
(
N6_INTERFACE
);
create_upf_interface_map_entry
(
N4_INTERFACE
);
...
...
@@ -103,12 +111,21 @@ void PFCP_Session_LookupProgram::setup() {
}
Logger
::
upf_app
().
debug
(
"Link
Non-GTP interface to interface %s"
,
mUD
PInterface
.
c_str
());
mpLifeCycle
->
link
(
"xdp_handle_downlink"
,
mUD
PInterface
.
c_str
());
"Link
GTP XDP Section to interface %s"
,
mGT
PInterface
.
c_str
());
mpLifeCycle
->
link
(
XDPSection
::
Uplink
,
mGT
PInterface
.
c_str
());
Logger
::
upf_app
().
debug
(
"Link GTP interface to interface %s"
,
mGTPInterface
.
c_str
());
mpLifeCycle
->
link
(
"xdp_handle_uplink"
,
mGTPInterface
.
c_str
());
"Link Non-GTP XDP Section to interface %s"
,
mUDPInterface
.
c_str
());
if
(
isQosEnabled
)
{
Logger
::
upf_app
().
debug
(
"QoS enforcement is enabled in the configuration. A TC BPF section is "
"created "
);
mpLifeCycle
->
link
(
XDPSection
::
Shaping
,
mUDPInterface
.
c_str
());
}
else
{
Logger
::
upf_app
().
debug
(
"QoS enforcement is disabled in the configuration."
);
mpLifeCycle
->
link
(
XDPSection
::
Downlink
,
mUDPInterface
.
c_str
());
}
}
/*---------------------------------------------------------------------------------------------------------------*/
...
...
src/upf_app/programs/pfcp_session_lookup_xdp_user.h
View file @
3313d4e2
...
...
@@ -42,7 +42,7 @@ class PFCP_Session_LookupProgram {
* @brief Setup the BPF program.
*
*/
void
setup
();
void
setup
(
bool
isQosEnabled
);
/*---------------------------------------------------------------------------------------------------------------*/
/**
...
...
src/upf_app/programs/qer_tc_user.cpp
View file @
3313d4e2
...
...
@@ -54,10 +54,6 @@
#endif // MAX_CEIL
#endif // DEFAULT_CEIL
#ifndef DEFAULT_QFI
#define DEFAULT_QFI 5
#endif // DEFAULT_QFI
#ifndef BUILD_DIRECTORY
#define BUILD_DIRECTORY \
"build/upf/build/upf_app/bpf/CMakeFiles/qer_tc.dir/rules/qer"
...
...
@@ -86,16 +82,10 @@ void QERProgram::storeQosFlow(std::shared_ptr<pfcp::pfcp_qer> pQer) {
struct
s_fiveQosFlow
fiveFlow
;
memset
(
&
fiveFlow
,
0
,
sizeof
(
struct
s_fiveQosFlow
));
fiveFlow
.
gate
.
dl_gate
=
pQer
->
gate_status
.
second
.
dl_gate
;
fiveFlow
.
gate
.
ul_gate
=
pQer
->
gate_status
.
second
.
ul_gate
;
fiveFlow
.
gbr
.
dl_gbr
=
pQer
->
gbr
.
second
.
dl_gbr
;
fiveFlow
.
gbr
.
ul_gbr
=
pQer
->
gbr
.
second
.
ul_gbr
;
fiveFlow
.
mbr
.
dl_mbr
=
pQer
->
mbr
.
second
.
dl_mbr
;
fiveFlow
.
mbr
.
ul_mbr
=
pQer
->
mbr
.
second
.
ul_mbr
;
fiveFlow
.
qfi
=
pQer
->
qfi
.
second
.
qfi
;
fiveFlow
.
gate
=
pQer
->
gate_status
.
second
.
dl_gate
;
fiveFlow
.
gbr
=
pQer
->
gbr
.
second
.
dl_gbr
;
fiveFlow
.
mbr
=
pQer
->
mbr
.
second
.
dl_mbr
;
fiveFlow
.
qfi
=
pQer
->
qfi
.
second
.
qfi
;
qosFlowsQfis
.
push_back
(
fiveFlow
);
...
...
@@ -117,6 +107,23 @@ bool QERProgram::no_htb_root_qdisc(std::string interface) {
return
ret
?
false
:
true
;
}
/*---------------------------------------------------------------------------------------------------------------*/
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>
QERProgram
::
retrive_default_qer_with_default_qfi
(
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
pQer
)
{
for
(
const
auto
&
qer
:
pQer
)
{
if
(
!
qer
->
gbr
.
first
&&
!
qer
->
mbr
.
first
)
{
Logger
::
upf_app
().
debug
(
"Default QoS Flow: (QER ID, QFI): (%d, %d)"
,
qer
->
qer_id
.
second
.
qer_id
,
qer
->
qfi
.
second
.
qfi
);
return
qer
;
}
}
// Return nullptr if no such QER is found
return
nullptr
;
}
/*---------------------------------------------------------------------------------------------------------------*/
void
QERProgram
::
setup
(
uint64_t
seid
,
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
pQer
)
{
...
...
@@ -125,7 +132,7 @@ void QERProgram::setup(
mpLifeCycle
->
load
();
mpLifeCycle
->
attach
();
st
ruct
qer_tc_kernel_c
*
obj
=
NULL
;
st
d
::
shared_ptr
<
pfcp
::
pfcp_qer
>
default_qer
=
nullptr
;
std
::
string
cmd
=
{};
int
rc
=
0
;
...
...
@@ -133,97 +140,106 @@ void QERProgram::setup(
uint32_t
udpInterfaceIndex
=
if_nametoindex
(
UDP_INTERFACE
.
c_str
());
uint32_t
gtpInterfaceIndex
=
if_nametoindex
(
GTP_INTERFACE
.
c_str
());
uint32_t
uplinkId
=
static_cast
<
uint32_t
>
(
FlowDirection
::
UPLINK
);
uint32_t
downlinkId
=
static_cast
<
uint32_t
>
(
FlowDirection
::
DOWNLINK
);
mpEgressIfindexMap
->
update
(
uplinkId
,
udpInterfaceIndex
,
BPF_ANY
);
mpEgressIfindexMap
->
update
(
downlinkId
,
gtpInterfaceIndex
,
BPF_ANY
);
if
(
no_htb_root_qdisc
(
GTP_INTERFACE
))
{
Logger
::
upf_app
().
info
(
"Creating Root qdisc on interface %s"
,
GTP_INTERFACE
.
c_str
());
cmd
=
fmt
::
format
(
"tc qdisc add dev {} root handle 1:0 htb default {}"
,
GTP_INTERFACE
,
DEFAULT_QFI
);
rc
=
system
((
const
char
*
)
cmd
.
c_str
());
if
(
udpInterfaceIndex
==
0
||
gtpInterfaceIndex
==
0
)
{
Logger
::
upf_app
().
error
(
"Failed to retrieve interface indices"
);
throw
std
::
runtime_error
(
"Invalid network interface index"
);
}
Logger
::
upf_app
().
info
(
"Create PDU Session Class 1:%d"
,
seid
);
cmd
=
fmt
::
format
(
"tc class add dev {} parent 1:0 classid 1:{} htb rate {}kbit"
,
GTP_INTERFACE
,
seid
,
MAX_RATE
);
rc
=
system
((
const
char
*
)
cmd
.
c_str
());
Logger
::
upf_app
().
debug
(
"QDISC Root DL Rate (GBR) : %dkbps"
,
MAX_RATE
);
Logger
::
upf_app
().
debug
(
"QDISC Root DL Ceil (MBR) : %dkbps"
,
MAX_CEIL
);
uint32_t
uplinkId
=
static_cast
<
uint32_t
>
(
FlowDirection
::
UPLINK
);
uint32_t
downlinkId
=
static_cast
<
uint32_t
>
(
FlowDirection
::
DOWNLINK
);
for
(
const
auto
&
qer
:
pQer
)
{
if
(
qer
==
nullptr
)
{
continue
;
}
uint8_t
qfi
=
qer
->
qfi
.
second
.
qfi
;
uint32_t
qer_id
=
qer
->
qer_id
.
second
.
qer_id
;
Logger
::
upf_app
().
warn
(
"Set dl_rate and dl_ceil to 1kbit, for QER %d, as the minimum required "
"values to
\n
"
"create a tc class within the Linux kernel. These values are only used "
"if
\n
"
" dl_rate and dl_ceil are null within the PFCP Establishment request. "
"Of course, the
\n
"
"class rate and ceil are updated from the PFCP Modification request"
,
qer_id
);
uint64_t
dl_rate
=
1
;
uint64_t
dl_ceil
=
1
;
uint64_t
ul_rate
=
1
;
uint64_t
ul_ceil
=
1
;
uint8_t
dl_gate
=
0
;
uint8_t
ul_gate
=
0
;
mpEgressIfindexMap
->
update
(
uplinkId
,
udpInterfaceIndex
,
BPF_ANY
);
mpEgressIfindexMap
->
update
(
downlinkId
,
gtpInterfaceIndex
,
BPF_ANY
);
if
(
qfi
!=
DEFAULT_QFI
)
{
if
(
qer
->
gbr
.
second
.
dl_gbr
!=
0
)
dl_rate
=
qer
->
gbr
.
second
.
dl_gbr
;
if
(
!
pQer
.
empty
()
)
{
default_qer
=
retrive_default_qer_with_default_qfi
(
pQer
)
;
if
(
qer
->
gbr
.
second
.
ul_gbr
!=
0
)
ul_rate
=
qer
->
gbr
.
second
.
ul_gbr
;
if
(
!
default_qer
)
{
Logger
::
upf_app
().
error
(
"QER with default QFI not found! select the first element as "
"default"
);
default_qer
=
pQer
.
front
();
}
if
(
qer
->
mbr
.
second
.
dl_mbr
!=
0
)
dl_ceil
=
qer
->
mbr
.
second
.
dl_mbr
;
// Configure Root Qdisc if not already present
if
(
no_htb_root_qdisc
(
GTP_INTERFACE
))
{
Logger
::
upf_app
().
info
(
"Create Root qdisc on interface %s"
,
GTP_INTERFACE
.
c_str
());
cmd
=
fmt
::
format
(
"tc qdisc add dev {} root handle 1:0 htb default {}"
,
GTP_INTERFACE
,
static_cast
<
uint8_t
>
(
default_qer
->
qfi
.
second
.
qfi
));
// rc = system((const char*) cmd.c_str());
if
(
system
(
cmd
.
c_str
())
!=
0
)
{
Logger
::
upf_app
().
error
(
"Failed to create root Qdisc"
);
}
}
if
(
qer
->
mbr
.
second
.
ul_mbr
!=
0
)
ul_ceil
=
qer
->
mbr
.
second
.
ul_mbr
;
// Create PDU Session Class
Logger
::
upf_app
().
info
(
"Create PDU Session Class 1:%d"
,
seid
);
cmd
=
fmt
::
format
(
"tc class add dev {} parent 1:0 classid 1:{} htb rate {}kbit"
,
GTP_INTERFACE
,
seid
,
MAX_RATE
);
dl_gate
=
qer
->
gate_status
.
second
.
dl_gate
;
ul_gate
=
qer
->
gate_status
.
second
.
ul_gate
;
if
(
system
(
cmd
.
c_str
())
!=
0
)
{
Logger
::
upf_app
().
error
(
"Failed to create PDU Session class"
)
;
}
struct
s_fiveQosFlow
fiveFlow
;
memset
(
&
fiveFlow
,
0
,
sizeof
(
struct
s_fiveQosFlow
));
fiveFlow
.
gate
.
dl_gate
=
dl_gate
;
fiveFlow
.
gate
.
ul_gate
=
ul_gate
;
fiveFlow
.
gbr
.
dl_gbr
=
dl_rate
;
fiveFlow
.
gbr
.
ul_gbr
=
ul_rate
;
fiveFlow
.
mbr
.
dl_mbr
=
dl_ceil
;
fiveFlow
.
mbr
.
ul_mbr
=
ul_ceil
;
fiveFlow
.
qfi
=
qfi
;
getQoSFlowMap
()
->
update
(
qer_id
,
fiveFlow
,
BPF_ANY
);
uint16_t
minor
=
(
ntohs
(
seid
)
*
256
)
+
(
qfi
*
251
%
256
);
cmd
=
fmt
::
format
(
"tc class add dev {} parent 1:{} classid {}:{} htb rate {}kbit ceil "
"{}kbit"
,
GTP_INTERFACE
,
seid
,
seid
,
minor
,
dl_rate
,
dl_ceil
);
rc
=
system
((
const
char
*
)
cmd
.
c_str
());
Logger
::
upf_app
().
debug
(
" HTB Class ID (QER) ........... %d"
,
qer_id
);
Logger
::
upf_app
().
debug
(
" Class QFI: %d"
,
qfi
);
Logger
::
upf_app
().
debug
(
" Class DL Rate: %dkbps"
,
dl_rate
);
Logger
::
upf_app
().
debug
(
" Class DL Ceil: %dkbps"
,
dl_ceil
);
}
Logger
::
upf_app
().
debug
(
"QDISC Root DL Rate (GBR) : %dkbps"
,
MAX_RATE
);
Logger
::
upf_app
().
debug
(
"QDISC Root DL Ceil (MBR) : %dkbps"
,
MAX_CEIL
);
// Process each QER
for
(
const
auto
&
qer
:
pQer
)
{
if
(
qer
==
default_qer
)
{
continue
;
}
if
((
qer
->
gbr
.
first
)
&&
(
qer
->
mbr
.
first
))
{
uint32_t
qer_id
=
qer
->
qer_id
.
second
.
qer_id
;
uint8_t
qfi
=
qer
->
qfi
.
second
.
qfi
;
uint64_t
dl_rate
=
qer
->
gbr
.
second
.
dl_gbr
?
qer
->
gbr
.
second
.
dl_gbr
:
1
;
uint64_t
dl_ceil
=
qer
->
mbr
.
second
.
dl_mbr
?
qer
->
mbr
.
second
.
dl_mbr
:
1
;
uint8_t
dl_gate
=
qer
->
gate_status
.
second
.
dl_gate
;
Logger
::
upf_app
().
warn
(
"Setting dl_rate and dl_ceil to minimum values (1 kbit) for QER %d "
"if GBR/MBR are null"
,
qer_id
);
// Update QoS flow map
struct
s_fiveQosFlow
fiveFlow
=
{};
fiveFlow
.
gate
=
dl_gate
;
fiveFlow
.
gbr
=
dl_rate
;
fiveFlow
.
mbr
=
dl_ceil
;
getQoSFlowMap
()
->
update
(
qer_id
,
fiveFlow
,
BPF_ANY
);
// Add tc class for QER
uint16_t
minor
=
(
ntohs
(
seid
)
*
256
)
+
(
qfi
*
251
%
256
);
cmd
=
fmt
::
format
(
"tc class add dev {} parent 1:{} classid {}:{} htb rate {}kbit "
"ceil "
"{}kbit"
,
GTP_INTERFACE
,
seid
,
seid
,
minor
,
dl_rate
,
dl_ceil
);
if
(
system
(
cmd
.
c_str
())
!=
0
)
{
Logger
::
upf_app
().
error
(
"Failed to add tc class for QER {}"
,
qer_id
);
}
Logger
::
upf_app
().
debug
(
" HTB Class ID (QER) ........... %d"
,
qer_id
);
Logger
::
upf_app
().
debug
(
" Class QFI: %d"
,
qfi
);
Logger
::
upf_app
().
debug
(
" Class DL Rate: %dkbps"
,
dl_rate
);
Logger
::
upf_app
().
debug
(
" Class DL Ceil: %dkbps"
,
dl_ceil
);
}
}
Logger
::
upf_app
().
info
(
"Attach Section tc_filter_traffic to gtp interface"
);
mpLifeCycle
->
tcAttachEgress
(
"tc_filter_traffic"
,
GTP_INTERFACE
.
c_str
());
Logger
::
upf_app
().
info
(
"Attach Section tc_filter_traffic to gtp interface"
);
mpLifeCycle
->
tcAttachEgress
(
"tc_filter_traffic"
,
GTP_INTERFACE
.
c_str
());
Logger
::
upf_app
().
info
(
"Attach Sesction tc_redirect to udp interface"
);
mpLifeCycle
->
tcAttachIngress
(
"tc_redirect_traffic"
,
UDP_INTERFACE
.
c_str
());
Logger
::
upf_app
().
info
(
"Attach Sesction tc_redirect to udp interface"
);
mpLifeCycle
->
tcAttachIngress
(
"tc_redirect_traffic"
,
UDP_INTERFACE
.
c_str
());
}
}
// change:
...
...
src/upf_app/programs/qer_tc_user.h
View file @
3313d4e2
...
...
@@ -109,6 +109,10 @@ class QERProgram : public BPFProgram {
// int add_clsact_qdisc(int ifindex, enum bpf_tc_attach_point attach_point);
bool
no_htb_root_qdisc
(
std
::
string
interface
);
/*---------------------------------------------------------------------------------------------------------------*/
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>
retrive_default_qer_with_default_qfi
(
std
::
vector
<
std
::
shared_ptr
<
pfcp
::
pfcp_qer
>>
pQer
);
/*---------------------------------------------------------------------------------------------------------------*/
private:
/**
...
...
src/upf_app/simpleswitch/pfcp_switch.cpp
View file @
3313d4e2
...
...
@@ -419,6 +419,7 @@ pfcp_switch::pfcp_switch()
ul_n3_teid2pfcp_pdr
(
PFCP_SWITCH_MAX_PDRS
),
up_seid2pfcp_sessions
(
PFCP_SWITCH_MAX_SESSIONS
),
sock_w
(
0
)
{
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
num_threads_
=
upf_cfg
.
n6
.
thread_rd_sched_params
.
thread_pool_size
;
int
num_blocks
=
num_threads_
*
16
;
free_pool_
=
new
folly
::
MPMCQueue
<
iovec_q_item_t
*>
(
num_blocks
);
...
...
@@ -440,7 +441,7 @@ pfcp_switch::pfcp_switch()
v
->
msg
.
msg_controllen
=
0
;
free_pool_
->
blockingWrite
(
v
);
}
if
(
!
upf_cfg
.
enable_bpf_datapath
)
{
if
(
!
isBpfAccelerationEnabled
)
{
// num_threads_ is currently fixed to 1
for
(
int
i
=
0
;
i
<
num_threads_
;
i
++
)
{
pwThread_
=
std
::
thread
(
...
...
@@ -689,6 +690,9 @@ void pfcp_switch::call_datapath(
void
pfcp_switch
::
handle_pfcp_session_establishment_request
(
std
::
shared_ptr
<
itti_n4_session_establishment_request
>
sreq
,
itti_n4_session_establishment_response
*
resp
)
{
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
bool
isQosEnabled
=
isBpfAccelerationEnabled
&&
upf_cfg
.
enable_qos
;
itti_n4_session_establishment_request
*
req
=
sreq
.
get
();
pfcp
::
fseid_t
fseid
=
{};
pfcp
::
cause_t
cause
=
{.
cause_value
=
CAUSE_VALUE_REQUEST_ACCEPTED
};
...
...
@@ -737,11 +741,11 @@ void pfcp_switch::handle_pfcp_session_establishment_request(
break
;
}
/*======================================================================*/
/*======================================================================*/
/*
* Add create_qers
*/
if
(
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
)
{
if
(
isQosEnabled
)
{
pfcp
::
qer_id_t
qer_id
=
{};
if
(
cr_pdr
.
get
(
qer_id
))
{
pfcp
::
create_qer
cr_qer
=
{};
...
...
@@ -759,9 +763,9 @@ void pfcp_switch::handle_pfcp_session_establishment_request(
session
->
create
(
cr_qer
,
cause
,
offending_ie
.
offending_ie
);
}
}
}
/*======================================================================*/
if
(
not
session
->
create
(
cr_pdr
,
cause
,
offending_ie
.
offending_ie
,
allocated_fteid
))
{
session
->
cleanup
();
...
...
@@ -779,7 +783,7 @@ void pfcp_switch::handle_pfcp_session_establishment_request(
}
}
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Establishing datapath: create PDRs + create FARs + create QERs "
"(if any)"
);
...
...
@@ -860,6 +864,9 @@ void pfcp_switch::handle_pfcp_session_establishment_request(
void
pfcp_switch
::
handle_pfcp_session_modification_request
(
std
::
shared_ptr
<
itti_n4_session_modification_request
>
sreq
,
itti_n4_session_modification_response
*
resp
)
{
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
bool
isQosEnabled
=
isBpfAccelerationEnabled
&&
upf_cfg
.
enable_qos
;
itti_n4_session_modification_request
*
req
=
sreq
.
get
();
std
::
shared_ptr
<
pfcp
::
pfcp_session
>
s
=
{};
...
...
@@ -882,7 +889,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
resp
->
seid
=
session
->
cp_fseid
.
seid
;
for
(
auto
it
:
req
->
pfcp_ies
.
remove_pdrs
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: remove PDRs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
...
...
@@ -904,7 +911,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
if
(
cause
.
cause_value
==
CAUSE_VALUE_REQUEST_ACCEPTED
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
remove_fars
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: remove FARs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
...
...
@@ -929,15 +936,13 @@ void pfcp_switch::handle_pfcp_session_modification_request(
/*
* Add remove_qers
*/
if
(
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
)
{
if
(
isQosEnabled
)
{
if
(
cause
.
cause_value
==
CAUSE_VALUE_REQUEST_ACCEPTED
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
remove_qers
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: remove QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
}
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: remove QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
remove_qer
&
qer
=
it
;
...
...
@@ -957,7 +962,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
if
(
cause
.
cause_value
==
CAUSE_VALUE_REQUEST_ACCEPTED
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
create_fars
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: create FARs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
...
...
@@ -1007,7 +1012,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
resp
->
pfcp_ies
.
set
(
created_pdr
);
}
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: create PDRs + create FARs"
);
call_datapath
(
...
...
@@ -1021,15 +1026,13 @@ void pfcp_switch::handle_pfcp_session_modification_request(
/*
* Add create_qers
*/
if
(
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
)
{
if
(
isQosEnabled
)
{
if
(
cause
.
cause_value
==
CAUSE_VALUE_REQUEST_ACCEPTED
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
create_qers
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: create QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
}
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: create QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
create_qer
&
cr_qer
=
it
;
if
(
not
session
->
create
(
cr_qer
,
cause
,
offending_ie
.
offending_ie
))
{
break
;
...
...
@@ -1041,7 +1044,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
if
(
cause
.
cause_value
==
CAUSE_VALUE_REQUEST_ACCEPTED
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
update_pdrs
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: update PDRs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
...
...
@@ -1059,7 +1062,7 @@ void pfcp_switch::handle_pfcp_session_modification_request(
}
for
(
auto
it
:
req
->
pfcp_ies
.
update_fars
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: update FARs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
...
...
@@ -1082,14 +1085,12 @@ void pfcp_switch::handle_pfcp_session_modification_request(
/*
* Add update_qers
*/
if
(
upf_cfg
.
enable_bpf_datapath
&&
upf_cfg
.
enable_qos
)
{
if
(
isQosEnabled
)
{
for
(
auto
it
:
req
->
pfcp_ies
.
update_qers
)
{
if
(
upf_cfg
.
enable_bpf_datapath
)
{
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: update QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
}
Logger
::
pfcp_switch
().
info
(
"Modifying datapath: update QERs"
);
call_datapath
(
NULL
,
req
,
NULL
,
session
,
spSessionManager
,
&
SessionManager
::
updateBPFSession
);
update_qer
&
qer
=
it
;
uint8_t
cause_value
=
CAUSE_VALUE_REQUEST_ACCEPTED
;
...
...
@@ -1151,6 +1152,8 @@ void pfcp_switch::handle_pfcp_session_modification_request(
void
pfcp_switch
::
handle_pfcp_session_deletion_request
(
std
::
shared_ptr
<
itti_n4_session_deletion_request
>
sreq
,
itti_n4_session_deletion_response
*
resp
)
{
bool
isBpfAccelerationEnabled
=
upf_cfg
.
enable_bpf_datapath
;
itti_n4_session_deletion_request
*
req
=
sreq
.
get
();
std
::
shared_ptr
<
pfcp
::
pfcp_session
>
s
=
{};
...
...
@@ -1165,7 +1168,7 @@ void pfcp_switch::handle_pfcp_session_deletion_request(
pfcp
::
pfcp_session
*
session
=
s
.
get
();
resp
->
seid
=
s
->
cp_fseid
.
seid
;
if
(
upf_cfg
.
enable_bpf_datapath
)
{
if
(
isBpfAccelerationEnabled
)
{
Logger
::
pfcp_switch
().
info
(
"Deleting datapath: delete PDRs + delete FARs"
);
call_datapath
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment