Commit 72314533 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

remove spgw-u

parent fb47b34e
#!/bin/bash
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the Apache License, Version 2.0 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
# file build_spgwu
# brief
# author Lionel Gauthier
# company Eurecom
# email: lionel.gauthier@eurecom.fr
#
set -o pipefail
INSTALL_DIR=/usr/local/bin
################################
# include helper functions
################################
THIS_SCRIPT_PATH=$(dirname $(readlink -f $0))
source $THIS_SCRIPT_PATH/build_helper.spgw
function help()
{
echo_error " "
echo_error "Usage: build_spgwu [OPTION]..."
echo_error "Build the SPGW-U executable."
echo_error " "
echo_error "Options:"
echo_error "Mandatory arguments to long options are mandatory for short options too."
echo_error " -b, --build-type Build type as defined in cmake, allowed values are: Debug Release RelWithDebInfo MinSizeRel"
echo_error " -c, --clean Clean the build generated files: config, object, executable files (build from scratch)"
echo_error " -f, --force No interactive script for installation of software packages."
echo_error " -h, --help Print this help."
echo_error " -I, --install-deps Check installed software necessary to build and run S/P-GW-U (support $SUPPORTED_DISTRO)."
echo_error " -i, --install-min-deps Check installed software necessary to run a statically linked S/P-GW-U (support $SUPPORTED_DISTRO)."
echo_error " -j, --jobs Multiple jobs for compiling."
echo_error " -v, --verbose Build process verbose."
echo_error " -V, --Verbose CMake only build process verbose, display compilation warnings and errors."
echo_error " "
}
function main()
{
local -i clean=0
local -i force=0
local -i debug=0
local -i verbose=0
local -i var_check_install_min_deps=0
local -i var_check_install_deps=0
local cmake_args=" "
export make_args=" "
until [ -z "$1" ]
do
case "$1" in
-b | --build-type)
list_include_item "Debug Release RelWithDebInfo MinSizeRel" $2
[[ $? -ne 0 ]] && echo_error "Build type $2 not recognized" && return $?
cmake_args="$cmake_args -DCMAKE_BUILD_TYPE=$2"
list_include_item "Debug" $2
[[ $? -ne 0 ]] && debug=1
shift 2;
;;
-c | --clean)
clean=1
echo "Clean the build generated files (build from scratch)"
shift;
;;
-f | --force)
force=1
echo "Force set (no interactive)"
shift;
;;
-h | --help)
help
shift;
return 0
;;
-I | --install-deps)
echo "Check installed software necessary to build and run S/P-GW-U (support $SUPPORTED_DISTRO):"
set_openair_env
var_check_install_deps=1
shift;
;;
-i | --install-min-deps)
echo "Check installed software necessary to run S/P-GW-U (support $SUPPORTED_DISTRO):"
set_openair_env
var_check_install_min_deps=1
shift;
;;
-j | --jobs)
make_args="$make_args -j`nproc`"
shift;
;;
-v | --verbose)
echo "Make build process verbose"
cmake_args="$cmake_args -DCMAKE_VERBOSE_MAKEFILE=ON"
make_args="VERBOSE=1 $make_args"
verbose=1
shift;
;;
-V | --Verbose)
echo "CMake build process verbose"
verbose=1
shift;
;;
*)
echo "Unknown option $1"
help
return 1
;;
esac
done
if [ ! -d /usr/local/etc/oai ]; then
$SUDO mkdir -m 777 -p /usr/local/etc/oai
fi
set_openair_env
local dlog=$OPENAIRCN_DIR/build/log
local dext=$OPENAIRCN_DIR/build/ext
mkdir -m 777 -p $dlog
mkdir -m 777 -p $dext
if [ $var_check_install_min_deps -gt 0 ];then
disable_ipv6
check_install_spgwu_min_deps $force $debug
if [[ $? -ne 0 ]]; then
echo_error "Error: SPGW-U minimal deps installation failed"
return 1
else
echo_success "SPGW-U minimal deps installation successful"
echo_warning "SPGW-U not compiled, to compile it, re-run build_spgwu without -i option"
return 0
fi
fi
if [ $var_check_install_deps -gt 0 ];then
disable_ipv6
check_install_spgwu_deps $force $debug
if [[ $? -ne 0 ]]; then
echo_error "Error: SPGW-U deps installation failed"
return 1
else
echo_success "SPGW-U deps installation successful"
echo_warning "SPGW-U not compiled, to compile it, re-run build_spgwu without -I option"
return 0
fi
fi
cmake_args="$cmake_args -DBUILD_SHARED_LIBS=OFF"
##############################################################################
# Clean
##############################################################################
cd $OPENAIRCN_DIR/build/spgw_u
if [ $clean -ne 0 ]; then
if [[ $verbose -eq 1 ]]; then
echo "Cleaning S/P-GW-U: generated configuration files, obj files, executable"
fi
rm -Rf $OPENAIRCN_DIR/build/spgw_u/build 2>&1
mkdir -m 777 -p -v build
fi
##############################################################################
# Compile S/P-GW
##############################################################################
cd $OPENAIRCN_DIR/build/spgw_u
if [ ! -d ./build ]; then
mkdir -m 777 -p -v build
fi
cd ./build
$CMAKE $cmake_args .. > /dev/null
ret=$?;[[ $ret -ne 0 ]] && return $ret
compilations spgw_u spgwu $OPENAIRCN_DIR/build/spgw_u/build/spgwu $verbose
ret=$?;[[ $ret -ne 0 ]] && return $ret
# For daemon should not be group writable
$SUDO chmod 755 $OPENAIRCN_DIR/build/spgw_u/build/spgwu
$SUDO cp -upv $OPENAIRCN_DIR/build/spgw_u/build/spgwu $INSTALL_DIR && $SUDO chmod 755 $INSTALL_DIR/spgwu && echo_success "spgwu installed"
return 0
}
main "$@"
# prompt has been removed for easier Ctrl+C Ctrl+V
sudo ifconfig eno1:sxu 172.55.55.102 up # SPGW-U SXab interface
sudo ifconfig eno1:s1u 192.168.248.159 up # SPGW-U S1U interface
INSTANCE=1
PREFIX='/usr/local/etc/oai'
sudo mkdir -m 0777 -p $PREFIX
cp ../../etc/spgw_u.conf $PREFIX
declare -A SPGWU_CONF
SPGWU_CONF[@INSTANCE@]=$INSTANCE
SPGWU_CONF[@PREFIX@]=$PREFIX
SPGWU_CONF[@PID_DIRECTORY@]='/var/run'
SPGWU_CONF[@SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP@]='eno1:s1u'
SPGWU_CONF[@SGW_INTERFACE_NAME_FOR_SX@]='eno1:sxu'
SPGWU_CONF[@SGW_INTERFACE_NAME_FOR_SGI@]='eno1'
for K in "${!SPGWU_CONF[@]}"; do
egrep -lRZ "$K" $PREFIX | xargs -0 -l sed -i -e "s|$K|${SPGWU_CONF[$K]}|g"
ret=$?;[[ ret -ne 0 ]] && echo "Tried to replace $K with ${SPGWU_CONF[$K]}"
done
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
cmake_minimum_required (VERSION 3.0.2)
# Override options for SPGW
set ( PACKAGE_NAME "S/P-GW-U" )
set ( STATIC_LINKING False )
#############################################
# Base directories, compatible with legacy OAI building
################################################
set (OPENAIRCN_DIR $ENV{OPENAIRCN_DIR})
set (BUILD_TOP_DIR ${OPENAIRCN_DIR}/build)
set (SRC_TOP_DIR $ENV{OPENAIRCN_DIR}/src)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../src/oai_spgwu/CMakeLists.txt)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/spgwu ${CMAKE_CURRENT_BINARY_DIR}/spgw_u)
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
SPGW-U =
{
INSTANCE = @INSTANCE@; # 0 is the default
PID_DIRECTORY = "@PID_DIRECTORY@"; # /var/run is the default
#ITTI_TASKS :
#{
#ITTI_TIMER_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 85;
#};
#S1U_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#SX_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#ASYNC_CMD_SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 84;
#};
#};
INTERFACES :
{
S1U_S12_S4_UP :
{
# S-GW binded interface for S1-U communication (GTPV1-U) can be ethernet interface, virtual ethernet interface, we don't advise wireless interfaces
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP@"; # STRING, interface name, YOUR NETWORK CONFIG HERE
IPV4_ADDRESS = "read"; # STRING, CIDR or "read to let app read interface configured IP address
#PORT = 2152; # Default is 2152
#SCHED_PARAMS :
#{
#CPU_ID = 2;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 98;
#};
};
SX :
{
# S/P-GW binded interface for SX communication
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_SX@"; # STRING, interface name
IPV4_ADDRESS = "read"; # STRING, CIDR or "read" to let app read interface configured IP address
#PORT = 8805; # Default is 8805
#SCHED_PARAMS :
#{
#CPU_ID = 1;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 95;
#};
};
SGI :
{
# No config to set, the software will set the SGi interface to the interface used for the default route.
INTERFACE_NAME = "@SGW_INTERFACE_NAME_FOR_SGI@"; # STRING, interface name or "default_gateway"
IPV4_ADDRESS = "read"; # STRING, CIDR or "read" to let app read interface configured IP address
#SCHED_PARAMS :
#{
#CPU_ID = 3;
#SCHED_POLICY = "SCHED_FIFO"; # Values in { SCHED_OTHER, SCHED_IDLE, SCHED_BATCH, SCHED_FIFO, SCHED_RR }
#SCHED_PRIORITY = 98;
#};
};
};
PDN_NETWORK_LIST = (
{NETWORK_IPV4 = "12.1.1.0/24"; NETWORK_IPV6 = "2001:1:2::0/64"; SNAT = "yes";},
{NETWORK_IPV4 = "12.1.2.0/24"; SNAT = "no";},
{NETWORK_IPV4 = "192.169.0.0/24"; SNAT = "no";},
{NETWORK_IPV4 = "192.170.0.0/24"; SNAT = "no";},
{NETWORK_IPV4 = "192.171.0.0/24"; SNAT = "no";}
);
SPGW-C_LIST = (
{IPV4_ADDRESS="172.55.55.101" ;}
);
};
This diff is collapsed.
/*
* Copyright (c) 2019 EURECOM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "async_shell_cmd.hpp"
#include "common_defs.h"
#include "itti.hpp"
#include "logger.hpp"
#include "options.hpp"
#include "pfcp_switch.hpp"
#include "pid_file.hpp"
#include "spgwu_app.hpp"
#include "spgwu_config.hpp"
#include <boost/asio.hpp>
#include <iostream>
#include <thread>
#include <signal.h>
#include <stdint.h>
#include <unistd.h> // get_pid(), pause()
#include <vector>
using namespace spgwu;
using namespace util;
using namespace std;
itti_mw *itti_inst = nullptr;
async_shell_cmd *async_shell_cmd_inst = nullptr;
pfcp_switch *pfcp_switch_inst = nullptr;
spgwu_app *spgwu_app_inst = nullptr;
spgwu_config spgwu_cfg;
boost::asio::io_service io_service;
//------------------------------------------------------------------------------
void my_app_signal_handler(int s){
std::cout << "Caught signal " << s << std::endl;
Logger::system().startup( "exiting" );
itti_inst->send_terminate_msg(TASK_SPGWU_APP);
itti_inst->wait_tasks_end();
std::cout << "Freeing Allocated memory..." << std::endl;
if (async_shell_cmd_inst) delete async_shell_cmd_inst; async_shell_cmd_inst = nullptr;
std::cout << "Async Shell CMD memory done." << std::endl;
if (itti_inst) delete itti_inst; itti_inst = nullptr;
std::cout << "ITTI memory done." << std::endl;
if (spgwu_app_inst) delete spgwu_app_inst; spgwu_app_inst = nullptr;
std::cout << "SPGW-U APP memory done." << std::endl;
std::cout << "Freeing Allocated memory done" << std::endl;
exit(0);
}
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
// Command line options
if ( !Options::parse( argc, argv ) )
{
std::cout << "Options::parse() failed" << std::endl;
return 1;
}
// Logger
Logger::init( "spgwu" , Options::getlogStdout() , Options::getlogRotFilelog());
Logger::spgwu_app().startup( "Options parsed" );
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_app_signal_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
// Config
spgwu_cfg.load(Options::getlibconfigConfig());
spgwu_cfg.display();
// Inter task Interface
itti_inst = new itti_mw();
itti_inst->start(spgwu_cfg.itti.itti_timer_sched_params);
// system command
async_shell_cmd_inst = new async_shell_cmd(spgwu_cfg.itti.async_cmd_sched_params);
// PGW application layer
spgwu_app_inst = new spgwu_app(Options::getlibconfigConfig());
// PID file
// Currently hard-coded value. TODO: add as config option.
string pid_file_name = get_exe_absolute_path("/var/run", spgwu_cfg.instance);
if (! is_pid_file_lock_success(pid_file_name.c_str())) {
Logger::spgwu_app().error( "Lock PID file %s failed\n", pid_file_name.c_str());
exit (-EDEADLK);
}
FILE *fp = NULL;
std::string filename = fmt::format("/tmp/spgwu_{}.status", getpid());
fp = fopen(filename.c_str(), "w+");
fprintf(fp, "STARTED\n");
fflush(fp);
fclose(fp);
// once all udp servers initialized
io_service.run();
pause();
return 0;
}
/*
* Copyright (c) 2017 Sprint
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "options.hpp"
int Options::options;
std::string Options::m_libconfigcfg;
bool Options::m_log_rot_file_log;
bool Options::m_log_stdout;
void Options::help()
{
std::cout << std::endl
<< "Usage: spgwu [OPTIONS]..." << std::endl
<< " -h, --help Print help and exit" << std::endl
<< " -c, --libconfigcfg filename Read the application configuration from this file." << std::endl
<< " -o, --stdoutlog Send the application logs to STDOUT fd." << std::endl
<< " -r, --rotatelog Send the application logs to local file (in current working directory)." << std::endl
;
}
bool Options::parse( int argc, char **argv ){
bool ret = true;
ret = parseInputOptions( argc, argv );
ret &= validateOptions();
return ret;
}
bool Options::validateOptions(){
return (
(options & libconfigcfg)
);
}
bool Options::parseInputOptions( int argc, char **argv )
{
int c;
int option_index = 0;
bool result = true;
struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "libconfigcfg", required_argument, NULL, 'f' },
{ "stdoutlog", no_argument, NULL, 'o' },
{ "rotatelog", no_argument, NULL, 'r' },
{ NULL,0,NULL,0 }
};
// Loop on arguments
while (1)
{
c = getopt_long(argc, argv, "horc:", long_options, &option_index );
if (c == -1)
break; // Exit from the loop.
switch (c)
{
case 'h': { help(); exit(0); break; }
case 'c': { m_libconfigcfg = optarg; options |= libconfigcfg; break; }
case 'o': { m_log_stdout = true; options |= log_stdout; break; }
case 'r': { m_log_rot_file_log = true; options |= log_rot_file_log; break; }
case '?':
{
switch ( optopt )
{
case 'c': { std::cout << "Option -l (libconfig config) requires an argument" << std::endl; break; }
case 'o': { std::cout << "Option -o do not requires an argument, can be also set with option -r." << std::endl; break; }
case 'r': { std::cout << "Option -r do not requires an argument, can be also set with option -o." << std::endl; break; }
default: { std::cout << "Unrecognized option [" << c << "]" << std::endl; break; }
}
result = false;
break;
}
default:
{
std::cout << "Unrecognized option [" << c << "]" << std::endl;
result = false;
}
}
}
return result;
}
/*
* Copyright (c) 2017 Sprint
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPTIONS_H
#define __OPTIONS_H
#include <stdint.h>
#include <string>
class Options
{
public:
static bool parse( int argc, char **argv );
static bool parseInputOptions( int argc, char **argv );
static bool parseJson();
static bool validateOptions();
static const std::string &getlibconfigConfig() { return m_libconfigcfg; }
static const bool &getlogRotFilelog() { return m_log_rot_file_log; }
static const bool &getlogStdout() { return m_log_stdout; }
private:
enum OptionsSelected {
libconfigcfg = 0x01,
log_stdout = 0x02,
log_rot_file_log = 0x04
};
static void help();
static int options;
static bool m_log_rot_file_log;
static bool m_log_stdout;
static std::string m_libconfigcfg;
};
#endif // #define __OPTIONS_H
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/gtpv1u)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/oai_spgwu)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/spgwu)
include_directories(${SRC_TOP_DIR}/spgwu/simpleswitch)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
add_library (SPGWU STATIC
spgwu_pfcp_association.cpp
spgwu_app.cpp
spgwu_config.cpp
spgwu_sx.cpp
)
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/gtpv1u)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/oai_spgwu)
include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/spgwu)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
#find_library(FOLLY folly)
add_library (SPGW_SWITCH STATIC
pfcp_far.cpp
pfcp_pdr.cpp
pfcp_session.cpp
pfcp_switch.cpp
spgwu_s1u.cpp
)
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_far.cpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#include "pfcp_far.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_config.hpp"
#include "spgwu_s1u.hpp"
using namespace pfcp;
using namespace spgwu;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_s1u *spgwu_s1u_inst;
extern spgwu_config spgwu_cfg;
//------------------------------------------------------------------------------
void pfcp_far::apply_forwarding_rules(struct iphdr* const iph, const std::size_t num_bytes, bool& nocp, bool& buff)
{
// TODO dupl
// TODO nocp
// TODO buff
//Logger::pfcp_switch().info( "pfcp_far::apply_forwarding_rules FAR id %4x ", far_id.far_id);
if (apply_action.forw) {
if (forwarding_parameters.first) {
if (forwarding_parameters.second.destination_interface.first) {
if (forwarding_parameters.second.destination_interface.second.interface_value == INTERFACE_VALUE_ACCESS) {
if (forwarding_parameters.second.outer_header_creation.first) {
switch (forwarding_parameters.second.outer_header_creation.second.outer_header_creation_description) {
case OUTER_HEADER_CREATION_GTPU_UDP_IPV4:
spgwu_s1u_inst->send_g_pdu(forwarding_parameters.second.outer_header_creation.second.ipv4_address,
spgwu_cfg.s1_up.port,
forwarding_parameters.second.outer_header_creation.second.teid,
reinterpret_cast<const char*>(iph), num_bytes);
break;
case OUTER_HEADER_CREATION_GTPU_UDP_IPV6:
spgwu_s1u_inst->send_g_pdu(forwarding_parameters.second.outer_header_creation.second.ipv6_address,
spgwu_cfg.s1_up.port,
forwarding_parameters.second.outer_header_creation.second.teid,
reinterpret_cast<const char*>(iph), num_bytes);
break;
case OUTER_HEADER_CREATION_UDP_IPV4: // TODO
case OUTER_HEADER_CREATION_UDP_IPV6: // TODO
default:;
}
}
} else if (forwarding_parameters.second.destination_interface.second.interface_value == INTERFACE_VALUE_CORE) {
pfcp_switch_inst->send_to_core(reinterpret_cast<char* const>(iph), num_bytes);
} else {
}
} else {
// Mandatory IE
}
} else {
// Mandatory if FW set in apply action
}
} else if (apply_action.drop) {
// DONE !
} else if (apply_action.buff) {
buff = true;
}
if (apply_action.nocp) {
nocp = true;
}
}
//------------------------------------------------------------------------------
bool pfcp_far::update(const pfcp::update_far& update, uint8_t& cause_value)
{
update.get(apply_action);
if (update.update_forwarding_parameters.first) {
forwarding_parameters.second.update(update.update_forwarding_parameters.second);
if (update.update_forwarding_parameters.second.pfcpsmreq_flags.first) {
// TODO
}
}
if (update.update_duplicating_parameters.first) {
duplicating_parameters.second.update(update.update_duplicating_parameters.second);
}
if (update.get(bar_id.second)) bar_id.first = true;
return true;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_far.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_PFCP_FAR_HPP_SEEN
#define FILE_PFCP_FAR_HPP_SEEN
#include <linux/ip.h>
#include <linux/ipv6.h>
#include "msg_pfcp.hpp"
namespace pfcp {
class pfcp_far {
public:
pfcp::far_id_t far_id;
pfcp::apply_action_t apply_action;
std::pair<bool, pfcp::forwarding_parameters> forwarding_parameters;
std::pair<bool, pfcp::duplicating_parameters> duplicating_parameters;
std::pair<bool, pfcp::bar_id_t> bar_id;
pfcp_far() : far_id(), apply_action(), forwarding_parameters(), duplicating_parameters(), bar_id() {}
explicit pfcp_far(const pfcp::create_far& c): forwarding_parameters(c.forwarding_parameters), duplicating_parameters(c.duplicating_parameters), bar_id(c.bar_id)
{
far_id = c.far_id.second;
apply_action = c.apply_action.second;
}
pfcp_far(const pfcp_far& c): far_id(c.far_id), apply_action(c.apply_action),
forwarding_parameters(c.forwarding_parameters), duplicating_parameters(c.duplicating_parameters),
bar_id(c.bar_id) {
}
//virtual ~pfcp_far() {};
void set(const pfcp::far_id_t& v) {far_id = v;}
void set(const pfcp::apply_action_t& v) {apply_action = v;}
void set(const pfcp::forwarding_parameters& v) {forwarding_parameters.first = true; forwarding_parameters.second = v;}
void set(const pfcp::duplicating_parameters& v) {duplicating_parameters.first = true; duplicating_parameters.second = v;}
void set(const pfcp::bar_id_t& v) {bar_id.first = true; bar_id.second = v;}
bool get(pfcp::far_id_t& v) const {v = far_id;return true;}
bool get(pfcp::apply_action_t& v) const {v = apply_action;return true;}
bool get(pfcp::forwarding_parameters& v) const {if (forwarding_parameters.first) {v = forwarding_parameters.second;return true;}return false;}
bool get(pfcp::duplicating_parameters& v) const {if (duplicating_parameters.first) {v = duplicating_parameters.second;return true;}return false;}
bool get(pfcp::bar_id_t& v) const {if (bar_id.first) {v = bar_id.second;return true;}return false;}
bool update(const pfcp::update_far& update, uint8_t& cause_value);
void apply_forwarding_rules(struct iphdr* const iph, const std::size_t num_bytes, bool& nocp, bool& buff);
};
}
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_pdr.cpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#include "common_defs.h"
#include "endian.h"
#include "pfcp_pdr.hpp"
#include "spgwu_sx.hpp"
using namespace pfcp;
extern spgwu::spgwu_sx *spgwu_sx_inst;
//------------------------------------------------------------------------------
bool pfcp_pdr::look_up_pack_in_access(struct iphdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint, const uint32_t tunnel_id)
{
// implicit packet arrives from ACCESS interface
if (outer_header_removal.first) {
if (outer_header_removal.second.outer_header_removal_description != OUTER_HEADER_REMOVAL_GTPU_UDP_IPV4) {
return false;
}
} else {
//IPV4/UDP/GTP header already removed
return false;
}
if (pdi.first) {
if (pdi.second.source_interface.first) {
if (pdi.second.source_interface.second.interface_value != INTERFACE_VALUE_ACCESS) {
return false;
}
}
// local_fteid should be fine since pdr created for this fteid
if (pdi.second.local_fteid.first) {
if (pdi.second.local_fteid.second.teid != tunnel_id) {
return false;
}
}
if (pdi.second.ue_ip_address.first) {
if (!pdi.second.ue_ip_address.second.v4) {
return false;
}
if (pdi.second.ue_ip_address.second.ipv4_address.s_addr != iph->saddr) {
return false;
}
}
// SDF filter
if (pdi.second.sdf_filter.first) {
// TODO (create ss_pdi_t with ss_sdf_filter_t with optimized flow description matching )
return true;
}
return true; // No SDF filter actually
} else {
// Mandatory IE
return false;
}
}
//------------------------------------------------------------------------------
bool pfcp_pdr::look_up_pack_in_core(struct iphdr* const iph, const std::size_t num_bytes)
{
// implicit packet arrives from CORE interface
if (outer_header_removal.first) {
//TODO ... when necessary (split U)
//Logger::pfcp_switch().info( "look_up_pack_in_core failed PDR id %4x, cause outer_header_removal present ", pdr_id.rule_id);
return false;
}
//if (pdi.second.source_interface.second.interface_value != INTERFACE_VALUE_CORE) {
// return false;
//}
if (pdi.second.ue_ip_address.first) {
if (!pdi.second.ue_ip_address.second.v4) {
//Logger::pfcp_switch().info( "look_up_pack_in_core failed PDR id %4x, cause ue_ip_address not present ", pdr_id.rule_id);
return false;
}
if (pdi.second.ue_ip_address.second.ipv4_address.s_addr != iph->daddr) {
//Logger::pfcp_switch().info( "look_up_pack_in_core failed PDR id %4x, cause PDR ue_ip_address %8X do not match IP dest %8X of packet ",
// pdr_id.rule_id, pdi.second.ue_ip_address.second.ipv4_address.s_addr, iph->daddr);
return false;
}
}
// SDF filters TODO vector
//if (pdi.second.sdf_filter.first) {
// TODO (create ss_pdi_t with ss_sdf_filter_t with optimized flow description matching )
return true;
//}
//return false;
}
//------------------------------------------------------------------------------
bool pfcp_pdr::update(const pfcp::update_pdr& update, uint8_t& cause_value)
{
if (update.get(outer_header_removal.second)) outer_header_removal.first = true;
if (update.get(precedence.second)) precedence.first = true;
if (update.get(pdi.second)) pdi.first = true;
if (update.get(far_id.second)) far_id.first = true;
if (update.get(urr_id.second)) urr_id.first = true;
if (update.get(qer_id.second)) qer_id.first = true;
// TODO activate_predefined_rules
// TODO deactivate_predefined_rules
return true;
}
//------------------------------------------------------------------------------
void pfcp_pdr::buffering_requested(const char *buffer, const std::size_t num_bytes)
{
Logger::spgwu_sx().warn( "TODO pfcp_pdr::buffering_requested()");
/*
// TODO find smarter solution
char filename[] = "/tmp/buff_pdrzzzxxxyyy.XXXXXX";
int fd = mkstemp(filename);
if (fd == -1) return 1;
write(fd, buffer, num_bytes);
close(fd);
unlink(filename);
num_packets++
*/
}
//------------------------------------------------------------------------------
void pfcp_pdr::notify_cp_requested(std::shared_ptr<pfcp::pfcp_session> session)
{
if (not notified_cp) {
Logger::spgwu_sx().trace( "notify_cp_requested()");
notified_cp = true;
pfcp::pfcp_session_report_request h;
pfcp::report_type_t report = {};
report.dldr = 1;
pfcp::downlink_data_report dl_data_report;
dl_data_report.set(pdr_id);
h.set(report);
h.set(dl_data_report);
spgwu_sx_inst->send_sx_msg(session->cp_fseid, h);
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_pdr.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_PFCP_PDR_HPP_SEEN
#define FILE_PFCP_PDR_HPP_SEEN
#include <linux/ip.h>
#include <linux/ipv6.h>
#include "endpoint.hpp"
#include "msg_pfcp.hpp"
#include <mutex>
namespace pfcp {
class pfcp_session;
class pfcp_pdr {
public:
mutable std::mutex lock;
uint64_t local_seid;
pfcp::pdr_id_t pdr_id;
std::pair<bool, pfcp::precedence_t> precedence;
std::pair<bool, pfcp::pdi> pdi;
std::pair<bool, pfcp::outer_header_removal_t> outer_header_removal;
std::pair<bool, pfcp::far_id_t> far_id;
std::pair<bool, pfcp::urr_id_t> urr_id;
std::pair<bool, pfcp::qer_id_t> qer_id;
std::pair<bool, pfcp::activate_predefined_rules_t> activate_predefined_rules;
bool notified_cp;
explicit pfcp_pdr(uint64_t lseid) : lock(), local_seid(lseid), pdr_id(), precedence(), pdi(), outer_header_removal(), far_id(), urr_id(), qer_id(), activate_predefined_rules(), notified_cp(false) {}
explicit pfcp_pdr(const pfcp::create_pdr& c) :
lock(), local_seid(0), pdr_id(c.pdr_id.second), precedence(c.precedence), pdi(c.pdi), outer_header_removal(c.outer_header_removal),
far_id(c.far_id), urr_id(c.urr_id), qer_id(c.qer_id), activate_predefined_rules(c.activate_predefined_rules), notified_cp(false)
{}
pfcp_pdr(const pfcp_pdr& c) : lock(), precedence(c.precedence), pdi(c.pdi), outer_header_removal(c.outer_header_removal),
far_id(c.far_id), urr_id(c.urr_id), qer_id(c.qer_id), activate_predefined_rules(c.activate_predefined_rules),
notified_cp(c.notified_cp)
{
local_seid = c.local_seid;
pdr_id = c.pdr_id;
}
//virtual ~pfcp_pdr() {};
void set(const uint64_t& v) {local_seid = v;}
void set(const pfcp::pdr_id_t& v) {pdr_id = v;}
void set(const pfcp::precedence_t& v) {precedence.first = true; precedence.second = v;}
void set(const pfcp::pdi& v) {pdi.first = true; pdi.second = v;}
void set(const pfcp::outer_header_removal_t& v) {outer_header_removal.first = true; outer_header_removal.second = v;}
void set(const pfcp::far_id_t& v) {far_id.first = true; far_id.second = v;}
void set(const pfcp::urr_id_t& v) {urr_id.first = true; urr_id.second = v;}
void set(const pfcp::qer_id_t& v) {qer_id.first = true; qer_id.second = v;}
void set(const pfcp::activate_predefined_rules_t& v) {activate_predefined_rules.first = true; activate_predefined_rules.second = v;}
bool get(uint64_t& v) const {v = local_seid;return true;}
bool get(pfcp::pdr_id_t& v) const {v = pdr_id;return true;}
bool get(pfcp::precedence_t& v) const {if (precedence.first) {v = precedence.second;return true;}return false;}
bool get(pfcp::pdi& v) const {if (pdi.first) {v = pdi.second;return true;}return false;}
bool get(pfcp::outer_header_removal_t& v) const {if (outer_header_removal.first) {v = outer_header_removal.second;return true;}return false;}
bool get(pfcp::far_id_t& v) const {if (far_id.first) {v = far_id.second;return true;}return false;}
bool get(pfcp::urr_id_t& v) const {if (urr_id.first) {v = urr_id.second;return true;}return false;}
bool get(pfcp::qer_id_t& v) const {if (qer_id.first) {v = qer_id.second;return true;}return false;}
bool get(pfcp::activate_predefined_rules_t& v) const {if (activate_predefined_rules.first) {v = activate_predefined_rules.second;return true;}return false;}
bool update(const pfcp::update_pdr& update, uint8_t& cause_value);
bool look_up_pack_in_access(struct iphdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint, const uint32_t tunnel_id);
bool look_up_pack_in_core(struct iphdr* const iph, const std::size_t num_bytes);
void buffering_requested(const char *buffer, const std::size_t num_bytes);
void notify_cp_requested(std::shared_ptr<pfcp::pfcp_session> session);
// For sorting in collections
bool operator<(const pfcp_pdr &rhs) const { return (precedence.second.precedence < rhs.precedence.second.precedence); }
};
}
#include "../../spgwu/simpleswitch/pfcp_session.hpp"
#endif
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_session.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_PFCP_SESSION_HPP_SEEN
#define FILE_PFCP_SESSION_HPP_SEEN
#include "3gpp_29.244.h"
#include "msg_pfcp.hpp"
#include "pfcp_far.hpp"
#include "pfcp_pdr.hpp"
namespace pfcp {
#define PFCP
class pfcp_session {
private:
void add(std::shared_ptr<pfcp::pfcp_far>);
void add(std::shared_ptr<pfcp::pfcp_pdr>);
bool remove(const pfcp::far_id_t& far_id, uint8_t& cause_value);
bool remove(const pfcp::pdr_id_t& pdr_id, uint8_t& cause_value);
public:
pfcp::fseid_t cp_fseid;
uint64_t seid; // User plane
//TO DO better than this :(sooner the better) when inserting or removing new PDRs, FARS, should not conflict with switching operations
std::vector<std::shared_ptr<pfcp::pfcp_pdr>> pdrs;
std::vector<std::shared_ptr<pfcp::pfcp_far>> fars;
pfcp_session() : cp_fseid(), seid(0), pdrs(), fars()
{
pdrs.reserve(8);
fars.reserve(8);
}
pfcp_session(pfcp::fseid_t& cp, uint64_t up_seid) : pfcp_session()
{
cp_fseid = cp;
seid = up_seid;
}
pfcp_session(const pfcp_session& c): cp_fseid(c.cp_fseid), seid(c.seid), pdrs(c.pdrs), fars(c.fars) {}
virtual ~pfcp_session()
{
cleanup();
cp_fseid = {};
seid = {};
};
void cleanup();
std::string to_string() const;
uint64_t get_up_seid() const {return seid;};
bool get(const uint32_t, std::shared_ptr<pfcp::pfcp_far>&) const;
bool get(const uint16_t, std::shared_ptr<pfcp::pfcp_pdr>&) const;
bool update(const pfcp::update_far& update, uint8_t& cause_value);
bool update(const pfcp::update_pdr& update, uint8_t& cause_value);
bool create(const pfcp::create_far& cr_far, pfcp::cause_t& cause, uint16_t& offending_ie);
bool create(const pfcp::create_pdr& cr_pdr, pfcp::cause_t& cause, uint16_t& offending_ie, pfcp::fteid_t& allocated_fteid);
bool remove(const pfcp::remove_far& rm_far, pfcp::cause_t& cause, uint16_t& offending_ie);
bool remove(const pfcp::remove_pdr& rm_pdr, pfcp::cause_t& cause, uint16_t& offending_ie);
};
}
#endif
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pfcp_switch.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_PFCP_SWITCH_HPP_SEEN
#define FILE_PFCP_SWITCH_HPP_SEEN
//#include "concurrentqueue.h"
#include "itti.hpp"
#include "itti_msg_sxab.hpp"
#include "msg_pfcp.hpp"
#include "pfcp_session.hpp"
#include "uint_generator.hpp"
#include "thread_sched.hpp"
#include <folly/AtomicHashMap.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <unordered_map>
#include <memory>
#include <netinet/in.h>
#include <thread>
#include <vector>
namespace spgwu {
// Have to be tuned for sdt situations
#define PFCP_SWITCH_MAX_SESSIONS 512
#define PFCP_SWITCH_MAX_PDRS 512
#define PDN_INTERFACE_NAME "pdn"
//class switching_records{
//public:
// switching_records() {
// cp_fseid2pfcp_sessions = {};
// up_seid2pfcp_sessions = {};
// ul_s1u_teid2pfcp_pdr = {};
// ue_ipv4_hbo2pfcp_pdr = {};
// }
// std::unordered_map<pfcp::fseid_t, std::shared_ptr<pfcp::pfcp_session>> cp_fseid2pfcp_sessions;
// std::unordered_map<uint64_t, std::shared_ptr<pfcp::pfcp_session>> up_seid2pfcp_sessions;
//};
//
//class switching_data_per_cpu_socket {
//public:
// switching_data_per_cpu_socket() {
// msg_iov_= {};
// switching_up_traffic_index = 0;
// switching_control_index = 1;
// switching_records[0] = {};
// switching_records[1] = {};
// }
// switching_records switching_records[2];
// struct iovec msg_iov_; /* scatter/gather array */
// uint8_t switching_up_traffic_index;
// uint8_t switching_control_index;
//};
class pfcp_switch {
private:
// Very unoptimized
#define PFCP_SWITCH_RECV_BUFFER_SIZE 2048
#define ROOM_FOR_GTPV1U_G_PDU 64
char recv_buffer_[PFCP_SWITCH_RECV_BUFFER_SIZE];
int sock_r;
int sock_w;
std::thread thread_sock_;
//std::string gw_mac_address;
int pdn_if_index;
util::uint_generator<uint64_t> seid_generator_;
util::uint_generator<teid_t> teid_s1u_generator_;
#define TASK_SPGWU_PFCP_SWITCH_MAX_COMMIT_INTERVAL (0)
#define TASK_SPGWU_PFCP_SWITCH_MIN_COMMIT_INTERVAL (1)
#define PFCP_SWITCH_MAX_COMMIT_INTERVAL_MILLISECONDS 200
#define PFCP_SWITCH_MIN_COMMIT_INTERVAL_MILLISECONDS 50
//switching_data_per_cpu_socket switching_data[];
struct iovec msg_iov_; /* scatter/gather array */
std::unordered_map<pfcp::fseid_t, std::shared_ptr<pfcp::pfcp_session>> cp_fseid2pfcp_sessions;
folly::AtomicHashMap<uint64_t, std::shared_ptr<pfcp::pfcp_session>> up_seid2pfcp_sessions;
folly::AtomicHashMap<teid_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>> ul_s1u_teid2pfcp_pdr;
folly::AtomicHashMap<uint32_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>> ue_ipv4_hbo2pfcp_pdr;
//moodycamel::ConcurrentQueue<pfcp::pfcp_session*> create_session_q;
void pdn_read_loop(const util::thread_sched_params& sched_params);
int create_pdn_socket (const char * const ifname, const bool promisc, int& if_index);
int create_pdn_socket (const char * const ifname);
void setup_pdn_interfaces();
timer_id_t timer_max_commit_interval_id;
timer_id_t timer_min_commit_interval_id;
void stop_timer_min_commit_interval();
void start_timer_min_commit_interval();
void stop_timer_max_commit_interval();
void start_timer_max_commit_interval();
void commit_changes();
bool get_pfcp_session_by_cp_fseid(const pfcp::fseid_t&, std::shared_ptr<pfcp::pfcp_session>&) const;
bool get_pfcp_session_by_up_seid(const uint64_t, std::shared_ptr<pfcp::pfcp_session>&) const;
bool get_pfcp_ul_pdrs_by_up_teid(const teid_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>&) const;
bool get_pfcp_dl_pdrs_by_ue_ip(const uint32_t, std::shared_ptr<std::vector<std::shared_ptr<pfcp::pfcp_pdr>>>&) const;
void add_pfcp_session_by_cp_fseid(const pfcp::fseid_t&, std::shared_ptr<pfcp::pfcp_session>&);
void add_pfcp_session_by_up_seid(const uint64_t, std::shared_ptr<pfcp::pfcp_session>&);
void add_pfcp_ul_pdr_by_up_teid(const teid_t teid, std::shared_ptr<pfcp::pfcp_pdr>& );
void remove_pfcp_session(std::shared_ptr<pfcp::pfcp_session>&);
uint64_t generate_seid() {return seid_generator_.get_uid();};
teid_t generate_teid_s1u() {return teid_s1u_generator_.get_uid();};
public:
pfcp_switch();
pfcp_switch(pfcp_switch const&) = delete;
void operator=(pfcp_switch const&) = delete;
void add_pfcp_dl_pdr_by_ue_ip(const uint32_t ue_ip, std::shared_ptr<pfcp::pfcp_pdr>& );
pfcp::fteid_t generate_fteid_s1u();
bool create_packet_in_access(std::shared_ptr<pfcp::pfcp_pdr>& pdr, const pfcp::fteid_t& in, uint8_t& cause);
void pfcp_session_look_up_pack_in_access(struct iphdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint, const uint32_t tunnel_id);
void pfcp_session_look_up_pack_in_access(struct ipv6hdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint, const uint32_t tunnel_id);
void pfcp_session_look_up_pack_in_access(struct iphdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint) {};
void pfcp_session_look_up_pack_in_access(struct ipv6hdr* const iph, const std::size_t num_bytes, const endpoint& r_endpoint) {};
//void pfcp_session_look_up(struct ethhdr* const ethh, const std::size_t num_bytes);
void pfcp_session_look_up_pack_in_core(const char *buffer, const std::size_t num_bytes);
void send_to_core(char* const ip_packet, const ssize_t len);
void handle_pfcp_session_establishment_request(std::shared_ptr<itti_sxab_session_establishment_request> sreq, itti_sxab_session_establishment_response* );
void handle_pfcp_session_modification_request(std::shared_ptr<itti_sxab_session_modification_request> sreq, itti_sxab_session_modification_response* );
void handle_pfcp_session_deletion_request(std::shared_ptr<itti_sxab_session_deletion_request> sreq, itti_sxab_session_deletion_response* );
void time_out_min_commit_interval(const uint32_t timer_id);
void time_out_max_commit_interval(const uint32_t timer_id);
void remove_pfcp_session(const pfcp::fseid_t& cp_fseid);
void remove_pfcp_ul_pdrs_by_up_teid(const teid_t);
void remove_pfcp_dl_pdrs_by_ue_ip(const uint32_t);
std::string to_string() const;
};
}
#endif /* FILE_PFCP_SWITCH_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_s1u.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "3gpp_conversions.hpp"
#include "common_defs.h"
#include "conversions.hpp"
#include "gtpu.h"
#include "itti.hpp"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_config.hpp"
#include "spgwu_s1u.hpp"
#include <stdexcept>
using namespace gtpv1u;
using namespace spgwu;
using namespace std;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_config spgwu_cfg;
extern spgwu_s1u *spgwu_s1u_inst;
void spgwu_s1u_task (void*);
//------------------------------------------------------------------------------
void spgwu_s1u_task (void *args_p)
{
const task_id_t task_id = TASK_SPGWU_S1U;
const util::thread_sched_params* const sched_params = (const util::thread_sched_params* const)args_p;
sched_params->apply(task_id, Logger::spgwu_s1u());
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case S1U_ECHO_RESPONSE:
spgwu_s1u_inst->handle_itti_msg(std::static_pointer_cast<itti_s1u_echo_response>(shared_msg));
break;
case S1U_ERROR_INDICATION:
spgwu_s1u_inst->handle_itti_msg(std::static_pointer_cast<itti_s1u_error_indication>(shared_msg));
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::spgwu_s1u().info( "TIME-OUT event timer id %d", to->timer_id);
}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::spgwu_s1u().info( "Received terminate message");
return;
}
break;
case HEALTH_PING:
break;
default:
Logger::spgwu_s1u().info( "no handler for msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
spgwu_s1u::spgwu_s1u () : gtpu_l4_stack(spgwu_cfg.s1_up.addr4, spgwu_cfg.s1_up.port, spgwu_cfg.s1_up.thread_rd_sched_params)
{
Logger::spgwu_s1u().startup("Starting...");
if (itti_inst->create_task(TASK_SPGWU_S1U, spgwu_s1u_task, &spgwu_cfg.itti.s1u_sched_params) ) {
Logger::spgwu_s1u().error( "Cannot create task TASK_SPGWU_S1U" );
throw std::runtime_error( "Cannot create task TASK_SPGWU_S1U" );
}
Logger::spgwu_s1u().startup( "Started" );
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint)
{
#define GTPU_MESSAGE_FLAGS_POS_IN_UDP_PAYLOAD 0
struct gtpuhdr* gtpuh = (struct gtpuhdr*)&recv_buffer[0];
if (gtpuh->version == 1) {
// Do it fast, do not go throught handle_receive_gtpv1u_msg()
if (gtpuh->message_type == GTPU_G_PDU) {
uint8_t gtp_flags = recv_buffer[GTPU_MESSAGE_FLAGS_POS_IN_UDP_PAYLOAD];
std::size_t gtp_payload_offset = GTPV1U_MSG_HEADER_MIN_SIZE;
std::size_t gtp_payload_length = be16toh(gtpuh->message_length);
if (gtp_flags & 0x07) {
gtp_payload_offset += 4;
gtp_payload_length -= 4;
}
uint32_t tunnel_id = be32toh(gtpuh->teid);
struct iphdr* iph = (struct iphdr*)&recv_buffer[gtp_payload_offset];
if (iph->version == 4) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access(iph, gtp_payload_length, r_endpoint, tunnel_id);
} else if (iph->version == 6) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access((struct ipv6hdr*)iph, gtp_payload_length, r_endpoint, tunnel_id);
} else {
Logger::spgwu_s1u().trace( "Unknown GTPU_G_PDU packet");
}
} else {
//Logger::spgwu_s1u().info( "handle_receive(%d bytes)", bytes_transferred);
//std::cout << string_to_hex(recv_buffer, bytes_transferred) << std::endl;
std::istringstream iss(std::istringstream::binary);
iss.rdbuf()->pubsetbuf(recv_buffer,bytes_transferred);
gtpv1u_msg msg = {};
try {
msg.load_from(iss);
handle_receive_gtpv1u_msg(msg, r_endpoint);
} catch (gtpu_exception& e) {
Logger::spgwu_s1u().info( "handle_receive exception %s", e.what());
}
}
} else {
struct iphdr* iph = (struct iphdr*)&recv_buffer[0];
if (iph->version == 4) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access(iph, bytes_transferred, r_endpoint);
} else if (iph->version == 6) {
pfcp_switch_inst->pfcp_session_look_up_pack_in_access((struct ipv6hdr*)iph, bytes_transferred, r_endpoint);
} else {
Logger::spgwu_s1u().trace( "Unknown IPX packet");
}
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive_gtpv1u_msg(gtpv1u_msg& msg, const endpoint& r_endpoint)
{
//Logger::spgwu_s1u().trace( "handle_receive_gtpv1u_msg msg type %d length %d", msg.get_message_type(), msg.get_message_length());
switch (msg.get_message_type()) {
case GTPU_ECHO_REQUEST:
handle_receive_echo_request(msg, r_endpoint);
break;
case GTPU_ECHO_RESPONSE:
case GTPU_ERROR_INDICATION:
case GTPU_SUPPORTED_EXTENSION_HEADERS_NOTIFICATION:
case GTPU_END_MARKER:
case GTPU_G_PDU:
break;
default:
Logger::spgwu_s1u().error( "handle_receive_gtpv1u_msg msg length %d", msg.get_message_length());
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::send_g_pdu(const struct in_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes)
{
//Logger::spgwu_s1u().info( "spgwu_s1u::send_g_pdu() TEID " TEID_FMT " %d bytes", num_bytes);
struct sockaddr_in peer_sock_addr;
peer_sock_addr.sin_family = AF_INET;
peer_sock_addr.sin_addr = peer_addr;
peer_sock_addr.sin_port = htobe16(peer_udp_port);
gtpu_l4_stack::send_g_pdu(peer_sock_addr, (teid_t)tunnel_id, send_buffer, num_bytes);
}
//------------------------------------------------------------------------------
void spgwu_s1u::send_g_pdu(const struct in6_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes)
{
struct sockaddr_in6 peer_sock_addr;
peer_sock_addr.sin6_family = AF_INET6;
peer_sock_addr.sin6_addr = peer_addr;
peer_sock_addr.sin6_port = htobe16(peer_udp_port);
peer_sock_addr.sin6_flowinfo = 0;
peer_sock_addr.sin6_scope_id = 0;
gtpu_l4_stack::send_g_pdu(peer_sock_addr, tunnel_id, send_buffer, num_bytes);
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_receive_echo_request(gtpv1u_msg& msg, const endpoint& r_endpoint)
{
itti_s1u_echo_request *echo = new itti_s1u_echo_request(TASK_SPGWU_S1U, TASK_SPGWU_APP);
gtpv1u_echo_request msg_ies_container = {};
msg.to_core_type(echo->gtp_ies);
echo->gtp_ies.r_endpoint = r_endpoint;
echo->gtp_ies.set_teid(msg.get_teid());
uint16_t sn = 0;
if (msg.get_sequence_number(sn)) {
echo->gtp_ies.set_sequence_number(sn);
}
std::shared_ptr<itti_s1u_echo_request> secho = std::shared_ptr<itti_s1u_echo_request>(echo);
int ret = itti_inst->send_msg(secho);
if (RETURNok != ret) {
Logger::spgwu_s1u().error( "Could not send ITTI message %s to task TASK_SPGWU_APP", echo->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_itti_msg (std::shared_ptr<itti_s1u_echo_response> m)
{
send_response(m->gtp_ies);
}
//------------------------------------------------------------------------------
void spgwu_s1u::handle_itti_msg (std::shared_ptr<itti_s1u_error_indication> m)
{
send_indication(m->gtp_ies);
}
//------------------------------------------------------------------------------
void spgwu_s1u::report_error_indication(const endpoint& r_endpoint, const uint32_t tunnel_id)
{
itti_s1u_error_indication *error_ind = new itti_s1u_error_indication(TASK_SPGWU_S1U, TASK_SPGWU_S1U);
error_ind->gtp_ies.r_endpoint = r_endpoint;
error_ind->gtp_ies.set_teid(0);
tunnel_endpoint_identifier_data_i_t tun_data = {};
tun_data.tunnel_endpoint_identifier_data_i = tunnel_id;
error_ind->gtp_ies.set(tun_data);
gtp_u_peer_address_t peer_address = {};
if (xgpp_conv::endpoint_to_gtp_u_peer_address(r_endpoint, peer_address)) {
error_ind->gtp_ies.set(peer_address);
} else {
// mandatory ie
delete error_ind;
return;
}
std::shared_ptr<itti_s1u_error_indication> serror_ind = std::shared_ptr<itti_s1u_error_indication>(error_ind);
int ret = itti_inst->send_msg(serror_ind);
if (RETURNok != ret) {
Logger::spgwu_s1u().error( "Could not send ITTI message %s to task TASK_SPGWU_S1U", error_ind->get_msg_name());
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_s1u.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SGWU_S1U_HPP_SEEN
#define FILE_SGWU_S1U_HPP_SEEN
#include "endpoint.hpp"
#include "gtpv1u.hpp"
#include "itti_msg_s1u.hpp"
#include "msg_gtpv1u.hpp"
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <netinet/in.h>
#include <thread>
namespace spgwu {
class spgwu_s1u : public gtpv1u::gtpu_l4_stack {
private:
std::thread::id thread_id;
std::thread thread;
void handle_receive_gtpv1u_msg(gtpv1u::gtpv1u_msg& msg, const endpoint& r_endpoint);
void handle_receive_echo_request(gtpv1u::gtpv1u_msg& msg, const endpoint& r_endpoint);
public:
spgwu_s1u();
spgwu_s1u(spgwu_s1u const&) = delete;
void operator=(spgwu_s1u const&) = delete;
//void handle_itti_msg (itti_s1u_echo_request& s) {};
void handle_itti_msg (std::shared_ptr<itti_s1u_echo_response> m);
void handle_itti_msg (std::shared_ptr<itti_s1u_error_indication> m);
//void handle_itti_msg (itti_s1u_supported_extension_headers_notification& s) {};
//void handle_itti_msg (itti_s1u_end_marker& s) {};
//void send_msg (itti_s1u_echo_request& s) {};
//void send_msg (itti_s1u_echo_response& s);
//void send_msg (itti_s1u_error_indication& s) {};
//void send_msg (itti_s1u_supported_extension_headers_notification& s) {};
//void send_msg (itti_s1u_end_marker& s) {};
void handle_receive_s1u_msg( gtpv1u::gtpv1u_msg& msg, const endpoint& r_endpoint);
void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& r_endpoint);
void send_g_pdu(const struct in_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes);
void send_g_pdu(const struct in6_addr& peer_addr, const uint16_t peer_udp_port, const uint32_t tunnel_id, const char* send_buffer, const ssize_t num_bytes);
void time_out_itti_event(const uint32_t timer_id);
void report_error_indication(const endpoint& r_endpoint, const uint32_t tunnel_id);
};
}
#endif /* FILE_SGWU_S1U_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_app.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "conversions.hpp"
#include "itti.hpp"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_app.hpp"
#include "spgwu_config.hpp"
#include "spgwu_s1u.hpp"
#include "spgwu_sx.hpp"
#include <stdexcept>
using namespace pfcp;
using namespace spgwu;
using namespace std;
// C includes
spgwu_sx *spgwu_sx_inst = nullptr;
spgwu_s1u *spgwu_s1u_inst = nullptr;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_app *spgwu_app_inst;
extern spgwu_config spgwu_cfg;
void spgwu_app_task (void*);
//------------------------------------------------------------------------------
void spgwu_app_task (void *args_p)
{
const task_id_t task_id = TASK_SPGWU_APP;
const util::thread_sched_params* const sched_params = (const util::thread_sched_params* const)args_p;
sched_params->apply(task_id, Logger::spgwu_app());
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case S1U_ECHO_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_s1u_echo_request>(shared_msg));
break;
case SXAB_SESSION_ESTABLISHMENT_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_establishment_request>(shared_msg));
break;
case SXAB_SESSION_MODIFICATION_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_modification_request>(shared_msg));
break;
case SXAB_SESSION_DELETION_REQUEST:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_deletion_request>(shared_msg));
break;
case SXAB_SESSION_REPORT_RESPONSE:
spgwu_app_inst->handle_itti_msg(std::static_pointer_cast<itti_sxab_session_report_response>(shared_msg));
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) {
case TASK_SPGWU_PFCP_SWITCH_MIN_COMMIT_INTERVAL:
pfcp_switch_inst->time_out_min_commit_interval(to->timer_id);
break;
case TASK_SPGWU_PFCP_SWITCH_MAX_COMMIT_INTERVAL:
pfcp_switch_inst->time_out_max_commit_interval(to->timer_id);
break;
default:
;
}
}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::spgwu_app().info( "Received terminate message");
return;
}
break;
case HEALTH_PING:
break;
default:
Logger::spgwu_app().info( "no handler for ITTI msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
spgwu_app::spgwu_app (const std::string& config_file)
{
Logger::spgwu_app().startup("Starting...");
spgwu_cfg.execute();
if (itti_inst->create_task(TASK_SPGWU_APP, spgwu_app_task, &spgwu_cfg.itti.spgwu_app_sched_params) ) {
Logger::spgwu_app().error( "Cannot create task TASK_SPGWU_APP" );
throw std::runtime_error( "Cannot create task TASK_SPGWU_APP" );
}
try {
spgwu_sx_inst = new spgwu_sx();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create SPGWU_SX: %s", e.what() );
throw;
}
try {
spgwu_s1u_inst = new spgwu_s1u();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create SPGWU_S1U: %s", e.what() );
throw;
}
try {
pfcp_switch_inst = new pfcp_switch();
} catch (std::exception& e) {
Logger::spgwu_app().error( "Cannot create PFCP_SWITCH: %s", e.what() );
throw;
}
Logger::spgwu_app().startup( "Started" );
}
//------------------------------------------------------------------------------
spgwu_app::~spgwu_app()
{
if (spgwu_sx_inst) delete spgwu_sx_inst;
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<itti_s1u_echo_request> m)
{
Logger::spgwu_app().debug("Received %s ", m->get_msg_name());
itti_s1u_echo_response *s1u_resp = new itti_s1u_echo_response(TASK_SPGWU_APP, TASK_SPGWU_S1U);
// May insert a call to a function here(throttle for example)
s1u_resp->gtp_ies.r_endpoint = m->gtp_ies.r_endpoint;
s1u_resp->gtp_ies.teid = m->gtp_ies.teid;
s1u_resp->gtp_ies.sequence_number = m->gtp_ies.sequence_number;
std::shared_ptr<itti_s1u_echo_response> msg = std::shared_ptr<itti_s1u_echo_response>(s1u_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_SPGWU_S1U", s1u_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_establishment_request> m)
{
Logger::spgwu_app().info("Received SXAB_SESSION_ESTABLISHMENT_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_establishment_response *sx_resp = new itti_sxab_session_establishment_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_establishment_request(m, sx_resp);
pfcp::node_id_t node_id = {};
spgwu_cfg.get_pfcp_node_id(node_id);
sx_resp->pfcp_ies.set(node_id);
sx_resp->trxn_id = m->trxn_id;
sx_resp->seid = m->pfcp_ies.cp_fseid.second.seid; // Mandatory IE, but... may be bad to do this
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_establishment_response> msg = std::shared_ptr<itti_sxab_session_establishment_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_modification_request> m)
{
Logger::spgwu_app().info("Received SXAB_SESSION_MODIFICATION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_modification_response *sx_resp = new itti_sxab_session_modification_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_modification_request(m, sx_resp);
sx_resp->trxn_id = m->trxn_id;
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_modification_response> msg = std::shared_ptr<itti_sxab_session_modification_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_deletion_request> m)
{
Logger::spgwu_app().info("Received SXAB_SESSION_DELETION_REQUEST seid " SEID_FMT " ", m->seid);
itti_sxab_session_deletion_response *sx_resp = new itti_sxab_session_deletion_response(TASK_SPGWU_APP, TASK_SPGWU_SX);
pfcp_switch_inst->handle_pfcp_session_deletion_request(m, sx_resp);
sx_resp->trxn_id = m->trxn_id;
sx_resp->r_endpoint = m->r_endpoint;
sx_resp->l_endpoint = m->l_endpoint;
std::shared_ptr<itti_sxab_session_deletion_response> msg = std::shared_ptr<itti_sxab_session_deletion_response>(sx_resp);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::spgwu_app().error( "Could not send ITTI message %s to task TASK_PGWC_SX", sx_resp->get_msg_name());
}
}
//------------------------------------------------------------------------------
void spgwu_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_report_response> m)
{
Logger::spgwu_app().info("Received SXAB_SESSION_REPORT_RESPONSE seid " SEID_FMT " ", m->seid);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_app.hpp
\author Lionel GAUTHIER
\date 2018
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_APP_HPP_SEEN
#define FILE_SPGWU_APP_HPP_SEEN
#include "common_root_types.h"
#include "itti_msg_sxab.hpp"
#include "itti_msg_s1u.hpp"
#include <boost/atomic.hpp>
#include <map>
#include <string>
#include <thread>
#include <memory>
#include <map>
#include <set>
namespace spgwu {
class spgwu_app {
private:
std::thread::id thread_id;
std::thread thread;
public:
explicit spgwu_app(const std::string& config_file);
~spgwu_app();
spgwu_app(spgwu_app const&) = delete;
void operator=(spgwu_app const&) = delete;
teid_t generate_s5s8_up_teid();
void handle_itti_msg (std::shared_ptr<itti_s1u_echo_request> m);
// void handle_itti_msg (itti_sxab_heartbeat_request& m);
// void handle_itti_msg (itti_sxab_heartbeat_response& m);
// void handle_itti_msg (itti_sxab_pfcp_pfd_management_request& m);
// void handle_itti_msg (itti_sxab_pfcp_pfd_management_response& m);
// void handle_itti_msg (itti_sxab_pfcp_association_setup_request& m);
// void handle_itti_msg (itti_sxab_pfcp_association_setup_response& m);
// void handle_itti_msg (itti_sxab_pfcp_association_update_request& m);
// void handle_itti_msg (itti_sxab_pfcp_association_update_response& m);
// void handle_itti_msg (itti_sxab_pfcp_association_release_request& m);
// void handle_itti_msg (itti_sxab_pfcp_association_release_response& m);
// void handle_itti_msg (itti_sxab_pfcp_version_not_supported_response& m);
// void handle_itti_msg (itti_sxab_pfcp_node_report_request& m);
// void handle_itti_msg (itti_sxab_pfcp_node_report_response& m);
void handle_itti_msg (std::shared_ptr<itti_sxab_session_establishment_request> m);
void handle_itti_msg (std::shared_ptr<itti_sxab_session_modification_request> m);
void handle_itti_msg (std::shared_ptr<itti_sxab_session_deletion_request> m);
// void handle_itti_msg (itti_sxab_session_deletion_response& m);
// void handle_itti_msg (itti_sxab_session_report_request& m);
void handle_itti_msg (std::shared_ptr<itti_sxab_session_report_response> m);
};
}
#endif /* FILE_SPGWU_APP_HPP_SEEN */
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_config.hpp
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_CONFIG_HPP_SEEN
#define FILE_SPGWU_CONFIG_HPP_SEEN
#include "3gpp_29.244.h"
#include "gtpv1u.hpp"
#include "pfcp.hpp"
#include "thread_sched.hpp"
#include <libconfig.h++>
#include <mutex>
#include <netinet/in.h>
#include <stdint.h>
#include <stdbool.h>
#include <string>
namespace spgwu {
#define SPGWU_CONFIG_STRING_SPGWU_CONFIG "SPGW-U"
#define SPGWU_CONFIG_STRING_PID_DIRECTORY "PID_DIRECTORY"
#define SPGWU_CONFIG_STRING_INSTANCE "INSTANCE"
#define SPGWU_CONFIG_STRING_INTERFACES "INTERFACES"
#define SPGWU_CONFIG_STRING_INTERFACE_NAME "INTERFACE_NAME"
#define SPGWU_CONFIG_STRING_IPV4_ADDRESS "IPV4_ADDRESS"
#define SPGWU_CONFIG_STRING_PORT "PORT"
#define SPGWU_CONFIG_STRING_SCHED_PARAMS "SCHED_PARAMS"
#define SPGWU_CONFIG_STRING_THREAD_RD_CPU_ID "CPU_ID"
#define SPGWU_CONFIG_STRING_THREAD_RD_SCHED_POLICY "SCHED_POLICY"
#define SPGWU_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY "SCHED_PRIORITY"
#define SPGWU_CONFIG_STRING_INTERFACE_SGI "SGI"
#define SPGWU_CONFIG_STRING_INTERFACE_SX "SX"
#define SPGWU_CONFIG_STRING_INTERFACE_S1U_S12_S4_UP "S1U_S12_S4_UP"
#define SPGWU_CONFIG_STRING_PDN_NETWORK_LIST "PDN_NETWORK_LIST"
#define SPGWU_CONFIG_STRING_NETWORK_IPV4 "NETWORK_IPV4"
#define SPGWU_CONFIG_STRING_NETWORK_IPV6 "NETWORK_IPV6"
#define SPGWU_CONFIG_STRING_ADDRESS_PREFIX_DELIMITER "/"
#define SPGWU_CONFIG_STRING_SNAT "SNAT"
#define SPGWU_CONFIG_STRING_MAX_PFCP_SESSIONS "MAX_PFCP_SESSIONS"
#define SPGWU_CONFIG_STRING_SPGWC_LIST "SPGW-C_LIST"
#define SPGWU_CONFIG_STRING_ITTI_TASKS "ITTI_TASKS"
#define SPGWU_CONFIG_STRING_ITTI_TIMER_SCHED_PARAMS "ITTI_TIMER_SCHED_PARAMS"
#define SPGWU_CONFIG_STRING_S1U_SCHED_PARAMS "S1U_SCHED_PARAMS"
#define SPGWU_CONFIG_STRING_SX_SCHED_PARAMS "SX_SCHED_PARAMS"
#define SPGWU_CONFIG_STRING_SPGWU_APP_SCHED_PARAMS "SPGWU_APP_SCHED_PARAMS"
#define SPGWU_CONFIG_STRING_ASYNC_CMD_SCHED_PARAMS "ASYNC_CMD_SCHED_PARAMS"
#define SPGW_ABORT_ON_ERROR true
#define SPGW_WARN_ON_ERROR false
typedef struct interface_cfg_s {
std::string if_name;
struct in_addr addr4;
struct in_addr network4;
struct in6_addr addr6;
unsigned int mtu;
unsigned int port;
util::thread_sched_params thread_rd_sched_params;
} interface_cfg_t;
typedef struct pdn_cfg_s {
struct in_addr network_ipv4;
int prefix_ipv4;
struct in6_addr network_ipv6;
int prefix_ipv6;
bool snat;
} pdn_cfg_t;
typedef struct itti_cfg_s {
util::thread_sched_params itti_timer_sched_params;
util::thread_sched_params s1u_sched_params;
util::thread_sched_params sx_sched_params;
util::thread_sched_params spgwu_app_sched_params;
util::thread_sched_params async_cmd_sched_params;
} itti_cfg_t;
class spgwu_config {
private:
int load_itti(const libconfig::Setting& itti_cfg, itti_cfg_t& cfg);
int load_interface(const libconfig::Setting& if_cfg, interface_cfg_t& cfg);
int load_thread_sched_params(const libconfig::Setting& thread_sched_params_cfg, util::thread_sched_params& cfg);
public:
/* Reader/writer lock for this configuration */
std::mutex m_rw_lock;
std::string pid_dir;
unsigned int instance;
interface_cfg_t s1_up;
interface_cfg_t sgi;
interface_cfg_t sx;
itti_cfg_t itti;
std::string gateway;
uint32_t max_pfcp_sessions;
std::vector<pdn_cfg_t> pdns;
std::vector<pfcp::node_id_t> spgwcs;
spgwu_config() : m_rw_lock(), pid_dir(), instance(0), s1_up(), sgi(), gateway(), sx(), itti(), pdns(), spgwcs(), max_pfcp_sessions(100)
{
itti.itti_timer_sched_params.sched_priority = 85;
itti.s1u_sched_params.sched_priority = 84;
itti.sx_sched_params.sched_priority = 84;
itti.spgwu_app_sched_params.sched_priority = 84;
itti.async_cmd_sched_params.sched_priority = 84;
s1_up.thread_rd_sched_params.sched_priority = 98;
s1_up.port = gtpv1u::default_port;
sgi.thread_rd_sched_params.sched_priority = 98;
sx.thread_rd_sched_params.sched_priority = 95;
sx.port = pfcp::default_port;
};
void lock() {m_rw_lock.lock();};
void unlock() {m_rw_lock.unlock();};
int load(const std::string& config_file);
int execute();
void display();
int get_pfcp_node_id(pfcp::node_id_t& node_id);
int get_pfcp_fseid(pfcp::fseid_t& fseid);
};
} // namespace spgwu
#endif /* FILE_SPGWU_CONFIG_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_pfcp_association.cpp
\brief
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#include "common_defs.h"
#include "logger.hpp"
#include "pfcp_switch.hpp"
#include "spgwu_pfcp_association.hpp"
#include "spgwu_sx.hpp"
using namespace spgwu;
using namespace std;
extern itti_mw *itti_inst;
extern pfcp_switch *pfcp_switch_inst;
extern spgwu_sx *spgwu_sx_inst;
//------------------------------------------------------------------------------
void pfcp_association::notify_add_session(const pfcp::fseid_t& cp_fseid)
{
std::unique_lock<std::mutex> l(m_sessions);
sessions.insert(cp_fseid);
}
//------------------------------------------------------------------------------
bool pfcp_association::has_session(const pfcp::fseid_t& cp_fseid) const
{
std::unique_lock<std::mutex> l(m_sessions);
auto it = sessions.find(cp_fseid);
if (it != sessions.end()) {
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
void pfcp_association::notify_del_session(const pfcp::fseid_t& cp_fseid)
{
std::unique_lock<std::mutex> l(m_sessions);
sessions.erase(cp_fseid);
}
//------------------------------------------------------------------------------
void pfcp_association::del_sessions()
{
std::unique_lock<std::mutex> l(m_sessions);
for (std::set<pfcp::fseid_t>::iterator it=sessions.begin(); it!=sessions.end();) {
pfcp_switch_inst->remove_pfcp_session(*it);
sessions.erase(it++);
}
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_association(pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp)
{
std::shared_ptr<pfcp_association> sa = {};
if (remove_peer_candidate_node(node_id, sa)) {
sa->recovery_time_stamp = recovery_time_stamp;
sa->function_features = {};
std::size_t hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
associations.insert((int32_t)hash_node_id, sa);
trigger_heartbeat_request_procedure(sa);
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_association(pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp, pfcp::cp_function_features_s&
function_features)
{
std::shared_ptr<pfcp_association> sa = {};
if (remove_peer_candidate_node(node_id, sa)) {
sa->recovery_time_stamp = recovery_time_stamp;
sa->set(function_features);
std::size_t hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
associations.insert((int32_t)hash_node_id, sa);
trigger_heartbeat_request_procedure(sa);
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::get_association(const pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa) const
{
std::size_t hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
auto pit = associations.find((int32_t)hash_node_id);
if ( pit == associations.end() )
return false;
else {
sa = pit->second;
return true;
}
}
//------------------------------------------------------------------------------
bool pfcp_associations::get_association(const pfcp::fseid_t& cp_fseid, std::shared_ptr<pfcp_association>& sa) const
{
folly::AtomicHashMap<int32_t, std::shared_ptr<pfcp_association>>::iterator it;
FOR_EACH (it, associations) {
std::shared_ptr<pfcp_association> a = it->second;
if (it->second->has_session(cp_fseid)) {
sa = it->second;
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::remove_peer_candidate_node(pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& s)
{
for (std::vector<std::shared_ptr<pfcp_association>>::iterator it=pending_associations.begin(); it < pending_associations.end(); ++it) {
if ((*it)->node_id == node_id) {
s = *it;
pending_associations.erase(it);
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
bool pfcp_associations::add_peer_candidate_node(const pfcp::node_id_t& node_id)
{
for (std::vector<std::shared_ptr<pfcp_association>>::iterator it=pending_associations.begin(); it < pending_associations.end(); ++it) {
if ((*it)->node_id == node_id) {
// TODO purge sessions of this node
Logger::spgwu_sx().info( "TODO purge sessions of this node");
pending_associations.erase(it);
break;
}
}
pfcp_association* association = new pfcp_association(node_id);
std::shared_ptr<pfcp_association> s = std::shared_ptr<pfcp_association>(association);
pending_associations.push_back(s);
return true;
//start_timer = itti_inst->timer_setup(0,0, TASK_SPGWU_SX, TASK_MME_S11_TIMEOUT_SEND_GTPU_PING, 0);
}
//------------------------------------------------------------------------------
void pfcp_associations::trigger_heartbeat_request_procedure(std::shared_ptr<pfcp_association>& s)
{
s->timer_heartbeat = itti_inst->timer_setup(5,0, TASK_SPGWU_SX, TASK_SPGWU_SX_TRIGGER_HEARTBEAT_REQUEST, s->hash_node_id);
}
//------------------------------------------------------------------------------
void pfcp_associations::initiate_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user)
{
size_t hash = (size_t)arg2_user;
for (auto it : associations) {
if (it.second->hash_node_id == hash) {
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE hash %u starting", hash);
it.second->num_retries_timer_heartbeat = 0;
spgwu_sx_inst->send_heartbeat_request(it.second);
}
}
}
//------------------------------------------------------------------------------
void pfcp_associations::timeout_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user)
{
size_t hash = (size_t)arg2_user;
for (auto it : associations) {
if (it.second->hash_node_id == hash) {
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE hash %u TIMED OUT", hash);
if (it.second->num_retries_timer_heartbeat < PFCP_ASSOCIATION_HEARTBEAT_MAX_RETRIES) {
it.second->num_retries_timer_heartbeat++;
spgwu_sx_inst->send_heartbeat_request(it.second);
} else {
it.second->del_sessions();
pfcp::node_id_t node_id = it.second->node_id;
std::size_t hash_node_id = it.second->hash_node_id;
associations.erase((uint32_t)hash_node_id);
add_peer_candidate_node(node_id);
break;
}
}
}
}
//------------------------------------------------------------------------------
void pfcp_associations::handle_receive_heartbeat_response(const uint64_t trxn_id)
{
for (auto it : associations) {
if (it.second->trxn_id_heartbeat == trxn_id) {
itti_inst->timer_remove(it.second->timer_heartbeat);
trigger_heartbeat_request_procedure(it.second);
return;
}
}
Logger::spgwu_sx().info( "PFCP HEARTBEAT PROCEDURE trxn_id %d NOT FOUND", trxn_id);
}
//------------------------------------------------------------------------------
void pfcp_associations::notify_add_session(const pfcp::node_id_t& node_id, const pfcp::fseid_t& cp_fseid)
{
std::shared_ptr<pfcp_association> sa = {};
if (get_association(node_id, sa)) {
sa->notify_add_session(cp_fseid);
}
}
//------------------------------------------------------------------------------
void pfcp_associations::notify_del_session(const pfcp::fseid_t& cp_fseid)
{
std::shared_ptr<pfcp_association> sa = {};
if (get_association(cp_fseid, sa)) {
sa->notify_del_session(cp_fseid);
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_pfcp_association.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN
#define FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN
#include "3gpp_29.244.h"
#include "itti.hpp"
#include <folly/AtomicHashMap.h>
#include <folly/AtomicLinkedList.h>
#include <mutex>
#include <vector>
namespace spgwu {
#define PFCP_ASSOCIATION_HEARTBEAT_MAX_RETRIES 5
class pfcp_association {
public:
pfcp::node_id_t node_id; // peer
std::size_t hash_node_id;
pfcp::recovery_time_stamp_t recovery_time_stamp;
std::pair<bool,pfcp::cp_function_features_s> function_features;
//
mutable std::mutex m_sessions;
std::set<pfcp::fseid_t> sessions;
//
timer_id_t timer_heartbeat;
int num_retries_timer_heartbeat;
uint64_t trxn_id_heartbeat;
timer_id_t timer_association;
explicit pfcp_association(const pfcp::node_id_t& node_id) :
node_id(node_id), recovery_time_stamp(), function_features(), m_sessions(), sessions() {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
}
pfcp_association(const pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp) :
node_id(node_id), recovery_time_stamp(recovery_time_stamp), function_features(), m_sessions(), sessions() {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
}
pfcp_association(const pfcp::node_id_t& ni, pfcp::recovery_time_stamp_t& rts, pfcp::cp_function_features_s& uff):
node_id(ni), recovery_time_stamp(rts), m_sessions(), sessions() {
hash_node_id = std::hash<pfcp::node_id_t>{}(node_id);
function_features.first = true;
function_features.second = uff;
timer_heartbeat = ITTI_INVALID_TIMER_ID;
num_retries_timer_heartbeat = 0;
trxn_id_heartbeat = 0;
timer_association = {};
}
// pfcp_association(pfcp_association const & p)
// {
// node_id = p.node_id;
// hash_node_id = p.hash_node_id;
// recovery_time_stamp = p.recovery_time_stamp;
// function_features = p.function_features;
// sessions = p.sessions;
// num_sessions = p.num_sessions;
// timer_heartbeat = p.timer_heartbeat;
// num_retries_timer_heartbeat = p.num_retries_timer_heartbeat;
// trxn_id_heartbeat = p.trxn_id_heartbeat;
// }
void notify_add_session(const pfcp::fseid_t& cp_fseid);
bool has_session(const pfcp::fseid_t& cp_fseid) const ;
void notify_del_session(const pfcp::fseid_t& cp_fseid);
void del_sessions();
void set(const pfcp::cp_function_features_s& ff) {function_features.first = true; function_features.second = ff;};
const pfcp::node_id_t& peer_node_id() const {return this->node_id;};
};
#define PFCP_MAX_ASSOCIATIONS 16
class pfcp_associations {
private:
std::vector<std::shared_ptr<pfcp_association>> pending_associations;
folly::AtomicHashMap<int32_t, std::shared_ptr<pfcp_association>> associations;
pfcp_associations() : associations(PFCP_MAX_ASSOCIATIONS), pending_associations() {};
void trigger_heartbeat_request_procedure(std::shared_ptr<pfcp_association>& s);
bool remove_peer_candidate_node(pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& s);
public:
static pfcp_associations& get_instance()
{
static pfcp_associations instance;
return instance;
}
pfcp_associations(pfcp_associations const&) = delete;
void operator=(pfcp_associations const&) = delete;
bool add_association(pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp);
bool add_association(pfcp::node_id_t& node_id, pfcp::recovery_time_stamp_t& recovery_time_stamp, pfcp::cp_function_features_s& function_features);
bool get_association(const pfcp::node_id_t& node_id, std::shared_ptr<pfcp_association>& sa) const;
bool get_association(const pfcp::fseid_t& cp_fseid, std::shared_ptr<pfcp_association>& sa) const;
void notify_add_session(const pfcp::node_id_t& node_id, const pfcp::fseid_t& cp_fseid);
void notify_del_session(const pfcp::fseid_t& cp_fseid);
bool add_peer_candidate_node(const pfcp::node_id_t& node_id);
void restore_sx_sessions(const pfcp::node_id_t& node_id);
void initiate_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user);
void timeout_heartbeat_request(timer_id_t timer_id, uint64_t arg2_user);
void handle_receive_heartbeat_response(const uint64_t trxn_id);
};
}
#endif /* FILE_SPGWU_PFCP_ASSOCIATION_HPP_SEEN */
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file spgwu_sx.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_SGWU_SX_HPP_SEEN
#define FILE_SGWU_SX_HPP_SEEN
#include "endpoint.hpp"
#include "pfcp.hpp"
#include "itti_msg_sxab.hpp"
#include "msg_pfcp.hpp"
#include "spgwu_pfcp_association.hpp"
#include <thread>
namespace spgwu {
#define TASK_SPGWU_SX_TRIGGER_HEARTBEAT_REQUEST (0)
#define TASK_SPGWU_SX_TIMEOUT_HEARTBEAT_REQUEST (1)
#define TASK_SPGWU_SX_TIMEOUT_ASSOCIATION_REQUEST (2)
class spgwu_sx : public pfcp::pfcp_l4_stack {
private:
std::thread::id thread_id;
std::thread thread;
uint64_t recovery_time_stamp; //timestamp in seconds
pfcp::up_function_features_s up_function_features;
void start_association(const pfcp::node_id_t& node_id);
public:
spgwu_sx();
spgwu_sx(spgwu_sx const&) = delete;
void operator=(spgwu_sx const&) = delete;
void handle_itti_msg (itti_sxab_heartbeat_request& s) {};
void handle_itti_msg (itti_sxab_heartbeat_response& s) {};
void handle_itti_msg (itti_sxab_association_setup_request& s) {};
void handle_itti_msg (itti_sxab_association_setup_response& s) {};
void handle_itti_msg (itti_sxab_association_update_request& s) {};
void handle_itti_msg (itti_sxab_association_update_response& s) {};
void handle_itti_msg (itti_sxab_association_release_request& s) {};
void handle_itti_msg (itti_sxab_association_release_response& s) {};
void handle_itti_msg (itti_sxab_version_not_supported_response& s) {};
void handle_itti_msg (itti_sxab_node_report_response& s) {};
void handle_itti_msg (itti_sxab_session_set_deletion_request& s) {};
void handle_itti_msg (itti_sxab_session_establishment_response& s);
void handle_itti_msg (itti_sxab_session_modification_response& s);
void handle_itti_msg (itti_sxab_session_deletion_response& s);
void handle_itti_msg (itti_sxab_session_report_response& s) {};
void send_sx_msg (itti_sxab_heartbeat_request& s) {};
void send_sx_msg (itti_sxab_heartbeat_response& s) {};
void send_sx_msg (itti_sxab_association_setup_request& s);
void send_sx_msg (itti_sxab_association_setup_response& s) {};
void send_sx_msg (itti_sxab_association_update_request& s) {};
void send_sx_msg (itti_sxab_association_update_response& s) {};
void send_sx_msg (itti_sxab_association_release_request& s) {};
void send_sx_msg (itti_sxab_association_release_response& s) {};
void send_sx_msg (itti_sxab_version_not_supported_response& s) {};
void send_sx_msg (itti_sxab_node_report_request& s) {};
void send_sx_msg (itti_sxab_session_set_deletion_response& s) {};
void send_sx_msg (itti_sxab_session_establishment_response& s);
void send_sx_msg (itti_sxab_session_modification_response& s);
void send_sx_msg (itti_sxab_session_deletion_response& s);
void send_sx_msg (itti_sxab_session_report_request& s) ;
void send_sx_msg(const pfcp::fseid_t& cp_fseid, const pfcp::pfcp_session_report_request& s);
void send_heartbeat_request(std::shared_ptr<pfcp_association>& a);
void send_heartbeat_response(const endpoint& r_endpoint, const uint64_t trxn_id);
void handle_receive_pfcp_msg( pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, const endpoint& remote_endpoint);
// node related
void handle_receive_heartbeat_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive_heartbeat_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive_association_setup_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
// session related
void handle_receive_session_establishment_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive_session_modification_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive_session_deletion_request(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void handle_receive_session_report_response(pfcp::pfcp_msg& msg, const endpoint& remote_endpoint);
void time_out_itti_event(const uint32_t timer_id);
};
}
#endif /* FILE_SGWU_SX_HPP_SEEN */
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