Commit bbd25304 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge branch 'upf-merging-qos-and-n4-interoperability-brahcnes' into 'develop'

QoS and N4 interoperability branch

See merge request oai/cn5g/oai-cn5g-upf!36
parents 5954b5c6 55faf299
......@@ -24,6 +24,14 @@
# author Laurent Thomas, Lionel GAUTHIER
#
#######################################
GREEN='\033[0;32m' # ANSI color code for green
RED='\033[0;31m' # ANSI color code for red
YELLOW='\033[1;93m' # ANSI color code for brighten yellow
NC='\033[0m' # ANSI color code to reset to default
################################
# include helper functions
################################
......@@ -37,6 +45,7 @@ source $THIS_SCRIPT_PATH/../common-build/installation/build_helper.yamlcpp
source $THIS_SCRIPT_PATH/../common-build/installation/build_helper.nlohmann
source $THIS_SCRIPT_PATH/../common-build/installation/build_helper.cpr
CONFIG_FILE=$THIS_SCRIPT_PATH/../../etc/config.yaml
# Get the kernel version
KERNEL_VERSION=$(uname -r | cut -d'-' -f1,2 | cut -d'.' -f1,2)
# The validated kernel versions for bpf-tool are between 5.7 and 5.15
......@@ -54,9 +63,12 @@ elif [[ $MAJOR_VERSION -eq 5 ]]; then
fi
fi
#-------------------------------------------------------------------------------
install_libbpf_from_git() {
echo "Starting to install libbpf from source"
echo "Install libbpf from source"
echo ""
if [ $1 -eq 0 ]; then
read -p "Do you want to install libbpf ? <y/N> " prompt
OPTION=""
......@@ -109,7 +121,8 @@ install_libbpf_from_git() {
python3"
fi
$SUDO $INSTALLER install -y $PACKAGE_LIST
cd libbpf && git checkout 051a4009f94d5633a8f734ca4235f0a78ee90469
cd libbpf
#&& git checkout 051a4009f94d5633a8f734ca4235f0a78ee90469
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
cd src && make -j $(nproc)
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
......@@ -120,9 +133,46 @@ install_libbpf_from_git() {
return 0
}
#-------------------------------------------------------------------------------
check_enable_bpf_datapath() {
# Parse the YAML Config file and check if enable_bpf_datapath is set to yes
enable_bpf_datapath=$(grep -A 3 "upf:" $CONFIG_FILE | grep "enable_bpf_datapath:" | awk '{print $2}')
if [ "$enable_bpf_datapath" == "yes" ]; then
return 0
else
return 1
fi
}
#-------------------------------------------------------------------------------
check_enable_qos() {
# Parse the YAML Config file and check if enable_qos is set to yes
enable_qos=$(grep -A 3 "upf:" $CONFIG_FILE | grep "enable_qos:" | awk '{print $2}')
if [ "$enable_qos" == "yes" ]; then
return 0
else
return 1
fi
}
#-------------------------------------------------------------------------------
install_netlink_libraries() {
echo ""
echo "Install Netlink libraries:"
if [[ $OS_DISTRO == "ubuntu" ]]; then
$SUDO $INSTALLER install -y libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libnl-nf-3-dev
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
$SUDO $INSTALLER install -y libnl3-devel libnl3-cli
fi
}
#-------------------------------------------------------------------------------
install_bpftool_from_git() {
echo "Starting to install bpftool from source"
echo "Install bpftool from source"
if [ $1 -eq 0 ]; then
read -p "Do you want to install bpftool ? <y/N> " prompt
OPTION=""
......@@ -150,7 +200,9 @@ install_bpftool_from_git() {
if [[ $prompt =~ [yY](es)* ]]
then
#GIT_URL=https://github.com/libbpf/bpftool.git
GIT_URL=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-$KERNEL_VERSION.tar.gz
#GIT_URL=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-$KERNEL_VERSION.tar.gz
GIT_URL=https://github.com/libbpf/bpftool.git
echo "Install bpftool from $GIT_URL"
pushd $OPENAIRCN_DIR/build/ext
echo "Downloading bpftool"
......@@ -159,29 +211,36 @@ install_bpftool_from_git() {
$SUDO rm -rf bpftool
fi
git clone --branch v7.3.0 --recurse-submodules $GIT_URL
if [[ $OS_DISTRO == "ubuntu" ]]; then
$SUDO $INSTALLER install -y wget gcc-multilib
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
$SUDO $INSTALLER install -y wget
fi
# trick for CI
if [ ! -f $OPENAIRCN_DIR/build/ext/linux-$KERNEL_VERSION.tar.gz ]; then
wget -nv --tries=4 --retry-connrefused --wait=8 $GIT_URL
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
fi
ls -lst linux-$KERNEL_VERSION.tar.gz && tar -xf linux-$KERNEL_VERSION.tar.gz && rm -rf linux-$KERNEL_VERSION.tar.gz
#if [ ! -f $OPENAIRCN_DIR/build/ext/linux-$KERNEL_VERSION.tar.gz ]; then
# wget -nv --tries=4 --retry-connrefused --wait=8 $GIT_URL
# ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
#fi
#ls -lst linux-$KERNEL_VERSION.tar.gz && tar -xf linux-$KERNEL_VERSION.tar.gz && rm -rf linux-$KERNEL_VERSION.tar.gz
cd bpftool
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
cd linux-$KERNEL_VERSION/tools/bpf/bpftool && make -j $(nproc)
#cd linux-$KERNEL_VERSION/tools/bpf/bpftool && make -j $(nproc)
cd src && CLANG=Nope make -j $(nproc)
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
$SUDO make install
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
$SUDO rm -rf linux-$KERNEL_VERSION
#ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
#$SUDO rm -rf linux-$KERNEL_VERSION
popd
fi
echo "bpftool installation complete"
return 0
}
#-------------------------------------------------------------------------------
#arg1 is force (0 or 1) (no interactive script)
#arg2 is debug (0 or 1) (install debug libraries)
......@@ -295,12 +354,47 @@ check_install_upf_deps() {
ret=$?;[[ $ret -ne 0 ]] && return $ret
echo_info "distro libs installation complete"
echo ""
echo "Auto-detecting UPF features:"
check_enable_bpf_datapath
if [ $? -eq 0 ]; then
check_enable_qos
if [ $? -eq 0 ]; then
echo -e " BPF Datapath: [$GREEN on $NC ]"
echo -e " QoS Feature: [$GREEN on $NC ]"
echo ""
else
echo -e " BPF Datapath: [$GREEN on $NC ]"
echo -e " QoS Feature: [$RED off $NC ]"
echo ""
fi
else
echo -e " BPF Datapath: [$RED off $NC ]"
echo -e " QoS Feature: [$RED off $NC ]"
echo ""
fi
echo -e "$YELLOW WARNINGS: "
echo -e " 1. Even when "BPF Datapath" and/or "QoS Feature" are/is disabled"
echo -e " we still build and install BPF and Netlinks libraries."
echo -e " The purpose is to have one-time UPF build process with all these libs"
echo -e " built and linked to the project. Thie difference would be on the"
echo -e " execution path, which depends on enabling or disabling these features."
echo ""
echo -e " 2. The QoS Feature is only available for the BPF Datapath mode, "
echo -e " so not usable for the Simple Switch mode. This is due to the "
echo -e " use of eBPF TC programming for qdisc filtering and classifying. $NC"
echo ""
install_libbpf_from_git $1 $2
ret=$?;[[ $ret -ne 0 ]] && return $ret
echo ""
install_bpftool_from_git $1 $2
ret=$?;[[ $ret -ne 0 ]] && return $ret
echo ""
install_netlink_libraries $1 $2
ret=$?;[[ $ret -ne 0 ]] && return $ret
install_fb_folly_from_source $1 $2
ret=$?;[[ $ret -ne 0 ]] && return $ret
......
......@@ -96,11 +96,13 @@ RUN rm -f /etc/rhsm-host && \
net-tools \
ethtool \
iproute \
llvm-libs \
iptables \
initscripts \
libicu \
boost \
libevent \
libnl3 \
#libasan \
findutils \
libconfig && \
......@@ -128,7 +130,7 @@ COPY --from=oai-upf-builder \
/usr/local/lib64/libyaml-cpp.so.0.* \
/usr/local/lib64/libcpr.so.1 \
# libbpf seems to be in the executable now
/openair-upf/build/ext/libbpf/src/libbpf.so.0 \
/openair-upf/build/ext/libbpf/src/libbpf.so.1 \
/lib64/
RUN ldconfig && \
echo "ldd /openair-upf/bin/oai_upf" && \
......
......@@ -78,10 +78,12 @@ RUN microdnf update -y && \
ethtool \
iproute \
iptables \
llvm-libs \
initscripts \
libicu \
boost \
libevent \
libnl3 \
#libasan \
findutils \
libconfig && \
......@@ -106,7 +108,7 @@ COPY --from=oai-upf-builder \
/usr/local/lib64/libyaml-cpp.so.0.* \
/usr/local/lib64/libcpr.so.1 \
# libbpf seems to be in the executable now
/openair-upf/build/ext/libbpf/src/libbpf.so.0 \
/openair-upf/build/ext/libbpf/src/libbpf.so.1 \
/lib64/
RUN ldconfig && \
echo "ldd /openair-upf/bin/oai_upf" && \
......
......@@ -86,6 +86,9 @@ RUN apt-get update && \
iproute2 \
ethtool \
arping \
libllvm14 \
libnl-3-200 \
libnl-route-3-200 \
sudo \
iptables \
netbase \
......@@ -125,7 +128,7 @@ COPY --from=oai-upf-builder \
# Ubuntu 22 --> libbfd-2.38
/usr/lib/x86_64-linux-gnu/libbfd-2.3?-system.so \
/usr/lib/x86_64-linux-gnu/libopcodes-2.3?-system.so \
/openair-upf/build/ext/libbpf/src/libbpf.so.0 \
/openair-upf/build/ext/libbpf/src/libbpf.so.1 \
# /openair-upf/build/upf/build/upf_app/utils/libupfutils.so \
./
......
......@@ -213,7 +213,9 @@ smf:
upf:
support_features:
enable_bpf_datapath: yes # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_bpf_datapath: no # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_qos: no # 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_snat: no # If "on": Source natting is done for UE, DEFAULT= off
remote_n6_gw: oai-ext-dn
smfs:
......
......@@ -1521,7 +1521,7 @@ typedef struct graceful_release_period_s {
//-------------------------------------
// 8.2.79 PDN Type
enum pdu_session_type_value_e {
enum pdn_type_value_e {
/* Request / Initial message */
IPV4 = 1,
IPV6 = 2,
......@@ -1530,10 +1530,10 @@ enum pdu_session_type_value_e {
ETHERNET = 5
};
typedef struct pdu_session_type_s {
typedef struct pdn_type_s {
uint8_t spare : 5;
uint8_t pdu_session_type : 3;
} pdu_session_type_t;
uint8_t pdn_type : 3;
} pdn_type_t;
//-------------------------------------
// 8.2.80 Failed Rule ID
......
......@@ -259,6 +259,15 @@ find_package(Threads REQUIRED)
#CPR
find_package(cpr REQUIRED)
set(CMAKE_MODULE_PATH "${SRC_TOP_DIR}/upf_app/cmake" "${CMAKE_MODULE_PATH}")
include(FindPkgConfig)
find_package (LibNL REQUIRED)
include(${SRC_TOP_DIR}/upf_app/cmake/FindLibNL.cmake)
################################################################
# Add sub modules
################################################################
......@@ -292,6 +301,7 @@ include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/upf_app)
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/app)
include_directories(${SRC_TOP_DIR}/upf_app/interfaces)
include_directories(${SRC_TOP_DIR}/upf_app/simpleswitch)
......@@ -318,6 +328,7 @@ IF(STATIC_LINKING)
SET(ASAN asan)
ENDIF(STATIC_LINKING)
## Common modules
include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/config/config.cmake)
include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/http/http.cmake)
......@@ -326,22 +337,24 @@ include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/nrf/nrf_model.cmake)
include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/common_model/common_model.cmake)
include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/utils/utils.cmake)
# folly glog dl double-conversion for FB folly library
target_link_libraries (upf
${ASAN} -Wl,--start-group CN_UTILS
${SRC_TOP_DIR}/../build/ext/libbpf/src/libbpf.so
APP
SIMPLE_SWITCH
interfaces
UDP
GTPV1U
PFCP
far_ebpf_xdp
pfcp_session_pdr_lookup_ebpf_xdp
pfcp_session_lookup_ebpf_xdp
UPF_XDP
gflags glog dl double-conversion folly fmt spdlog -Wl,--end-group
pthread m rt config++
event boost_system curl yaml-cpp cpr::cpr
${ASAN} -Wl,--start-group CN_UTILS
${SRC_TOP_DIR}/../build/ext/libbpf/src/libbpf.so
APP
SIMPLE_SWITCH
interfaces
UDP
GTPV1U
PFCP
far_xdp
pfcp_session_pdr_lookup_xdp
pfcp_session_lookup_xdp
qer_tc
UPF_XDP
UPF_TC
gflags glog dl double-conversion folly fmt spdlog -Wl,--end-group
pthread m rt config++
event boost_system curl yaml-cpp cpr::cpr
)
......@@ -39,7 +39,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <RulesUtilitiesImpl.h>
//#include <RulesUtilitiesImpl.h>
#include <SessionManager.h>
#include <SessionProgramManager.h>
#include <UserPlaneComponent.h>
......@@ -58,11 +58,15 @@ bool single_teardown_call;
#ifndef N3_IF_NAME
#define N3_IF_NAME upf_cfg.n3.if_name
#endif
#endif // N3_IF_NAME
#ifndef N6_IF_NAME
#define N6_IF_NAME upf_cfg.n6.if_name
#endif
#endif // N6_IF_NAME
#ifndef HTB_SCHEDULER
#define HTB_SCHEDULER "htb"
#endif // HTB_SCHEDULER
std::unique_ptr<upf_config_yaml> upf_cfg_yaml = nullptr;
std::shared_ptr<oai::http::http_client> http_client_inst = nullptr;
......@@ -114,15 +118,15 @@ void my_app_signal_handler(int s) {
//------------------------------------------------------------------------------
void setup_bpf() {
std::shared_ptr<RulesUtilities> mpRulesFactory;
mpRulesFactory = std::make_shared<RulesUtilitiesImpl>();
// 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());
UserPlaneComponent::getInstance().setup(
mpRulesFactory, sGTPInterface, sUDPInterface);
UserPlaneComponent::getInstance().setup(sGTPInterface, sUDPInterface);
}
//------------------------------------------------------------------------------
......@@ -189,7 +193,9 @@ int main(int argc, char** argv) {
fflush(fp);
fclose(fp);
if (upf_cfg.enable_bpf_datapath) setup_bpf();
if (upf_cfg.enable_bpf_datapath) {
setup_bpf();
}
// once all udp servers initialized
io_service.run();
......
......@@ -670,12 +670,11 @@ pfcp_ie* pfcp_ie::new_pfcp_ie_from_stream(std::istream& is) {
// return ie;
// }
// break;
// case PFCP_IE_PDN_TYPE: {
// pfcp_pdn_type_ie *ie = new pfcp_pdn_type_ie(tlv);
// ie->load_from(is);
// return ie;
// }
// break;
case PFCP_IE_PDN_TYPE: {
pfcp_pdn_type_ie* ie = new pfcp_pdn_type_ie(tlv);
ie->load_from(is);
return ie;
} break;
case PFCP_IE_FAILED_RULE_ID: {
pfcp_failed_rule_id_ie* ie = new pfcp_failed_rule_id_ie(tlv);
ie->load_from(is);
......@@ -920,6 +919,11 @@ pfcp_ie* pfcp_ie::new_pfcp_ie_from_stream(std::istream& is) {
// pfcp_framed_ipv6_route_ie(tlv); ie->load_from(is); return ie;
// }
// break;
case PFCP_IE_APN_DNN: {
pfcp_apn_dnn_ie* ie = new pfcp_apn_dnn_ie(tlv);
ie->load_from(is);
return ie;
} break;
case PFCP_IE_3GPP_INTERFACE_TYPE: {
pfcp_3gpp_interface_type_ie* ie = new pfcp_3gpp_interface_type_ie(tlv);
ie->load_from(is);
......
......@@ -6536,8 +6536,10 @@ class pfcp_far_id_ie : public pfcp_ie {
s.set(v);
}
};
//-------------------------------------
// IE QER_ID
/*****************************************************************************************************************/
// 8.2.75 IE QER ID
/*****************************************************************************************************************/
class pfcp_qer_id_ie : public pfcp_ie {
public:
uint32_t qer_id;
......@@ -6579,7 +6581,10 @@ class pfcp_qer_id_ie : public pfcp_ie {
s.set(v);
}
};
////-------------------------------------
/*****************************************************************************************************************/
// 8.2.75 IE OCI_FLAGS
/*****************************************************************************************************************/
//// IE OCI_FLAGS
// class pfcp_oci_flags_ie : public pfcp_ie {
// public:
......@@ -6720,51 +6725,57 @@ class pfcp_qer_id_ie : public pfcp_ie {
// s.set(graceful_release_period);
// }
//};
////-------------------------------------
//// IE PDN_TYPE
// class pfcp_pdn_type_ie : public pfcp_ie {
// public:
// uint8_t todo;
//
// //--------
// pfcp_pdn_type_ie(const pfcp::pdn_type_t& b) : pfcp_ie(PFCP_IE_PDN_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_pdn_type_ie() : pfcp_ie(PFCP_IE_PDN_TYPE){
// todo = 0;
// tlv.set_length(1);
// }
// //--------
// pfcp_pdn_type_ie(const pfcp_tlv& t) : pfcp_ie(t) {
// todo = 0;
// };
// //--------
// void to_core_type(pfcp::pdn_type_t& b) {
// b.todo = todo;
// }
// //--------
// void dump_to(std::ostream& os) {
// tlv.dump_to(os);
// os.write(reinterpret_cast<const char*>(&todo), sizeof(todo));
// }
// //--------
// void load_from(std::istream& is) {
// //tlv.load_from(is);
// if (tlv.get_length() != 1) {
// throw pfcp_tlv_bad_length_exception(tlv.type, tlv.get_length(),
// __FILE__, __LINE__);
// }
// is.read(reinterpret_cast<char*>(&todo), sizeof(todo));
// }
// //--------
// void to_core_type(pfcp_ies_container& s) {
// pfcp::pdn_type_t pdn_type = {};
// to_core_type(pdn_type);
// s.set(pdn_type);
// }
//};
//-------------------------------------
// IE PDN_TYPE
class pfcp_pdn_type_ie : public pfcp_ie {
public:
union {
struct {
uint8_t pdn_type : 3;
uint8_t spare1 : 5;
} bf;
uint8_t b;
} u1;
//--------
pfcp_pdn_type_ie(const pfcp::pdn_type_t& b) : pfcp_ie(PFCP_IE_PDN_TYPE) {
u1.b = 0;
tlv.set_length(1);
}
//--------
pfcp_pdn_type_ie() : pfcp_ie(PFCP_IE_PDN_TYPE) {
u1.b = 0;
tlv.set_length(1);
}
//--------
pfcp_pdn_type_ie(const pfcp_tlv& t) : pfcp_ie(t) { u1.b = 0; };
//--------
void to_core_type(pfcp::pdn_type_t& b) {
u1.b = 0;
u1.bf.pdn_type = b.pdn_type;
}
//--------
void dump_to(std::ostream& os) {
tlv.dump_to(os);
os.write(reinterpret_cast<const char*>(&u1.b), sizeof(u1.b));
}
//--------
void load_from(std::istream& is) {
// tlv.load_from(is);
if (tlv.get_length() != 1) {
throw pfcp_tlv_bad_length_exception(
tlv.type, tlv.get_length(), __FILE__, __LINE__);
}
is.read(reinterpret_cast<char*>(&u1.b), sizeof(u1.b));
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::pdn_type_t pdn_type = {};
to_core_type(pdn_type);
s.set(pdn_type);
}
};
//-------------------------------------
// IE FAILED_RULE_ID
class pfcp_failed_rule_id_ie : public pfcp_ie {
......@@ -6888,6 +6899,7 @@ class pfcp_failed_rule_id_ie : public pfcp_ie {
s.set(v);
}
};
////-------------------------------------
//// IE TIME_QUOTA_MECHANISM
// class pfcp_time_quota_mechanism_ie : public pfcp_ie {
......@@ -6934,6 +6946,7 @@ class pfcp_failed_rule_id_ie : public pfcp_ie {
// s.set(time_quota_mechanism);
// }
//};
//-------------------------------------
// IE USER_PLANE_IP_RESOURCE_INFORMATION
class pfcp_user_plane_ip_resource_information_ie : public pfcp_ie {
......@@ -7144,6 +7157,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
s.set(v);
}
};
////-------------------------------------
//// IE AGGREGATED_URRS
// class pfcp_aggregated_urrs_ie : public pfcp_ie {
......@@ -7190,6 +7204,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
// s.set(aggregated_urrs);
// }
//};
////-------------------------------------
//// IE MULTIPLIER
// class pfcp_multiplier_ie : public pfcp_ie {
......@@ -7236,6 +7251,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
// s.set(multiplier);
// }
//};
////-------------------------------------
//// IE AGGREGATED_URR_ID
// class pfcp_aggregated_urr_id_ie : public pfcp_ie {
......@@ -7282,6 +7298,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
// s.set(aggregated_urr_id);
// }
//};
////-------------------------------------
//// IE SUBSEQUENT_VOLUME_QUOTA
// class pfcp_subsequent_volume_quota_ie : public pfcp_ie {
......@@ -7329,6 +7346,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
// s.set(subsequent_volume_quota);
// }
//};
////-------------------------------------
//// IE SUBSEQUENT_TIME_QUOTA
// class pfcp_subsequent_time_quota_ie : public pfcp_ie {
......@@ -7375,6 +7393,7 @@ class pfcp_user_plane_inactivity_timer_ie : public pfcp_ie {
// s.set(subsequent_time_quota);
// }
//};
//-------------------------------------
// IE RQI
class pfcp_rqi_ie : public pfcp_ie {
......@@ -7423,6 +7442,7 @@ class pfcp_rqi_ie : public pfcp_ie {
s.set(v);
}
};
//-------------------------------------
// IE QFI
class pfcp_qfi_ie : public pfcp_ie {
......@@ -7471,6 +7491,7 @@ class pfcp_qfi_ie : public pfcp_ie {
s.set(v);
}
};
////-------------------------------------
//// IE QUERY_URR_REFERENCE
// class pfcp_query_urr_reference_ie : public pfcp_ie {
......@@ -7517,6 +7538,7 @@ class pfcp_qfi_ie : public pfcp_ie {
// s.set(query_urr_reference);
// }
//};
////-------------------------------------
//// IE ADDITIONAL_USAGE_REPORTS_INFORMATION
// class pfcp_additional_usage_reports_information_ie : public pfcp_ie {
......@@ -9069,6 +9091,49 @@ class pfcp_user_id_ie : public pfcp_ie {
// }
//};
/*****************************************************************************************************************/
// 8.2.117 APN/DNN
/*****************************************************************************************************************/
class pfcp_apn_dnn_ie : public pfcp_ie {
public:
std::string apn_dnn;
//--------
explicit pfcp_apn_dnn_ie(const pfcp::apn_dnn_t& b)
: pfcp_ie(PFCP_IE_APN_DNN) {
apn_dnn = b.apn_dnn;
tlv.set_length(apn_dnn.size());
}
//--------
pfcp_apn_dnn_ie() : pfcp_ie(PFCP_IE_APN_DNN) {
apn_dnn = {};
tlv.set_length(0);
}
//--------
explicit pfcp_apn_dnn_ie(const pfcp_tlv& t) : pfcp_ie(t){};
//--------
void to_core_type(pfcp::apn_dnn_t& b) { b.apn_dnn = apn_dnn; }
//--------
void dump_to(std::ostream& os) {
tlv.dump_to(os);
os << apn_dnn;
}
//--------
void load_from(std::istream& is) {
// tlv.load_from(is);
uint16_t l = tlv.get_length();
char e[l];
is.read(e, l);
apn_dnn.assign(e, l);
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::apn_dnn_t apn_dnn = {};
to_core_type(apn_dnn);
s.set(apn_dnn);
}
};
// IE 3gpp_interface_type
class pfcp_3gpp_interface_type_ie : public pfcp_ie {
public:
......
......@@ -1104,15 +1104,11 @@ class pfcp_ies_container {
0, PFCP_IE_GRACEFUL_RELEASE_PERIOD, __FILE__, __LINE__);
}
// PFCP_IE_PDN_TYPE
// virtual bool get(pfcp::pdn_type_t& v) const {throw
// pfcp_msg_illegal_ie_exception(0, PFCP_IE_PDN_TYPE, __FILE__, __LINE__);}
// virtual void set(const pfcp::pdn_type_t& v) {throw
// pfcp_msg_illegal_ie_exception(0, PFCP_IE_PDN_TYPE, __FILE__, __LINE__);}
virtual bool get(pfcp::pdu_session_type_t& v) const {
virtual bool get(pfcp::pdn_type_t& v) const {
throw pfcp_msg_illegal_ie_exception(
0, PFCP_IE_PDN_TYPE, __FILE__, __LINE__);
}
virtual void set(const pfcp::pdu_session_type_t& v) {
virtual void set(const pfcp::pdn_type_t& v) {
throw pfcp_msg_illegal_ie_exception(
0, PFCP_IE_PDN_TYPE, __FILE__, __LINE__);
}
......@@ -1458,6 +1454,15 @@ class pfcp_ies_container {
throw pfcp_msg_illegal_ie_exception(
0, PFCP_IE_FRAMED_IPV6_ROUTE, __FILE__, __LINE__);
}
// PFCP_IE_APN_DNN
virtual bool get(pfcp::apn_dnn_t& v) const {
throw pfcp_msg_illegal_ie_exception(0, PFCP_IE_APN_DNN, __FILE__, __LINE__);
}
virtual void set(const pfcp::apn_dnn_t& v) {
throw pfcp_msg_illegal_ie_exception(0, PFCP_IE_APN_DNN, __FILE__, __LINE__);
}
// PFCP_IE_3GPP_INTERFACE_TYPE
virtual bool get(pfcp::_3gpp_interface_type_t& v) const {
throw pfcp_msg_illegal_ie_exception(
......@@ -6385,8 +6390,8 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
std::vector<pfcp::create_qer> create_qers;
std::pair<bool, pfcp::create_bar> create_bar;
std::pair<bool, pfcp::create_traffic_endpoint> create_traffic_endpoint;
// std::pair<bool, pfcp::pdn_type_t> pdn_type;
std::pair<bool, pfcp::pdu_session_type_t> pdu_session_type;
std::pair<bool, pfcp::pdn_type_t> pdn_type;
std::pair<bool, pfcp::apn_dnn_t> apn_dnn;
std::pair<bool, fq_csid_t> sgw_c_fq_csid;
std::pair<bool, fq_csid_t> mme_fq_csid;
std::pair<bool, fq_csid_t> pgw_c_fq_csid;
......@@ -6406,7 +6411,8 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
create_qers(),
create_bar(),
create_traffic_endpoint(),
pdu_session_type(),
pdn_type(),
apn_dnn(),
sgw_c_fq_csid(),
mme_fq_csid(),
pgw_c_fq_csid(),
......@@ -6426,7 +6432,8 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
create_qers = i.create_qers;
create_bar = i.create_bar;
create_traffic_endpoint = i.create_traffic_endpoint;
pdu_session_type = i.pdu_session_type;
pdn_type = i.pdn_type;
apn_dnn = i.apn_dnn;
sgw_c_fq_csid = i.sgw_c_fq_csid;
mme_fq_csid = i.mme_fq_csid;
pgw_c_fq_csid = i.pgw_c_fq_csid;
......@@ -6510,6 +6517,23 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
}
return false;
}
bool get(pfcp::pdn_type_t& v) const {
if (pdn_type.first) {
v = pdn_type.second;
return true;
}
return false;
}
bool get(pfcp::apn_dnn_t& v) const {
if (apn_dnn.first) {
v = apn_dnn.second;
return true;
}
return false;
}
bool get(pfcp::trace_information_t& v) const {
if (trace_information.first) {
v = trace_information.second;
......@@ -6528,6 +6552,17 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
return false;
}
bool get(const pfcp::qer_id_t& fid, pfcp::create_qer& create_qer) const {
for (auto it : create_qers) {
pfcp::qer_id_t qer_id = {};
if ((it.get(qer_id)) && (fid.qer_id == qer_id.qer_id)) {
create_qer = it;
return true;
}
}
return false;
}
void set(const pfcp::node_id_t& v) {
node_id.first = true;
node_id.second = v;
......@@ -6576,6 +6611,15 @@ class pfcp_session_establishment_request : public pfcp_ies_container {
trace_information.first = true;
trace_information.second = v;
}
void set(const pfcp::pdn_type_t& v) {
pdn_type.first = true;
pdn_type.second = v;
}
void set(const pfcp::apn_dnn_t& v) {
apn_dnn.first = true;
apn_dnn.second = v;
}
};
//------------------------------------------------------------------------------
class pfcp_session_establishment_response : public pfcp_ies_container {
......
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/toolchain.cmake)
add_subdirectory(bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/bpf_pfcp)
include_directories(${SRC_TOP_DIR}/upf_app/simpleswitch)
......@@ -22,6 +23,19 @@ include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/nrf/nrf_model.cmake)
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(${SRC_TOP_DIR}/upf_app/app)
set(GTP_INTERFACE $ENV{GTP_INTERFACE})
......@@ -32,20 +46,17 @@ add_library(UPF_XDP STATIC
UserPlaneComponent.cpp
Configuration.cpp
SignalHandler.cpp
NextHopFinder.cpp
CmdRunner.cpp
helpers/NextHopFinder.cpp
helpers/CmdRunner.cpp
SessionProgramManager.cpp
SessionManager.cpp
SessionPrograms.cpp
programs/pfcp_session_pdr_lookup_ebpf_xdp_prgrm_user.cpp
programs/pfcp_session_lookup_ebpf_xdp_prgrm_user.cpp
programs/far_ebpf_xdp_prgrm_user.cpp
programs/pfcp_session_pdr_lookup_xdp_user.cpp
programs/pfcp_session_lookup_xdp_user.cpp
programs/far_xdp_user.cpp
programs/BPFProgram.cpp
wrappers/BPFMaps.cpp
wrappers/BPFMap.cpp
# utils/Logger.cpp
# utils/Util.cpp
# utils/NextProgRuleKey.cpp
)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../build/ext/libbpf/src)
......@@ -67,7 +78,7 @@ target_include_directories(UPF_XDP PUBLIC
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/programs>
)
add_dependencies(UPF_XDP upf_ebpf_xdp_all)
add_dependencies(UPF_XDP upf_xdp_all)
install(
TARGETS UPF_XDP
......@@ -78,3 +89,69 @@ install(
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
##############################################################
# QER #
##############################################################
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/GetNicInformation.cpp
#helpers/QdiscHelpers.cpp
SessionProgramManager.cpp
SessionManager.cpp
SessionPrograms.cpp
programs/qer_tc_user.cpp
programs/BPFProgram.cpp
wrappers/BPFMaps.cpp
wrappers/BPFMap.cpp
)
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
)
target_include_directories(UPF_TC PUBLIC
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/include>
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/>
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/bpf>
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/skel>
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/interfaces>
$<BUILD_INTERFACE:${SRC_TOP_DIR}/upf_app/programs>
)
add_dependencies(UPF_TC upf_tc_all)
install(
TARGETS UPF_TC
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
# Headers:
# * ./*.h -> <prefix>/include/*.h
# install(
# DIRECTORY "./"
# DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
# FILES_MATCHING PATTERN "*.h"
# )
This diff is collapsed.
......@@ -4,7 +4,7 @@
#include <UserPlaneComponent.h>
#include <ie/fseid.h>
#include <ie/pdr_id.h>
#include <interfaces/RulesUtilities.h>
// #include <interfaces/RulesUtilities.h>
#include <memory>
#include <pfcp/pfcp_far.h>
#include <pfcp/pfcp_pdr.h>
......@@ -21,8 +21,8 @@
#include "itti_msg_n4.hpp"
class BPFMap;
class ForwardingActionRules;
class PacketDetectionRules;
// class ForwardingActionRules;
// class PacketDetectionRules;
class SessionBpf;
// FIXME: This class compose the UserPlaneComponent. When the program is
......@@ -42,8 +42,8 @@ class SessionManager {
public:
// Set of PDRs.
using pdrs_t = std::vector<std::shared_ptr<PacketDetectionRules>>;
/*****************************************************************************************************************/
// using pdrs_t = std::vector<std::shared_ptr<PacketDetectionRules>>;
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Construct a new Session Manager object.
......@@ -51,21 +51,21 @@ class SessionManager {
*/
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.
......@@ -75,7 +75,7 @@ class SessionManager {
*/
void removeSession(uint64_t seid);
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Creates BPF pipeline.
*
......@@ -87,7 +87,7 @@ class SessionManager {
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.
......@@ -100,7 +100,7 @@ class SessionManager {
itti_n4_session_modification_request* mod_req,
itti_n4_session_deletion_request* del_req);
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Remove BPF pipeline.
*
......@@ -113,56 +113,101 @@ class SessionManager {
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);
/*****************************************************************************************************************/
bool extractPdiAndInterface(
std::shared_ptr<pfcp::pfcp_pdr> pdr, pfcp::pdi& pdi,
pfcp::source_interface_t& sourceInterface,
pfcp::ue_ip_address_t& ueIpAddress);
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);
/*****************************************************************************************************************/
bool extractPdi(std::shared_ptr<pfcp::pfcp_pdr> pdr, pfcp::pdi& pdi);
/*****************************************************************************************************************/
bool extractSourceIface(
pfcp::pdi& pdi, pfcp::source_interface_t& sourceInterface);
/*****************************************************************************************************************/
bool extractUeIpv4(pfcp::pdi& pdi, pfcp::ue_ip_address_t& ueIpAddress);
/*---------------------------------------------------------------------------------------------------------------*/
bool extractFar(
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_session> session,
std::shared_ptr<pfcp::pfcp_far>& outFar);
/*****************************************************************************************************************/
bool extractForwardingParameters(
/*---------------------------------------------------------------------------------------------------------------*/
bool extractQer(
std::shared_ptr<pfcp::pfcp_pdr> pdr,
std::shared_ptr<pfcp::pfcp_session> session,
std::vector<std::shared_ptr<pfcp::pfcp_qer>>* outQer);
/*---------------------------------------------------------------------------------------------------------------*/
bool extractForwardingParams(
std::shared_ptr<pfcp::pfcp_far> far,
pfcp::forwarding_parameters& forwardingParams);
/*****************************************************************************************************************/
uint32_t findUplinkTeid(
uint32_t seid,
/*---------------------------------------------------------------------------------------------------------------*/
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);
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.
This diff is collapsed.
......@@ -2,7 +2,7 @@
#define __SESSIONPROGRAMS_H__
#include <memory>
#include <far_ebpf_xdp_prgrm_user.h>
#include <far_xdp_user.h>
#include <unistd.h>
#include <next_prog_rule_key.h>
......
#include "UserPlaneComponent.h"
#include <RulesUtilities.h>
//#include <RulesUtilities.h>
#include <SessionManager.h>
#include <pfcp_session_pdr_lookup_ebpf_xdp_prgrm_user.h>
#include <pfcp_session_pdr_lookup_xdp_user.h>
#include <SessionProgramManager.h>
#include <SignalHandler.h>
#include <pfcp_session_lookup_ebpf_xdp_prgrm_user.h>
#include <pfcp_session_lookup_xdp_user.h>
#include "logger.hpp"
#include <helpers/GetNicInformation.hpp>
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
UserPlaneComponent::UserPlaneComponent() {
// Set new handlers for libbpf.
#ifdef DEBUG_LIBBPF
......@@ -15,67 +16,61 @@ UserPlaneComponent::UserPlaneComponent() {
#endif
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
UserPlaneComponent::~UserPlaneComponent() {
tearDown();
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
std::shared_ptr<SessionManager> UserPlaneComponent::getSessionManager() const {
return mpSessionManager;
}
/*****************************************************************************************************************/
std::shared_ptr<RulesUtilities> UserPlaneComponent::getRulesUtilities() const {
return mpRulesUtilities;
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
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);
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
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::setup(
std::shared_ptr<RulesUtilities> pRulesUtilities,
/*---------------------------------------------------------------------------------------------------------------*/
void UserPlaneComponent::setMembers(
const std::string& gtpInterface, const std::string& udpInterface) {
mpRulesUtilities = pRulesUtilities;
mGTPInterface = gtpInterface;
mUDPInterface = udpInterface;
mGTPInterface = gtpInterface;
mUDPInterface = udpInterface;
mpPFCP_Session_LookupProgram =
std::make_shared<PFCP_Session_LookupProgram>(gtpInterface, udpInterface);
......@@ -83,7 +78,12 @@ void UserPlaneComponent::setup(
Logger::upf_app().error("The eBPF Program is Not Initialized");
throw std::runtime_error("The eBPF Program is Not Initialized");
}
}
/*---------------------------------------------------------------------------------------------------------------*/
void UserPlaneComponent::setup(
const std::string& gtpInterface, const std::string& udpInterface) {
setMembers(gtpInterface, udpInterface);
SignalHandler::getInstance().enable();
mpPFCP_Session_LookupProgram->setup();
......@@ -91,7 +91,7 @@ void UserPlaneComponent::setup(
mpSessionManager = std::make_shared<SessionManager>();
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
void UserPlaneComponent::tearDown() {
mpPFCP_Session_LookupProgram->tearDown();
SessionProgramManager::getInstance().removeAll();
......
......@@ -7,7 +7,6 @@
#include <observer/OnStateChangeSessionProgramObserver.h>
class SessionManager;
class RulesUtilities;
class PFCP_Session_LookupProgram;
class PFCP_Session_PDR_LookupProgram;
......@@ -19,12 +18,12 @@ class PFCP_Session_PDR_LookupProgram;
class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
public:
/**
* @brief Destroy the User Plane Component object.
* @brief Destroy the User Plane Component object
*
*/
virtual ~UserPlaneComponent();
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the Instance object.
*
......@@ -32,20 +31,27 @@ class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
*/
static UserPlaneComponent& getInstance();
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Setup User Plane Component.
* Used to setup all the program.
*
* @param pRulesUtilities
* @param gtpInterface
* @param udpInterface
*/
void setup(
std::shared_ptr<RulesUtilities> pRulesUtilities,
void setup(const std::string& gtpInterface, const std::string& udpInterface);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Set Members of the class UserPlaneComponent
*
* @param gtpInterface
* @param udpInterface
*/
void setMembers(
const std::string& gtpInterface, const std::string& udpInterface);
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Tear down User Plane Component.
* Tear down all programs that were setup.
......@@ -53,7 +59,7 @@ class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
*/
void tearDown();
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the Session Manager object.
*
......@@ -61,15 +67,7 @@ class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
*/
std::shared_ptr<SessionManager> getSessionManager() const;
/*****************************************************************************************************************/
/**
* @brief Get the Rules Factory object.
*
* @return std::shared_ptr<RulesFactory> The rules factory reference.
*/
std::shared_ptr<RulesUtilities> getRulesUtilities() const;
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get PFCP_Session_LookupProgram object.
*
......@@ -79,38 +77,46 @@ class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
std::shared_ptr<PFCP_Session_LookupProgram> getPFCP_Session_LookupProgram()
const;
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get the GTP interface.
* @brief Getter
* Get the GTP interface.
*
* @return std::string The GTP interface.
*/
std::string getGTPInterface() const;
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Get UDP interface.
* @brief Getter
* Get UDP interface.
*
* @return std::string The UDP interface.
*/
std::string getUDPInterface() const;
/*****************************************************************************************************************/
// From onNewSessionProgramObserver.
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief What to Do on New SessionProgram
*
* @param programId
* @param fileDescriptor
*/
void onNewSessionProgram(
u_int32_t programId, u_int32_t fileDescriptor) override;
/*****************************************************************************************************************/
// From onNewSessionProgramObserver.
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief What to Do when Destroying SessionProgram
*
* @param programId
*/
void onDestroySessionProgram(u_int32_t programId) override;
// TODO: getSessionManger?
private:
/**
* @brief Construct a new User Plane Component object.
*
* @param pRulesUtilities the wrapper for rules (PDR, FAR).
*/
UserPlaneComponent();
......@@ -118,12 +124,11 @@ class UserPlaneComponent : public OnStateChangeSessionProgramObserver {
static int printLibbpfLog(
enum libbpf_print_level lvl, const char* fmt, va_list args);
/*------------------------------------------------------------------------------------------------------------------*/
// The session manager reference.
std::shared_ptr<SessionManager> mpSessionManager;
// The rules factory reference.
std::shared_ptr<RulesUtilities> mpRulesUtilities;
// The PFCP_Session_LookupProgram (BPF program entry point) reference.
std::shared_ptr<PFCP_Session_LookupProgram> mpPFCP_Session_LookupProgram;
......
......@@ -51,6 +51,7 @@
constexpr auto UPF_CONFIG_OPTION_YES_STR = "Yes";
constexpr auto UPF_CONFIG_OPTION_NO_STR = "No";
const oai::model::common::Snssai DEFAULT_SNSSAI{1};
const std::vector<oai::model::nrf::DnnUpfInfoItem> DEFAULT_DNN_LIST = {
oai::model::nrf::DnnUpfInfoItem("default")};
......@@ -124,6 +125,7 @@ class upf_config {
bool enable_5g_features;
bool enable_bpf_datapath;
bool enable_qos;
bool register_nrf;
struct in_addr remote_n6;
upf_info_t upf_info;
......@@ -167,6 +169,7 @@ class upf_config {
enable_5g_features = true;
enable_bpf_datapath = false;
enable_qos = false;
register_nrf = false;
upf_info = {};
......
......@@ -33,10 +33,15 @@ namespace oai::config {
//------------------------------------------------------------------------------
upf_support_features::upf_support_features(
bool enable_bpf_datapath, bool enable_snat) {
m_config_name = "Supported Features";
bool enable_bpf_datapath, bool enable_qos, bool enable_snat) {
m_config_name = "Supported Features";
m_enable_bpf_datapath = option_config_value(
UPF_CONFIG_SUPPORT_FEATURES_ENABLE_BPF_LABEL, enable_bpf_datapath);
m_enable_qos = option_config_value(
UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS_LABEL, enable_qos);
m_enable_snat = option_config_value(
UPF_CONFIG_SUPPORT_FEATURES_ENABLE_SNAT_LABEL, enable_snat);
}
......@@ -47,6 +52,11 @@ void upf_support_features::from_yaml(const YAML::Node& node) {
m_enable_bpf_datapath.from_yaml(
node[UPF_CONFIG_SUPPORT_FEATURES_ENABLE_BPF]);
}
if (node[UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS]) {
m_enable_qos.from_yaml(node[UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS]);
}
if (node[UPF_CONFIG_SUPPORT_FEATURES_ENABLE_SNAT]) {
m_enable_snat.from_yaml(node[UPF_CONFIG_SUPPORT_FEATURES_ENABLE_SNAT]);
}
......@@ -57,6 +67,7 @@ std::string upf_support_features::to_string(const std::string& indent) const {
std::string out;
unsigned int inner_width = get_inner_width(indent.length());
// Enable BPF
std::string enable_bpf_datapath = m_enable_bpf_datapath.get_value() ?
UPF_CONFIG_OPTION_YES_STR :
UPF_CONFIG_OPTION_NO_STR;
......@@ -65,6 +76,15 @@ std::string upf_support_features::to_string(const std::string& indent) const {
UPF_CONFIG_SUPPORT_FEATURES_ENABLE_BPF_LABEL, inner_width,
enable_bpf_datapath));
// Enable QoS
std::string enable_qos = m_enable_qos.get_value() ?
UPF_CONFIG_OPTION_YES_STR :
UPF_CONFIG_OPTION_NO_STR;
out.append(indent).append(fmt::format(
BASE_FORMATTER, INNER_LIST_ELEM,
UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS_LABEL, inner_width, enable_qos));
// Enable SNAT
std::string enable_snat = m_enable_snat.get_value() ?
UPF_CONFIG_OPTION_YES_STR :
UPF_CONFIG_OPTION_NO_STR;
......@@ -79,7 +99,7 @@ upf::upf(
const std::string& name, const std::string& host, const sbi_interface& sbi,
const std::map<std::string, upf_interface_config>& interfaces)
: nf(name, host, sbi),
m_upf_support_features(false, false),
m_upf_support_features(false, false, false),
m_interfaces(interfaces) {
model::nrf::SnssaiUpfInfoItem item;
item.setSNssai(DEFAULT_SNSSAI);
......@@ -180,6 +200,11 @@ bool upf_support_features::get_option_enable_bpf_datapath() const {
return m_enable_bpf_datapath.get_value();
}
//------------------------------------------------------------------------------
bool upf_support_features::get_option_enable_qos() const {
return m_enable_qos.get_value();
}
//------------------------------------------------------------------------------
bool upf_support_features::get_option_enable_snat() const {
return m_enable_snat.get_value();
......@@ -359,6 +384,7 @@ void upf_config_yaml::to_upf_config(upf_config& cfg) {
cfg.enable_bpf_datapath =
upf_local->get_support_features().get_option_enable_bpf_datapath();
cfg.enable_qos = upf_local->get_support_features().get_option_enable_qos();
cfg.enable_snat = upf_local->get_support_features().get_option_enable_snat();
auto snssai_upf_list = upf_local->get_upf_info().getSNssaiUpfInfoList();
......
......@@ -39,6 +39,9 @@ constexpr auto UPF_CONFIG_SUPPORT_FEATURES_ENABLE_BPF_LABEL =
constexpr auto UPF_CONFIG_SUPPORT_FEATURES_ENABLE_SNAT = "enable_snat";
constexpr auto UPF_CONFIG_SUPPORT_FEATURES_ENABLE_SNAT_LABEL = "Enable SNAT";
constexpr auto UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS = "enable_qos";
constexpr auto UPF_CONFIG_SUPPORT_FEATURES_ENABLE_QOS_LABEL = "Enable QoS";
constexpr auto UPF_CONFIG_REMOTE_N6_GW = "remote_n6_gw";
constexpr auto UPF_CONFIG_REMOTE_N6_GW_LABEL = "Remote N6 Gateway";
......@@ -52,15 +55,18 @@ namespace oai::config {
class upf_support_features : public config_type {
private:
option_config_value m_enable_bpf_datapath{};
option_config_value m_enable_qos{};
option_config_value m_enable_snat{};
public:
explicit upf_support_features(bool enable_bpf_datapath, bool enable_snat);
explicit upf_support_features(
bool enable_bpf_datapath, bool enable_qos, bool enable_snat);
void from_yaml(const YAML::Node& node) override;
[[nodiscard]] std::string to_string(const std::string& indent) const override;
[[nodiscard]] bool get_option_enable_bpf_datapath() const;
[[nodiscard]] bool get_option_enable_qos() const;
[[nodiscard]] bool get_option_enable_snat() const;
};
......
include(${SRC_TOP_DIR}/upf_app/cmake/toolchain.cmake)
include_directories(${SRC_TOP_DIR}/upf_app)
include_directories(${SRC_TOP_DIR}/upf_app/bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules)
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)
add_definitions(-DKERNEL_SPACE)
add_custom_target(upf_ebpf_xdp_all DEPENDS pfcp_session_lookup_ebpf_xdp pfcp_session_pdr_lookup_ebpf_xdp far_ebpf_xdp)
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)
function(bpf prefix)
add_library(${prefix}_ebpf_xdp STATIC ${prefix}_ebpf_xdp_prgrm_kernel.c)
###########################################################################
# GENERATE eBPF XDP Skeletons #
###########################################################################
function(xdp arg)
if (${arg} STREQUAL "pfcp_session_lookup" OR ${arg} STREQUAL "pfcp_session_pdr_lookup")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/pdr")
elseif (${arg} STREQUAL "far")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/far")
else()
message(FATAL_ERROR "Invalid arg: ${arg}")
endif()
add_library(${arg}_xdp STATIC ${source_dir}/${arg}_xdp_kernel.c)
add_custom_command(
TARGET ${arg}_xdp
PRE_LINK
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/../skel
COMMAND bpftool gen skeleton $<TARGET_OBJECTS:${arg}_xdp> > ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${arg}_xdp_kernel_skel.h
COMMAND sed -i '9i\#define typeof\(x\) __typeof__\(x\)' ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${arg}_xdp_kernel_skel.h
DEPENDS ${source_dir}/${arg}_xdp_kernel.c
)
endfunction()
xdp(pfcp_session_lookup)
xdp(pfcp_session_pdr_lookup)
xdp(far)
###########################################################################
# GENERATE eBPF TC Skeletons #
###########################################################################
function(tc arg)
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/qer")
add_library(${arg}_tc STATIC ${source_dir}/${arg}_tc_kernel.c)
add_custom_command(
TARGET ${prefix}_ebpf_xdp
TARGET ${arg}_tc
PRE_LINK
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/../skel
COMMAND bpftool gen skeleton $<TARGET_OBJECTS:${prefix}_ebpf_xdp> > ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
COMMAND sed -i '9i\#define typeof\(x\) __typeof__\(x\)' ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${prefix}_ebpf_xdp_prgrm_kernel.c
COMMAND bpftool gen skeleton $<TARGET_OBJECTS:${arg}_tc> > ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${arg}_tc_kernel_skel.h
COMMAND sed -i '9i\#define typeof\(x\) __typeof__\(x\)' ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${arg}_tc_kernel_skel.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${arg}_tc_kernel.c
)
endfunction()
bpf(pfcp_session_lookup)
bpf(pfcp_session_pdr_lookup)
bpf(far)
\ No newline at end of file
tc(qer)
\ No newline at end of file
#ifndef __FAR_MAPS_H__
#define __FAR_MAPS_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <pfcp/pfcp_far.h>
#include <types.h>
#include "arp_table_maps.h"
#define MAX_INTERFACES 10
#define ARP_ENTRIES_MAX_SIZE 12
#define FAR_TAILS_MAX 1
/*****************************************************************************************************************/
// The unique FAR that will be consumed in this program.
struct bpf_map_def SEC("maps") m_far = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u8),
.value_size = sizeof(pfcp_far_t_),
.max_entries = FAR_TAILS_MAX, // 1,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_redirect_interfaces = {
.type = BPF_MAP_TYPE_DEVMAP,
.key_size = sizeof(u32), // id
.value_size = sizeof(u32), // tx port
.max_entries = MAX_INTERFACES, // 10,
};
/*****************************************************************************************************************/
// Static ARP Table. Used to get the MAC address of the next hop.
// TODO: Pin this maps. It does not depend on the session program
// struct bpf_map_def SEC("maps") m_arp_table = {
// .type = BPF_MAP_TYPE_HASH,
// .key_size = sizeof(u32), // IPv4 address
// .value_size = 6, // MAC address
// .max_entries = ARP_ENTRIES_MAX_SIZE, // 2,
// };
struct bpf_map_def SEC("maps") m_arp_table = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // IPv4 address
.value_size = sizeof(struct s_arp_mapping), // <IP Address, MAC address>
.max_entries = ARP_ENTRIES_MAX_SIZE, // 2,
};
/*****************************************************************************************************************/
// BPF_ANNOTATE_KV_PAIR(m_far, u8, pfcp_far_t_);
// BPF_ANNOTATE_KV_PAIR(m_redirect_interfaces, u32, u32);
// BPF_ANNOTATE_KV_PAIR(m_arp_table, u32, ??);
#endif // __FAR_MAPS_H__
......@@ -17,7 +17,7 @@
// INTERFACE_VALUE_5G_VN_INTERNAL = 4
// };
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
typedef struct source_interface {
ie_base_t_ base;
u8 interface_value;
......
#ifndef __INTERFACES_MAP_H__
#define __INTERFACES_MAP_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include "interfaces.h"
#define INTERFACE_ENTRIES_MAX 12
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_upf_interfaces = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(e_reference_point),
.value_size = sizeof(struct s_interface),
.max_entries = INTERFACE_ENTRIES_MAX, // 6,
};
// BPF_ANNOTATE_KV_PAIR(m_next_rule_prog_index, struct next_rule_prog_index_key,
// u32);
#endif // __INTERFACES_MAP_H__
\ No newline at end of file
#ifndef __PFCP_SESSION_LOOKUP_MAPS_H__
#define __PFCP_SESSION_LOOKUP_MAPS_H__
#include <ie/group_ie/create_pdr.h>
#include <pfcp/pfcp_pdr.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 "interfaces.h"
//#include "traffic_classification.h"
// #include "session_mapping.h"
// #include "ue_teid_qfi_matching.h"
// #include "qfi_flow_mapping_table.h"
#define MAX_LENGTH 5000 // 10
#define INTERFACE_ENTRIES_MAX 12
#define MAX_UEs 100000
/*****************************************************************************************************************/
// Maps TEID to PFCP_Session_PDR_LookupProgram
struct bpf_map_def SEC("maps") m_teid_session = {
.type =
BPF_MAP_TYPE_PROG_ARRAY, //!< Must have the key and value with 4 bytes
.key_size = sizeof(teid_t_), //!< program identifier.
.value_size = sizeof(s32), //!< program which represents the session.
// TODO: Check how the management works. The size should be equal
// to the maximum number of sessions.
.max_entries = MAX_LENGTH, // 10000, //!< TODO: Is it enought?
};
/*****************************************************************************************************************/
// Maps UE IPv4 address to PFCP_Session_PDR_LookupProgram
// FIXME: Select a primary key. We could use a hash value of the IP as a key.
struct bpf_map_def SEC("maps") m_ueip_session = {
.type =
BPF_MAP_TYPE_PROG_ARRAY, //!< Must have the key and value with 4 bytes
.key_size = sizeof(u32), //!< program identifier.
.value_size = sizeof(s32), //!< program which represents the session.
// TODO Check how the management works. The size should be equal
// to the maximum number of sessions.
.max_entries = MAX_UEs, //!< TODO: Is it enought?
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_ue_ip_pdr = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), //!< UE IP
.value_size = sizeof(u32), //!< PDR
.max_entries = MAX_UEs,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_next_rule_prog_index = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct next_rule_prog_index_key),
.value_size = sizeof(u32),
.max_entries = MAX_LENGTH, // 10,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_upf_interfaces = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(e_reference_point),
.value_size = sizeof(struct s_interface),
.max_entries = INTERFACE_ENTRIES_MAX, // 6,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_session_mapping = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // ue_ip_address
.value_size = sizeof(u32), // teid_dl
.max_entries = MAX_LENGTH,
};
/*****************************************************************************************************************/
// struct bpf_map_def SEC("maps") m_traffic_classification = {
// .type = BPF_MAP_TYPE_HASH,
// .key_size = sizeof(struct s_traffic),
// .value_size = sizeof(u32), // teid_dl
// .max_entries = MAX_LENGTH,
// };
/*****************************************************************************************************************/
// struct bpf_map_def SEC("maps") m_ue_qfi_teid = {
// .type = BPF_MAP_TYPE_HASH,
// .key_size = sizeof(struct s_ue_qfi),
// .value_size = sizeof(u32), // teid_ul
// .max_entries = MAX_LENGTH,
// };
/*****************************************************************************************************************/
// struct bpf_map_def SEC("maps") m_qos_flow_map = {
// .type = BPF_MAP_TYPE_HASH,
// .key_size = sizeof(u8), // dscp
// .value_size = sizeof(struct s_qfi_parameters),
// .max_entries = MAX_LENGTH,
// };
#endif // __PFCP_SESSION_LOOKUP_MAPS_H__
#ifndef __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#define __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#include <linux/bpf.h>
#include <types.h>
#include <pfcp/pfcp_pdr.h>
#include <pfcp/pfcp_far.h>
#include <ie/fteid.h>
#include <ie/fseid.h>
#define MAX_LENGTH 5000 // 10
#define PDR_ENTRIES_MAX_SIZE 5000 // 10
#define FAR_ENTRIES_MAX_SIZE 5000 // 10
#define ARP_ENTRIES_MAX_SIZE 12
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_fars = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // teid
.value_size = sizeof(pfcp_far_t_), // list of pdr
.max_entries = FAR_ENTRIES_MAX_SIZE,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_redirect_interfaces = {
.type = BPF_MAP_TYPE_DEVMAP,
.key_size = sizeof(u32), // id
.value_size = sizeof(u32), // tx port
.max_entries = MAX_LENGTH, // 10,
};
/*****************************************************************************************************************/
// Uplink map.
// TODO: Store multiple PDR.
struct bpf_map_def SEC("maps") m_teid_pdr = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(teid_t_), // teid
.value_size = sizeof(pfcp_pdr_t_), // assuming only one PDR
.max_entries = PDR_ENTRIES_MAX_SIZE, // 10,
};
/*****************************************************************************************************************/
// Downlink map.
// TODO: Store multiple PDR.
struct bpf_map_def SEC("maps") m_ueip_pdr = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // UE IP address
.value_size = sizeof(pfcp_pdr_t_), // assuming only one PDR
.max_entries = PDR_ENTRIES_MAX_SIZE, // 10,
};
/*****************************************************************************************************************/
// Static ARP Table. Used to get the MAC address of the next hop.
// TODO: Pin this maps. It does not depend on the session program
struct bpf_map_def SEC("maps") m_arp_table = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // IPv4 address
.value_size = 6, // MAC address
.max_entries = ARP_ENTRIES_MAX_SIZE, // 2,
};
#endif // __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#ifndef __QFI_FLOW_MAPPING_TABLE_H__
#define __QFI_FLOW_MAPPING_TABLE_H__
#include <types.h>
#include <stdint.h>
typedef enum { DELAY_CRITICAL_GBR, GBR, NON_GBR } e_resource_type;
struct s_qfi_parameters {
e_resource_type resource_type;
u8 qfi;
u32 qos;
};
#endif // __QFI_FLOW_MAPPING_TABLE_H__
\ No newline at end of file
#ifndef __FAR_MAPS_H__
#define __FAR_MAPS_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <pfcp/pfcp_far.h>
#include <types.h>
#include "arp_table_maps.h"
#define ARP_ENTRIES_MAX_SIZE 12
#define FAR_TAILS_MAX 1
#define MAX_INTERFACES 10
#define MAX_FAR_PROGRAMS 100
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, FAR_TAILS_MAX); // 1,
__type(key, u8);
__type(value, pfcp_far_t_);
} m_far SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_DEVMAP);
__uint(max_entries, MAX_INTERFACES); // 10,
__type(key, u32); // id
__type(value, u32); // tx port
} m_redirect_interfaces SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, ARP_ENTRIES_MAX_SIZE); // 2,
__type(key, u32); // IPv4 address
__type(value, struct s_arp_mapping); // <IP Address, MAC address>
} m_arp_table SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_FAR_PROGRAMS); // 1,
__type(key, u32);
__type(value, u32);
} m_enforcing_qos SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
#endif // __FAR_MAPS_H__
......@@ -42,8 +42,8 @@ static __always_inline bool retrieve_upf_iface_from_map(
/*****************************************************************************************************************/
static __always_inline bool update_dst_mac_address(
u32 ip, struct ethhdr* p_eth) {
struct s_arp_mapping* map_entry;
memset(&map_entry, 0, sizeof(struct s_arp_mapping));
struct s_arp_mapping* map_entry = {0};
// memset(&map_entry, 0, sizeof(struct s_arp_mapping));
map_entry = bpf_map_lookup_elem(&m_arp_table, &ip);
......@@ -206,7 +206,7 @@ create_outer_header_gtpu_ipv4(struct xdp_md* ctx, pfcp_far_t_* p_far) {
}
/*****************************************************************************************************************/
SEC("xdp_far")
SEC("xdp")
int far_entry_point(struct xdp_md* ctx) {
bpf_debug("================< FAR Sesction >================");
void* data = (void*) (long) ctx->data;
......@@ -223,18 +223,13 @@ int far_entry_point(struct xdp_md* ctx) {
return XDP_DROP;
}
if (!p_far) {
bpf_debug("Invalid FAR!");
return XDP_DROP;
}
// Check if it is a forward action.
u8 dest_interface =
p_far->forwarding_parameters.destination_interface.interface_value;
u16 outer_header_creation =
p_far->forwarding_parameters.outer_header_creation
.outer_header_creation_description;
// u16 outer_header_creation =
// p_far->forwarding_parameters.outer_header_creation
// .outer_header_creation_description;
// Check forwarding action
if (!p_far->apply_action.forw) {
......@@ -280,7 +275,24 @@ int far_entry_point(struct xdp_md* ctx) {
} else if (dest_interface == INTERFACE_VALUE_ACCESS) {
create_outer_header_gtpu_ipv4(ctx, p_far);
return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
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: {
}
}
}
}
}
......@@ -289,4 +301,4 @@ int far_entry_point(struct xdp_md* ctx) {
}
char _license[] SEC("license") = "GPL";
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
#ifndef __INTERFACES_MAP_H__
#define __INTERFACES_MAP_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include "interfaces.h"
#define INTERFACE_ENTRIES_MAX 12
#define MAX_INTERFACES 10
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_DEVMAP);
__uint(max_entries, MAX_INTERFACES); // 10,
__type(key, u32); // id
__type(value, u32); // tx port
} m_redirect_interfaces SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, INTERFACE_ENTRIES_MAX);
__type(key, e_reference_point);
__type(value, struct s_interface); // 6,
} m_upf_interfaces SEC(".maps");
#endif // __INTERFACES_MAP_H__
\ No newline at end of file
#ifndef __PFCP_SESSION_LOOKUP_MAPS_H__
#define __PFCP_SESSION_LOOKUP_MAPS_H__
#include <ie/group_ie/create_pdr.h>
#include <pfcp/pfcp_pdr.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 "interfaces.h"
#include "session_id.h"
#define MAX_LENGTH 5000 // 10
#define INTERFACE_ENTRIES_MAX 12
#define MAX_UEs 100000
/*---------------------------------------------------------------------------------------------------------------*/
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");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, INTERFACE_ENTRIES_MAX); // 6,
__type(key, e_reference_point);
__type(value, struct s_interface);
} m_upf_interfaces SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, MAX_LENGTH);
__type(key, u32); // ue_ip_address
__type(value, struct session_id); // < teid_ul, teid_dl, seid >
} m_session_mapping SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
#endif // __PFCP_SESSION_LOOKUP_MAPS_H__
#ifndef __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#define __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#include <linux/bpf.h>
#include <types.h>
#include <pfcp/pfcp_pdr.h>
#include <pfcp/pfcp_far.h>
#include <ie/fteid.h>
#include <ie/fseid.h>
#define MAX_LENGTH 5000 // 10
#define PDR_ENTRIES_MAX_SIZE 5000 // 10
#define FAR_ENTRIES_MAX_SIZE 5000 // 10
#define ARP_ENTRIES_MAX_SIZE 12
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, FAR_ENTRIES_MAX_SIZE);
__type(key, u32); // teid
__type(value, pfcp_far_t_); // list of pdr
} m_fars SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_DEVMAP);
__uint(max_entries, MAX_LENGTH); // 10,
__type(key, u32); // id
__type(value, u32); // tx port
} m_redirect_interfaces SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, PDR_ENTRIES_MAX_SIZE); // 10,
__type(key, teid_t_); // teid
__type(value, pfcp_pdr_t_); // assuming only one PDR
} m_teid_pdr SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, PDR_ENTRIES_MAX_SIZE); // 10,
__type(key, u32); // UE IP address
__type(value, pfcp_pdr_t_); // assuming only one PDR
} m_ueip_pdr SEC(".maps");
/*---------------------------------------------------------------------------------------------------------------*/
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, ARP_ENTRIES_MAX_SIZE); // 2,
__type(key, u32); // IPv4 address
__type(value, unsigned char[8]); // MAC address
} m_arp_table SEC(".maps");
#endif // __PFCP_SESSION_PDR_LOOKUP_MAPS_H__
#ifndef __SESSION_MAPPING_H__
#define __SESSION_MAPPING_H__
#ifndef __SESSION_ID_H__
#define __SESSION_ID_H__
#include <types.h>
#include <stdint.h>
struct s_session_mapping {
u32 ue_ip_address;
struct session_id {
u32 teid_ul;
u32 teid_dl;
u32 seid;
};
#endif // __SESSION_MAPPING_H__
\ No newline at end of file
#endif // __SESSION_ID_H__
\ No newline at end of file
......@@ -16,13 +16,12 @@
#include "xdp_stats_kern_user.h"
#endif
/* Keeps stats per (enum) xdp_action */
struct bpf_map_def SEC("maps") mc_stats = {
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(struct datarec),
.max_entries = XDP_ACTION_MAX,
};
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, XDP_ACTION_MAX);
__type(key, __u32);
__type(value, struct datarec);
} mc_stats SEC(".maps");
/**
* @brief Record actions in map.
......
......@@ -18,12 +18,13 @@
* | | |
* +--------------------------+---------------------------+
*/
struct bpf_map_def SEC("maps") m_next_rule_prog = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(s32),
.max_entries = MAX_LENGTH, // 10,
};
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(max_entries, MAX_LENGTH); // 10,
__type(key, u32);
__type(value, s32);
} m_next_rule_prog SEC(".maps");
// BPF_ANNOTATE_KV_PAIR(m_next_rule_prog, u32, s32);
......
#define KBUILD_MODNAME pfcp_session_lookup_ebpf_xdp_prgrm_kernel
#define KBUILD_MODNAME pfcp_session_lookup_xdp_kernel
// clang-format off
#include <types.h>
......@@ -60,7 +60,7 @@ static __always_inline u32 tail_call_next_prog(
return XDP_DROP;
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
static __always_inline u32
handle_downlink_traffic(struct xdp_md* ctx, u32 ue_ip_address) {
......@@ -78,7 +78,7 @@ handle_downlink_traffic(struct xdp_md* ctx, u32 ue_ip_address) {
return XDP_PASS;
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* Uplink SECTION.
*/
......@@ -133,7 +133,7 @@ handle_uplink_traffic(struct xdp_md* ctx, struct udphdr* udph) {
return XDP_PASS;
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* IP SECTION.
......@@ -174,7 +174,7 @@ static __always_inline u32 ipv4_handle(struct xdp_md* ctx, struct iphdr* iph) {
}
}
/*****************************************************************************************************************/
/*---------------------------------------------------------------------------------------------------------------*/
/**
* ETHERNET SECTION.
*/
......@@ -224,9 +224,9 @@ static __always_inline u32 eth_handle(struct xdp_md* ctx, struct ethhdr* ethh) {
}
}
/*****************************************************************************************************************/
SEC("xdp_entry_point")
int entry_point(struct xdp_md* ctx) {
/*---------------------------------------------------------------------------------------------------------------*/
SEC("xdp")
int xdp_entry_point(struct xdp_md* ctx) {
bpf_debug("================< PFCP PDR Sesction >================");
struct ethhdr* ethh = (void*) (long) ctx->data;
......@@ -240,4 +240,4 @@ int entry_point(struct xdp_md* ctx) {
char _license[] SEC("license") = "GPL";
/*****************************************************************************************************************/
\ No newline at end of file
/*---------------------------------------------------------------------------------------------------------------*/
\ No newline at end of file
#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__
#ifndef __QER_MAPS_H__
#define __QER_MAPS_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include "filter_key.h"
#include "qos_flow.h"
#define QFI_MAX_ENTRIES 5000
#define FIVE_QI_MAX_ENTRIES 100
#define QOS_FLOWS_MAX_ENTRIES 100
#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_DEVMAP);
__uint(max_entries, MAX_INTERFACES);
__type(key, u32);
__type(value, u32);
} m_egress_ifindex SEC(".maps");
#endif // __QER_MAPS_H__
\ No newline at end of file
// clang-format off
#include <types.h>
// clang-format on
#include "xdp_stats_kern.h"
#include <bpf_helpers.h>
#include <endian.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <pfcp/pfcp_far.h>
#include <pfcp/pfcp_pdr.h>
#include <protocols/gtpu.h>
#include <protocols/ip.h>
#include <protocols/tcp.h>
#include <utils/csum.h>
#include <utils/logger.h>
#include <utils/utils.h>
//#include <far_maps.h>
#include <interfaces.h>
//#include <pfcp_session_lookup_maps.h>
#include <string.h> //Needed for memcpy
#include "bpf_endian.h"
#include <linux/pkt_cls.h>
#include <qer_maps.h>
#include <linux/netdevice.h>
#include <linux/pkt_sched.h>
#define MARK_VALUE 0x12345678 // Marker value to match
#define OFFSET 0 // Example offset where marker is stored
#define TARGET_INTF 644
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Filter the Uplink traffic
*
* @param skb
* @param udph UDP header
* @return __inline u32 the TC action taken
*/
static __always_inline u32 egress_sdf_filter(
struct __sk_buff* skb, struct ethhdr* ethh, struct udphdr* udph) {
void* data_end = (void*) (long) skb->data_end;
struct gtpuhdr* gtpuh = (struct gtpuhdr*) (udph + 1);
// Check if the GTP header extends beyond the data end.
if ((void*) gtpuh + sizeof(*gtpuh) > data_end) {
bpf_debug("Invalid GTPU packet");
return TC_ACT_SHOT;
}
struct gtpu_extn_pdu_session_container* gtpu_ext_h = (void*) (gtpuh + 1);
// Check if the GTP extension header extends beyond the data end.
if ((void*) gtpu_ext_h + sizeof(*gtpu_ext_h) > data_end) {
bpf_debug("Invalid GTPU Extension packet");
return TC_ACT_SHOT;
}
struct iphdr* iph_inner = (void*) (ethh + 1);
if ((void*) iph_inner + sizeof(*iph_inner) > data_end) {
bpf_debug("Invalid Inner IP packet");
return TC_ACT_SHOT;
}
struct filter_key* key = {0};
u8 protocol = iph_inner->protocol;
key->src_ip = iph_inner->saddr;
key->dst_ip = iph_inner->daddr;
key->protocol = protocol;
switch (protocol) {
case IPPROTO_UDP: {
// Extract UDP header
struct udphdr* udph = (struct udphdr*) (iph_inner + 1);
if ((void*) (udph + 1) > data_end) {
bpf_debug("Invalid UDP header");
return TC_ACT_SHOT;
}
key->dst_port = udph->dest;
break;
}
case IPPROTO_TCP: {
// Extract TCP header
struct tcphdr* tcph = (struct tcphdr*) (iph_inner + 1);
if ((void*) (tcph + 1) > data_end) {
bpf_debug("Invalid TCP header");
return TC_ACT_SHOT;
}
key->dst_port = tcph->dest;
break;
}
default: {
bpf_debug("Unknown header");
bpf_debug("Use best effort QoS flow (i.e. default qfi)");
key->dst_port = 65535;
}
}
struct session_qfi* retrieved_value =
bpf_map_lookup_elem(&m_sdf_filter, &key);
if (retrieved_value) {
u8 qfi = retrieved_value->qfi;
u64 seid = bpf_ntohs(retrieved_value->seid);
gtpu_ext_h->qfi = qfi;
u32 classid =
(seid << 16) |
((seid * 256) + (qfi * 251 % 256)); // ( major << 16 ) | minor
skb->tc_classid = classid;
return TC_ACT_OK;
}
// default value qfi = 5 (NON-GBR QoS Flow)
skb->tc_classid = gtpu_ext_h->qfi;
return TC_ACT_OK;
}
/*---------------------------------------------------------------------------------------------------------------*/
/**
* IP SECTION.
*/
/**
* @brief Filter IPv4 header.
*
* @param skb The user accessible metadata for tc packet hook.
* @param iph The IP header.
* @return u32 The TC action.
*/
static __always_inline u32
ipv4_sdf_filter(struct __sk_buff* skb, struct ethhdr* ethh, struct iphdr* iph) {
void* data_end = (void*) (long) skb->data_end;
u8 protocol = iph->protocol;
switch (protocol) {
case IPPROTO_UDP: {
// Extract UDP header
struct udphdr* udph = (struct udphdr*) (iph + 1);
if ((void*) (udph + 1) > data_end) {
bpf_debug("Invalid UDP header");
return TC_ACT_SHOT;
}
if (htons(udph->dest) == GTP_UDP_PORT) {
bpf_printk("This is a GTP traffic");
return egress_sdf_filter(skb, ethh, udph);
}
}
default: {
return XDP_DROP;
}
}
}
/*---------------------------------------------------------------------------------------------------------------*/
struct meta_info {
__u32 mark;
} __attribute__((aligned(4)));
/**
* @brief Filter traffic according to ETH_TYPE
*
* @param skb
* @param ethh Ethernet header
* @return ** __inline TC taken action
*/
static __always_inline u32
sdf_filter(struct __sk_buff* skb, struct ethhdr* ethh) {
void* data_end = (void*) (long) skb->data_end;
u16 eth_type = htons(ethh->h_proto);
bpf_debug("Debug: eth_type:0x%x", eth_type);
switch (eth_type) {
case ETH_P_IP: {
// Extract IP header
struct iphdr* iph = (struct iphdr*) (ethh + 1);
if ((void*) (iph + 1) > data_end) {
bpf_debug("Invalid IPv4 header");
return TC_ACT_SHOT;
}
return ipv4_sdf_filter(skb, ethh, iph);
}
case ETH_P_IPV6: {
// TODO: Check if traitment is needed here
return TC_ACT_OK;
}
case ETH_P_8021Q: {
// TODO: Check if traitment is needed here
return TC_ACT_OK;
}
case ETH_P_8021AD: {
// TODO: Check if traitment is needed here
return TC_ACT_OK;
}
case ETH_P_ARP: {
// TODO: Check if traitment is needed here
return TC_ACT_OK;
}
default: {
// TODO: Check if traitment is needed here
return TC_ACT_OK;
}
}
}
/*---------------------------------------------------------------------------------------------------------------*/
SEC("tc")
int tc_filter_traffic(struct __sk_buff* skb) {
bpf_debug("==========< QER Rules >==========\n");
// void *data = (void *)(long)skb->data;
// void *data_meta = (void *)(long)skb->data_meta;
// struct meta_info *meta = data_meta;
// /* Check SKB gave us some data_meta */
// if ((void *)(meta + 1) > data) {
// skb->mark = 41;
// bpf_debug("No Meta_data found! Drop the packet");
// return TC_ACT_SHOT;
// }
// /* Hint: See func tc_cls_act_is_valid_access() for BPF_WRITE access */
// skb->mark = meta->mark; /* Transfer XDP-mark to SKB-mark */
bpf_debug("TC Retrieves a Marker metadata value: %d", skb->mark);
// Check if the marker matches
// if (skb->mark == htonl(MARK_VALUE)) {
// bpf_debug("TC_REDIRECT: Redirecting packet to N3 tc layer");
// return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
// }
// Extract Ethernet header
struct ethhdr* ethh = (void*) (long) skb->data;
if ((void*) (ethh + 1) > (void*) (long) skb->data_end) {
bpf_debug("Invalid Ethernet header");
return TC_ACT_SHOT;
}
return sdf_filter(skb, ethh);
}
// /*---------------------------------------------------------------------------------------------------------------*/
SEC("tc")
int tc_redirect_traffic(struct __sk_buff* skb) {
int key = DOWNLINK, *ifindex;
// return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
/* Lookup what ifindex to redirect packets to */
ifindex = bpf_map_lookup_elem(&m_egress_ifindex, &key);
if (ifindex) {
bpf_debug("TC_REDIRECT: Redirecting packet to N3 tc layer");
return bpf_redirect(*ifindex, 0);
}
bpf_debug("TC Packets not redirected! Drop them");
return TC_ACT_SHOT;
}
char _license[] SEC("license") = "GPL";
/*---------------------------------------------------------------------------------------------------------------*/
#ifndef __QOS_FLOW_H__
#define __QOS_FLOW_H__
#include <types.h>
/* 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_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;
};
#endif //__QOS_FLOW_H__
\ No newline at end of file
#ifndef __TRAFFIC_H__
#define __TRAFFIC_H__
#include <types.h>
#include <stdint.h>
// u16 dscp_dl_or_qfi_ul; TODO: add this field when it works
// u16 src_port;
// u16 dest_port;
// Add other relevant parameters as needed
struct s_traffic {
u32 src_ip;
u8 protocol;
u32 dest_ip;
};
#endif // __TRAFFIC_H__
\ No newline at end of file
#ifndef __UE_TEID_QFI_MATCHING_H__
#define __UE_TEID_QFI_MATCHING_H__
#include <types.h>
#include <stdint.h>
struct s_ue_qfi {
u32 src_ip;
u8 qfi;
};
#endif // __UE_TEID_QFI_MATCHING_H__
\ No newline at end of file
#include <ForwardingActionRule.h>
\ No newline at end of file
#ifndef __FORWARDINGACTIONRULE_H__
#define __FORWARDINGACTIONRULE_H__
class ForwardingActionRule {
public:
ForwardingActionRule(/* args */);
~ForwardingActionRule();
};
#endif // __FORWARDINGACTIONRULE_H__
#include "PacketDetectionInformation.h"
/**************************************************************************************************/
PacketDetectionInformation::PacketDetectionInformation(
u32 teid, u32 ueIpAddress, SourceInterface sourceInterface)
: mTeid(teid),
mUeIpAddress(ueIpAddress),
mSourceInterface(sourceInterface) {}
/**************************************************************************************************/
PacketDetectionInformation::~PacketDetectionInformation() {}
/**************************************************************************************************/
u32 PacketDetectionInformation::getTeid() {
return mTeid;
}
/**************************************************************************************************/
u32 PacketDetectionInformation::getUeIpAddress() {
return mUeIpAddress;
}
/**************************************************************************************************/
u32 PacketDetectionInformation::getSourceInterface() {
return mSourceInterface;
}
/**************************************************************************************************/
#ifndef __PACKETDETECTIONINFORMATION_H__
#define __PACKETDETECTIONINFORMATION_H__
#include <types.h>
class PacketDetectionInformation {
public:
enum SourceInterface {
INTERFACE_VALUE_ACCESS = 0,
INTERFACE_VALUE_CORE = 1,
INTERFACE_VALUE_SGI_LAN_N6_LAN = 2,
INTERFACE_VALUE_CP_FUNCTION = 3,
INTERFACE_VALUE_5G_VN_INTERNAL = 4
};
PacketDetectionInformation(
u32 teid, u32 ueIpAddress, SourceInterface sourceInterface);
virtual ~PacketDetectionInformation();
u32 getTeid();
u32 getUeIpAddress();
u32 getSourceInterface();
private:
u32 mTeid;
u32 mUeIpAddress;
SourceInterface mSourceInterface;
};
#endif // __PACKETDETECTIONINFORMATION_H__
#include "PacketDetectionRule.h"
/**************************************************************************************************/
PacketDetectionRule::PacketDetectionRule(
u32 precedence, std::shared_ptr<PacketDetectionInformation> pdi, u32 farId)
: mPrecedence(precedence), mPDI(pdi), mFarId(farId) {}
/**************************************************************************************************/
PacketDetectionRule::~PacketDetectionRule() {}
/**************************************************************************************************/
u32 PacketDetectionRule::getPrecedence() {
return mPrecedence;
}
/**************************************************************************************************/
std::shared_ptr<PacketDetectionInformation> PacketDetectionRule::getPDI() {
return mPDI;
}
/**************************************************************************************************/
u32 PacketDetectionRule::getFarId() {
return mFarId;
}
/**************************************************************************************************/
#ifndef __PACKETDETECTIONRULE_H__
#define __PACKETDETECTIONRULE_H__
#include "PacketDetectionInformation.h"
#include <ie/far_id.h>
#include <memory.h>
#include <types.h>
class PacketDetectionRule {
public:
PacketDetectionRule(
u32 precedence, std::shared_ptr<PacketDetectionInformation> mPDI,
u32 farId);
virtual ~PacketDetectionRule();
u32 getPrecedence();
std::shared_ptr<PacketDetectionInformation> getPDI();
u32 getFarId();
private:
u32 mPrecedence;
std::shared_ptr<PacketDetectionInformation> mPDI;
u32 mFarId;
};
#endif // __PACKETDETECTIONRULE_H__
#include <Session.h>
/**************************************************************************************************/
Session::Session(u64 seid) : mSeid(seid) {}
/**************************************************************************************************/
Session::~Session() {}
/**************************************************************************************************/
void Session::addPDR(std::shared_ptr<PacketDetectionRule> pPdr) {
mPDRs.push_back(pPdr);
mPDRs.sort(Session::comparePDR);
}
/**************************************************************************************************/
void Session::addFAR(std::shared_ptr<ForwardingActionRule> pFar) {
mFARs.push_back(pFar);
}
/**************************************************************************************************/
void Session::addPDR(std::shared_ptr<pfcp::pfcp_pdr> pPdr) {
// mpSession->pdrs
}
/**************************************************************************************************/
void Session::addFAR(std::shared_ptr<pfcp::pfcp_far> pFAR) {}
/**************************************************************************************************/
bool Session::comparePDR(
const std::shared_ptr<PacketDetectionRule>& first,
const std::shared_ptr<PacketDetectionRule>& second) {
return first->getPrecedence() < second->getPrecedence();
}
/**************************************************************************************************/
std::shared_ptr<PacketDetectionRule> Session::getHighestPrecedencePDR() {
return *mPDRs.begin();
}
/**************************************************************************************************/
#ifndef __SESSION_H__
#define __SESSION_H__
#include "PacketDetectionRule.h"
#include "ForwardingActionRule.h"
#include <list>
#include <vector>
#include <memory>
#include "pfcp_session.hpp"
#include "pfcp_pdr.hpp"
#include "pfcp_far.hpp"
class Session {
public:
Session(u64 seid);
virtual ~Session();
void addPDR(std::shared_ptr<PacketDetectionRule> pPdr);
void addFAR(std::shared_ptr<ForwardingActionRule> pFar);
void addPDR(std::shared_ptr<pfcp::pfcp_pdr> pPdr);
void addFAR(std::shared_ptr<pfcp::pfcp_far> pFAR);
static bool comparePDR(
const std::shared_ptr<PacketDetectionRule>& first,
const std::shared_ptr<PacketDetectionRule>& second);
std::shared_ptr<PacketDetectionRule> getHighestPrecedencePDR();
private:
std::list<std::shared_ptr<PacketDetectionRule>> mPDRs;
std::vector<std::shared_ptr<ForwardingActionRule>> mFARs;
u64 mSeid;
std::shared_ptr<pfcp::pfcp_session> mpSession;
};
#endif // __SESSION_H__
if (LibNL_FIND_REQUIRED)
message(" (required)")
else (LibNL_FIND_REQUIRED)
message(" (not required)")
endif (LibNL_FIND_REQUIRED)
find_path(LibNL_INCLUDE_DIR netlink/netlink.h
/usr/include
/usr/include/libnl3
/usr/local/include
/usr/local/include/libnl3
)
find_library(LibNL_LIBRARY NAMES nl nl-3)
find_library(LibNL_ROUTE_LIBRARY NAMES nl-route nl-route-3)
if (LibNL_INCLUDE_DIR AND LibNL_LIBRARY)
set(LibNL_FOUND TRUE)
endif (LibNL_INCLUDE_DIR AND LibNL_LIBRARY)
if (LibNL_FOUND)
if (NOT LibNL_FIND_QUIETLY)
set(LibNL_LIBRARIES ${LibNL_LIBRARY} ${LibNL_ROUTE_LIBRARY})
endif (NOT LibNL_FIND_QUIETLY)
ELSE (LibNL_FOUND)
if (LibNL_FIND_REQUIRED)
message("Netlink version 3 development packages cannot be found.")
message("In Debian/Ubuntu, they may be called:")
message("libnl-3-dev libnl-genl-3dev libnl-nf-3-dev libnl-route-3-dev")
message(FATAL_ERROR "Could not find netlink library.")
endif (LibNL_FIND_REQUIRED)
endif (LibNL_FOUND)
#include "GetNicInformation.hpp"
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <types.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <fstream>
#include <string>
#include <stdexcept>
#include <arpa/inet.h>
#include <sstream>
#define COMMAND_MAX_LENGTH 256
#define OUTPUT_MAX_LENGTH 256
/*---------------------------------------------------------------------------------------------------------------*/
// Function to read a value from a file
std::string readValueFromFile(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
std::cerr << "Error: Failed to open file " << path << std::endl;
return "";
}
std::string value;
file >> value;
file.close();
return value;
}
/*---------------------------------------------------------------------------------------------------------------*/
uint64_t NicInformationGetter::retrieveRate(std::string interface) {
// Paths to files containing interface information speed rate
std::string speedPath = "/sys/class/net/" + interface + "/speed";
// Read speed
std::string speed = readValueFromFile(speedPath);
uint64_t rate = 0;
std::istringstream iss(speed);
iss >> rate;
return rate * 1000;
}
/*---------------------------------------------------------------------------------------------------------------*/
uint64_t NicInformationGetter::retrieveCeil(std::string interface) {
// Paths to files containing interface information speed rate
std::string speedPath = "/sys/class/net/" + interface + "/speed";
// Read speed
std::string speed = readValueFromFile(speedPath);
uint64_t ceil = 0;
std::istringstream iss(speed);
iss >> ceil;
return ceil * 1000;
}
/*---------------------------------------------------------------------------------------------------------------*/
uint32_t NicInformationGetter::retrieveBurst(std::string interface) {
return 0;
}
/*---------------------------------------------------------------------------------------------------------------*/
uint32_t NicInformationGetter::retrieveCBurst(std::string interface) {
return 0;
}
#ifndef __GET_NIC_INFORMATION_HPP__
#define __GET_NIC_INFORMATION_HPP__
#include <string>
#include <memory>
#include <netinet/ether.h>
#include "logger.hpp"
class NicInformationGetter {
public:
/**
* @brief Construct a new Nic Information Getter object
*
*/
// NicInformationGetter();
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Retrieve the Transmission Rate of NIC
*
* @return uint32_t rate
*/
static uint64_t retrieveRate(std::string interface);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Retrieve the Ceil transmission of NIC
*
* @return uint32_t ceil
*/
static uint64_t retrieveCeil(std::string interface);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Retrieve the Rate Buffer of the NIC
*
* @return uint32_t rate_buffer
*/
static uint32_t retrieveBurst(std::string interface);
/*---------------------------------------------------------------------------------------------------------------*/
/**
* @brief Retrieve the Ceil Buffer of the NIC
*
* @return uint32_t ceil_buffer
*/
static uint32_t retrieveCBurst(std::string interface);
/*---------------------------------------------------------------------------------------------------------------*/
private:
// static const std::string INTERFACE_DIR = "/sys/class/net/";
};
#endif //__GET_NIC_INFORMATION_HPP__
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_ENDIAN__
#define __BPF_ENDIAN__
/*
* Isolate byte #n and put it into byte #m, for __u##b type.
* E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
* 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
* 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
* 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
* 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
*/
#define ___bpf_mvb(x, b, n, m) \
((__u##b) (x) << (b - (n + 1) * 8) >> (b - 8) << (m * 8))
#define ___bpf_swab16(x) \
((__u16) (___bpf_mvb(x, 16, 0, 1) | ___bpf_mvb(x, 16, 1, 0)))
#define ___bpf_swab32(x) \
((__u32) (___bpf_mvb(x, 32, 0, 3) | ___bpf_mvb(x, 32, 1, 2) | ___bpf_mvb(x, 32, 2, 1) | ___bpf_mvb(x, 32, 3, 0)))
#define ___bpf_swab64(x) \
( \
( \
__u64) (___bpf_mvb(x, 64, 0, 7) | ___bpf_mvb(x, 64, 1, 6) | ___bpf_mvb(x, 64, 2, 5) | ___bpf_mvb(x, 64, 3, 4) | ___bpf_mvb(x, 64, 4, 3) | ___bpf_mvb(x, 64, 5, 2) | ___bpf_mvb(x, 64, 6, 1) | ___bpf_mvb(x, 64, 7, 0)))
/* LLVM's BPF target selects the endianness of the CPU
* it compiles on, or the user specifies (bpfel/bpfeb),
* respectively. The used __BYTE_ORDER__ is defined by
* the compiler, we cannot rely on __BYTE_ORDER from
* libc headers, since it doesn't reflect the actual
* requested byte order.
*
* Note, LLVM's BPF target has different __builtin_bswapX()
* semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
* in bpfel and bpfeb case, which means below, that we map
* to cpu_to_be16(). We could use it unconditionally in BPF
* case, but better not rely on it, so that this header here
* can be used from application and BPF program side, which
* use different targets.
*/
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define __bpf_ntohs(x) __builtin_bswap16(x)
#define __bpf_htons(x) __builtin_bswap16(x)
#define __bpf_constant_ntohs(x) ___bpf_swab16(x)
#define __bpf_constant_htons(x) ___bpf_swab16(x)
#define __bpf_ntohl(x) __builtin_bswap32(x)
#define __bpf_htonl(x) __builtin_bswap32(x)
#define __bpf_constant_ntohl(x) ___bpf_swab32(x)
#define __bpf_constant_htonl(x) ___bpf_swab32(x)
#define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
#define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
#define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x)
#define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define __bpf_ntohs(x) (x)
#define __bpf_htons(x) (x)
#define __bpf_constant_ntohs(x) (x)
#define __bpf_constant_htons(x) (x)
#define __bpf_ntohl(x) (x)
#define __bpf_htonl(x) (x)
#define __bpf_constant_ntohl(x) (x)
#define __bpf_constant_htonl(x) (x)
#define __bpf_be64_to_cpu(x) (x)
#define __bpf_cpu_to_be64(x) (x)
#define __bpf_constant_be64_to_cpu(x) (x)
#define __bpf_constant_cpu_to_be64(x) (x)
#else
#error "Fix your compiler's __BYTE_ORDER__?!"
#endif
#define bpf_htons(x) \
(__builtin_constant_p(x) ? __bpf_constant_htons(x) : __bpf_htons(x))
#define bpf_ntohs(x) \
(__builtin_constant_p(x) ? __bpf_constant_ntohs(x) : __bpf_ntohs(x))
#define bpf_htonl(x) \
(__builtin_constant_p(x) ? __bpf_constant_htonl(x) : __bpf_htonl(x))
#define bpf_ntohl(x) \
(__builtin_constant_p(x) ? __bpf_constant_ntohl(x) : __bpf_ntohl(x))
#define bpf_cpu_to_be64(x) \
(__builtin_constant_p(x) ? __bpf_constant_cpu_to_be64(x) : \
__bpf_cpu_to_be64(x))
#define bpf_be64_to_cpu(x) \
(__builtin_constant_p(x) ? __bpf_constant_be64_to_cpu(x) : \
__bpf_be64_to_cpu(x))
#endif /* __BPF_ENDIAN__ */
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.
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2019 Facebook */
#ifndef __LIBBPF_LIBBPF_UTIL_H
#define __LIBBPF_LIBBPF_UTIL_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Use these barrier functions instead of smp_[rw]mb() when they are
* used in a libbpf header file. That way they can be built into the
* application that uses libbpf.
*/
#if defined(__i386__) || defined(__x86_64__)
#define libbpf_smp_rmb() asm volatile("" : : : "memory")
#define libbpf_smp_wmb() asm volatile("" : : : "memory")
#define libbpf_smp_mb() \
asm volatile("lock; addl $0,-4(%%rsp)" : : : "memory", "cc")
/* Hinders stores to be observed before older loads. */
#define libbpf_smp_rwmb() asm volatile("" : : : "memory")
#elif defined(__aarch64__)
#define libbpf_smp_rmb() asm volatile("dmb ishld" : : : "memory")
#define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory")
#define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory")
#define libbpf_smp_rwmb() libbpf_smp_mb()
#elif defined(__arm__)
/* These are only valid for armv7 and above */
#define libbpf_smp_rmb() asm volatile("dmb ish" : : : "memory")
#define libbpf_smp_wmb() asm volatile("dmb ishst" : : : "memory")
#define libbpf_smp_mb() asm volatile("dmb ish" : : : "memory")
#define libbpf_smp_rwmb() libbpf_smp_mb()
#else
/* Architecture missing native barrier functions. */
#define libbpf_smp_rmb() __sync_synchronize()
#define libbpf_smp_wmb() __sync_synchronize()
#define libbpf_smp_mb() __sync_synchronize()
#define libbpf_smp_rwmb() __sync_synchronize()
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (C) 2021 Facebook */
#ifndef __LIBBPF_VERSION_H
#define __LIBBPF_VERSION_H
#define LIBBPF_MAJOR_VERSION 1
#define LIBBPF_MINOR_VERSION 5
#endif /* __LIBBPF_VERSION_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -12,9 +12,9 @@ include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/${MOUNTED_COMMON}/logger)
add_library(interfaces STATIC
${CMAKE_CURRENT_SOURCE_DIR}/ForwardingActionRulesImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/PacketDetectionRulesImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/RulesUtilitiesImpl.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/ForwardingActionRulesImpl.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/PacketDetectionRulesImpl.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/RulesUtilitiesImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SessionBpfImpl.cpp
)
......
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.
......@@ -45,6 +45,7 @@ include_directories(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/common_model)
add_library (SIMPLE_SWITCH STATIC
pfcp_far.cpp
pfcp_pdr.cpp
pfcp_qer.cpp
pfcp_session.cpp
pfcp_switch.cpp
simple_switch.cpp
......
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