Commit cf5767fd authored by lfq's avatar lfq

Update: improve the throughput

parent 13514de8
################################################################################
# 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 CN Configuration File
### This file can be used by all OAI NFs
# Configuration File
### This file can be used by all NFs
### Some fields are specific to an NF and will be ignored by other NFs
### The {{ env['ENV_NAME'] }} syntax lets you define these values in a docker-compose file
### If you intend to mount this file or use a bare-metal deployment, please refer to README.md
### The README.md also defines default values and allowed values for each configuration parameter
## NOTE ON YAML ANCHORS ##
# We use YAML anchors to ease the configuration and to avoid duplicating parts of the configuration.
# This is especially true for the SNSSAIs, as we have to define them for multiple NFs.
# Please note that the use of anchors is not mandatory, and you can define the SNSSAI in each NF yourself.
# You can read more about anchors here: https://yaml.org/spec/1.2.2/#anchors-and-aliases
############# Common configuration
......@@ -35,79 +17,79 @@ log_level:
# If you enable registration, the other NFs will use the NRF discovery mechanism
register_nf:
general: yes
http_version: 2
http_version: 1
############## SBI Interfaces
### Each NF takes its local SBI interfaces and remote interfaces from here, unless it gets them using NRF discovery mechanisms
nfs:
amf:
host: oai-amf
host: openxg-amf
sbi:
port: 8080
port: 8001
api_version: v1
interface_name: eth0
n2:
interface_name: eth0
port: 38412
smf:
host: oai-smf
host: openxg-smf
sbi:
port: 8080
port: 8002
api_version: v1
interface_name: eth0
n4:
interface_name: eth0
port: 8805
upf:
host: oai-upf
host: openxg-upf
sbi:
port: 8080
port: 8003
api_version: v1
interface_name: demo-oai
interface_name: enp6s0
n3:
interface_name: demo-n3
interface_name: enp1s0f0np0
port: 2152
n4:
interface_name: demo-oai
interface_name: enp6s0
port: 8805
n6:
interface_name: demo-n6
interface_name: enp1s0f1np1
n9:
interface_name: demo-oai
interface_name: enp1s0f1np1
port: 2152
udm:
host: oai-udm
host: openxg-udm
sbi:
port: 8080
port: 8004
api_version: v1
interface_name: eth0
udr:
host: oai-udr
host: openxg-udr
sbi:
port: 8080
port: 8005
api_version: v1
interface_name: eth0
ausf:
host: oai-ausf
host: openxg-ausf
sbi:
port: 8080
port: 8006
api_version: v1
interface_name: eth0
nrf:
host: oai-nrf
host: openxg-nrf
sbi:
port: 8080
port: 8007
api_version: v1
interface_name: eth0
#### Common for UDR and AMF
database:
host: mysql
user: test
host: 172.11.200.10
user: root
type: mysql
password: test
database_name: oai_db
password: 123456
database_name: OpenXG-DB
generate_random: true
connection_timeout: 300 # seconds
......@@ -119,130 +101,139 @@ snssais:
- &embb_slice2
sst: 1
sd: 000001 # in hex
- &custom_slice
sst: 222
sd: 00007B # in hex
############## NF-specific configuration
nrf:
nrf_name: "OpenXG-NRF"
udr:
udr_name: "OpenXG-UDR"
udm:
udm_name: "OpenXG-UDM"
ausf:
ausf_name: "OpenXG-AUSF"
amf:
pid_directory: "/var/run"
amf_name: "OAI-AMF"
amf_name: "OpenXG-AMF"
# This really depends on if we want to keep the "mini" version or not
support_features_options:
enable_simple_scenario: no
enable_simple_scenario: no # "no" by default with the normal deployment scenarios with AMF/SMF/UPF/AUSF/UDM/UDR/NRF.
# set it to "yes" to use with the minimalist deployment scenario (including only AMF/SMF/UPF) by using the internal AUSF/UDM implemented inside AMF.
# There's no NRF in this scenario, SMF info is taken from "nfs" section.
enable_nssf: no
enable_smf_selection: yes
use_external_udm: no
relative_capacity: 30
statistics_timer_interval: 20 #in seconds
statistics_timer_interval: 20 # in seconds
emergency_support: false
served_guami_list:
- mcc: 208
mnc: 95
amf_region_id: 128
amf_set_id: 1
amf_pointer: 1
- mcc: 460
mnc: 11
amf_region_id: 10
amf_set_id: 1
amf_pointer: 1
- mcc: 466
mnc: 92
amf_region_id: 01
amf_set_id: 001
amf_pointer: 01
- mcc: 001
mnc: 01
amf_region_id: 01
amf_set_id: 001
amf_pointer: 01
plmn_support_list:
- mcc: 208
mnc: 95
tac: 0xa000
- mcc: 466
mnc: 92
tac: 0x0064
nssai:
- sst: 1
- sst: 1
sd: 000001
- sst: 222
sd: 00007B
- *embb_slice1
- *embb_slice2
supported_integrity_algorithms:
- "NIA0"
- "NIA1"
- "NIA2"
- "NIA1"
- "NIA0"
supported_encryption_algorithms:
- "NEA0"
- "NEA1"
- "NEA2"
smf:
smf_name: "OpenXG-SMF"
ue_mtu: 1500
support_features:
use_local_subscription_info: yes # Use infos from local_subscription_info or from UDM
use_local_pcc_rules: yes # Use infos from local_pcc_rules or from PCF
# we resolve from NRF, this is just to configure usage_reporting
upfs:
# - host: oai-spgwu
- host: oai-upf
- host: openxg-upf
config:
enable_usage_reporting: no
ue_dns:
primary_ipv4: "172.21.3.100"
primary_ipv4: "114.114.114.114"
primary_ipv6: "2001:4860:4860::8888"
secondary_ipv4: "8.8.8.8"
secondary_ipv6: "2001:4860:4860::8888"
ims:
pcscf_ipv4: "127.0.0.1"
pcscf_ipv6: "fe80::7915:f408:1787:db8b"
# the DNN you configure here should be configured in "dnns"
# the DNN you configure here should be configured in "dnns"
# follows the SmfInfo datatype from 3GPP TS 29.510
smf_info:
sNssaiSmfInfoList:
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "ctnet"
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "internet"
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "default"
local_subscription_infos:
- single_nssai:
sst: 1
dnn: "oai"
- single_nssai: *embb_slice1
dnn: "ctnet"
qos_profile:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
- single_nssai:
sst: 1
sd: 1
dnn: "oai.ipv4"
session_ambr_ul: "100Gbps"
session_ambr_dl: "100Gbps"
- single_nssai: *embb_slice1
dnn: "internet"
qos_profile:
5qi: 9
session_ambr_ul: "100Mbps"
session_ambr_dl: "200Mbps"
- single_nssai:
sst: 222
sd: 123
session_ambr_ul: "100Gbps"
session_ambr_dl: "100Gbps"
- single_nssai: *embb_slice1
dnn: "default"
qos_profile:
5qi: 9
session_ambr_ul: "50Mbps"
session_ambr_dl: "100Mbps"
session_ambr_ul: "100Gbps"
session_ambr_dl: "100Gbps"
upf:
upf_name: "OpenXG-UPF"
support_features:
enable_bpf_datapath: yes # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_qos: yes # Only supported for BPF datapath. If "on" we use qdiscs to manage the QoS
#qdisc_scheduler: "htb" # This value is used only in case QoS is enabled
enable_bpf_datapath: yes # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_qos: yes
enable_snat: no # If "on": Source natting is done for UE, DEFAULT= off
remote_n6_gw: oai-ext-dn
remote_n6_gw: remote_n6 # Dummy host since simple-switch does not use N6 GW
smfs:
- host: oai-smf # To be used for PFCP association in case of no-NRF
- host: openxg-smf # To be used for PFCP association in case of no-NRF
upf_info:
sNssaiUpfInfoList:
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "oai"
- sNssai: *embb_slice2
- dnn: "ctnet"
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "oai.ipv4"
- sNssai: *custom_slice
- dnn: "internet"
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "default"
## DNN configuration
dnns:
- dnn: "oai"
pdu_session_type: "IPV4"
- dnn: "ctnet"
pdu_session_type: "IPV4V6"
ipv4_subnet: "12.1.1.0/24"
- dnn: "oai.ipv4"
- dnn: "internet"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.2.0/24"
ipv4_subnet: "12.1.1.0/24"
- dnn: "default"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.3.0/24"
ipv4_subnet: "12.1.1.0/26"
- dnn: "ims"
pdu_session_type: "IPV4V6"
ipv4_subnet: "14.1.1.2/24"
#!/bin/sh
sudo ip link set dev demo-n3 xdp off
sudo ip link set dev demo-n6 xdp off
sudo ip link set dev enp1s0f0np0 xdp off
sudo ip link set dev enp1s0f1np1 xdp off
......@@ -257,7 +257,7 @@ void SessionManager::processPDRs(
}
if (!qer) {
Logger::upf_n4().error(
Logger::upf_n4().debug(
"QER not found for PDR: " + std::to_string(pdr->pdr_id.rule_id));
}
......@@ -581,7 +581,7 @@ void SessionManager::updateBPFSessionDL(
seidul, fteid.teid, INTERFACE_VALUE_CORE,
ueIpAddress.ipv4_address.s_addr, pFar, pSession->qers, true, teid_ul);
} else {
Logger::upf_app().error("Uplink TEID not found for session: 0x%x", seidul);
Logger::upf_app().debug("Uplink TEID not found for session: 0x%x", seidul);
SessionProgramManager::getInstance().createPipeline(
seidul, fteid.teid, INTERFACE_VALUE_CORE,
ueIpAddress.ipv4_address.s_addr, pFar, pSession->qers, true, 0);
......
......@@ -192,21 +192,46 @@ void SessionProgramManager::storeFARInFARMap(
/*---------------------------------------------------------------------------------------------------------------*/
// Function to update ARP table with remoteN6 IP and MAC address
// void SessionProgramManager::updateARPTableForN6(
// std::shared_ptr<FARProgram> pFARProgram, uint32_t dnIP, uint32_t upfn6IP) {
// try {
// // uint32_t remoteN6 = getRemoteIP(upfn6IP, dnIP);
// uint32_t ipnexremoteN6hop = (is_little_endian()) ?
// htole32(getRemoteIP(upfn6IP, dnIP)) :
// getRemoteIP(upfn6IP, dnIP);
// auto remoteN6MAC = NextHopFinder::retrieveNextHopMAC(ipnexremoteN6hop);
// struct s_arp_mapping map_table;
// memset(&map_table, 0, sizeof(struct s_arp_mapping));
// memcpy(map_table.mac_address, remoteN6MAC->ether_addr_octet, 6);
// map_table.ipv4_address = ipnexremoteN6hop;
// pFARProgram->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(
std::shared_ptr<FARProgram> pFARProgram, uint32_t dnIP, uint32_t upfn6IP) {
try {
// uint32_t remoteN6 = getRemoteIP(upfn6IP, dnIP);
uint32_t ipnexremoteN6hop = (is_little_endian()) ?
htole32(getRemoteIP(upfn6IP, dnIP)) :
getRemoteIP(upfn6IP, dnIP);
auto remoteN6MAC = NextHopFinder::retrieveNextHopMAC(ipnexremoteN6hop);
struct s_arp_mapping map_table;
memset(&map_table, 0, sizeof(struct s_arp_mapping));
memcpy(map_table.mac_address, remoteN6MAC->ether_addr_octet, 6);
map_table.ipv4_address = ipnexremoteN6hop;
pFARProgram->getArpTableMap()->update(upfn6IP, map_table, BPF_ANY);
std::string remoteDN = "192.168.20.100";
uint32_t remoteN6IPv4 = inet_addr(remoteDN.c_str());
//const char* remoteN6MAC = "6c:b3:11:29:5a:87";
uint8_t remoteN6MAC[6] = {0x6c, 0xb3, 0x11, 0x29, 0x5a, 0x87};
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;
pFARProgram->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");
......@@ -216,34 +241,71 @@ void SessionProgramManager::updateARPTableForN6(
/*---------------------------------------------------------------------------------------------------------------*/
// Function to update ARP table with remoteN3 IP and MAC address
// void SessionProgramManager::updateARPTableForN3(
// std::shared_ptr<FARProgram> pFARProgram, uint32_t gNodeBIP,
// uint32_t upfn3IP, uint64_t seid) {
// try {
// // uint32_t remoteN3 = getRemoteIP(upfn3IP, gNodeBIP);
// uint32_t ipnexremoteN3hop = (is_little_endian()) ?
// htole32(getRemoteIP(upfn3IP, gNodeBIP)) :
// getRemoteIP(upfn3IP, gNodeBIP);
// auto remoteN3MAC = NextHopFinder::retrieveNextHopMAC(ipnexremoteN3hop);
// struct s_arp_mapping map_table;
// memset(&map_table, 0, sizeof(struct s_arp_mapping));
// memcpy(map_table.mac_address, remoteN3MAC->ether_addr_octet, 6);
// map_table.ipv4_address = ipnexremoteN3hop;
// pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
// for (auto it = farPrograms->begin(); it != farPrograms->end(); ++it) {
// // Access the members of the 'farprograms' struct
// uint64_t savedSeid = it->seid;
// std::shared_ptr<FARProgram> pFARProgram = it->pFARProgram;
// if (savedSeid == seid) {
// pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
// }
// }
// } catch (const std::exception& ex) {
// // Handle the exception here or log it for debugging
// // Note: It's better to handle exceptions rather than ignoring them.
// Logger::upf_app().error(
// "Error: The ARP table was not updated for N3 Next HOP");
// }
// }
void SessionProgramManager::updateARPTableForN3(
std::shared_ptr<FARProgram> pFARProgram, uint32_t gNodeBIP,
uint32_t upfn3IP, uint64_t seid) {
uint32_t upfn3IP, uint32_t seid) {
try {
// uint32_t remoteN3 = getRemoteIP(upfn3IP, gNodeBIP);
uint32_t ipnexremoteN3hop = (is_little_endian()) ?
htole32(getRemoteIP(upfn3IP, gNodeBIP)) :
getRemoteIP(upfn3IP, gNodeBIP);
auto remoteN3MAC = NextHopFinder::retrieveNextHopMAC(ipnexremoteN3hop);
struct s_arp_mapping map_table;
memset(&map_table, 0, sizeof(struct s_arp_mapping));
memcpy(map_table.mac_address, remoteN3MAC->ether_addr_octet, 6);
map_table.ipv4_address = ipnexremoteN3hop;
pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
for (auto it = farPrograms->begin(); it != farPrograms->end(); ++it) {
// Access the members of the 'farprograms' struct
uint64_t savedSeid = it->seid;
std::shared_ptr<FARProgram> pFARProgram = it->pFARProgram;
if (savedSeid == seid) {
pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
std::string remoteGnB = "192.168.10.100";
uint32_t remoteN3IPv4 = inet_addr(remoteGnB.c_str());
//const char* remoteN3MAC = "6c:b3:11:29:5a:86";
uint8_t remoteN3MAC[6] = {0x6c, 0xb3, 0x11, 0x29, 0x5a, 0x86};
Logger::upf_app().warn(
"updateARPTableForN3 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, remoteN3MAC, 6);
map_table.ipv4_address = remoteN3IPv4;
pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
for (auto it = farPrograms->begin(); it != farPrograms->end(); ++it) {
// Access the members of the 'farprograms' struct
uint64_t savedSeid = it->seid;
std::shared_ptr<FARProgram> pFARProgram = it->pFARProgram;
if (savedSeid == seid) {
pFARProgram->getArpTableMap()->update(upfn3IP, map_table, BPF_ANY);
}
}
}
} catch (const std::exception& ex) {
} catch (const std::exception& ex) {
// Handle the exception here or log it for debugging
// Note: It's better to handle exceptions rather than ignoring them.
Logger::upf_app().error(
......
......@@ -151,7 +151,7 @@ class SessionProgramManager {
/*---------------------------------------------------------------------------------------------------------------*/
void updateARPTableForN3(
std::shared_ptr<FARProgram> pFARProgram, uint32_t gNodeBIP,
uint32_t upfn3IP, uint64_t seid);
uint32_t upfn3IP, uint32_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
uint32_t getGnodebIp(std::shared_ptr<pfcp::pfcp_far> pFar);
......
......@@ -208,7 +208,7 @@ create_outer_header_gtpu_ipv4(struct xdp_md* ctx, pfcp_far_t_* p_far) {
/*****************************************************************************************************************/
SEC("xdp")
int far_entry_point(struct xdp_md* ctx) {
bpf_debug("================< FAR Sesction >================");
bpf_debug("================< FAR Sesction >================");
void* data = (void*) (long) ctx->data;
void* data_end = (void*) (long) ctx->data_end;
......
......@@ -70,6 +70,8 @@ handle_downlink_traffic(struct xdp_md* ctx, u32 ue_ip_address) {
bpf_debug(
"TEID downlink: 0x%x was found for UE IP: 0x%x", ue_ip_address,
*teid_dl);
int ifindex = 3;
return bpf_redirect(ifindex, 0);
tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, ue_ip_address);
}
......@@ -195,7 +197,6 @@ static __always_inline u32 eth_handle(struct xdp_md* ctx, struct ethhdr* ethh) {
u64 offset = sizeof(*ethh);
bpf_debug("Debug: eth_type:0x%x", eth_type);
switch (eth_type) {
case ETH_P_IP: {
struct iphdr* iph = (struct iphdr*) ((void*) ethh + offset);
......@@ -226,8 +227,9 @@ static __always_inline u32 eth_handle(struct xdp_md* ctx, struct ethhdr* ethh) {
/*---------------------------------------------------------------------------------------------------------------*/
SEC("xdp")
int xdp_entry_point(struct xdp_md* ctx) {
int xdp_handle_uplink(struct xdp_md* ctx) {
bpf_debug("================< PFCP PDR Sesction >================");
struct ethhdr* ethh = (void*) (long) ctx->data;
if ((void*) (ethh + 1) > (void*) (long) ctx->data_end) {
......@@ -238,6 +240,44 @@ int xdp_entry_point(struct xdp_md* ctx) {
return eth_handle(ctx, ethh);
}
/*---------------------------------------------------------------------------------------------------------------*/
SEC("xdp")
int xdp_handle_downlink(struct xdp_md* ctx) {
bpf_debug("================< PFCP PDR Sesction >================");
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");
return XDP_DROP;
}
struct iphdr* iph = (struct iphdr*) ((void*) ethh + offset);
if ((void*) (iph + 1) > data_end) {
bpf_debug("Invalid IPv4 Packet");
return XDP_DROP;
}
u32 ip_dest = iph->daddr;
u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &ip_dest);
if (teid_dl) {
bpf_debug(
"TEID downlink: 0x%x was found for UE IP: 0x%x", ip_dest, *teid_dl);
int ifindex = 3;
return bpf_redirect(ifindex, 0);
tail_call_next_prog(ctx, *teid_dl, INTERFACE_VALUE_CORE, ip_dest);
}
bpf_debug("BPF tail call was not executed!");
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
/*---------------------------------------------------------------------------------------------------------------*/
\ No newline at end of file
......@@ -6,7 +6,7 @@
#include <bpf_helpers.h>
#define DEBUG 1
// #define DEBUG 1
#ifdef DEBUG
/* Only use this for debug output. Notice output from bpf_trace_printk()
* end-up in /sys/kernel/debug/tracing/trace_pipe
......
......@@ -45,11 +45,11 @@ void PFCP_Session_LookupProgram::setup() {
Logger::upf_app().debug(
"Link UDP interface to interface %s", mUDPInterface.c_str());
mpLifeCycle->link("xdp_entry_point", mUDPInterface.c_str());
mpLifeCycle->link("xdp_handle_downlink", mUDPInterface.c_str());
Logger::upf_app().debug(
"Link GTP interface to interface %s", mGTPInterface.c_str());
mpLifeCycle->link("xdp_entry_point", mGTPInterface.c_str());
mpLifeCycle->link("xdp_handle_uplink", mGTPInterface.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