Commit 4cf75961 authored by Tariro Mukute's avatar Tariro Mukute

Merge remote-tracking branch 'origin/develop' into chore_enable_disabling_of_bpf_logs

parents 2083e7cc 2edad4d5
......@@ -40,6 +40,15 @@ cppcheckResource = params.CppCheckResource
formatCheckNode = params.FormatCheckNode
formatCheckResource = params.FormatCheckResource
// Its main purpose is the ARM Neoverse-v2 Build
armBuildResource = params.armBuildResource
// Boolean param to control trivy scan
runTrivyScan = params.runTrivyScan
// Boolean param to control the run of "Pushing Image to Official Registry" stage (keep it false by default)
runDockerHubPushStage = false // Please set it to true when replaying a "PUSH" event Pipeline
// Tags/Branches to use
def upf_tag = "develop"
def upf_branch = "develop"
......@@ -76,7 +85,7 @@ pipeline {
gitLabConnection('OAI GitLab')
// Minimal checks
gitlabBuilds(builds: [
"Build Ubuntu UPF Image",
"Build Ubuntu ARM Neoverse V2 (Grace) Image",
"Build Ubuntu UPF Image with LTTNG",
"Build RHEL UPF Image",
"Static Code Analysis",
......@@ -153,12 +162,13 @@ pipeline {
}
stage('Build Core Network Function') {
parallel {
stage ('Build Ubuntu UPF Image') {
stage ('Build Ubuntu ARM Neoverse V2 (Grace) Image') {
steps {
// Now it is only locked during this build stage and not for the whole pipeline
lock(ubuntuBuildResource) {
lock(armBuildResource) {
script {
gitlabCommitStatus(name: "Build Ubuntu UPF Image") {
gitlabCommitStatus(name: "Build Ubuntu ARM Neoverse V2 (Grace) Image") {
sh "docker image rm oai-upf:${upf_tag} || true"
sh "docker image prune --force"
if ("PUSH".equals(env.gitlabActionType)) {
......@@ -168,21 +178,35 @@ pipeline {
dockerBuildOptions = ''
sh "date --rfc-email > src/common-src/date.txt"
}
sh "docker buildx build ${dockerBuildOptions} --target oai-upf --tag oai-upf:${upf_tag} --file docker/Dockerfile.upf.ubuntu . > archives/upf_ubuntu_image_build.log 2>&1"
// Putting a place holder to try out on the flattening of image.
// If not satisfactory, we can remove it.
sh "python3 ./ci-scripts/flatten_image.py --tag oai-upf:${upf_tag}"
sh "docker image prune --force"
sh "docker image ls | egrep --color=never 'upf|REPOSITORY' >> archives/upf_ubuntu_image_build.log"
// Pushing to local private registry for testing purpose
sh "docker login -u oaicicd -p oaicicd ${PrivateRegistryURL}"
sh "docker image tag oai-upf:${upf_tag} ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker push ${PrivateRegistryURL}/oai-upf:${upf_tag}"
// Remove all images locally
sh "docker rmi oai-upf:${upf_tag} ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker buildx build ${dockerBuildOptions} \
--target oai-upf \
--tag ${PrivateRegistryURL}/oai-upf:${upf_tag} \
--platform linux/amd64,linux/arm64 \
--build-arg GIT_COMMIT=\"${shortenShaOne}\" \
--file docker/Dockerfile.upf.ubuntu \
--builder multiarch-localremote-builder \
--progress=plain \
--push . > archives/upf_ubuntu_image_build.log 2>&1"
sh "docker image prune --force"
sh "docker rmi ${PrivateRegistryURL}/oai-upf:${upf_tag} || true"
sh "docker pull ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker image inspect ${PrivateRegistryURL}/oai-upf:${upf_tag} | jq '.[0] | {RepoTags, Labels: .Config.Labels, DockerVersion}' >> archives/upf_ubuntu_image_build.log 2>&1"
sh "docker images ${PrivateRegistryURL}/oai-upf:${upf_tag} >> archives/upf_ubuntu_image_build.log 2>&1"
// Run the trivy scan only if the boolean variable runTrivyScan is True
if (runTrivyScan) {
sh "docker rmi oai-upf:${shortenShaOne} || true"
sh "docker image tag ${PrivateRegistryURL}/oai-upf:${upf_tag} oai-upf:${shortenShaOne}"
sh "trivy image --exit-code 1 --severity MEDIUM,HIGH,CRITICAL --no-progress --format=template --template @./ci-scripts/common/html-templates/trivy_html.tpl --output archives/upf_multiarch_image_trivy_report.html oai-upf:${shortenShaOne} > /dev/null || true"
sh "docker rmi oai-upf:${shortenShaOne} || true"
}
sh "docker rmi ${PrivateRegistryURL}/oai-upf:${upf_tag} || true"
sh "docker logout ${PrivateRegistryURL}"
sh "bash ./ci-scripts/common/bash/extract_arm_amd_logs.sh archives/upf_ubuntu_image_build.log"
}
}
}
}
}
post {
......@@ -521,17 +545,16 @@ pipeline {
lock(ubuntuBuildResource) {
script {
// Only in case of push to target branch!
if ("PUSH".equals(env.gitlabActionType)) {
if ("PUSH".equals(env.gitlabActionType) || runDockerHubPushStage) {
withCredentials([
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.DockerHubCredentials}", usernameVariable: 'DH_Username', passwordVariable: 'DH_Password']
]) {
sh "echo ${DH_Password} | docker login --username ${DH_Username} --password-stdin"
}
sh "docker login -u oaicicd -p oaicicd ${PrivateRegistryURL}"
sh "docker pull ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker image tag ${PrivateRegistryURL}/oai-upf:${upf_tag} ${DH_Account}/oai-upf:develop"
sh "docker push ${DH_Account}/oai-upf:develop"
sh "docker rmi ${DH_Account}/oai-upf:develop ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker rmi ${PrivateRegistryURL}/oai-upf:${upf_tag} || true"
sh "docker buildx imagetools create -t ${DH_Account}/oai-upf:develop ${PrivateRegistryURL}/oai-upf:${upf_tag}"
sh "docker rmi ${DH_Account}/oai-upf:develop ${PrivateRegistryURL}/oai-upf:${upf_tag} || true"
sh "docker logout ${PrivateRegistryURL}"
sh "docker logout"
}
......@@ -579,7 +602,11 @@ pipeline {
}
// Zipping all archived log files
sh "zip -r -qq docker_logs.zip archives"
if (fileExists('archives/upf_multiarch_image_trivy_report.html'))
{
archiveArtifacts artifacts: 'archives/upf_multiarch_image_trivy_report.html'
}
sh "zip -r -qq docker_logs.zip archives -x archives/upf_multiarch_image_trivy_report.html"
if (fileExists('docker_logs.zip')) {
archiveArtifacts artifacts: 'docker_logs.zip'
}
......
common @ 3407df4f
Subproject commit 382e158f4ba0c40db45d271692ce3f6b6f3b5018
Subproject commit 3407df4f295246ab12718488745d7923c4023f43
......@@ -30,7 +30,7 @@
# BASE IMAGE
#---------------------------------------------------------------------
ARG BASE_IMAGE=ubuntu:jammy
FROM $BASE_IMAGE as oai-upf-base
FROM $BASE_IMAGE AS oai-upf-base
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
......@@ -63,7 +63,7 @@ RUN ./build_upf --install-deps --force
#---------------------------------------------------------------------
# BUILDER IMAGE
#---------------------------------------------------------------------
FROM oai-upf-base as oai-upf-builder
FROM oai-upf-base AS oai-upf-builder
# Copy the rest of source code
COPY . /openair-upf
# Building UPF
......@@ -89,7 +89,7 @@ RUN if [ "$ENABLE_LTTNG" = "true" ]; then apt-get update && \
#---------------------------------------------------------------------
# TARGET IMAGE
#---------------------------------------------------------------------
FROM $BASE_IMAGE as oai-upf
FROM $BASE_IMAGE AS oai-upf
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
ARG ENABLE_LTTNG=false
......@@ -135,7 +135,9 @@ WORKDIR /openair-upf/bin
COPY --from=oai-upf-builder \
/usr/local/sbin/bpftool \
/openair-upf/build/upf/build/oai_upf \
/openair-upf/build/upf/build/upf_app/bpf/CMakeFiles/qer_tc.dir/rules/qer/qer_tc_kernel.c.o \
/openair-upf/scripts/healthcheck.sh \
/openair-upf/scripts/entrypoint.sh \
./
WORKDIR /usr/local/lib
......@@ -168,6 +170,15 @@ WORKDIR /openair-upf
LABEL support-multi-sgwu-instances="true"
LABEL support-nrf-fdqn="true"
ARG GIT_COMMIT
LABEL org.opencontainers.image.authors="OpenAirInterface <contact@openairinterface.org>" \
org.opencontainers.image.vendor="OpenAirInterface Software Alliance" \
org.opencontainers.image.licenses="OAI Public License, Version 1.1" \
org.opencontainers.image.title="OAI UPF" \
org.opencontainers.image.description="OpenAirInterface User Plane Function" \
org.opencontainers.image.revision="commit:${GIT_COMMIT}"
# expose ports
EXPOSE 2152/udp 8805/udp 5342 5343 5344
# healthcheck
......@@ -177,3 +188,5 @@ HEALTHCHECK --interval=10s \
CMD /openair-upf/bin/healthcheck.sh
CMD ["/openair-upf/bin/oai_upf", "-c", "/openair-upf/etc/config.yaml", "-o"]
ENTRYPOINT [ "sh", "/openair-upf/bin/entrypoint.sh" ]
\ No newline at end of file
......@@ -22,9 +22,12 @@
# OAI CN Configuration File
### This file can be used by all OAI 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,7 +38,7 @@ log_level:
# If you enable registration, the other NFs will use the NRF discovery mechanism
register_nf:
general: yes
http_version: 2
############## SBI Interfaces
......@@ -74,7 +77,7 @@ nfs:
n6:
interface_name: demo-n6
n9:
interface_name: demo-oai
interface_name: demo-n9
port: 2152
udm:
host: oai-udm
......@@ -100,6 +103,12 @@ nfs:
port: 8080
api_version: v1
interface_name: eth0
pcf:
host: oai-pcf
sbi:
port: 8080
api_version: v1
interface_name: eth0
#### Common for UDR and AMF
database:
......@@ -125,41 +134,39 @@ snssais:
############## NF-specific configuration
amf:
pid_directory: "/var/run"
amf_name: "OAI-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
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
nssai:
- sst: 1
- sst: 1
sd: 000001
- sst: 222
sd: 00007B
- *embb_slice1
- *embb_slice2
- *custom_slice
supported_integrity_algorithms:
- "NIA0"
- "NIA1"
- "NIA0"
- "NIA2"
supported_encryption_algorithms:
- "NEA0"
......@@ -169,14 +176,14 @@ amf:
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
use_local_subscription_info: no # Use infos from local_subscription_info or from UDM
use_local_pcc_rules: no # 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: 192.168.70.129
config:
enable_usage_reporting: no
enable_qers: no
ue_dns:
primary_ipv4: "172.21.3.100"
primary_ipv6: "2001:4860:4860::8888"
......@@ -185,26 +192,33 @@ smf:
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: "oai"
- sNssai: *embb_slice2
dnnSmfInfoList:
- dnn: "oai.ipv4"
- sNssai: *custom_slice
dnnSmfInfoList:
- dnn: "default"
local_subscription_infos:
- single_nssai:
sst: 1
- single_nssai: *embb_slice1
dnn: "oai"
qos_profile:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
- single_nssai:
sst: 1
sd: 1
- single_nssai: *embb_slice2
dnn: "oai.ipv4"
qos_profile:
5qi: 9
session_ambr_ul: "100Mbps"
session_ambr_dl: "200Mbps"
- single_nssai:
sst: 222
sd: 123
- single_nssai: *custom_slice
dnn: "default"
qos_profile:
5qi: 9
......@@ -213,12 +227,9 @@ smf:
upf:
support_features:
enable_bpf_datapath: yes # If "yes": BPF is used as datapath else simpleswitch is used, DEFAULT= no
enable_qos: no # Only supported for BPF datapath. If "yes" we use qdisc to manage the QoS
enable_snat: no # If "no": Source natting is done for UE, DEFAULT= no
enable_bpf_datapath: yes # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_qos: yes
remote_n6_gw: oai-ext-dn
smfs:
- host: oai-smf # To be used for PFCP association in case of no-NRF
upf_info:
sNssaiUpfInfoList:
- sNssai: *embb_slice1
......@@ -235,13 +246,20 @@ upf:
dnns:
- dnn: "oai"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.1.0/24"
ipv4_subnet: "12.1.1.128/25"
- dnn: "oai.ipv4"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.2.0/24"
ipv4_subnet: "12.1.1.64/26"
- 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"
pcf:
local_policy:
policy_decisions_path: /openair-pcf/policies/policy_decisions
pcc_rules_path: /openair-pcf/policies/pcc_rules
traffic_rules_path: /openair-pcf/policies/traffic_rules
qos_data_path: /openair-pcf/policies/qos_data
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
# OAI UPF EBPF MAP SIZES Configuration File
###
# This configuration file defines key parameters for optimizing memory allocation and tuning the User Plane Function (UPF). The values set in this file directly impact the size of eBPF maps used for packet processing.
# Configuration Parameters. Each parameter in this file controls a specific aspect of UPF behavior.
# 1. Network Interface Limits
# max_upf_interfaces (Default: 8)
# Specifies the maximum number of network interfaces that UPF can manage.
# Example: Physical/virtual interfaces for GTP-U traffic.
# max_upf_redirect_interfaces (Default: 4)
# Defines the maximum number of interfaces used for traffic redirection.
# Example: Used in PDRs for forwarding packets to specific egress interfaces.
max_upf_interfaces = 8
max_upf_redirect_interfaces = 4
# 2. Session and Rule Limits
# max_pdu_session (Default: 10,000)
# Determines the maximum number of concurrent PDU sessions that UPF can handle.
# Affects the memory allocation for session-related eBPF maps.
# max_pdrs_per_pdu_session (Default: 8)
# Defines the maximum number of Packet Detection Rules (PDRs) that can be applied per PDU session.
# PDRs dictate how packets are processed, forwarded, or dropped.
# max_qos_flows_per_pdu_session (Default: 8)
# Sets the maximum number of QoS flows that a single PDU session can manage.
# Impacts QoS-related eBPF maps (e.g., shaping, policing).
# max_sdf_filters_per_pdu_session (Default: 8)
# Specifies the maximum number of Service Data Flow (SDF) filters per session.
# SDF filters define how traffic is classified within a QoS flow.
max_pdu_session = 10000
max_pdrs_per_pdu_session = 8
max_qos_flows_per_pdu_session = 8
max_sdf_filters_per_pdu_session = 8
# 3. ARP Table Limit
# max_arp_entries (Default: 4)
# Limits the number of ARP table entries stored in eBPF maps.
# Used for resolving MAC addresses in the UPF forwarding path.
max_arp_entries = 1572
# Usage Instructions
# Modify Configuration Values
# Edit the file ebpf_maps.conf to adjust UPF parameters based on deployment needs.
# Example:
# max_pdu_session = 5000
# max_pdrs_per_pdu_session = 16
# Loading the Configuration in Code
# A configuration parser (e.g., ConfigLoader) should read this file and apply the values at runtime.
# Example (C++):
# ConfigLoader config;
# config.loadConfig("upf_config.conf");
# int max_pdu_sessions = config.getValue("max_pdu_session", 10000);
# Memory Optimization
# Ensure the values are optimized to avoid excessive memory usage.
# Example: Reducing max_pdu_session decreases memory footprint.
# Best Practices
# Monitor Resource Usage: Adjust values based on system memory and performance requirements.
# Tune PDU Session Limits: Increase max_pdu_session if handling high session loads.
# Optimize QoS Handling: Set appropriate values for max_qos_flows_per_pdu_session based on traffic characteristics.
#!/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
#!/bin/sh
# Mount bpffs and debugfs if not present already
if [ $(/bin/mount | /bin/grep /sys/fs/bpf -c) -eq 0 ]; then
/bin/mount bpffs /sys/fs/bpf -t bpf;
fi
if [ $(/bin/mount | /bin/grep debugfs -c) -eq 0 ]; then
/bin/mount debugfs /sys/kernel/debug -t debugfs;
fi
exec "$@"
#!/bin/bash
set -eo pipefail
STATUS=0
SGW_PORT_FOR_N3=2152
SGW_PORT_FOR_SX=8805
SGW_IP_N3_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_N3 | grep inet | awk {'print $2'})
SGW_IP_SX_INTERFACE=$(ifconfig $SGW_INTERFACE_NAME_FOR_SX | grep inet | awk {'print $2'})
if [[ ${ENABLE_BPF_DATAPATH} == "no" ]]; then
N3_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_N3_INTERFACE:$SGW_PORT_FOR_N3")
fi
SX_PORT_STATUS=$(netstat -unpl | grep -o "$SGW_IP_SX_INTERFACE:$SGW_PORT_FOR_SX")
#Check if entrypoint properly configured the conf file and no parameter is unset (optional)
NB_UNREPLACED_AT=`cat /openair-upf/etc/*.conf | grep -v contact@openairinterface.org | grep -c @ || true`
if [ $NB_UNREPLACED_AT -ne 0 ]; then
STATUS=1
echo "Healthcheck error: UNHEALTHY configuration file is not configured properly"
fi
if [[ ${ENABLE_BPF_DATAPATH} == "no" ]]; then
if [[ -z $N3_PORT_STATUS ]]; then
STATUS=1
echo "Healthcheck error: UNHEALTHY N3 port $SGW_PORT_FOR_N3 is not listening."
fi
fi
if [[ -z $SX_PORT_STATUS ]]; then
STATUS=1
echo "Healthcheck error: UNHEALTHY SX port $SGW_PORT_FOR_SX is not listening."
fi
exit $STATUS
######################################################################################################
# Function to check if BPF datapath is enabled
######################################################################################################
check_enable_bpf_datapath() {
enable_bpf_datapath=$(cat /openair-upf/etc/*.yaml | grep "enable_bpf_datapath:" | awk '{print $2}')
# Check if bpf_datapath is set to yes
if [ "$enable_bpf_datapath" == "yes" ]; then
return 0 # BPF Datapath is enabled
else
return 1 # BPF Datapath is not enabled
fi
}
######################################################################################################
# Function to check if BPF QoS enforcement datapath is enabled
######################################################################################################
check_enable_qos() {
enable_qos=$(cat /openair-upf/etc/*.yaml | grep -A 3 "upf:" | grep "enable_qos:" | awk '{print $2}')
# Check if enable_qos is set to yes
if [[ "$enable_qos" == "yes" ]]; then
return 0 # QoS is enabled
else
return 1 # QoS is not enabled
fi
}
######################################################################################################
# Function to retrieve interface from config file
######################################################################################################
get_interface_name() {
local reference_point=$1
# Extract the interface name for the given reference point (n3, n4, n6, etc.) under UPF
interface_name=$(cat /openair-upf/etc/*.yaml | grep -A 16 "upf:" | awk -v ref="$reference_point:" '
$0 ~ ref {found=1}
found && /interface_name:/ {print $2; exit}
')
if [[ -z "$interface_name" ]]; then
echo "Error: interface_name not found for reference point $reference_point."
return 1
fi
echo "$interface_name"
}
######################################################################################################
# Function to check if the configuration file is properly set
######################################################################################################
check_configuration_file() {
NB_UNREPLACED_AT=$(cat /openair-upf/etc/*.yaml | grep -v contact@openairinterface.org | grep -c @ || true)
if [ $NB_UNREPLACED_AT -ne 0 ]; then
echo "Healthcheck error: UNHEALTHY configuration file is not configured properly"
return 1
fi
}
######################################################################################################
# Function to check if the N3 XDP program <xdp_handle_uplink> properly attached
######################################################################################################
check_n3_xdp_program() {
local interface_name="$1"
# Retrieve the XDP program ID associated with the n3 interface
XDP_PROGRAM_ID=$(ip link show dev $interface_name | grep -oP 'prog/xdp id \K\d+')
if [[ -z "$XDP_PROGRAM_ID" ]]; then
echo "Healthcheck error: XDP program ID not found for $interface_name interface."
return 1
fi
# Retrieve the program name associated with the XDP program ID from bpftool
XDP_PROGRAM_NAME=$(/openair-upf/bin/bpftool prog list | grep -w "$XDP_PROGRAM_ID" | awk '{print $4}')
if [[ -z "$XDP_PROGRAM_NAME" ]]; then
echo "Healthcheck error: XDP program name not found for $interface_name interface."
return 1
fi
if [[ "$XDP_PROGRAM_NAME" == "xdp_handle_uplink" ]]; then
echo "xdp_handle_uplink program is correctly linked to $interface_name interface."
else
echo "Healthcheck error: xdp_handle_uplink program not linked to $interface_name interface. Found $XDP_PROGRAM_NAME instead."
return 1
fi
}
######################################################################################################
# Function to check if the N6 XDP program <xdp_handle_downlink> or <xdp_handle_shaping> properly attached
######################################################################################################
check_n6_xdp_program() {
local interface_name="$1"
# Retrieve the XDP program ID associated with the n6 interface
XDP_PROGRAM_ID=$(ip link show dev $interface_name | grep -oP 'prog/xdp id \K\d+')
if [[ -z "$XDP_PROGRAM_ID" ]]; then
echo "Healthcheck error: XDP program ID not found for $interface_name interface."
return 1
fi
# Retrieve the program name associated with the XDP program ID from bpftool
XDP_PROGRAM_NAME=$(/openair-upf/bin/bpftool prog list | grep -w "$XDP_PROGRAM_ID" | awk '{print $4}')
if [[ -z "$XDP_PROGRAM_NAME" ]]; then
echo "Healthcheck error: XDP program name not found for interface_name interface."
return 1
fi
# Check if QoS is enabled
if check_enable_qos; then
# If QoS is enabled, check if the program name is xdp_handle_shaping
if [[ "$XDP_PROGRAM_NAME" == "xdp_handle_shaping" ]]; then
echo "xdp_handle_shaping program is correctly linked to $interface_name interface."
else
echo "Healthcheck error: xdp_handle_shaping program not linked to $interface_name interface. Found $XDP_PROGRAM_NAME instead."
return 1
fi
else
# If QoS is not enabled, check if the program name is xdp_handle_downlink
if [[ "$XDP_PROGRAM_NAME" == "xdp_handle_downlink" ]]; then
echo "xdp_handle_downlink program is correctly linked to $interface_name interface."
else
echo "Healthcheck error: xdp_handle_downlink program not linked to $interface_name interface. Found $XDP_PROGRAM_NAME instead."
return 1
fi
fi
}
######################################################################################################
# Function to check port status
######################################################################################################
check_port_status() {
local interface_name=$1
local port=$2
local ip_interface=$(ifconfig $interface_name | grep inet | awk '{print $2}')
if [[ -z "$ip_interface" ]]; then
echo "Error: Could not retrieve IP address for interface $interface_name."
return 1
fi
# Check if the port is listening on the specified IP interface
if netstat -unpl | grep -q "$ip_interface:$port"; then
echo "Port $port is listening on $ip_interface."
return 0
else
echo "Port $port is NOT listening on $ip_interface."
return 1
fi
}
######################################################################################################
# Main healthcheck function
######################################################################################################
main() {
STATUS=0
N4_PORT=8805
echo "Retrieving interface names..."
N3_INTERFACE=$(get_interface_name "n3")
echo "N3_INTERFACE: $N3_INTERFACE"
N4_INTERFACE=$(get_interface_name "n4")
echo "N4_INTERFACE: $N4_INTERFACE"
N6_INTERFACE=$(get_interface_name "n6")
echo "N6_INTERFACE: $N6_INTERFACE"
if check_configuration_file; then
echo "Configuration file is OK."
if check_enable_bpf_datapath; then
echo "BPF Datapath is enabled."
echo "Checking N3 XDP program..."
check_n3_xdp_program "$N3_INTERFACE"
if [ $? -ne 0 ]; then
STATUS=1
fi
echo "Checking N6 XDP program..."
check_n6_xdp_program "$N6_INTERFACE"
if [ $? -ne 0 ]; then
STATUS=1
fi
echo "Checking N4 Port Status..."
check_port_status "$N4_INTERFACE" "$N4_PORT"
if [ $? -ne 0 ]; then
STATUS=1
fi
else
echo "TODO: Add checking for SPGW-Tiny"
fi
else
echo "Configuration file check failed."
STATUS=1
fi
echo "Final Status: $STATUS"
exit $STATUS
}
######################################################################################################
# Run the main function
######################################################################################################
main
......@@ -157,7 +157,7 @@ set(CMAKE_C_FLAGS
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP"
)
set(CMAKE_C_FLAGS "-Wno-unused-function -Wno-error -Wno-return-type")
set(CMAKE_C_FLAGS "-Wno-unused-function -Wno-error -Wno-return-type -Wno-empty-body")
# set a flag for changes in the source code
# these changes are related to hardcoded path to include .h files
......@@ -357,8 +357,7 @@ target_link_libraries (upf
UDP
GTPV1U
PFCP
far_xdp
pfcp_session_pdr_lookup_xdp
#far_xdp
pfcp_session_lookup_xdp
qer_tc
UPF_XDP
......
......@@ -45,6 +45,8 @@
#include <SessionProgramManager.h>
#include <UserPlaneComponent.h>
#include "helpers/ConfigLoader.hpp"
using namespace oai::upf::app;
using namespace oai::config;
using namespace oai::utils;
......@@ -116,13 +118,10 @@ 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());
Logger::upf_app().info("UDP interface: %s", sUDPInterface.c_str());
Logger::upf_app().info("Non-GTP interface: %s", sUDPInterface.c_str());
UserPlaneComponent::getInstance().setup(sGTPInterface, sUDPInterface);
......@@ -134,11 +133,23 @@ void setup_bpf() {
//------------------------------------------------------------------------------
int main(int argc, char** argv) {
// Command line options
// std::string configPath =
// "/home/messaoudi/workspace/project-oai-qos/oai-cn5g-upf/etc/"
// "ebpf_maps.conf";
if (!Options::parse(argc, argv)) {
std::cout << "Options::parse() failed" << std::endl;
return 1;
}
// if (!ConfigLoader::getInstance().loadConfig(configPath)) {
// std::cerr << "Failed to load ebpf map sizes config file" << std::endl;
// return 1; // Exit if config fails
// }
// printFileContents(configPath);
// Logger
// Config
std::string conf_file_name = Options::getlibconfigConfig();
......@@ -213,7 +224,9 @@ int main(int argc, char** argv) {
fflush(fp);
fclose(fp);
if (upf_cfg.enable_bpf_datapath) {
const bool isBpfAccelerationEnabled = upf_cfg.enable_bpf_datapath;
if (isBpfAccelerationEnabled) {
setup_bpf();
}
// once all udp servers initialized
......
......@@ -26,15 +26,12 @@ include_directories(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/common_model.cmake)
include_directories(${SRC_TOP_DIR}/upf_app/bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/include)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/pdr)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/urr)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/bar)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/mar)
##############################################################
# FAR #
##############################################################
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/far)
include_directories(${LibNL_INCLUDE_DIR})
# include_directories(${LibNL_INCLUDE_DIR})
include_directories(${SRC_TOP_DIR}/upf_app/app)
set(GTP_INTERFACE $ENV{GTP_INTERFACE})
......@@ -47,12 +44,12 @@ add_library(UPF_XDP STATIC
SignalHandler.cpp
helpers/NextHopFinder.cpp
helpers/CmdRunner.cpp
helpers/SdfFilterParser.cpp
SessionProgramManager.cpp
SessionManager.cpp
SessionPrograms.cpp
programs/pfcp_session_pdr_lookup_xdp_user.cpp
programs/pfcp_session_lookup_xdp_user.cpp
programs/far_xdp_user.cpp
#programs/far_xdp_user.cpp
programs/BPFProgram.cpp
wrappers/BPFMaps.cpp
wrappers/BPFMap.cpp
......@@ -92,17 +89,16 @@ install(
##############################################################
# QER #
##############################################################
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibNL.cmake)
# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibNL.cmake)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/qer)
add_library(UPF_TC STATIC
#NetlinkManager.cpp
UserPlaneComponent.cpp
Configuration.cpp
SignalHandler.cpp
helpers/NextHopFinder.cpp
helpers/SdfFilterParser.cpp
helpers/GetNicInformation.cpp
#helpers/QdiscHelpers.cpp
SessionProgramManager.cpp
SessionManager.cpp
SessionPrograms.cpp
......@@ -115,13 +111,9 @@ install(
target_link_libraries(UPF_TC
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../build/ext/libbpf/src/libbpf.a
${CMAKE_CURRENT_SOURCE_DIR}/../../build/ext/libbpf/src/libbpf.so.1
# PUBLIC upfutils
# PRIVATE spdlog
PRIVATE elf
PRIVATE z
#/usr/lib/x86_64-linux-gnu/libnl-3.so
libnl-3.so
#/usr/lib/x86_64-linux-gnu/libnl-route-3.so
libnl-route-3.so
)
......@@ -134,7 +126,7 @@ install(
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/programs>
)
add_dependencies(UPF_TC upf_tc_all)
add_dependencies(UPF_TC upf_xdp_all)
install(
TARGETS UPF_TC
......@@ -145,12 +137,3 @@ install(
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
# Headers:
# * ./*.h -> <prefix>/include/*.h
# install(
# DIRECTORY "./"
# DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
# FILES_MATCHING PATTERN "*.h"
# )
This diff is collapsed.
......@@ -25,189 +25,97 @@ class BPFMap;
// class PacketDetectionRules;
class SessionBpf;
// FIXME: This class compose the UserPlaneComponent. When the program is
// deleted, this class must be updated.
// TODO: SessionRequestHandler? SessionMessageHandler?
// TODO: Decouple PDR and FAR management.
/**
* @brief This class abstracts the communication to manager the session BPF
* maps. It communicate with BPF maps in order to update its PDRs and FARs. This
* class does not validate the input.
*/
class SessionManager {
public:
// Set of PDRs.
// using pdrs_t = std::vector<std::shared_ptr<PacketDetectionRules>>;
/*---------------------------------------------------------------------------------------------------------------*/
enum class Direction { Uplink, Downlink };
/**
* @brief Construct a new Session Manager object.
*
*/
public:
SessionManager();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Destroy the Session Manager object.
*
*/
virtual ~SessionManager();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Create a Session object in BPF map.
*
* @param pSession The session object to be created.
*/
void createSession(std::shared_ptr<SessionBpf> pSession);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Remove a session object from BPF map.
*
* @param seid The session endpoint identifier representing the session to be
* removed.
*/
void removeSession(uint64_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Creates BPF pipeline.
*
* @param pSession The PFCP session which contains the context that will be
* deployed.
*/
void createBPFSession(
void createBpfSession(
std::shared_ptr<pfcp::pfcp_session> pSession,
itti_n4_session_establishment_request* est_req,
itti_n4_session_modification_request* mod_req,
itti_n4_session_deletion_request* del_req);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Update a Session object in BPF map.
*
* @param pSession The session object to be updated.
*/
void updateBPFSession(
void updateBpfSession(
std::shared_ptr<pfcp::pfcp_session> pSession,
itti_n4_session_establishment_request* est_req,
itti_n4_session_modification_request* mod_req,
itti_n4_session_deletion_request* del_req);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Remove BPF pipeline.
*
* @param seid The PFCP session which contains the context that will be
* removed.
*/
void removeBPFSession(
void modifyBpfSession(
std::shared_ptr<pfcp::pfcp_session> session,
itti_n4_session_establishment_request* est_req,
itti_n4_session_modification_request* mod_req,
itti_n4_session_deletion_request* del_req);
void removeBpfSession(
std::shared_ptr<pfcp::pfcp_session> pSession,
itti_n4_session_establishment_request* est_req,
itti_n4_session_modification_request* mod_req,
itti_n4_session_deletion_request* del_req);
/*---------------------------------------------------------------------------------------------------------------*/
void createBPFSessionUL(
std::shared_ptr<pfcp::pfcp_session> pSession,
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedenceUl);
/*---------------------------------------------------------------------------------------------------------------*/
void createBPFSessionDL(
std::shared_ptr<pfcp::pfcp_session> pSession,
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedenceDl);
/*---------------------------------------------------------------------------------------------------------------*/
void updateBPFSessionUL(
std::shared_ptr<pfcp::pfcp_session> pSession,
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedenceUl);
/*---------------------------------------------------------------------------------------------------------------*/
void updateBPFSessionDL(
std::shared_ptr<pfcp::pfcp_session> pSession,
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedenceDl);
/*****************************************************************************************************************/
void processPDRDetails(
std::shared_ptr<pfcp::pfcp_session> pSession,
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedence, int interfaceValue,
const std::string& direction);
/*****************************************************************************************************************/
/**
* @brief Process PDRs to populate uplink and downlink vectors
* @param std::shared_ptr<pfcp::pfcp_session>
*/
void processPDRs(std::shared_ptr<pfcp::pfcp_session> pSession_establishment);
/*****************************************************************************************************************/
/**
* @brief Sort uplink and downlink vectors
* @param std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs_uplink
* @param std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs_downlink
*/
void sortPDRs(
std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs_uplink,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs_downlink);
/*****************************************************************************************************************/
/**
* @brief Create BPF session for specific direction
* @param std::shared_ptr<pfcp::pfcp_session> pSession_establishment
* @param std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs
* @param const std::string& direction
*/
void createSessionDirection(
std::shared_ptr<pfcp::pfcp_session> pSession_establishment,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs,
const std::string& direction);
std::shared_ptr<pfcp::pfcp_pdr> pdrHighPrecedence);
/*****************************************************************************************************************/
bool extractPdi(std::shared_ptr<pfcp::pfcp_pdr> pdr, pfcp::pdi& pdi);
void processPDRs(std::shared_ptr<pfcp::pfcp_session> pSession_establishment);
/*****************************************************************************************************************/
bool extractSourceIface(
pfcp::pdi& pdi, pfcp::source_interface_t& sourceInterface);
void sortPDRs(std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdr);
/*****************************************************************************************************************/
bool extractUeIpv4(pfcp::pdi& pdi, pfcp::ue_ip_address_t& ueIpAddress);
void prepareEbpfSession(
std::shared_ptr<pfcp::pfcp_session> pSession_establishment,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs);
/*---------------------------------------------------------------------------------------------------------------*/
bool extractFar(
std::shared_ptr<pfcp::pfcp_pdr> pdr,
bool getFar(
std::shared_ptr<pfcp::pfcp_session> session,
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_far>& outFar);
/*---------------------------------------------------------------------------------------------------------------*/
bool extractQer(
std::shared_ptr<pfcp::pfcp_pdr> pdr,
bool getQer(
std::shared_ptr<pfcp::pfcp_session> session,
std::vector<std::shared_ptr<pfcp::pfcp_qer>>* outQer);
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_qer>& outQer);
/*---------------------------------------------------------------------------------------------------------------*/
bool extractForwardingParams(
std::shared_ptr<pfcp::pfcp_far> far,
pfcp::forwarding_parameters& forwardingParams);
uint32_t retrieveTeid(std::shared_ptr<pfcp::pfcp_session> session);
/*---------------------------------------------------------------------------------------------------------------*/
uint64_t findUplinkTeid(
uint64_t seid,
const std::vector<std::shared_ptr<pfcp::pfcp_session>>& sessions);
/*---------------------------------------------------------------------------------------------------------------*/
static bool comparePDR(
const std::shared_ptr<pfcp::pfcp_pdr>& first,
const std::shared_ptr<pfcp::pfcp_pdr>& second);
void categorizePDRs(std::shared_ptr<pfcp::pfcp_session> session);
std::shared_ptr<pfcp::pfcp_qer> findQER(
std::shared_ptr<pfcp::pfcp_session> session, uint32_t qer_id);
void setupEbpfPipeline(
std::shared_ptr<pfcp::pfcp_session> session,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>>& pdrs, Direction direction);
std::vector<std::shared_ptr<pfcp::pfcp_session>> sessions;
/*---------------------------------------------------------------------------------------------------------------*/
std::unordered_map<uint64_t, std::shared_ptr<pfcp::pfcp_session>>
mSeidToSession;
};
......
This diff is collapsed.
......@@ -6,197 +6,119 @@
#include <map>
#include <pfcp_far.hpp>
#include <pfcp_qer.hpp>
#include "pfcp_pdr.hpp"
#include <array>
#include <pfcp/pfcp_far.h>
#include <pfcp/pfcp_pdr.h>
#include <pfcp/pfcp_qer.h>
#include <next_prog_rule_key.h>
#include <session_id.h>
#include <netinet/ether.h>
class BPFMap;
class OnStateChangeSessionProgramObserver;
class PFCP_Session_LookupProgram;
class PFCP_Session_PDR_LookupProgram;
class SessionPrograms;
class FARProgram;
/**
* @brief This class is used to manager the PFCP Sesssion (eBPF bytecode) in
* kernel space. It store all the BPFProgram that was loaded on the datapath.
*
*/
struct farprograms {
struct pfcpprograms {
uint64_t seid;
std::shared_ptr<FARProgram> pFARProgram;
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram;
};
struct pduSessionInfo {
uint32_t teid_ul;
uint32_t teid_dl;
uint32_t ueIP;
};
class SessionProgramManager {
public:
/**
* @brief Destroy the Session Program Manager object.
*
*/
virtual ~SessionProgramManager();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the Instance object.
*
* @return SessionProgramManager& The unique instance.
*/
static SessionProgramManager& getInstance();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Set the Programs Map object.
*
* @param pProgramsMaps The programs wrapper for BPF map.
*/
void setTeidSessionMap(std::shared_ptr<BPFMap> pProgramsMaps);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Create a new program related to the SEID.
* The context will be empty.
*
* @param seid The session identifier.
*/
void create(uint64_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
void remove(uint64_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Remove all programs.
*
*/
void removeAll();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Set the On New Session Observer object.
*
* @param pObserver The observer which will be notified when a
* PFCP_Session_PDR_LookupProgram is created.
*/
void setOnNewSessionObserver(OnStateChangeSessionProgramObserver* pObserver);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Find the Session Program object.
*
* @param seid The session identifier.
* @return std::shared_ptr<PFCP_Session_PDR_LookupProgram> The program, which
* represents the session.
*/
std::shared_ptr<PFCP_Session_PDR_LookupProgram> findSessionProgram(
uint64_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
void addFarProgram(uint64_t seid, std::shared_ptr<FARProgram> pFARProgram);
/*---------------------------------------------------------------------------------------------------------------*/
void updateArpTableMap(
std::shared_ptr<FARProgram> pFARProgram, uint32_t upfIP,
uint32_t remoteIP);
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram,
uint32_t upfIP, uint32_t remoteIP);
uint32_t getRemoteIP(uint32_t upfIP, uint32_t remoteIP);
/*---------------------------------------------------------------------------------------------------------------*/
pfcp_far_t_ createFar(std::shared_ptr<pfcp::pfcp_far> pFar);
/*---------------------------------------------------------------------------------------------------------------*/
pfcp_pdr_t_ createPdr(std::shared_ptr<pfcp::pfcp_pdr> pPdr);
pfcp_qer_t_ createQer(std::shared_ptr<pfcp::pfcp_qer> pQer);
void createPipeline(std::shared_ptr<pfcp::pfcp_session> session);
void modifyPipeline(
std::shared_ptr<pfcp::pfcp_session> session, uint32_t teid);
void modifyPipeline(
std::shared_ptr<pfcp::pfcp_session> session, uint32_t teid_ul,
uint32_t teid_dl);
void addFramedRoutes(
uint32_t ueIpAddress,
const std::vector<pfcp::framed_route_t>& framedRoutes);
/*---------------------------------------------------------------------------------------------------------------*/
void removeFramedRoutes(
const std::vector<pfcp::framed_route_t>& framedRoutes);
/*---------------------------------------------------------------------------------------------------------------*/
void createPipeline(
uint64_t seid, uint32_t teid1, uint8_t sourceInterface,
uint32_t ueIpAddress, std::shared_ptr<pfcp::pfcp_far> pFar,
std::vector<std::shared_ptr<pfcp::pfcp_qer>> pQer,
std::vector<std::shared_ptr<pfcp::pfcp_pdr>> pdrs,
bool isModification = false, uint32_t teid2 = 0);
/*---------------------------------------------------------------------------------------------------------------*/
void initializeNextRuleProgIndexKey(
next_rule_prog_index_key& key, uint32_t teid, uint32_t ueIpAddress,
uint8_t sourceInterface);
/*---------------------------------------------------------------------------------------------------------------*/
void storeFarProgramIndexInNextProgRuleIndexMap(
std::shared_ptr<FARProgram> pFARProgram,
const next_rule_prog_index_key& key,
void addPFCPProgram(
uint64_t seid,
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram);
/*---------------------------------------------------------------------------------------------------------------*/
void storeSessionMappingMap(
void storePduSessionInMap(
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram,
uint32_t ue_ip_address, uint32_t teid_dl, uint32_t teid_ul,
uint32_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
uint64_t seid);
void storeFARInFARMap(
std::shared_ptr<FARProgram> pFARProgram,
std::shared_ptr<pfcp::pfcp_far> pFar);
/*---------------------------------------------------------------------------------------------------------------*/
void saveSeidWithinFARProgram(
uint64_t seid, std::shared_ptr<FARProgram> pFARProgram,
uint64_t seid,
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram,
const next_rule_prog_index_key& key);
/*---------------------------------------------------------------------------------------------------------------*/
void updateARPTableForN6(
std::shared_ptr<FARProgram> pFARProgram, uint32_t dnIP, uint32_t upfn6IP);
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram,
uint32_t dnIP, uint32_t upfn6IP);
void updateARPTableForN3(
std::shared_ptr<FARProgram> pFARProgram, uint32_t gNodeBIP,
uint32_t upfn3IP, uint64_t seid);
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram,
uint32_t gNodeBIP, uint32_t upfn3IP, uint32_t seid);
bool getFar(
std::shared_ptr<pfcp::pfcp_session> session,
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_far>& outFar);
bool getQer(
std::shared_ptr<pfcp::pfcp_session> session,
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_qer>& outQer);
uint32_t getGnodebIp(std::shared_ptr<pfcp::pfcp_far> pFar);
/*---------------------------------------------------------------------------------------------------------------*/
uint32_t retrieveGnbIp(std::shared_ptr<pfcp::pfcp_session> session);
uint32_t retrieveUeIp(std::shared_ptr<pfcp::pfcp_session> session);
void updatePipeline(
uint64_t seid, uint32_t teid, uint32_t gNBIpAddress, bool isModification);
/*---------------------------------------------------------------------------------------------------------------*/
void removePipeline(uint64_t seid);
std::shared_ptr<SessionPrograms> findSessionPrograms(uint64_t seid);
void sessionIds(
session_id& key, uint64_t seid, uint32_t teid_ul, uint32_t teid_dl);
// std::shared_ptr<vector><struct farprograms> farPrograms;
std::shared_ptr<std::vector<struct farprograms>> farPrograms;
std::shared_ptr<std::vector<struct pfcpprograms>> pfcpPrograms;
private:
/**
* @brief Construct a new Session Program Manager object.
*
*/
SessionProgramManager();
int32_t getEmptySlot();
std::shared_ptr<BPFMap> mpTeidSessionMap;
std::shared_ptr<BPFMap> mpUeIpSessionMap;
// The observer which will be notified when a PFCP_Session_PDR_LookupProgram
// is created.
OnStateChangeSessionProgramObserver* mpOnNewSessionProgramObserver;
// The Maps to store the instance of the programs.
std::map<uint32_t, std::shared_ptr<PFCP_Session_PDR_LookupProgram>>
mSessionProgramMap;
// The Maps to store the PFCP session deployed in datapath.
std::map<uint32_t, std::shared_ptr<SessionPrograms>> mSessionProgramsMap;
std::array<int64_t, 10> mProgramArray;
struct pduSessionInfo sessionInfo;
};
#endif // __SESSIONPROGRAMMANAGER_H__
#include "SessionPrograms.h"
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
SessionPrograms::SessionPrograms(
struct next_rule_prog_index_key key,
std::shared_ptr<FARProgram> pFARProgram)
: mKey(key), mpFARProgram(pFARProgram) {}
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram)
: mKey(key), mpPFCP_Session_LookupProgram(pPFCP_Session_LookupProgram) {}
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
SessionPrograms::~SessionPrograms() {
mpFARProgram->tearDown();
mpPFCP_Session_LookupProgram->tearDown();
}
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
struct next_rule_prog_index_key SessionPrograms::getKey() const {
return mKey;
}
/**************************************************************************************************/
std::shared_ptr<FARProgram> SessionPrograms::getFARProgram() const {
return mpFARProgram;
//---------------------------------------------------------------------------------------------------------------
std::shared_ptr<PFCP_Session_LookupProgram> SessionPrograms::getPFCPProgram()
const {
return mpPFCP_Session_LookupProgram;
}
/**************************************************************************************************/
......@@ -2,13 +2,13 @@
#define __SESSIONPROGRAMS_H__
#include <memory>
#include <far_xdp_user.h>
#include <pfcp_session_lookup_xdp_user.h>
#include <unistd.h>
#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.
*
*/
......@@ -16,13 +16,13 @@ class SessionPrograms {
public:
SessionPrograms(
struct next_rule_prog_index_key key,
std::shared_ptr<FARProgram> pFARProgram);
std::shared_ptr<PFCP_Session_LookupProgram> pPFCP_Session_LookupProgram);
virtual ~SessionPrograms();
struct next_rule_prog_index_key getKey() const;
std::shared_ptr<FARProgram> getFARProgram() const;
std::shared_ptr<PFCP_Session_LookupProgram> getPFCPProgram() const;
private:
std::shared_ptr<FARProgram> mpFARProgram;
std::shared_ptr<PFCP_Session_LookupProgram> mpPFCP_Session_LookupProgram;
struct next_rule_prog_index_key mKey;
};
......
#include "SignalHandler.h"
#include <UserPlaneComponent.h>
//---------------------------------------------------------------------------------------------------------------
void my_app_signal_handler(int s);
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
SignalHandler& SignalHandler::getInstance() {
static SignalHandler sInstance;
return sInstance;
}
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
SignalHandler::~SignalHandler() {}
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
void SignalHandler::enable() {
signal(SIGINT, SignalHandler::tearDown);
signal(SIGTERM, SignalHandler::tearDown);
signal(SIGSEGV, SignalHandler::tearDown);
}
/**************************************************************************************************/
//---------------------------------------------------------------------------------------------------------------
void SignalHandler::tearDown(int signal) {
UserPlaneComponent::getInstance().tearDown();
// calling the other tear down routine
my_app_signal_handler(signal);
exit(0);
}
/**************************************************************************************************/
#include "UserPlaneComponent.h"
//#include <RulesUtilities.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.
#ifdef DEBUG_LIBBPF
......@@ -16,56 +18,56 @@ UserPlaneComponent::UserPlaneComponent() {
#endif
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
UserPlaneComponent::~UserPlaneComponent() {
tearDown();
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
std::shared_ptr<SessionManager> UserPlaneComponent::getSessionManager() const {
return mpSessionManager;
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
std::shared_ptr<PFCP_Session_LookupProgram>
UserPlaneComponent::getPFCP_Session_LookupProgram() const {
return mpPFCP_Session_LookupProgram;
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
std::string UserPlaneComponent::getGTPInterface() const {
return mGTPInterface;
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
std::string UserPlaneComponent::getUDPInterface() const {
return mUDPInterface;
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
void UserPlaneComponent::onNewSessionProgram(
u_int32_t programId, u_int32_t fileDescriptor) {
mpPFCP_Session_LookupProgram->updateProgramMap(programId, fileDescriptor);
// mpPFCP_Session_LookupProgram->updateProgramMap(programId, fileDescriptor);
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
void UserPlaneComponent::onDestroySessionProgram(u_int32_t programId) {
mpPFCP_Session_LookupProgram->removeProgramMap(programId);
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
int UserPlaneComponent::printLibbpfLog(
enum libbpf_print_level lvl, const char* fmt, va_list args) {
return vfprintf(stderr, fmt, args);
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
UserPlaneComponent& UserPlaneComponent::getInstance() {
static UserPlaneComponent sInstance;
return sInstance;
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
void UserPlaneComponent::setMembers(
const std::string& gtpInterface, const std::string& udpInterface) {
mGTPInterface = gtpInterface;
......@@ -80,18 +82,21 @@ void UserPlaneComponent::setMembers(
}
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
void UserPlaneComponent::setup(
const std::string& gtpInterface, const std::string& udpInterface) {
const bool isQosEnabled = upf_cfg.enable_bpf_datapath && 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>();
}
/*---------------------------------------------------------------------------------------------------------------*/
//---------------------------------------------------------------------------------------------------------------
void UserPlaneComponent::tearDown() {
mpPFCP_Session_LookupProgram->tearDown();
SessionProgramManager::getInstance().removeAll();
......
......@@ -6,9 +6,6 @@ include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/include)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/pdr)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/far)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/qer)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/urr)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/bar)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/mar)
include_directories(${SRC_TOP_DIR}/upf_app/include)
include_directories(${SRC_TOP_DIR}/${MOUNTED_COMMON}/utils)
......@@ -20,8 +17,8 @@ if(DEFINED BPF_DEBUG)
endif()
endif()
add_custom_target(upf_xdp_all DEPENDS pfcp_session_lookup_xdp pfcp_session_pdr_lookup_xdp far_xdp)
add_custom_target(upf_tc_all DEPENDS qer_tc)
add_custom_target(upf_xdp_all DEPENDS pfcp_session_lookup_xdp)
# add_custom_target(upf_tc_all DEPENDS qer_tc)
......@@ -29,7 +26,7 @@ add_custom_target(upf_tc_all DEPENDS qer_tc)
# GENERATE eBPF XDP Skeletons #
###########################################################################
function(xdp arg)
if (${arg} STREQUAL "pfcp_session_lookup" OR ${arg} STREQUAL "pfcp_session_pdr_lookup")
if (${arg} STREQUAL "pfcp_session_lookup")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/pdr")
elseif (${arg} STREQUAL "far")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/far")
......@@ -49,8 +46,7 @@ function(xdp arg)
endfunction()
xdp(pfcp_session_lookup)
xdp(pfcp_session_pdr_lookup)
xdp(far)
#xdp(far)
......
#ifndef __GATE_STATUS_H__
#define __GATE_STATUS_H__
#include <types.h>
#include <ie/ie_base.h>
// 8.2.7 Gate Status
enum gate_status_e {
/* Request / Initial message */
OPEN = 0,
CLOSED = 1
};
typedef struct gate_status_s {
u8 ul_gate : 2;
u8 dl_gate : 2;
} gate_status_t;
#endif // __GATE_STATUS_H__
\ No newline at end of file
#if !defined(CREATE_QER_H)
#define CREATE_QER_H
#include <ie/ie_base.h>
#include <ie/qer_id.h>
#include <ie/qer_correlation_id.h>
#include <ie/gate_status.h>
#include <ie/guaranteed_bitrate.h>
#include <ie/maximum_bitrate.h>
#include <ie/qos_flow_identifier.h>
#include <ie/reflective_qos.h>
#include <ie/paging_policy_indicator.h>
//------------------------------------------------------------------------------
// Table 7.5.2.5-1: Create QER IE within PFCP Session Establishment Request
typedef struct create_qer_s {
qer_id_t_ qer_id;
qer_correlation_id_t qer_correlation_id;
gate_status_t gate_status;
mbr_t maximum_bitrate;
gbr_t guaranteed_bitrate;
qfi_t qos_flow_identifier;
rqi_t reflective_qos;
paging_policy_indicator_t paging_policy_indicator;
} create_qer_t;
#endif // CREATE_QER_H
#ifndef __GUARANTEED_BITRATE_H__
#define __GUARANTEED_BITRATE_H__
#include <types.h>
#include <ie/ie_base.h>
// 8.2.9 GBR
typedef struct gbr_s {
u64 ul_gbr;
u64 dl_gbr;
} gbr_t;
#endif // __GUARANTEED_BITRATE_H__
\ No newline at end of file
#ifndef __MAXIMUM_BITRATE_H__
#define __MAXIMUM_BITRATE_H__
#include <types.h>
#include <ie/ie_base.h>
// 8.2.8 MBR
typedef struct mbr_s {
u64 ul_mbr;
u64 dl_mbr;
} mbr_t;
#endif // __MAXIMUM_BITRATE_H__
\ No newline at end of file
#ifndef __PAGING_POLICY_INDICATOR_H__
#define __PAGING_POLICY_INDICATOR_H__
#include <types.h>
#include <ie/ie_base.h>
// 8.2.116 Paging Policy Indicator (PPI)
typedef struct paging_policy_indicator_s {
u8 spare : 4;
u8 ppi_value : 4;
} paging_policy_indicator_t;
#endif // __PAGING_POLICY_INDICATOR_H__
\ No newline at end of file
#ifndef __QER_CORRELATION_ID_H__
#define __QER_CORRELATION_ID_H__
#include <types.h>
#include <ie/ie_base.h>
//-------------------------------------
// 8.2.10 QER Correlation ID
typedef struct qer_correlation_id_s {
u32 qer_correlation_id;
} qer_correlation_id_t;
#endif // __QER_CORRELATION_ID_H__
\ No newline at end of file
#ifndef __QOS_FLOW_IDENTIFIER_H__
#define __QOS_FLOW_IDENTIFIER_H__
#include <types.h>
#include <ie/ie_base.h>
// 8.2.89 QFI
typedef struct qfi_s {
u8 spare : 2;
u8 qfi : 6;
// qfi_s() : qfi(0), spare(0) {}
// qfi_s(const u8& q) : qfi(q), spare(0) {}
// qfi_s(const struct qfi_s& q) : qfi(q.qfi), spare(q.spare) {}
// inline bool operator==(const struct qfi_s& rhs) const {
// return ((qfi == rhs.qfi) && (spare == rhs.spare));
// }
// inline bool operator!=(const struct qfi_s& rhs) const {
// return !((qfi == rhs.qfi) && (spare == rhs.spare));
// }
} qfi_t;
#endif // __QOS_FLOW_IDENTIFIER_H__
\ No newline at end of file
#ifndef __REFLECTIVE_QOS_H__
#define __REFLECTIVE_QOS_H__
#include <types.h>
#include <ie/ie_base.h>
/// 8.2.88 RQI
typedef struct rqi_s {
u8 spare : 7;
u8 rqi : 1;
} rqi_t;
#endif // __REFLECTIVE_QOS_H__
\ No newline at end of file
......@@ -4,6 +4,8 @@
#include <types.h>
#include <ie/ie_base.h>
#define MAX_FLOW_DESC_LEN 256 // Set a reasonable max length
//-------------------------------------
// 8.2.5 SDF Filter
typedef struct sdf_filter {
......@@ -16,10 +18,10 @@ typedef struct sdf_filter {
u8 fd : 1;
u16 length_of_flow_description;
// TODO It is a string based on length_of_flow_description. How to solve this?
u8 flow_description;
u8 tos_traffic_class[2]; // 2 octets
u8 security_parameter_index[4]; // 4 octets
u8 flow_label[3]; // 3 octets
char flow_description[MAX_FLOW_DESC_LEN];
char tos_traffic_class[2]; // 2 octets
char security_parameter_index[4]; // 4 octets
char flow_label[3]; // 3 octets
u32 sdf_filter_id;
} sdf_filter_t_;
......
......@@ -14,6 +14,5 @@ typedef struct pfcp_far_s {
forwarding_parameters_t_ forwarding_parameters;
duplicating_parameters_t_ duplicating_parameters;
bar_id_t_ bar_id;
} pfcp_far_t_;
#endif // __PFCP_FAR_H__
#ifndef __PFCP_QER_H__
#define __PFCP_QER_H__
#include <types.h>
#include <ie/group_ie/create_qer.h>
#include <ie/qer_id.h>
#include <ie/qer_correlation_id.h>
#include <ie/gate_status.h>
#include <ie/guaranteed_bitrate.h>
#include <ie/maximum_bitrate.h>
#include <ie/qos_flow_identifier.h>
#include <ie/reflective_qos.h>
#include <ie/paging_policy_indicator.h>
typedef struct pfcp_qer_s {
qer_id_t_ qer_id;
qer_correlation_id_t qer_correlation_id;
gate_status_t gate_status;
mbr_t maximum_bitrate;
gbr_t guaranteed_bitrate;
qfi_t qos_flow_identifier;
rqi_t reflective_qos;
paging_policy_indicator_t paging_policy_indicator;
} pfcp_qer_t_;
#endif // __PFCP_QER_H__
......@@ -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
......@@ -13,12 +13,12 @@
#define MAX_FAR_PROGRAMS 10000
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, FAR_TAILS_MAX);
__type(key, u8);
__type(value, pfcp_far_t_);
} m_far SEC(".maps");
// struct {
// __uint(type, BPF_MAP_TYPE_HASH);
// __uint(max_entries, FAR_TAILS_MAX);
// __type(key, u8);
// __type(value, pfcp_far_t_);
// } m_far SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
......@@ -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");
/*---------------------------------------------------------------------------------------------------------------*/
......
......@@ -212,8 +212,8 @@ int far_entry_point(struct xdp_md* ctx) {
void* data = (void*) (long) ctx->data;
void* data_end = (void*) (long) ctx->data_end;
u32 key = 0;
pfcp_far_t_* p_far = bpf_map_lookup_elem(&m_far, &key);
u32 key = 0;
pfcp_far_t_* p_far; //= bpf_map_lookup_elem(&m_far, &key);
if (p_far) {
struct ethhdr* ethh = data;
......@@ -275,24 +275,7 @@ int far_entry_point(struct xdp_md* ctx) {
} else if (dest_interface == INTERFACE_VALUE_ACCESS) {
create_outer_header_gtpu_ipv4(ctx, p_far);
uint32_t far_id_key = p_far->far_id.far_id;
uint32_t* enforcing_qos =
bpf_map_lookup_elem(&m_enforcing_qos, &far_id_key);
if (enforcing_qos) {
switch (*enforcing_qos) {
case 0: {
bpf_debug("The packet is redirected to N3 interface");
return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
}
case 1: {
bpf_debug("The packet is passed to tc layer");
return XDP_PASS;
}
default: {
}
}
}
return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
}
}
......
......@@ -3,60 +3,30 @@
#include <ie/group_ie/create_pdr.h>
#include <pfcp/pfcp_pdr.h>
#include <pfcp/pfcp_far.h>
#include <pfcp/pfcp_session.h>
#include <linux/bpf.h>
#include <stdint.h>
#include <ie/teid.h>
#include <next_prog_rule_map.h>
#include <next_prog_rule_key.h>
#include <rules_matching_pdr.h>
#include "interfaces.h"
#include "session_id.h"
#define MAX_LENGTH 10000
#define MAX_LENGTH 10000 // 10
#define INTERFACE_ENTRIES_MAX 12
#define MAX_UEs 10000
#define MAX_PDRS_PER_SESSION 32
#define MAX_SDF_FITLER_ENTRIES 1000
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(
type,
BPF_MAP_TYPE_PROG_ARRAY); //!< Must have the key and value with 4 bytes
__type(key, teid_t_); //!< program identifier.
__type(value, s32); //!< program which represents the session.
// TODO: Check how the management works. The size should be equal
// to the maximum number of sessions.
__uint(max_entries, MAX_LENGTH); // 10000, //!< TODO: Is it enought?
} m_teid_session SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(
type,
BPF_MAP_TYPE_PROG_ARRAY); //!< Must have the key and value with 4 bytes
__type(key, u32); //!< program identifier.
__type(value, s32); //!< program which represents the session.
// TODO Check how the management works. The size should be equal
// to the maximum number of sessions.
__uint(max_entries, MAX_UEs); //!< TODO: Is it enought?
} m_ueip_session SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_UEs);
__type(key, u32); //!< UE IP
__type(value, u32); //!< PDR
} m_ue_ip_pdr SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH); // 10,
__type(key, struct next_rule_prog_index_key);
__type(value, u32);
} m_next_rule_prog_index SEC(".maps");
__uint(max_entries, MAX_SDF_FITLER_ENTRIES);
__type(key, struct session_qfi); // <qfi, seid>
__type(value, struct sdf_filtr);
} m_sdf_filter SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, INTERFACE_ENTRIES_MAX);
......@@ -64,7 +34,6 @@ struct {
__type(value, struct s_interface);
} m_upf_interfaces SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH);
......@@ -72,8 +41,28 @@ struct {
__type(value, struct session_id); // < teid_ul, teid_dl, seid >
} m_session_mapping SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
/* Framed Routing */
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH);
__type(key, u64); // seid
__type(value, pfcp_pdr_t_[MAX_PDRS_PER_SESSION]);
} m_session_pdrs SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(
max_entries,
MAX_LENGTH); // max_rules = max_pdrs_per_pdu_session * max_pdu_session
__type(key, struct pdrs_per_session); // < pdr_id, seid >
__type(value, struct rules_match_pdr); // < FAR, QER, /* MAR, BAR, URR */ >
} m_rules_match_pdr SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH); // Store only one entry for the QoS flag
__type(key, u64); // seid
__type(value, u32); // Value type (0 for false, 1 for true)
} m_qos_enabling SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_HASH);
......
#ifndef __RULES_MATCHING_PDR_H__
#define __RULES_MATCHING_PDR_H__
#include <pfcp/pfcp_far.h>
#include <pfcp/pfcp_qer.h>
struct rules_match_pdr {
pfcp_far_t_ far;
pfcp_qer_t_ qer;
// TODO: add other RUles here !
};
struct pdrs_per_session {
uint16_t pdr_id;
uint64_t seid;
};
// struct sdfs_per_session {
// uint16_t qer_id;
// uint64_t seid;
// };
#endif // __RULES_MATCHING_PDR_H__
#ifndef __SDF_FILTER_H__
#define __SDF_FILTER_H__
#include <types.h>
//#include <linux/in.h>
//#include <linux/ip.h>
//#include <linux/ipv6.h>
//#include <linux/tcp.h>
//#include <linux/udp.h>
/*---------------------------------------------------------------------------------------------------------------*/
static inline uint16_t generate_minor_id(uint64_t seid, uint8_t qfi) {
uint16_t hash = (seid ^ (seid >> 16) ^ (seid >> 32) ^ (seid >> 48));
uint16_t minor_id =
(hash + (qfi * 37)) & 0xFFFF; // Avoid modulo, use bitmask
// Limit minor_id to a max of 9999
minor_id = (minor_id > 9999) ? 9999 : minor_id;
return minor_id ? minor_id : 1; // Ensure nonzero
}
/*---------------------------------------------------------------------------------------------------------------*/
struct ip_subnet {
u8 type;
/*
* 0: any, 1: ip4, 2: ip6
* If type != any, ip field has meaningful value.
* If IPv4 -> lower 32 bits. If IPv6 -> all 128 bits.
*/
u128 ip;
/*
* If type != any, mask field has meaningful value.
* If IPv4 mask -> lower 32 bits. If IPv6 mask -> all 128 bits.
* Should always be applied to matching ip (except type == any).
*/
u128 mask;
};
struct port_range {
__u16 lower_bound; // If not specified in SDF: 0
__u16 upper_bound; // If not specified in SDF: 65535
};
struct packet_filter {
u32 src_ip;
u32 dst_ip;
u16 protocol;
u16 src_port;
u16 dst_port;
// u32 tos;
} __attribute__((aligned(8)));
struct session_qfi {
u64 seid;
u8 qfi;
};
struct sdf_filtr {
u16 protocol;
struct ip_subnet src_addr;
struct port_range src_port;
struct ip_subnet dst_addr;
struct port_range dst_port;
struct session_qfi session;
};
#endif // __SDF_FILTER_H__
......@@ -7,7 +7,7 @@
struct session_id {
u32 teid_ul;
u32 teid_dl;
u32 seid;
u64 seid;
};
#endif // __SESSION_ID_H__
\ No newline at end of file
......@@ -5,7 +5,7 @@
#include <linux/bpf.h>
#include <types.h>
#define MAX_LENGTH 10000
#define MAX_LENGTH 10000 // 10
/*
* +------------------------------------------------------+
......@@ -19,12 +19,12 @@
* +--------------------------+---------------------------+
*/
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(max_entries, MAX_LENGTH);
__type(key, u32);
__type(value, s32);
} m_next_rule_prog SEC(".maps");
// struct {
// __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
// __uint(max_entries, MAX_LENGTH);
// __type(key, u32);
// __type(value, s32);
// } m_next_rule_prog SEC(".maps");
// BPF_ANNOTATE_KV_PAIR(m_next_rule_prog, u32, s32);
......
#ifndef __FILTER_KEY_H__
#define __FILTER_KEY_H__
#include <types.h>
struct filter_key {
u32 src_ip;
u32 dst_ip;
u8 protocol;
u16 dst_port;
u32 tos;
};
struct session_qfi {
u64 seid;
u8 qfi;
};
#endif // __FILTER_KEY_H__
......@@ -4,35 +4,35 @@
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include "filter_key.h"
#include "sdf_filter.h"
#include "qos_flow.h"
#define QFI_MAX_ENTRIES 10000
#define FIVE_QI_MAX_ENTRIES 100
//#define QFI_MAX_ENTRIES 10000
//#define FIVE_QI_MAX_ENTRIES 100
#define QOS_FLOWS_MAX_ENTRIES 10000
#define MAX_INTERFACES 10
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, QFI_MAX_ENTRIES); // 10,
__type(key, struct filter_key);
__type(value, struct session_qfi);
} m_sdf_filter SEC(".maps");
// struct {
// __uint(type, BPF_MAP_TYPE_HASH);
// __uint(max_entries, QOS_FLOWS_MAX_ENTRIES);
// __type(key, u32);
// __type(value, struct s_fiveQosFlow);
// } m_qos_flow SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, QOS_FLOWS_MAX_ENTRIES);
__type(key, u32);
__type(value, struct s_fiveQosFlow);
} m_qos_flow SEC(".maps");
// struct {
// __uint(type, BPF_MAP_TYPE_ARRAY);
// __uint(max_entries, 1);
// __type(key, u32);
// __type(value, u8);
// } m_default_qfi SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_DEVMAP);
__uint(max_entries, MAX_INTERFACES);
__type(key, u32);
__type(key, u32); // u8?
__type(value, u32);
} m_egress_ifindex SEC(".maps");
......
This diff is collapsed.
......@@ -4,27 +4,34 @@
#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_gbr {
// uint64_t ul_gbr;
// uint64_t dl_gbr;
// };
// struct s_fiveQosFlow {
// struct s_gate gate;
// struct s_mbr mbr;
// struct s_gbr gbr;
// uint64_t qfi;
// };
struct s_fiveQosFlow {
struct s_gate gate;
struct s_mbr mbr;
struct s_gbr gbr;
uint64_t qfi;
uint8_t gate;
uint64_t mbr;
uint64_t gbr;
uint8_t qfi;
};
#endif //__QOS_FLOW_H__
\ No newline at end of file
......@@ -192,8 +192,8 @@ static int pcn_l4_csum_replace(
}
ptr = (__sum16*) ((void*) (long) ctx->data + csum_offset);
bpf_debug("Here the value of csum_offset %x", (__sum16*) TCP_CSUM_OFFSET);
bpf_debug("Here the value of ptr %x", *ptr);
// bpf_debug("Here the value of csum_offset %x", (__sum16*) TCP_CSUM_OFFSET);
// bpf_debug("Here the value of ptr %x", *ptr);
if (is_mmzero && !do_mforce && !*ptr) return 0;
......
#ifndef CONFIG_LOADER_H
#define CONFIG_LOADER_H
#include <unordered_map>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class ConfigLoader {
public:
static ConfigLoader& getInstance() {
static ConfigLoader instance; // Singleton instance
return instance;
}
bool loadConfig(const std::string& filename) {
std::ifstream file(filename);
if (!file) {
std::cerr << "Error: Cannot open config file " << filename << std::endl;
return false;
}
std::string line;
while (std::getline(file, line)) {
std::istringstream is_line(line);
std::string key;
if (std::getline(is_line, key, '=')) {
std::string value;
if (std::getline(is_line, value)) {
config[key] = std::stoi(value);
}
}
}
file.close();
return true;
}
int getValue(const std::string& key, int default_value = 0) {
return (config.find(key) != config.end()) ? config[key] : default_value;
}
private:
ConfigLoader() {} // Private constructor
std::unordered_map<std::string, int> config;
};
#endif // CONFIG_LOADER_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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